/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.uima.cas.impl;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.uima.UIMAFramework;
import org.apache.uima.UIMARuntimeException;
import org.apache.uima.UimaContext;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.CommonArrayFS;
import org.apache.uima.cas.Marker;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.cas.impl.CasSerializerSupport.CasDocSerializer;
import org.apache.uima.cas.impl.CasSerializerSupport.CasSerializerSupportSerialize;
import org.apache.uima.cas.impl.XmiSerializationSharedData.OotsElementData;
import org.apache.uima.cas.impl.XmiSerializationSharedData.XmiArrayElement;
import org.apache.uima.internal.util.Misc;
import org.apache.uima.internal.util.XmlAttribute;
import org.apache.uima.internal.util.XmlElementName;
import org.apache.uima.internal.util.XmlElementNameAndContents;
import org.apache.uima.jcas.cas.ByteArray;
import org.apache.uima.jcas.cas.CommonList;
import org.apache.uima.jcas.cas.FSArray;
import org.apache.uima.jcas.cas.Sofa;
import org.apache.uima.jcas.cas.StringArray;
import org.apache.uima.jcas.cas.StringList;
import org.apache.uima.jcas.cas.TOP;
import org.apache.uima.util.XMLSerializer;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

/**
 * CAS serializer for XMI format; writes a CAS in the XML Metadata Interchange (XMI) format.
 *  
 * To use, 
 *   - create an instance of this class, 
 *   - optionally) configure the instance, and then 
 *   - call serialize on the instance, optionally passing in additional parameters.
 *   
 * After the 1st 2 steps, the serializer instance may be used for multiple calls (on multiple threads) to
 * the 3rd serialize step, if all calls use the same configuration.
 * 
 * There are "convenience" static serialize methods that do these three steps for common configurations.
 * 
 * Parameters can be configured in the XmiCasSerializer instance (I), and/or as part of the serialize(S) call.
 * 
 * The parameters that can be configured are:
 * <ul>
 *   <li>(S) The CAS to serialize
 *   <li>(S) where to put the output - an OutputStream</li>
 *   <li>(I,S) a type system - (default null) if supplied, it is used to "filter" types and features that are serialized.  If provided, only 
 *   those that exist in the passed in type system are included in the serialization</li>
 *   <li>(I,S) a flag for prettyprinting - default false (no prettyprinting)</li>
 *   <li>(I) (optional) If supplied, a map used to generate a "schemaLocation" attribute in the XMI
 *          output. This argument must be a map from namespace URIs to the schema location for
 *          that namespace URI.
 *   <li>(S) (optional) if supplied XmiSerializationSharedData representing FeatureStructures
 *       that were set aside when deserializing, and are to be "merged" back in when serializing
 *   <li>(S) a Marker (default: null) if supplied, where the separation between "new" and previously
 *       exisiting FeatureStructures are in the CAS; causes "delta" serialization, where only the 
 *       new and changed FeatureStructures are serialized.
 * </ul>
 * 
 * Once the XmiCasSerializer instance is configured, the serialize method is called
 * to serialized a CAS to an output.
 * 
 * Instances of this class must be used on only one thread while configuration is being done;
 * afterwards, multiple threads may use the configured instance, to call serialize.
 */
public class XmiCasSerializer {
  
  static final char [] URIPFX = new char[] {'h','t','t','p',':','/','/','/'};
  
  static final char [] URISFX = new char[] {'.','e','c','o','r','e'};

  private static final String CDATA_TYPE = "CDATA";

  public static final String XMLNS_NS_URI = "http://www.w3.org/2000/xmlns/";

  public static final String XMI_NS_URI = "http://www.omg.org/XMI";

  public static final String XSI_NS_URI = "http://www.w3.org/2001/XMLSchema-instance";

  public static final String XMI_NS_PREFIX = "xmi";
  
  public static final String ID_ATTR_NAME = "xmi:id";

  public static final String XMI_TAG_LOCAL_NAME = "XMI";

  public static final String XMI_TAG_QNAME = "xmi:XMI";
  
  public static final XmlElementName XMI_TAG = new XmlElementName(XMI_NS_URI, XMI_TAG_LOCAL_NAME,
          XMI_TAG_QNAME);
    
  public static final String XMI_VERSION_LOCAL_NAME = "version";

  public static final String XMI_VERSION_QNAME = "xmi:version";

  public static final String XMI_VERSION_VALUE = "2.0";

  /** Namespace URI to use for UIMA types that have no namespace (the "default pacakge" in Java) */
  public static final String DEFAULT_NAMESPACE_URI = "http:///uima/noNamespace.ecore"; 
  
  public final static String SYSTEM_LINE_FEED;
  static {
      String lf = System.getProperty("line.separator");
      SYSTEM_LINE_FEED = (lf == null) ? "\n" : lf;
  }

  public final static char[] INT_TO_HEX = "0123456789ABCDEF".toCharArray();
  
  private final CasSerializerSupport css = new CasSerializerSupport();
  
  private Map<String, String> nsUriToSchemaLocationMap = null;
  
  /***********************************************
   *         C O N S T R U C T O R S             *  
   ***********************************************/

  /**
   * Creates a new XmiCasSerializer.
   * 
   * @param ts
   *          An optional typeSystem (or null) to filter the types that will be serialized. If any CAS that is later passed to
   *          the <code>serialize</code> method that contains types and features that are not in
   *          this typesystem, the serialization will not contain instances of those types or values
   *          for those features. So this can be used to filter the results of serialization.
   *          A null value indicates that all types and features  will be serialized.
   */
  public XmiCasSerializer(TypeSystem ts) {
    this(ts, (Map<String, String>) null);
  }

  /**
   * Creates a new XmiCasSerializer.
   * 
   * @param ts
   *          An optional typeSystem (or null) to filter the types that will be serialized. If any CAS that is later passed to
   *          the <code>serialize</code> method that contains types and features that are not in
   *          this typesystem, the serialization will not contain instances of those types or values
   *          for those features. So this can be used to filter the results of serialization.
   * @param nsUriToSchemaLocationMap
   *          Map if supplied, this map is used to generate a "schemaLocation" attribute in the XMI
   *          output. This argument must be a map from namespace URIs to the schema location for
   *          that namespace URI.
   */
  
