docs: JmsDestination processURI(String uri, int qmProcessing, Map<String,String> nvpReturn) throws JMSException {
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "processURI", new Object[]{uri, qmProcessing});
  
      boolean isQueue;
      JmsDestination result;
  
      // Setup for queue or topic depending on uri prefix
      if (uri.startsWith(JmsTopicImpl.TOPIC_PREFIX)) {
        result = new JmsTopicImpl();
        isQueue = false;
      }
      else if (uri.startsWith(JmsQueueImpl.QUEUE_PREFIX)) {
        result = new JmsQueueImpl();
        isQueue = true;
      }
      else {
        // throw an exception
        throw (JMSException) JmsErrorUtils.newThrowable(
          JMSException.class,
          "INTERNAL_ERROR_CWSIA0386",
          null,
          tc);
      }
  
      // Retrieve substring starting from AFTER the prefix to the end of the URI.
      // To do this we take off the first 8 characters which represent the queue prefix.
      String destURI = uri.substring(8, uri.length());
  
      // Split the string into the dest name and the optional name-value pairs
      // by searching for a non-escaped '?'
      // The 2 indicates that we only want the string split into 2 parts, i.e. at the first
      // non-escaped ?.
      // If a non-escaped ? is not found, the entire string is copied to parts[0].
      String[] parts = splitOnNonEscapedChar(destURI, '?', 2);
  
      // parts[0] is the dest name.
      String destName = parts[0];
  
      // parts[1] (if present) is the NVPs.
      String nvps = null;
      if (parts.length > 1) nvps = parts[1].trim();
  
      // If it is a queue, do some Queue specific modifications to destName
      if (isQueue) {
        // split at first unescaped / to break into qm/queue
        parts = splitOnNonEscapedChar(destName, '/', 2);
        String qmName=null, queueName=null;
        if (parts.length > 1) {
          qmName = parts[0];
          queueName = parts[1];
          // tidy up empty qmName
          if (qmName.trim().equals("")) qmName = null;
        }
        else {
          // no /, so everything is queueName and it's all in parts[0]
          queueName = parts[0];
        }
  
        // All of the cases below use queueName as the first part of the destName,
        // so factor out to simplify the code:
        destName = queueName;
  
        switch (qmProcessing) {
          case QM_TRANSFORM:
            // Support MA88-style Queue URI containing a queue manager.
            // recode as queue@QM if QM supplied
            if (qmName != null) {
              destName += "@" + qmName;
            }
            break;
          case QM_DISCARD:
            // DISCARD = discard the QM. - no-op, destName already set above.
            break;
          case QM_PEV:
            // For PEV, the QM name is used as the bus name
            result.setBusName(qmName);
            break;
          case QM_ERROR:
            // Perform a check to find an MA88-style Queue URI which identifies a
            // queue manager.
            // This URI would look like "queue://QM1/myQueue" - and should result
            // in an exception
            // being thrown because Jetstream does not support Queue Managers.
            if (qmName != null ) {
              throw (JMSException) JmsErrorUtils.newThrowable(JMSException.class,
                  "INVALID_URI_ELEMENT_CWSIA0385", new Object[] { uri }, tc);
            }
            // else everything ok, so destName becomes the queueName, which has already been set
            break;
          default:
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Unknown value for qmProcessing: " + qmProcessing);
            // throw an internal error
            throw (JMSException) JmsErrorUtils.newThrowable(JMSException.class,
                "INTERNAL_ERROR_CWSIA0386", null, tc);
        }
  
        // Now we know there are no unescaped /s, we can remove the escapes.
        destName = unescape(destName, '/');
      }
  
      // de-escape any '\?'s
      // There can't be any non-escaped ?s, as we split destName before the first one.
      destName = unescape(destName, '?');
  
      // The only valid escape sequences that should be left are "\\" which
      // transforms to a single '\'
      destName = unescapeBackslash(destName);
  
      // Finally, we can put the processed destName into the Destination
      if (isQueue) {
        ((JmsQueueImpl) result).setQueueName(destName);
      }
      else {
        ((JmsTopicImpl) result).setTopicName(destName);
      }
  
      processNVPs(nvps, result, nvpReturn);
  
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "processURI",  result);
      return result;
    }