docs: @Override
      public Object getIdentifierValue(Identifier id,
                                       boolean ignoreType,
                                       Object contextValue,
                                       boolean returnList)
                      throws BadMessageFormatMatchingException {
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.entry(this, tc, "getIdentifierValue", new Object[] { id, ignoreType, contextValue, returnList });
  
          Object value = null;
          boolean dontTraceNonNullValue = false;
  
          /* Determine the messaging domain: JMS or SI Core message */
          SelectorDomain domain = SelectorDomain.getSelectorDomain(id.getSelectorDomain());
  
          // If the domain is XPATH1 ....
          if (domain == SelectorDomain.XPATH1) {
  
              try {
  
                  // Check any contextValue is actually a Node, we will catch, FFDC & wrap it below
                  if (contextValue != null && !(contextValue instanceof Node)) {
                      throw new IllegalArgumentException("contextValue must be a Node");
                  }
  
                  XPathExpression xrep = (XPathExpression) id.getCompiledExpression();
  
                  // If a list of nodes is required.........
                  if (returnList) {
                      if (xrep != null) {
  
                          // If the contextValue is null, use payload document as the root
                          if (contextValue == null) {
                              contextValue = getPayloadDocument();
                          }
  
                          if (contextValue != null) {
                              NodeList nodeList = (NodeList) xrep.evaluate(contextValue, XPathConstants.NODESET);
  
                              // Now we have to turn the NodeList (if we have one) into a real List to return
                              if ((nodeList != null) && (nodeList.getLength() > 0)) {
                                  value = new ArrayList(nodeList.getLength());
                                  for (int i = 0; i < nodeList.getLength(); i++) {
                                      ((ArrayList) value).add(nodeList.item(i));
                                  }
                              }
                              // if the nodeList is null or empty, we just drop through to return value=null
                          }
                          // if contextValue is still null, we just drop through to return value=null
                      }
                      // if xrep == null, we just drop through to return value=null
                  }
  
                  // ... if not, we just need to return a Boolean, which is easier
                  else {
                      if (xrep != null) {
  
                          // If the contextValue is null, use payload document as the root
                          if (contextValue == null) {
                              contextValue = getPayloadDocument();
                          }
  
                          if (contextValue != null) {
                              value = xrep.evaluate(contextValue, XPathConstants.BOOLEAN);
                          }
                          // Return FALSE if the the contextValue is still null
                          else {
                              value = Boolean.FALSE;
                          }
                      }
                      else {
                          // Return FALSE if the XPath expression is null
                          value = Boolean.FALSE;
                      }
                  }
  
              } catch (Exception e) {
                  FFDCFilter.processException(e, "com.ibm.ws.sib.mfp.impl.JsApiMessageImpl.getIdentifierValue", "795");
                  throw new BadMessageFormatMatchingException(e);
              }
  
          }
  
          // If the SelectorDomain is not XPATH1, we must be selecting on a named property
          else {
  
              /* Get the name of the identifier. */
              String fieldName = id.getName();
  
              /* Decide if the fieldName means we shouldn't trace non-null results */
              dontTraceNonNullValue = PasswordUtils.containsPassword(fieldName);
  
              /* Get the value of the property: */
              /* If we're processing on behalf of the Core SPI, the property can be a */
              /* JMS property (starting "JMS") or an SI Core property (starting "SI_") */
              /* or a user property. */
              /* If we're processing a JMS message however we can have JMS properties */
              /* but _not_ SI Core properties; anything else must be a user property, */
              /* but only user properties of types supported by JMS are 'found'. */
  
              /* If fieldName starts with JMS check for the JMS headers & properties */
              if (fieldName.startsWith(JMS_PREFIX)) {
  
                  /* If it isn't one of the properties we don't match on, get the value */
                  if (!(fieldName.equals(SIProperties.JMSDestination))
                      && !(fieldName.equals(SIProperties.JMSReplyTo))
                      && !(fieldName.equals(SIProperties.JMS_IBM_ExceptionMessage))
                      && !(fieldName.startsWith(JMS_IBM_MQMD_PREFIX))) {
                      value = getJMSSystemProperty(fieldName, true);
                  }
              }
  
              /* If we're processing on behalf of JMS, look for a JMS-type user property */
              else if (domain == SelectorDomain.JMS) {
                  /* Usually it would be in the JMS Property Map */
                  if (mayHaveJmsUserProperties()) {
                      value = getJmsUserPropertyMap().get(fieldName);
                  }
                  /* If we haven't found the property, check for the Maelstrom wierdo */
                  if ((value == null)
                      && (fieldName.equals(MfpConstants.PRP_TRANSVER))) {
                      value = getTransportVersion();
                  }
              }
  
              /* If we're processing on behalf of the Core SPI.... */
              else if (domain == SelectorDomain.SIMESSAGE) {
  
                  /* If fieldName starts with SI_ it must be a header field */
                  if (fieldName.startsWith(SI_PREFIX)) {
                      /* If it isn't one of the properties we don't match on, get the value */
                      if (!fieldName.equals(SIProperties.SI_ExceptionInserts)) {
                          value = getSIProperty(fieldName, true);
                      }
                  }
  
                  /* Otherwise it should start with "user." */
                  else if (fieldName.startsWith(USER_PREFIX)) {
  
                      String remainder = fieldName.substring(USER_PREFIX_LENGTH);
                      try {
                          value = getUserProperty(remainder, true);
                      } catch (Exception e) {
                          /* No Exception can be thrown as getUserProperty was called with */
                          /* forMatching set to true. */
                          // No FFDC code needed.
                      }
                  }
  
                  /* Otherwise, value remains null as no other fieldName is supported. */
  
              }
  
              /* If the value existed, check it is the right type (if we care) */
              if ((value != null) && (!ignoreType)) {
                  value = typeCheck(value, id.getType());
              }
  
          } // End of not-XPATH
  
          /* Value may be null after running typeCheck, even if it wasn't before! */
          if (value == null) {
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                  SibTr.exit(this, tc, "getIdentifierValue", null);
          }
          else {
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                  SibTr.exit(this, tc, "getIdentifierValue", new Object[] { PasswordUtils.replacePossiblePassword(dontTraceNonNullValue, value), value.getClass() });
          }
  
          return value;
      }