  public XmiCasSerializer(TypeSystem ts, Map<String, String> nsUriToSchemaLocationMap) {
    this(ts, nsUriToSchemaLocationMap, false);
  }

  /**
   * Creates a new XmiCasSerializer
   * @param ts
   *          An optional typeSystem (or null) to filter the types that will be serialized. If any CAS that is later passed to
   *          the <code>serialize</code> method that contains types and features that are not in
   *          this typesystem, the serialization will not contain instances of those types or values
   *          for those features. So this can be used to filter the results of serialization.
   * @param nsUriToSchemaLocationMap
   *          Map if supplied, this map is used to generate a "schemaLocation" attribute in the XMI
   *          output. This argument must be a map from namespace URIs to the schema location for
   *          that namespace URI.
   * @param isFormattedOutput true makes serialization pretty print
   */
  public XmiCasSerializer(TypeSystem ts, Map<String, String> nsUriToSchemaLocationMap, boolean isFormattedOutput) {
    css.filterTypeSystem = (TypeSystemImpl) ts;
    this.nsUriToSchemaLocationMap = nsUriToSchemaLocationMap;
    css.logger = UIMAFramework.getLogger(XmiCasSerializer.class);
    css.isFormattedOutput = isFormattedOutput;
  }

  /**
   * Creates a new XmiCasSerializer.
   * 
   * @param ts
   *          An optional typeSystem (or null) to filter the types that will be serialized. If any CAS that is later passed to
   *          the <code>serialize</code> method that contains types and features that are not in
   *          this typesystem, the serialization will not contain instances of those types or values
   *          for those features. So this can be used to filter the results of serialization.
   * @param uimaContext
   *          not used
   * @param nsUriToSchemaLocationMap
   *          Map if supplied, this map is used to generate a "schemaLocation" attribute in the XMI
   *          output. This argument must be a map from namespace URIs to the schema location for
   *          that namespace URI.
   * 
   * @deprecated Use {@link #XmiCasSerializer(TypeSystem, Map)} instead. The UimaContext reference
   *             is never used by this implementation.
   */
  @Deprecated
  public XmiCasSerializer(TypeSystem ts, UimaContext uimaContext, Map<String, String> nsUriToSchemaLocationMap) {
    this(ts, nsUriToSchemaLocationMap);
  }

  /**
   * Creates a new XmiCasSerializer.
   * 
   * @param ts
   *          An optional typeSystem (or null) to filter the types that will be serialized. If any CAS that is later passed to
   *          the <code>serialize</code> method that contains types and features that are not in
   *          this typesystem, the serialization will not contain instances of those types or values
   *          for those features. So this can be used to filter the results of serialization.
   * @param uimaContext
   *          not used
   * 
   * @deprecated Use {@link #XmiCasSerializer(TypeSystem)} instead. The UimaContext reference is
   *             never used by this implementation.
   */
  @Deprecated
  public XmiCasSerializer(TypeSystem ts, UimaContext uimaContext) {
    this(ts);
  }

  
  /***************************************************
   *  Static XMI Serializer methods for convenience  *  
   ***************************************************/
  
  /**
   * Serializes a CAS to an XMI stream.
   * 
   * @param aCAS
   *          CAS to serialize.
   * @param aStream
   *          output stream to which to write the XMI document
   * 
   * @throws SAXException
   *           if a problem occurs during XMI serialization
   */
  public static void serialize(CAS aCAS, OutputStream aStream) throws SAXException {
    serialize(aCAS, null, aStream, false, null);
  }

  /**
   * Serializes a CAS to an XMI stream. Allows a TypeSystem to be specified, to which the produced
   * XMI will conform. Any types or features not in the target type system will not be serialized.
   * 
   * @param aCAS
   *          CAS to serialize.
   * @param aTargetTypeSystem
   *          type system to which the produced XMI will conform. Any types or features not in the
   *          target type system will not be serialized.  A null value indicates that all types and features
   *          will be serialized.
   * @param aStream
   *          output stream to which to write the XMI document
   * 
   * @throws SAXException
   *           if a problem occurs during XMI serialization
   */
  public static void serialize(CAS aCAS, TypeSystem aTargetTypeSystem, OutputStream aStream)
          throws SAXException {
    serialize(aCAS, aTargetTypeSystem, aStream, false, null);
  }
  
  /**
   * Serializes a CAS to an XMI stream.  This version of this method allows many options to be configured.
   * 
   * @param aCAS
   *          CAS to serialize.
   * @param aTargetTypeSystem
   *          type system to which the produced XMI will conform. Any types or features not in the
   *          target type system will not be serialized.  A null value indicates that all types and features
   *          will be serialized.
   * @param aStream
   *          output stream to which to write the XMI document
   * @param aPrettyPrint
   *          if true the XML output will be formatted with newlines and indenting.  If false it will be unformatted.
   * @param aSharedData
   *          an optional container for data that is shared between the {@link XmiCasSerializer} and the {@link XmiCasDeserializer}.
   *          See the JavaDocs for {@link XmiSerializationSharedData} for details.
   * 
   * @throws SAXException
   *           if a problem occurs during XMI serialization
   */
  public static void serialize(CAS aCAS, TypeSystem aTargetTypeSystem, OutputStream aStream, boolean aPrettyPrint, 
          XmiSerializationSharedData aSharedData)
          throws SAXException {
    serialize(aCAS, aTargetTypeSystem, aStream, aPrettyPrint, aSharedData, null);
  }  
  
