/**
   * It is possible for us (Synapse) to cause the creation of a duplicate relatesTo as we try to
   * hold onto the outgoing message ID even for POX messages using the relates to Now once we get a
   * response, make sure we remove any trace of this before we proceed any further
   *
   * @param mc the message context from which a possibly duplicated relatesTo should be removed
   * @param relates the existing relatedTo array of the message
   */
  private void removeDuplicateRelatesTo(MessageContext mc, RelatesTo[] relates) {

    int insertPos = 0;
    RelatesTo[] newRelates = new RelatesTo[relates.length];

    for (RelatesTo current : relates) {
      boolean found = false;
      for (int j = 0; j < newRelates.length && j < insertPos; j++) {
        if (newRelates[j].equals(current) || newRelates[j].getValue().equals(current.getValue())) {
          found = true;
          break;
        }
      }
      if (!found) {
        newRelates[insertPos++] = current;
      }
    }

    RelatesTo[] trimmedRelates = new RelatesTo[insertPos];
    System.arraycopy(newRelates, 0, trimmedRelates, 0, insertPos);
    mc.setRelationships(trimmedRelates);
  }
  /**
   * Everytime a response message is received this method gets invoked. It will then select the
   * outgoing *Synapse* message context for the reply we received, and determine what action to take
   * at the Synapse level
   *
   * @param messageCtx the Axis2 message context of the reply received
   * @throws AxisFault
   */
  public void receive(MessageContext messageCtx) throws AxisFault {

    String messageID = null;

    /**
     * In an Out-only scenario if the client receives a HTTP 202 accepted we need to remove the call
     * back/s registered for that request. This if will check weather this is a message sent in a
     * that scenario and remove the callback
     */
    if (messageCtx.getProperty(NhttpConstants.HTTP_202_RECEIVED) != null
        && "true".equals(messageCtx.getProperty(NhttpConstants.HTTP_202_RECEIVED))) {
      if (callbackStore.containsKey(messageCtx.getMessageID())) {
        callbackStore.remove(messageCtx.getMessageID());
        if (log.isDebugEnabled()) {
          log.debug(
              "CallBack registered with Message id : "
                  + messageCtx.getMessageID()
                  + " removed from the "
                  + "callback store since we got an accepted Notification");
        }
      }

      return;
    }

    if (messageCtx.getOptions() != null && messageCtx.getOptions().getRelatesTo() != null) {
      // never take a chance with a NPE at this stage.. so check at each level :-)
      Options options = messageCtx.getOptions();
      if (options != null) {
        RelatesTo relatesTo = options.getRelatesTo();
        if (relatesTo != null) {
          messageID = relatesTo.getValue();
        }
      }
    } else if (messageCtx.getProperty(SandeshaClientConstants.SEQUENCE_KEY) == null) {
      messageID = (String) messageCtx.getProperty(SynapseConstants.RELATES_TO_FOR_POX);
    }

    if (messageID != null) {
      AsyncCallback callback = (AsyncCallback) callbackStore.remove(messageID);
      if (log.isDebugEnabled()) {
        log.debug(
            "Callback removed for request message id : "
                + messageID
                + ". Pending callbacks count : "
                + callbackStore.size());
      }

      RelatesTo[] relates = messageCtx.getRelationships();
      if (relates != null && relates.length > 1) {
        // we set a relates to to the response message so that if WSA is not used, we
        // could still link back to the original message. But if WSA was used, this
        // gets duplicated, and we should remove it
        removeDuplicateRelatesTo(messageCtx, relates);
      }

      if (callback != null) {
        handleMessage(
            messageID,
            messageCtx,
            ((AsyncCallback) callback).getSynapseOutMsgCtx(),
            (AsyncCallback) callback);

      } else {
        // TODO invoke a generic synapse error handler for this message
        log.warn(
            "Synapse received a response for the request with message Id : "
                + messageID
                + " But a callback is not registered (anymore) to process this response");
      }

    } else if (!messageCtx.isPropertyTrue(NhttpConstants.SC_ACCEPTED)) {
      // TODO invoke a generic synapse error handler for this message
      log.warn("Synapse received a response message without a message Id");
    }
  }