docs: List<DataSlice> flatten(Object store, byte[] nameBytes) throws MessageEncodeFailedException {
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "flatten", new Object[] {store, nameBytes});
  
      // Initial capacity is sufficient for a 2 part message
      List<DataSlice> messageSlices = new ArrayList<DataSlice>(3);
  
      /* If we have a message store we need to ensure it contains all the       */
      /* schema defintions needed to be able decode this message sometime later */
      long[] encodeIds;
      if (store != null) {
        if (!(store instanceof MessageStore)) {
          throw new IllegalArgumentException("store is not a MessageStore instance");
        }
        JMFSchema[] encodeSchemas = getEncodingSchemas();
        SchemaStore.saveSchemas((MessageStore)store, encodeSchemas);
        encodeIds = new long[encodeSchemas.length];
        for (int i = 0; i < encodeSchemas.length; i++) {
          encodeIds[i] = encodeSchemas[i].getID();
        }
      }
      else {
        encodeIds = new long[0];
      }
  
      // Write the first slice - this just contains name & ids information
      int bufferLength = 0;
      bufferLength += ArrayUtil.INT_SIZE;
      bufferLength += nameBytes.length;
      bufferLength += ArrayUtil.INT_SIZE;
      bufferLength += encodeIds.length * ArrayUtil.LONG_SIZE;
      bufferLength += IDS_LENGTH;                             // for the top-level versions & schema ids
      bufferLength += ArrayUtil.INT_SIZE;                     // for the length of the header part
      byte[] buff0 = new byte[bufferLength];
  
      int offset = 0;
      ArrayUtil.writeInt(buff0, offset, nameBytes.length);   // the length of the class name
      offset += ArrayUtil.INT_SIZE;
      ArrayUtil.writeBytes(buff0, offset, nameBytes);        // the class name
      offset += nameBytes.length;
      ArrayUtil.writeInt(buff0, offset, encodeIds.length);   // the number of encoding schema ids
      offset += ArrayUtil.INT_SIZE;
      for (int i = 0; i < encodeIds.length; i++) {
        ArrayUtil.writeLong(buff0, offset, encodeIds[i]);    // each encoding schema id
        offset += ArrayUtil.LONG_SIZE;
      }
  
      // Write the top-level Schema Ids & their versions to the buffer & wrap it in a DataSlice
      offset += encodeIds(buff0, offset);
      DataSlice slice0  = new DataSlice(buff0, 0, bufferLength);
  
      try {
        // We need to lock the message around the call to updateDataFields() and the
        // actual encode of the part(s), so that noone can update any JMF message data
        // during that time (because they can not get the hdr2, api, or payload part).
        // Otherwise it is possible to get an inconsistent view of the message with some updates
        // included but those to the cached values 'missing'.
        // It is still strictly possible for the top-level schema header fields to be
        // updated, but this will not happen to any fields visible to an app.
        synchronized(theMessage) {
  
          // Next ensure any cached message data is written back before we get the
          // low level (JSMessageImpl) locks                                  d364050
          theMessage.updateDataFields(MfpConstants.UDF_FLATTEN);
  
          DataSlice slice1  = null;
          DataSlice slice2  = null;
  
          // Write the second slice - this contains the header
          slice1 = encodeHeaderPartToSlice(headerPart);
  
          // Now we have to tell the buffer in the slice0 how long the header part is
          ArrayUtil.writeInt(buff0, offset, slice1.getLength());
  
          // Now the first 2 slices are complete we can put them in the list.
          // Slices must be added in the correct order.
          messageSlices.add(slice0);
          messageSlices.add(slice1);
  
          // Now for the 3rd slice, which will contain the payload (if there is one)
          if (payloadPart != null) {
            slice2 = encodePayloadPartToSlice(payloadPart, null);
            messageSlices.add(slice2);
          }
        }
  
      }
      catch (MessageEncodeFailedException e1) {
        // This will have been thrown by encodeXxxxxPartToSlice() which will
        // already have dumped the appropriate message part.
        FFDCFilter.processException(e1, "com.ibm.ws.sib.mfp.impl.JsMsgObject.flatten", "jmo580", this,
          new Object[] { MfpConstants.DM_MESSAGE, null, theMessage });
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "flatten failed: " + e1);
        throw e1;
      }
      catch (Exception e) {
        // Not sure this can ever happen, but if it does dump the whole message.
        FFDCFilter.processException(e, "com.ibm.ws.sib.mfp.impl.JsMsgObject.flatten", "jmo590", this,
            new Object[] {
              new Object[] { MfpConstants.DM_MESSAGE, headerPart.jmfPart, theMessage },
              new Object[] { MfpConstants.DM_MESSAGE, payloadPart.jmfPart, theMessage }
            }
          );
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "flatten failed: " + e);
        throw new MessageEncodeFailedException(e);
      }
  
      // If debug trace, dump the message & slices before returning
      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Flattened JMF Message", debugMsg());
      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Message DataSlices: ", SibTr.formatSlices(messageSlices, MfpDiagnostics.getDiagnosticDataLimitInt()));
  
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "flatten");
      return messageSlices;
    }