  /**
   * Serializes a Delta CAS to an XMI stream.  This version of this method allows many options to be configured.
   *     
   *    
   * @param aCAS
   *          CAS to serialize.
   * @param aTargetTypeSystem
   *          type system to which the produced XMI will conform. Any types or features not in the
   *          target type system will not be serialized.  A null value indicates that all types and features
   *          will be serialized.
   * @param aStream
   *          output stream to which to write the XMI document
   * @param aPrettyPrint
   *          if true the XML output will be formatted with newlines and indenting.  If false it will be unformatted.
   * @param aSharedData
   *          an optional container for data that is shared between the {@link XmiCasSerializer} and the {@link XmiCasDeserializer}.
   *          See the JavaDocs for {@link XmiSerializationSharedData} for details.
   * @param aMarker
   *          an optional object that is used to filter and serialize a Delta CAS containing only
   *          those FSs and Views created after Marker was set and preexisting FSs and views that were modified.
   *          See the JavaDocs for {@link Marker} for details.
   * @throws SAXException
   *           if a problem occurs during XMI serialization
   */
  public static void serialize(CAS aCAS, TypeSystem aTargetTypeSystem, OutputStream aStream, boolean aPrettyPrint, 
          XmiSerializationSharedData aSharedData, Marker aMarker)
          throws SAXException {
    XmiCasSerializer xmiCasSerializer = new XmiCasSerializer(aTargetTypeSystem);
    XMLSerializer sax2xml = new XMLSerializer(aStream, aPrettyPrint);
    xmiCasSerializer.serialize(aCAS, sax2xml.getContentHandler(), null, aSharedData, aMarker);
  } 
  
  /***************************************************
   *       non-static XMI Serializer methods         * 
   *  To use: first make an instance of this class
   *    and set any configuration info needed
   *  Then call these methods
   *  
   *  The serialize calls are thread-safe
   ***************************************************/
  
  /**
   * Write the CAS data to a SAX content handler.
   * 
   * @param cas
   *          The CAS to be serialized.
   * @param contentHandler
   *          The SAX content handler the data is written to.
   * 
   * @throws SAXException if there was a SAX exception
   */
  public void serialize(CAS cas, ContentHandler contentHandler) throws SAXException {
    this.serialize(cas, contentHandler, (ErrorHandler) null);
  }

  /**
   * Write the CAS data to a SAX content handler.
   * 
   * @param cas
   *          The CAS to be serialized.
   * @param contentHandler
   *          The SAX content handler the data is written to.
   * @param errorHandler the SAX Error Handler to use
   * 
   * @throws SAXException if there was a SAX exception
   */
  public void serialize(CAS cas, ContentHandler contentHandler, ErrorHandler errorHandler)
          throws SAXException {
    serialize(cas, contentHandler, errorHandler, null, null);
  }

  /**
   * Write the CAS data to a SAX content handler.
   * 
   * @param cas
   *          The CAS to be serialized.
   * @param contentHandler
   *          The SAX content handler the data is written to.
   * @param sharedData
   *          data structure used to allow the XmiCasSerializer and XmiCasDeserializer to share
   *          information.
   * @param errorHandler the SAX Error Handler to use
   * 
   * @throws SAXException if there was a SAX exception
   */
  public void serialize(CAS cas, ContentHandler contentHandler, ErrorHandler errorHandler,
          XmiSerializationSharedData sharedData) throws SAXException {
    serialize(cas, contentHandler, errorHandler, sharedData, null);
  }  
  
  /**
   * Write the CAS data to a SAX content handler.
   * 
   * @param cas
   *          The CAS to be serialized.
   * @param contentHandler
   *          The SAX content handler the data is written to.
   * @param errorHandler the SAX Error Handler to use
   * @param sharedData
   *          data structure used to allow the XmiCasSerializer and XmiCasDeserializer to share
   *          information.
   * @param marker
   *        an object used to filter the FSs and Views to determine if these were created after
   *          the mark was set. Used to serialize a Delta CAS consisting of only new FSs and views and
   *          preexisting FSs and Views that have been modified.
   *          
   * @throws SAXException if there was a SAX exception
   */
  public void serialize(CAS cas, ContentHandler contentHandler, ErrorHandler errorHandler,
          XmiSerializationSharedData sharedData, Marker marker) throws SAXException {
    
    contentHandler.startDocument();
    if (errorHandler != null) {
      css.setErrorHandler(errorHandler);
    }
    XmiDocSerializer ser = new XmiDocSerializer(contentHandler, ((CASImpl) cas).getBaseCAS(), sharedData, (MarkerImpl) marker);
    try {
      ser.cds.serialize();
    } catch (Exception e) {
      if (e instanceof SAXException) {
        throw (SAXException) e;
      } else {
        throw new UIMARuntimeException(e);
      }
    }  
    contentHandler.endDocument();
  }
  
  // this method just for testing - uses existing content handler and CasDocSerializer instance
  // package private for test case access
  void serialize(CAS cas, ContentHandler contentHandler, XmiDocSerializer ser) throws SAXException {
    contentHandler.startDocument();
    try {
      ser.cds.serialize();
    } catch (Exception e) {
      throw (SAXException) e;
    }
    contentHandler.endDocument();
  }
    
  /********************************************************
   *   Routines to set/reset configuration                *
   ********************************************************/
  /**
   * set or reset the pretty print flag (default is false)
   * @param pp true to do pretty printing of output
   * @return the original instance, possibly updated
   */
  public XmiCasSerializer setPrettyPrint(boolean pp) {
    css.setPrettyPrint(pp);
    return this;
  }
    
  /**
   * pass in a type system to use for filtering what gets serialized;
   * only those types and features which are defined this type system are included.
   * @param ts the filter
   * @return the original instance, possibly updated
   */
  public XmiCasSerializer setFilterTypes(TypeSystemImpl ts) {
    css.setFilterTypes(ts);
    return this;
  }
  

  // not done here, done on serialize call, because typically changes for each call
//  /**
//   * set the Marker to specify delta cas serialization
//   * @param m - the marker
//   * @return the original instance, possibly updated
//   */
//  public XmiCasSerializer setDeltaCas(Marker m) {
//    css.setDeltaCas(m);
//    return this;
//  }
  
  /**
   * set an error handler to receive information about errors
   * @param eh the error handler
   * @return the original instance, possibly updated
   */
  public XmiCasSerializer setErrorHandler(ErrorHandler eh) {
    css.errorHandler = eh;
    return this;
  }
  
  class XmiDocSerializer extends CasSerializerSupportSerialize {
    
    private final CasDocSerializer cds;
    
    private final ContentHandler ch;
    
    private final AttributesImpl emptyAttrs = new AttributesImpl();

    private final AttributesImpl workAttrs = new AttributesImpl();

    // the number of children can't be easily computed, until serialization is attempted,
    // because the decision on whether to serialize arrays and lists "inline" or as separate
    // sub-elements is made at the point they're about to be serialized.
    
