class RELPFrameHandler {

    public void handle(final RELPFrame frame, final ChannelResponder<SocketChannel> responder, final String sender)
            throws IOException, InterruptedException {

        // respond to open and close commands immediately, create and queue an event for everything else
        if (CMD_OPEN.equals(frame.getCommand())) {
            Map<String,String> offers = RELPResponse.parseOffers(frame.getData(), charset);
            ChannelResponse response = new RELPChannelResponse(encoder, RELPResponse.open(frame.getTxnr(), offers));
            responder.addResponse(response);
            responder.respond();
        } else if (CMD_CLOSE.equals(frame.getCommand())) {
            ChannelResponse response = new RELPChannelResponse(encoder, RELPResponse.ok(frame.getTxnr()));
            responder.addResponse(response);
            responder.respond();
            dispatcher.completeConnection(key);
        } else {
            final Map<String, String> metadata = EventFactoryUtil.createMapWithSender(sender.toString());
            metadata.put(RELPMetadata.TXNR_KEY, String.valueOf(frame.getTxnr()));
            metadata.put(RELPMetadata.COMMAND_KEY, frame.getCommand());

            final E event = eventFactory.create(frame.getData(), metadata, responder);
            events.offer(event);
        }
    }

    public  RELPFrameHandler(final SelectionKey selectionKey,
                            final Charset charset,
                            final EventFactory<E> eventFactory,
                            final BlockingQueue<E> events,
                            final AsyncChannelDispatcher dispatcher,
                            final ComponentLog logger);

}