/**
   * Encode (for some cheap value of 'encode') a resulting resource into a ResourceState.
   *
   * @param ctx
   * @param response The response to encode.
   * @throws Exception
   */
  protected void encode(ChannelHandlerContext ctx, ResourceResponse response) {
    final ClientResourceResponse.ResponseType responseType = ClientResourceResponse.ResponseType.OK;
    if (response.resource() == null) {
      ctx.writeAndFlush(
          new ClientResourceResponseImpl(
              response.inReplyTo(),
              responseType,
              response.inReplyTo().resourcePath().toString(),
              null));
      ctx.fireUserEventTriggered(new RequestCompleteEvent(response.requestId()));
      return;
    }

    ctx.writeAndFlush(
        new ClientResourceResponseImpl(
            response.inReplyTo(),
            responseType,
            response.inReplyTo().resourcePath().toString(),
            response.state()));
    ctx.fireUserEventTriggered(new RequestCompleteEvent(response.requestId()));
  }
  @Test
  public void testCorrelationWithRequestReplacement() throws Exception {

    List<Interceptor> interceptors = new ArrayList<>();

    MockInterceptor interceptor1 = new MockInterceptor();
    DefaultInterceptor interceptor2 =
        new DefaultInterceptor() {
          @Override
          public void onInbound(InboundInterceptorContext context) throws Exception {
            ResourceRequest replacement =
                new DefaultResourceRequest.Builder(context.request()).build();
            context.forward(replacement);
          }

          @Override
          public void onOutbound(OutboundInterceptorContext context) throws Exception {
            ResourceResponse replacement =
                new DefaultResourceResponse(context.request(), ResourceResponse.ResponseType.ERROR);
            context.forward(replacement);
          }
        };
    MockInterceptor interceptor3 = new MockInterceptor();

    interceptors.add(interceptor1);
    interceptors.add(interceptor2);
    interceptors.add(interceptor3);

    EmbeddedChannel channel =
        new EmbeddedChannel(
            new ChannelDuplexHandler() {
              @Override
              public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)
                  throws Exception {
                InterceptorChain chain =
                    new InterceptorChain(ctx, interceptors, (ResourceResponse) msg);
                chain.fireOutbound();
              }

              @Override
              public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                InterceptorChain chain =
                    new InterceptorChain(ctx, interceptors, (ResourceRequest) msg);
                chain.fireInbound();
              }
            });

    ResourceRequest request =
        new DefaultResourceRequest.Builder(RequestType.READ, new ResourcePath("/foo/bar")).build();
    channel.writeInbound(request);
    ResourceRequest endRequest = (ResourceRequest) channel.readInbound();

    assertThat(request).isNotSameAs(endRequest);
    assertThat(request.requestId()).isEqualTo(endRequest.requestId());

    ResourceResponse response =
        new DefaultResourceResponse(endRequest, ResourceResponse.ResponseType.READ);
    channel.writeAndFlush(response);
    ResourceResponse endResponse = (ResourceResponse) channel.readOutbound();

    assertThat(response).isNotSameAs(endResponse);
    assertThat(response.inReplyTo()).isNotSameAs(request);
    assertThat(response.requestId()).isEqualTo(request.requestId());
  }