    // No one appears to be using this.  Vinci uses the number of children, but it's based on 
    // the XCASSerializer implementation, not this one.
    
//    // number of children of current element
//    private int numChildren;
//    /**
//     * Gets the number of children of the current element. This is guaranteed to be set correctly at
//     * the time when startElement is called. Needed for streaming Vinci serialization.
//     * 
//     * @return the number of children of the current element
//     */
//    protected int getNumChildren() {
//      return numChildren;
//    }
    
    private XmiDocSerializer(ContentHandler ch, CASImpl cas, XmiSerializationSharedData sharedData, MarkerImpl marker) {
      cds = css.new CasDocSerializer(ch, cas, sharedData, marker, this);
      this.ch = ch;
    }
    
    @Override
    protected void initializeNamespaces() {
      /**
       * Populates nsUriToPrefixMap and typeCode2namespaceNames structures based on CAS type system.
       */
        
      cds.nsUriToPrefixMap.put(XMI_NS_URI, XMI_NS_PREFIX);

      //Add any namespace prefix mappings used by out of type system data.
      //Need to do this before the in-typesystem namespaces so that the prefix
      //used here are reserved and won't be reused for any in-typesystem namespaces.
           
      if (cds.sharedData != null) {
        Iterator<OotsElementData> ootsIter = cds.sharedData.getOutOfTypeSystemElements().iterator();
        while (ootsIter.hasNext()) {
          OotsElementData oed = ootsIter.next();
          String nsUri = oed.elementName.nsUri;                           //  http://... etc
          String qname = oed.elementName.qName;                           //    xxx:yyy
          String localName = oed.elementName.localName;                   //        yyy
          String prefix = qname.substring(0, qname.indexOf(localName)-1); // xxx
          cds.nsUriToPrefixMap.put(nsUri, prefix);
          cds.nsPrefixesUsed.add(prefix);
        }
      }

      /*
       * Convert x.y.z.TypeName to prefix-uri, TypeName, and ns:TypeName
       */
      Iterator<Type> it = cds.tsi.getTypeIterator();
      while (it.hasNext()) {
        TypeImpl t = (TypeImpl) it.next();
        // this also populates the nsUriToPrefix map
        cds.typeCode2namespaceNames[t.getCode()] = uimaTypeName2XmiElementName(t.getName());
      }
    }
    
    @Override
    protected void writeFeatureStructures(int iElementCount) throws Exception {
      workAttrs.clear();
      computeNamespaceDeclarationAttrs(workAttrs);
      workAttrs.addAttribute(XMI_NS_URI, XMI_VERSION_LOCAL_NAME, XMI_VERSION_QNAME, "CDATA",
          XMI_VERSION_VALUE);
      startElement(XMI_TAG, workAttrs, iElementCount);
      writeNullObject(); // encodes 1 element
      cds.encodeIndexed(); // encodes indexedFSs.size() element
      cds.encodeQueued(); // encodes queue.size() elements
      if (!cds.isDelta) {  // if delta, the out-of-type-system elements, are guaranteed not to be modified
        serializeOutOfTypeSystemElements(); //encodes sharedData.getOutOfTypeSystemElements().size() elements
      }

    }
    
    @Override
    protected void writeViews() throws Exception {
      cds.writeViewsCommons();  
    }
    
    @Override
    protected void writeEndOfSerialization() throws SAXException {
      endElement(XMI_TAG);
      endPrefixMappings();    
    }
    
    @Override
    protected void writeView(Sofa sofa, Collection<TOP> members) throws Exception {
      workAttrs.clear();
      // this call should never generate a new XmiId, it should just retrieve the existing one for the sofa
      String sofaXmiId = (sofa == null) ? null : cds.getXmiId(sofa);   
      if (sofaXmiId != null && sofaXmiId.length() > 0) {
        addAttribute(workAttrs, "sofa", sofaXmiId);
      }
      StringBuilder membersString = new StringBuilder();
      boolean isPastFirstElement = writeViewMembers(membersString, members);
      //check for out-of-typesystem members
      if (cds.sharedData != null) {
        List<String> ootsMembers = cds.sharedData.getOutOfTypeSystemViewMembers(sofaXmiId);
        writeViewMembers(membersString, ootsMembers, isPastFirstElement);
      }
      if (membersString.length() > 0) {
        workAttrs.addAttribute(
            "", 
            "members",
            "members",
            CDATA_TYPE, 
            membersString.toString());

//      addAttribute(workAttrs, "members", membersString.substring(0, membersString.length() - 1));
        if (membersString.length() > 0) {
          XmlElementName elemName = uimaTypeName2XmiElementName("uima.cas.View");
          startElement(elemName, workAttrs, 0);
          endElement(elemName);
        }
      }
    }
    
    /**
     * version for out-of-type-system data being merged back in
     * not currently supported for JSON
     * @param sb - where output goes
     * @param members string representations of the out of type system ids
     * @param isPastFirstElement -
     * @return
     */
    private StringBuilder writeViewMembers(StringBuilder sb, Collection<String> members, boolean isPastFirstElement) {
      if (members != null) {
        for (String member : members) {
          if (isPastFirstElement) {
            sb.append(' ');
          } else {
            isPastFirstElement = true;
          }
          sb.append(member);
        }
      }
      return sb;
    }

    
    private boolean writeViewMembers(StringBuilder sb, Collection<TOP> members) throws SAXException {
      boolean isPastFirstElement = false;
      int nextBreak = (((sb.length() - 1) / CasSerializerSupport.PP_LINE_LENGTH) + 1) * CasSerializerSupport.PP_LINE_LENGTH;
      for (TOP member : members) {
        int xmiId = cds.getXmiIdAsInt(member);
        if (xmiId != 0) { // to catch filtered FS         
          if (isPastFirstElement) {
            sb.append(' ');
          } else {
            isPastFirstElement = true;
          }
          sb.append(xmiId);
          if (cds.isFormattedOutput_inner && (sb.length() > nextBreak)) {
            sb.append(SYSTEM_LINE_FEED);
            nextBreak += CasSerializerSupport.PP_LINE_LENGTH; 
          }
        }
      }
      return isPastFirstElement;
    }

