/**
  * Goes through SynapsePath argument list, evaluating each by calling stringValueOf and returns a
  * HashMap String, String array where each item will contain a hash map with key "evaluated
  * expression" and value "SynapsePath type".
  *
  * @param synCtx
  * @return
  */
 private HashMap<String, String>[] getArgValues(MessageContext synCtx) {
   HashMap<String, String>[] argValues = new HashMap[pathArgumentList.size()];
   HashMap<String, String> valueMap;
   String value = "";
   for (int i = 0; i < pathArgumentList.size(); ++i) {
       /*ToDo use foreach*/
     Argument arg = pathArgumentList.get(i);
     if (arg.getValue() != null) {
       value = arg.getValue();
       if (!isWellFormedXML(value)) {
         value = StringEscapeUtils.escapeXml(value);
       }
       value = Matcher.quoteReplacement(value);
     } else if (arg.getExpression() != null) {
       value = arg.getExpression().stringValueOf(synCtx);
       if (value != null) {
         // XML escape the result of an expression that produces a literal, if the target format
         // of the payload is XML.
         if (!isWellFormedXML(value)
             && !arg.getExpression().getPathType().equals(SynapsePath.JSON_PATH)
             && XML_TYPE.equals(getType())) {
           value = StringEscapeUtils.escapeXml(value);
         }
         value = Matcher.quoteReplacement(value);
       } else {
         value = "";
       }
     } else {
       handleException("Unexpected arg type detected", synCtx);
     }
     // value = value.replace(String.valueOf((char) 160), " ").trim();
     valueMap = new HashMap<String, String>();
     if (null != arg.getExpression()) {
       valueMap.put(value, arg.getExpression().getPathType());
     } else {
       valueMap.put(value, SynapsePath.X_PATH);
     }
     argValues[i] = valueMap;
   }
   return argValues;
 }
  /**
   * Replaces the payload format with SynapsePath arguments which are evaluated using
   * getArgValues().
   *
   * @param format
   * @param result
   * @param synCtx
   */
  private void replace(String format, StringBuffer result, MessageContext synCtx) {
    HashMap<String, String>[] argValues = getArgValues(synCtx);
    HashMap<String, String> replacement;
    Map.Entry<String, String> replacementEntry;
    String replacementValue = null;
    Matcher matcher;

    matcher = pattern.matcher(format);
    try {
      while (matcher.find()) {
        String matchSeq = matcher.group();
        int argIndex;
        try {
          argIndex = Integer.parseInt(matchSeq.substring(1, matchSeq.length()));
        } catch (NumberFormatException e) {
          argIndex = Integer.parseInt(matchSeq.substring(2, matchSeq.length() - 1));
        }
        replacement = argValues[argIndex - 1];
        replacementEntry = replacement.entrySet().iterator().next();
        if (mediaType.equals(JSON_TYPE)
            && inferReplacementType(replacementEntry).equals(XML_TYPE)) {
          // XML to JSON conversion here
          try {
            replacementValue = "<jsonObject>" + replacementEntry.getKey() + "</jsonObject>";
            OMElement omXML = AXIOMUtil.stringToOM(replacementValue);
            replacementValue =
                JsonUtil.toJsonString(omXML)
                    .toString()
                    .replaceAll(
                        ESCAPE_DOUBLE_QUOTE_WITH_FIVE_BACK_SLASHES,
                        ESCAPE_DOUBLE_QUOTE_WITH_NINE_BACK_SLASHES)
                    .replaceAll(
                        ESCAPE_DOLLAR_WITH_TEN_BACK_SLASHES, ESCAPE_DOLLAR_WITH_SIX_BACK_SLASHES);
            replacementValue = JsonUtil.toJsonString(omXML).toString();
          } catch (XMLStreamException e) {
            handleException(
                "Error parsing XML for JSON conversion, please check your xPath expressions return valid XML: ",
                synCtx);
          } catch (AxisFault e) {
            handleException("Error converting XML to JSON", synCtx);
          }
        } else if (mediaType.equals(XML_TYPE)
            && inferReplacementType(replacementEntry).equals(JSON_TYPE)) {
          // JSON to XML conversion here
          try {
            OMElement omXML =
                JsonUtil.toXml(IOUtils.toInputStream(replacementEntry.getKey()), false);
            if (JsonUtil.isAJsonPayloadElement(omXML)) { // remove <jsonObject/> from result.
              Iterator children = omXML.getChildElements();
              String childrenStr = "";
              while (children.hasNext()) {
                childrenStr += (children.next()).toString().trim();
              }
              replacementValue = childrenStr;
            } else { /// ~
              replacementValue = omXML.toString();
            }
            // replacementValue = omXML.toString();
          } catch (AxisFault e) {
            handleException(
                "Error converting JSON to XML, please check your JSON Path expressions return valid JSON: ",
                synCtx);
          }
        } else {
          // No conversion required, as path evaluates to regular String.
          replacementValue = replacementEntry.getKey();
          // This is to replace " with \" and \\ with \\\\
          if (mediaType.equals(JSON_TYPE)
              && inferReplacementType(replacementEntry).equals(STRING_TYPE)
              && (!replacementValue.startsWith("{") && !replacementValue.startsWith("["))) {
            replacementValue =
                replacementValue
                    .replaceAll(
                        Matcher.quoteReplacement("\\\\"),
                        ESCAPE_BACK_SLASH_WITH_SIXTEEN_BACK_SLASHES)
                    .replaceAll("\"", ESCAPE_DOUBLE_QUOTE_WITH_TEN_BACK_SLASHES);
          } else if ((mediaType.equals(JSON_TYPE)
                  && inferReplacementType(replacementEntry).equals(JSON_TYPE))
              && (!replacementValue.startsWith("{") && !replacementValue.startsWith("["))) {
            // This is to handle only the string value
            replacementValue =
                replacementValue.replaceAll("\"", ESCAPE_DOUBLE_QUOTE_WITH_TEN_BACK_SLASHES);
          }
        }
        matcher.appendReplacement(result, replacementValue);
      }
    } catch (ArrayIndexOutOfBoundsException e) {
      log.error("#replace. Mis-match detected between number of formatters and arguments", e);
    }
    matcher.appendTail(result);
  }