docs: public JsMessage restoreJsMessage(List<DataSlice> slices, Object store) throws MessageRestoreFailedException {
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(tc, "restoreJsMessage", slices);
  
      JsMessage newMsg = null;
  
      // The slices are those returned from a previous flatten, so we know the list
      // contains the following:
      //   slice 0 : Message class name & other information OR a single slice representing the whole buffer
      //   slice 1 : Header (or only) JSMessage
      //   slice 2 : Payload JSMessage (optional)
      // ... so we need to ensure we have at least 2 slices
      if ((slices == null) || (slices.size() < 1)) {
        String exString = nls.getFormattedMessage("NO_DATASLICES_IN_LIST_CWSIF0002"
                                                 ,null
                                                 ,"A null or empty DataSlice List was passed to the message restore");
        MessageRestoreFailedException e = new MessageRestoreFailedException(exString);
        FFDCFilter.processException(e, "com.ibm.ws.sib.mfp.impl.JsMessageFactoryImpl.restore", "373");
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Exception: DataSlice list was null or empty");
        throw e;
      }
  
      // If there is only one slice it had better be the whole message, so just extract
      // the buffer and pass it to the old-style restore for processing.
      else if (slices.size() == 1) {
         newMsg = restoreJsMessage(slices.get(0).getBytes(), store);
      }
  
      // Otherwise, we have 2 or more slices we're really in the brave new world so carry on....
      else {
  
        String className;
  
        /* The first slice contains:                                              */
        /*     the message class name                                             */
        /*     the list of JMF schema ids needed to decode the message            */
        /*     the message itself                                                 */
        DataSlice slice0 = slices.get(0);
        byte[] buffer = slice0.getBytes();
        int offset = slice0.getOffset();
        // Trace the first slice just in case we get passed rubbish
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Slice0: ", SibTr.formatSlice(slice0));
  
        // Extract the classname from the buffer
        int temp = ArrayUtil.readInt(buffer, offset);               // the length of the class name
        offset += ArrayUtil.INT_SIZE;
        try {
          className = getClassName(buffer, offset, temp);         // the class name itself
        }
        catch (RuntimeException e) {
          // Dump both the buffer portion contained in slice0, and the entire buffer it is a portion of.
          // (These may be the same things as it may be an entire buffer.)
          FFDCFilter.processException(e, "com.ibm.ws.sib.mfp.impl.JsMessageFactoryImpl.restoreJsMessage", "484", this,
                                                  new Object[] {
                                                    new Object[]{ MfpConstants.DM_BUFFER, buffer, slice0.getOffset(), slice0.getLength()},
                                                    new Object[]{ MfpConstants.DM_BUFFER, buffer, 0, buffer.length}
                                                  } );
          // This is a disaster - presumably the buffer is garbage - so we have to throw the exception on
          throw new MessageRestoreFailedException(e);
        }
        offset += temp;
  
        // Extract the message schema ids from the buffer, & ensure the schemas are available.
        offset = ensureSchemasAvailable(buffer, offset, store);
  
        // We have now read the stuff specific to a restore only, & the rest of the information
        // in the first DataSlice will also be needed to build the new JMO
        // We therefore update the first DataSlice in the list so
        // the JMO can ignore the class name information.
        DataSlice newSlice0 = new DataSlice(buffer, offset, slice0.getLength() - offset);
        slices.set(0, newSlice0);
  
        try {
          /* Create a new JMO from the slices  */
          JsMsgObject newJmo = new JsMsgObject(JsHdrAccess.schema, JsPayloadAccess.schema, slices);
  
          /* Get the class for the appropriate specialization */
          Class  msgClass = Class.forName(className);
  
          /* Now create the new JsMessage and set the JMO               */
          newMsg = (JsMessage)msgClass.newInstance();
          ((JsMessageImpl)newMsg).setJmo(newJmo);
  
          /* Set the approxLength as we know it */
          ((JsMessageImpl)newMsg).setApproximateLength(newJmo.getOriginalLength());
        }
        catch (ClassNotFoundException e1) {
          FFDCFilter.processException(e1, "com.ibm.ws.sib.mfp.impl.JsMessageFactoryImpl.restore", "446");
          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Exception " + e1.toString() + " finding class " + className);
          throw new MessageRestoreFailedException(e1);
        }
        catch (MessageDecodeFailedException e2) {
          /* No need to FFDC this as JsMsgObject will already have done so */
          // No FFDC code needed
          throw new MessageRestoreFailedException(e2);
        }
        catch (Exception e3) {
          /* Any other exceptions from instantiation should never happen */
          FFDCFilter.processException(e3, "com.ibm.ws.sib.mfp.impl.JsMessageFactoryImpl.restore", "457");
          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Exception " + e3.toString() + " instantiating class " + className);
          throw new MessageRestoreFailedException(e3);
        }
  
      }
  
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "restoreJsMessage");
      return newMsg;
    }