    private void writeViewForDeltas(String kind, Collection<TOP> deltaMembers) throws SAXException {
      StringBuilder sb = new StringBuilder();
      writeViewMembers(sb, deltaMembers);   
      if (sb.length() > 0) {
        addAttribute(workAttrs, kind, sb.toString());
      }
    }

    @Override
    protected void writeView(Sofa sofa, Collection<TOP> added, Collection<TOP> deleted, Collection<TOP> reindexed) throws SAXException {
      String sofaXmiId = cds.getXmiId(sofa);
      workAttrs.clear();
      if (sofaXmiId != null && sofaXmiId.length() > 0) {
        addAttribute(workAttrs, "sofa", sofaXmiId);
      }
      writeViewForDeltas("added_members", added);
      writeViewForDeltas("deleted_members", deleted);
      writeViewForDeltas("reindexed_members", reindexed);
            
      XmlElementName elemName = uimaTypeName2XmiElementName("uima.cas.View");
      startElement(elemName, workAttrs, 0);
      endElement(elemName);
    }
    
    /**
     * Writes a special instance of dummy type uima.cas.NULL, having xmi:id=0. This is needed to
     * represent nulls in multi-valued references, which aren't natively supported in Ecore.
     * @throws SAXException 
     * 
     */
    void writeNullObject() throws SAXException {
      workAttrs.clear();
      addIdAttribute(workAttrs, "0");
      XmlElementName elemName = uimaTypeName2XmiElementName("uima.cas.NULL");
      startElement(elemName, workAttrs, 0);
      endElement(elemName);
    }        

    @Override
    protected void writeFs(TOP fs, int typeCode) throws SAXException {
      writeFsOrLists(fs, typeCode, false);
    }

    @Override
    protected void writeListsAsIndividualFSs(TOP fs, int typeCode) throws SAXException {
      writeFsOrLists((TOP)fs, typeCode, true);
    }

    private void writeFsOrLists(TOP fs, int typeCode, boolean isListAsFSs) throws SAXException {
      // encode features. this populates the attributes (workAttrs). It also
      // populates the child elements list with features that are to be encoded
      // as child elements (currently required for string arrays).
      List<XmlElementNameAndContents> childElements = encodeFeatures(fs, workAttrs, isListAsFSs);
      XmlElementName xmlElementName = cds.typeCode2namespaceNames[typeCode];
      startElement(xmlElementName, workAttrs, childElements.size());
      sendElementEvents(childElements);
      endElement(xmlElementName);
    }
  
    @Override
    protected void writeArrays(TOP fsArray, int typeCode, int typeClass) throws SAXException {
      XmlElementName xmlElementName = cds.typeCode2namespaceNames[typeCode];
      
      if (fsArray instanceof StringArray) {

        // string arrays are encoded as elements, in case they contain whitespace
        List<XmlElementNameAndContents> childElements = new ArrayList<XmlElementNameAndContents>();
        stringArrayToElementList("elements", (StringArray) fsArray, childElements);
        startElement(xmlElementName, workAttrs, childElements.size());
        sendElementEvents(childElements);
        endElement(xmlElementName);        

      } else {
        // Saxon requirement? - can't omit (by using "") just one of localName & qName
        workAttrs.addAttribute("", "elements", "elements", "CDATA", arrayToString(fsArray, typeClass));
        startElement(xmlElementName, workAttrs, 0);
        endElement(xmlElementName);      
      }
    }
    
    private void endPrefixMappings() throws SAXException {
      Iterator<Map.Entry<String, String>> it = cds.nsUriToPrefixMap.entrySet().iterator();
      while (it.hasNext()) {
        Map.Entry<String, String> entry = it.next();
        String prefix = entry.getValue();
        ch.endPrefixMapping(prefix);
      }
      if (nsUriToSchemaLocationMap != null) {
        ch.endPrefixMapping("xsi");
      }
    }

    
    /*    
     * @param workAttrs2 where to put the attributes and values
     * @throws SAXException
     */
    private void computeNamespaceDeclarationAttrs(AttributesImpl workAttrs2) throws SAXException {
      Iterator<Map.Entry<String, String>> it = cds.nsUriToPrefixMap.entrySet().iterator();
      while (it.hasNext()) {
        Map.Entry<String, String> entry = it.next();
        
           // key = e.g.  http:///....
           // value = e.g.   "xmi" or last name part (plus int to disambiguate)
        String nsUri = entry.getKey();
        String prefix = entry.getValue();
        
        // write attribute
        workAttrs.addAttribute(XMLNS_NS_URI, 
                               prefix, 
                               "xmlns:" + prefix, 
                               "CDATA", 
                               nsUri);  
        ch.startPrefixMapping(prefix, nsUri);
      }
      // also add schemaLocation if specified
      if (nsUriToSchemaLocationMap != null) {
        // write xmlns:xsi attribute
        workAttrs.addAttribute(XMLNS_NS_URI, "xsi", "xmlns:xsi", "CDATA", XSI_NS_URI);
        ch.startPrefixMapping("xsi", XSI_NS_URI);
        
        // write xsi:schemaLocation attributaiton
        StringBuilder buf = new StringBuilder();
        it = nsUriToSchemaLocationMap.entrySet().iterator();
        while (it.hasNext()) {
          Map.Entry<String, String> entry = it.next();
          buf.append(entry.getKey()).append(' ').append(entry.getValue()).append(' ');
        }
        workAttrs.addAttribute(XSI_NS_URI, "xsi", "xsi:schemaLocation", "CDATA", buf.toString());
      }
      
    }
    
    /**
     * Serializes all of the out-of-typesystem elements that were recorded
     * in the XmiSerializationSharedData during the last deserialization.
     */
    private void serializeOutOfTypeSystemElements() throws SAXException {
      if (cds.marker != null)
            return;
      if (cds.sharedData == null)
        return;
      Iterator<OotsElementData> it = cds.sharedData.getOutOfTypeSystemElements().iterator();
      while (it.hasNext()) {
        OotsElementData oed = it.next();
        workAttrs.clear();
        // Add ID attribute
        addIdAttribute(workAttrs, oed.xmiId);

        // Add other attributes
        Iterator<XmlAttribute> attrIt = oed.attributes.iterator();
        while (attrIt.hasNext()) {
          XmlAttribute attr = attrIt.next();
          addAttribute(workAttrs, attr.name, attr.value);
        }
        // debug
        if (oed.elementName.qName.endsWith("[]")) {
          Misc.internalError(new Exception("XMI Cas Serialization: out of type system data has type name ending with []"));
        }
        // serialize element
        startElement(oed.elementName, workAttrs, oed.childElements.size());
        
        //serialize features encoded as child elements
        Iterator<XmlElementNameAndContents> childElemIt = oed.childElements.iterator();
        while (childElemIt.hasNext()) {
          XmlElementNameAndContents child = childElemIt.next();
          workAttrs.clear();
          Iterator<XmlAttribute> attrIter = child.attributes.iterator();
          while (attrIter.hasNext()) {
            XmlAttribute attr =attrIter.next();
            addAttribute(workAttrs, attr.name, attr.value);
          }
          
          if (child.contents != null) {
            startElement(child.name, workAttrs, 1);
            addText(child.contents);
          }
          else {
            startElement(child.name, workAttrs, 0);            
          }
          endElement(child.name);
        }
        
        endElement(oed.elementName);
      }
    }

    /**
     * Encode features of a regular (non-array) FS.
     * 
     * @param addr
     *          Address of the FS
     * @param attrs
     *          SAX Attributes object, to which we will add attributes
     * @param insideListNode
     *          true iff this FS is a List type.
     * 
     * @return a List of XmlElementNameAndContents objects, each of which represents an element that
     *         should be added as a child of the FS
     * @throws SAXException passthru
     */
    private List<XmlElementNameAndContents> encodeFeatures(TOP fs, AttributesImpl attrs, boolean insideListNode)
            throws SAXException {
      List<XmlElementNameAndContents> childElements = new ArrayList<XmlElementNameAndContents>();
//      int heapValue = cds.cas.getHeapValue(addr);
//      int[] feats = cds.tsi.ll_getAppropriateFeatures(heapValue);

      String  attrValue;
      // boolean isSofa = false;
      // if (sofaTypeCode == heapValue)
      // {
      // // set isSofa flag to apply SofaID mapping and to store sofaNum->xmi:id mapping
      // isSofa = true;
      // }
      for (final FeatureImpl fi : fs._getTypeImpl().getFeatureImpls()) {

        if (cds.isFiltering) {
          // skip features that aren't in the target type system
          String fullFeatName = fi.getName();
          if (cds.filterTypeSystem_inner.getFeatureByFullName(fullFeatName) == null) {
            continue;
          }
        }

        final String featName = fi.getShortName();
        final int featureValueClass = fi.rangeTypeClass;
        
        switch (featureValueClass) {
        
        case LowLevelCAS.TYPE_CLASS_BYTE:
        case LowLevelCAS.TYPE_CLASS_SHORT:
        case LowLevelCAS.TYPE_CLASS_INT:
        case LowLevelCAS.TYPE_CLASS_LONG:
        case LowLevelCAS.TYPE_CLASS_FLOAT:
        case LowLevelCAS.TYPE_CLASS_DOUBLE: 
        case LowLevelCAS.TYPE_CLASS_BOOLEAN:
          attrValue = fs.getFeatureValueAsString(fi);
          break;
        
        case LowLevelCAS.TYPE_CLASS_STRING:
          attrValue = fs.getFeatureValueAsString(fi);
          break;

          // Arrays
        case LowLevelCAS.TYPE_CLASS_INTARRAY:
        case LowLevelCAS.TYPE_CLASS_FLOATARRAY:
        case LowLevelCAS.TYPE_CLASS_BOOLEANARRAY:
        case LowLevelCAS.TYPE_CLASS_BYTEARRAY:
        case LowLevelCAS.TYPE_CLASS_SHORTARRAY:
        case LowLevelCAS.TYPE_CLASS_LONGARRAY:
        case LowLevelCAS.TYPE_CLASS_DOUBLEARRAY:
        case LowLevelCAS.TYPE_CLASS_FSARRAY: 
          if (cds.isStaticMultiRef(fi)) {
            attrValue = cds.getXmiId(fs.getFeatureValue(fi));
          } else {
            attrValue = arrayToString(fs.getFeatureValue(fi), featureValueClass);
          }
          break;
        
          // special case for StringArrays, which stored values as child elements rather
          // than attributes.
        case LowLevelCAS.TYPE_CLASS_STRINGARRAY: 
          if (cds.isStaticMultiRef(fi)) {
            attrValue = cds.getXmiId(fs.getFeatureValue(fi));
          } else {
            stringArrayToElementList(featName, (StringArray) fs.getFeatureValue(fi), childElements);
            attrValue = null;
          }
          break;
        
          // Lists
        case CasSerializerSupport.TYPE_CLASS_INTLIST:
        case CasSerializerSupport.TYPE_CLASS_FLOATLIST:
        case CasSerializerSupport.TYPE_CLASS_FSLIST: 
          TOP startNode = fs.getFeatureValue(fi);
          if (insideListNode || cds.isStaticMultiRef(fi)) {
            // If the feature has multipleReferencesAllowed = true OR if we're already
            // inside another list node (i.e. this is the "tail" feature), serialize as a normal FS.
            // Otherwise, serialize as a multi-valued property.
//            if (cds.isStaticMultRef(feats[i]) ||
//                cds.embeddingNotAllowed.contains(featVal) ||
//                insideListNode) {
            
            attrValue = cds.getXmiId(startNode);
          } else {
            attrValue = listToString((CommonList) fs.getFeatureValue(fi));
          }
          break;
        
          // special case for StringLists, which stored values as child elements rather
          // than attributes.
        case CasSerializerSupport.TYPE_CLASS_STRINGLIST: 
          if (insideListNode || cds.isStaticMultiRef(fi)) {
            attrValue = cds.getXmiId(fs.getFeatureValue(fi));
          } else {
            // it is not safe to use a space-separated attribute, which would
            // break for strings containing spaces. So use child elements instead.
            StringList stringList = (StringList) fs.getFeatureValue(fi);
            if (stringList != null) {
              List<String> listOfStrings = stringList.anyListToStringList(null, cds);
//              if (array.length > 0 && !arrayAndListFSs.put(featVal, featVal)) {
//                reportWarning("Warning: multiple references to a ListFS.  Reference identity will not be preserved.");
//              }
              for (String string : listOfStrings) {
                childElements.add(new XmlElementNameAndContents(new XmlElementName("", featName,
                        featName), string));
              }
            }
            attrValue = null;
          }
          break;
        
        default: // Anything that's not a primitive type, array, or list.
            attrValue = cds.getXmiId(fs.getFeatureValue(fi));
            break;
          
        } // end of switch
        
        if (attrValue != null && featName != null) {
          addAttribute(attrs, featName, attrValue, "");
        }
      } // end of for loop over all features
      
      //add out-of-typesystem features, if any
      if (cds.sharedData != null) {
        OotsElementData oed = cds.sharedData.getOutOfTypeSystemFeatures(fs);
        if (oed != null) {
          //attributes
          Iterator<XmlAttribute> attrIter = oed.attributes.iterator();
          while (attrIter.hasNext()) {
            XmlAttribute attr = attrIter.next();
            addAttribute(workAttrs, attr.name, attr.value);
          }
          //child elements
          childElements.addAll(oed.childElements);
        }
      }
      return childElements;
    }
    
    /**
     * Create a string to represent array values, embedded format
     * Not called for StringArray
     * @param addr
     * @param arrayType
     * @return
     * @throws SAXException
     */
    private String arrayToString(TOP fsIn, int arrayType) throws SAXException {
      if (fsIn == null) {
        return null;
      }

      StringBuilder buf = new StringBuilder();
      CommonArrayFS fs = (CommonArrayFS) fsIn;
      String elemStr = null;
      
      // FS arrays: handle shared data items
      if (fs instanceof FSArray) {
        List<XmiArrayElement> ootsArrayElementsList = cds.sharedData == null ? null : 
                                                      cds.sharedData.getOutOfTypeSystemArrayElements((FSArray) fs);
        int ootsIndex = 0;

        int j = -1;
        for (TOP elemFS : ((FSArray)fs)._getTheArray()) {
          j++;
          if (elemFS == null) { // null case
            // special NULL object with xmi:id=0 is used to represent
            // a null in an FSArray
            elemStr = "0";
            // However, this null array element might have been a reference to an 
            //out-of-typesystem FS, so check the ootsArrayElementsList
            if (ootsArrayElementsList != null) {

             while (ootsIndex < ootsArrayElementsList.size()) {
                XmiArrayElement arel = ootsArrayElementsList.get(ootsIndex++);
                if (arel.index == j) {
                  elemStr = arel.xmiId;
                  break;
                }                
              }
            }
            
          } else {  // not null
            String xmiId = cds.getXmiId(elemFS);
            if (cds.isFiltering) { // return as null any references to types not in target TS
              String typeName = elemFS._getTypeImpl().getName();
              if (cds.filterTypeSystem_inner.getType(typeName) == null) {
                xmiId = "0";
              }
            }
            elemStr = xmiId;
          }
          
          if (buf.length() > 0) {
            buf.append(' ');
          }
          buf.append(elemStr);
        }  // end of loop over FS Array elements
        
        return buf.toString();
        
      } else if (fs instanceof ByteArray) {
        
        // special case for byte arrays: serialize as hex digits 
        byte[] ba = ((ByteArray) fs)._getTheArray();
        
        char[] r = new char[ba.length * 2];
        
        int i = 0;
        for (byte b : ba) {
          r[i++] = INT_TO_HEX[(b & 0xF0) >>> 4];
          r[i++] = INT_TO_HEX[b & 0x0F];
        }
        return new String(r);
      } else {
        // is not FSarray, is not ByteArray, is not String Array
//        CommonArrayFS fs;
//        String[] fsvalues;
//
//        switch (arrayType) {
//          case LowLevelCAS.TYPE_CLASS_INTARRAY:
//            fs = new IntArrayFSImpl(addr, cds.cas);
//            break;
//          case LowLevelCAS.TYPE_CLASS_FLOATARRAY:
//            fs = new FloatArrayFSImpl(addr, cds.cas);
//            break;
//          case LowLevelCAS.TYPE_CLASS_BOOLEANARRAY:
//            fs = new BooleanArrayFSImpl(addr, cds.cas);
//            break;
//          case LowLevelCAS.TYPE_CLASS_SHORTARRAY:
//            fs = new ShortArrayFSImpl(addr, cds.cas);
//            break;
//          case LowLevelCAS.TYPE_CLASS_LONGARRAY:
//            fs = new LongArrayFSImpl(addr, cds.cas);
//            break;
//          case LowLevelCAS.TYPE_CLASS_DOUBLEARRAY:
//            fs = new DoubleArrayFSImpl(addr, cds.cas);
//            break;
//          case LowLevelCAS.TYPE_CLASS_BYTEARRAY:
//            fs = new ByteArrayFSImpl(addr, cds.cas);
//            break;
//          default: {
//            return "";
//          }
//        }

//        if (arrayType == LowLevelCAS.TYPE_CLASS_STRINGARRAY) {   // this method never called for StringArrays
//          StringArrayFS strFS = new StringArrayFSImpl(addr, cds.cas);
//          fsvalues = strFS.toArray();
//        } else {
        String[] fsvalues = fs.toStringArray();
//        }

        for (String s : fsvalues) {
          if (buf.length() > 0) {
            buf.append(' ');
          }
          buf.append(s);
        }
        return buf.toString();
      }
    }
    
    private void stringArrayToElementList(
        String featName, 
        StringArray stringArray, 
        List<? super XmlElementNameAndContents> resultList) {
      if (stringArray == null) {
        return;
      }
      // it is not safe to use a space-separated attribute, which would
      // break for strings containing spaces. So use child elements instead.
      
      for (String s : stringArray._getTheArray()) {
        resultList.add(new XmlElementNameAndContents(new XmlElementName("", featName, featName),
            s));
      }
    }


    /**
     * Converts a CAS List of Int, Float, or FsRefs to its string representation for use in multi-valued XMI properties.
     * Only called if no sharing of list nodes exists.
     * Only called for list nodes referred to by Feature value slots in some non-list FS.
     * 
     * @param curNode
     *          address of the CAS ListFS
     * 
     * @return String representation of the array, or null if passed in CASImpl.NULL
     * @throws SAXException passthru
     */
    private String listToString(CommonList fs) throws SAXException {
      if (fs == null) {
        return null;  // different from ""
      }
      final StringBuilder sb = new StringBuilder();
      fs.anyListToOutput(cds.sharedData, cds, s -> {if (sb.length() > 0) {
                                                     sb.append(' ').append(s);
                                                    } else {
                                                     sb.append(s);
                                                    }});
      return sb.toString();
    }

    /**
     * Generate startElement, characters, and endElement SAX events.
     * Only for StringArray and StringList kinds of things
     * Only called for XMI (not JSON)
     * 
     * @param elements
     *          a list of XmlElementNameAndContents objects representing the elements to generate
     * @throws SAXException passthru
     */
    private void sendElementEvents(List<? extends XmlElementNameAndContents> elements) throws SAXException {
      Iterator<? extends XmlElementNameAndContents> childIter = elements.iterator();
      while (childIter.hasNext()) {
        XmlElementNameAndContents elem = childIter.next();
        if (elem.contents != null) {
          startElement(elem.name, emptyAttrs, 1);
          addText(elem.contents);
        } else {
          startElement(elem.name, emptyAttrs, 0);
        }
        endElement(elem.name);
      }      
    }

    
    private void startElement(XmlElementName name, Attributes attrs, int aNumChildren)
        throws SAXException {
      // Previously the NS URI was omitted, claiming:	
      //    >>> That causes XMI serializer to include the xmlns attribute in every element <<<
      // But without it Saxon omits process namespaces
      ch.startElement(
          name.nsUri, 
          name.localName, 
          name.qName, 
          attrs);
    }
    
    private void endElement(XmlElementName name) throws SAXException {
    //  if (name == null) {
    //    ch.endElement(null, null, null);
    //  } else {
        ch.endElement(name.nsUri, name.localName, name.qName);
    //  }
    }
    
    private void addAttribute(AttributesImpl attrs, String attrName, String attrValue) {
      addAttribute(attrs, attrName, attrValue, CDATA_TYPE);
    }

    // type info for attributes uses string values taken from
    //   http://www.w3.org/TR/xmlschema-2/
    //     decimal string boolean 
    private void addAttribute(AttributesImpl attrs, String attrName, String attrValue, String type) {
      // Provide identical values for the qName & localName (although Javadocs indicate that both can be omitted!)
      attrs.addAttribute("", attrName, attrName, type, attrValue);
      // Saxon throws an exception if either omitted:
      //     "Saxon requires an XML parser that reports the QName of each element"
      //     "Parser configuration problem: namespsace reporting is not enabled"
      // The IBM JRE implementation produces bad xml if the qName is omitted,
      //     but handles a missing localName correctly
    }

    private void addIdAttribute(AttributesImpl attrs, String attrValue) {
      attrs.addAttribute(XMI_NS_URI, "id", ID_ATTR_NAME, CDATA_TYPE, attrValue);
    }

    private void addText(String text) throws SAXException {
      ch.characters(text.toCharArray(), 0, text.length());
    }
    
    @Override
    protected void checkForNameCollision(XmlElementName xmlElementName) {}

    @Override
    protected void addNameSpace(XmlElementName xmlElementName) {};

    @Override
    protected boolean writeFsStart(TOP fs, int typeCode /* ignored */) {
      workAttrs.clear();
      addIdAttribute(workAttrs, cds.getXmiId(fs));
      return false;  // ignored
    }
   
    /**
     * Converts a UIMA-style dotted type name to the element name that should be used in the XMI
     * serialization. The XMI element name consists of three parts - the Namespace URI, the Local
     * Name, and the QName (qualified name).
     * Namespace URI = http:///uima/noNamespace.ecore or
     *                 http:///uima/package/name/with/slashes.ecore
     *   
     * 
     * @param uimaTypeName
     *          a UIMA-style dotted type name
     * @return a data structure holding the three components of the XML element name
     */
    @Override
    protected XmlElementName uimaTypeName2XmiElementName(String uimaTypeName) {
      if (uimaTypeName.endsWith(TypeSystemImpl.ARRAY_TYPE_SUFFIX)) {
        // can't write out xyz[] as the qname.  Use FSArray instead
        uimaTypeName = CASImpl.TYPE_NAME_FS_ARRAY;
      }

      // split uima type name into namespace and short name
      String shortName, nsUri;
      final int lastDotIndex = uimaTypeName.lastIndexOf('.');
      if (lastDotIndex == -1) // no namespace
      {
//        namespace = null;
        shortName = uimaTypeName;
        nsUri = DEFAULT_NAMESPACE_URI;
      } else {
//        namespace = uimaTypeName.substring(0, lastDotIndex);
        shortName = uimaTypeName.substring(lastDotIndex + 1);
        char[] sb = new char[lastDotIndex + URIPFX.length + URISFX.length];
        System.arraycopy(URIPFX, 0, sb, 0, URIPFX.length);  // http:///
        int i = 0;
        for (; i < lastDotIndex; i++) {                     // http:///uima/tcas  or http:///org/a/b/c
          char c = uimaTypeName.charAt(i);
          sb[URIPFX.length + i] = ( c == '.') ? '/' : c;
        }
        System.arraycopy(URISFX, 0, sb, URIPFX.length + i, URISFX.length);  // http:///uima/tcas.name_space
        nsUri = cds.getUniqueString(new String(sb));
        
//        nsUri = "http:///" + namespace.replace('.', '/') + ".ecore"; 
      }
      // convert short name to shared string, without interning, reduce GCs
      shortName = cds.getUniqueString(shortName);

      // determine what namespace prefix to use
      String prefix = cds.getNameSpacePrefix(uimaTypeName, nsUri, lastDotIndex);
      // debug
      return new XmlElementName(nsUri, shortName, cds.getUniqueString(prefix + ':' + shortName));
    }

    @Override
    protected void writeEndOfIndividualFs() {}

    @Override
    protected void writeFsRef(TOP fs) throws Exception {} // only for JSON, not used here
     
  }
        
//  // for testing
//  public XmiDocSerializer getTestXmiDocSerializer(ContentHandler ch, CASImpl cas) {
//    return new XmiDocSerializer(ch, cas, null);
//  }  
  
}
