You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by sc...@apache.org on 2016/05/13 20:12:53 UTC

svn commit: r1743747 - /uima/uimaj/branches/experiment-v3-jcas/uimaj-json/src/main/java/org/apache/uima/json/JsonCasSerializer.java

Author: schor
Date: Fri May 13 20:12:53 2016
New Revision: 1743747

URL: http://svn.apache.org/viewvc?rev=1743747&view=rev
Log:
[UIMA-4674] _typeImpl not final (to support ll_setInt backward compatibility), change refs to it to _getTypeImpl() for protection, and change in data type returned for getFeatureImpls.

Modified:
    uima/uimaj/branches/experiment-v3-jcas/uimaj-json/src/main/java/org/apache/uima/json/JsonCasSerializer.java

Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-json/src/main/java/org/apache/uima/json/JsonCasSerializer.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-json/src/main/java/org/apache/uima/json/JsonCasSerializer.java?rev=1743747&r1=1743746&r2=1743747&view=diff
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-json/src/main/java/org/apache/uima/json/JsonCasSerializer.java (original)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-json/src/main/java/org/apache/uima/json/JsonCasSerializer.java Fri May 13 20:12:53 2016
@@ -20,21 +20,24 @@
 package org.apache.uima.json;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.uima.cas.ByteArrayFS;
 import org.apache.uima.cas.CAS;
+import org.apache.uima.cas.FeatureStructure;
 import org.apache.uima.cas.Marker;
 import org.apache.uima.cas.TypeSystem;
-import org.apache.uima.cas.impl.ByteArrayFSImpl;
+import org.apache.uima.cas.function.IntConsumer_withIOException;
 import org.apache.uima.cas.impl.CASImpl;
 import org.apache.uima.cas.impl.CasSerializerSupport;
 import org.apache.uima.cas.impl.CasSerializerSupport.CasDocSerializer;
 import org.apache.uima.cas.impl.CasSerializerSupport.CasSerializerSupportSerialize;
-import org.apache.uima.cas.impl.ListUtils;
+import org.apache.uima.cas.impl.FeatureImpl;
 import org.apache.uima.cas.impl.LowLevelCAS;
 import org.apache.uima.cas.impl.MarkerImpl;
 import org.apache.uima.cas.impl.TypeImpl;
@@ -42,10 +45,28 @@ import org.apache.uima.cas.impl.TypeSyst
 import org.apache.uima.cas.impl.XmiSerializationSharedData;
 import org.apache.uima.cas.impl.XmiSerializationSharedData.XmiArrayElement;
 import org.apache.uima.internal.util.IntVector;
+import org.apache.uima.internal.util.Misc;
 import org.apache.uima.internal.util.PositiveIntSet;
 import org.apache.uima.internal.util.PositiveIntSet_impl;
 import org.apache.uima.internal.util.XmlElementName;
 import org.apache.uima.internal.util.rb_trees.RedBlackTree;
+import org.apache.uima.jcas.cas.BooleanArray;
+import org.apache.uima.jcas.cas.ByteArray;
+import org.apache.uima.jcas.cas.CommonArray;
+import org.apache.uima.jcas.cas.DoubleArray;
+import org.apache.uima.jcas.cas.EmptyList;
+import org.apache.uima.jcas.cas.FSArray;
+import org.apache.uima.jcas.cas.FloatArray;
+import org.apache.uima.jcas.cas.IntegerArray;
+import org.apache.uima.jcas.cas.LongArray;
+import org.apache.uima.jcas.cas.NonEmptyFSList;
+import org.apache.uima.jcas.cas.NonEmptyFloatList;
+import org.apache.uima.jcas.cas.NonEmptyIntegerList;
+import org.apache.uima.jcas.cas.NonEmptyStringList;
+import org.apache.uima.jcas.cas.ShortArray;
+import org.apache.uima.jcas.cas.Sofa;
+import org.apache.uima.jcas.cas.StringArray;
+import org.apache.uima.jcas.cas.TOP;
 import org.apache.uima.json.impl.JsonContentHandlerJacksonWrapper;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.ErrorHandler;
@@ -99,8 +120,6 @@ import com.fasterxml.jackson.core.io.Ser
  */
 public class JsonCasSerializer {
 
-  private static final Integer[] EMPTY_INTEGER_ARRAY = new Integer[0];
-
   private static final SerializedString CONTEXT_NAME = new SerializedString("_context");
  
   private static final SerializedString TYPE_SYSTEM_NAME = new SerializedString("_type_system");
@@ -454,16 +473,14 @@ public class JsonCasSerializer {
     private final JsonContentHandlerJacksonWrapper jch;
 
     private final JsonGenerator jg;
-    
-    private final String typeSystemReference;
-       
+           
     private final Map<String, SerializedString> serializedStrings = new HashMap<String, SerializedString>();
     
     private final Map<String, XmlElementName> usedTypeName2XmlElementName;
     
     private final MapType2Subtypes mapType2Subtypes = new MapType2Subtypes();
     
-    private final IntVector parentTypesWithNoInstances = new IntVector();
+    private final List<TypeImpl> parentTypesWithNoInstances = new ArrayList<>();
    
     private int lastEncodedTypeCode;
     
@@ -473,8 +490,6 @@ public class JsonCasSerializer {
     
     private final boolean isWithContext;
 
-    private final boolean isWithExpandedTypeNames;
-
     private final boolean isWithSubtypes;
     
     private boolean indexId;  // true causes fs to be listed as "id" : { ...}, false as "type" : [ {...}
@@ -489,9 +504,7 @@ public class JsonCasSerializer {
     private JsonDocSerializer(ContentHandler ch, CASImpl cas, XmiSerializationSharedData sharedData, MarkerImpl marker) {
       cds = css.new CasDocSerializer(ch, cas, sharedData, marker, this, JsonCasSerializer.this.isDynamicEmbedding);
       this.isOmitDefaultValues = JsonCasSerializer.this.isOmit0Values;  
-      isWithExpandedTypeNames = JsonCasSerializer.this.isWithExpandedTypeNames; 
       isWithSubtypes = JsonCasSerializer.this.isWithSubtypes; 
-      typeSystemReference = JsonCasSerializer.this.typeSystemReference;
       jch = (JsonContentHandlerJacksonWrapper) ch;
       jg = jch.getJsonGenerator();
       isWithContext = JsonCasSerializer.this.isWithContext || isWithSubtypes || isWithExpandedTypeNames; 
@@ -541,23 +554,21 @@ public class JsonCasSerializer {
       jg.writeFieldName(VIEWS_NAME);
       jg.writeStartObject();
       
-      final Integer[][] byViewByTypeFSs = sortByViewType(); 
+      final List<TOP>[] byViewByTypeFSs = sortByViewType(); 
       
       for (int viewNbr = 1; viewNbr <= byViewByTypeFSs.length; viewNbr++) {
         // viewNbr starts at 1
         lastEncodedTypeCode = -1;
-        final Integer[] fssInView = byViewByTypeFSs[viewNbr - 1];
-        final int sofaAddr = cds.getSofaAddr(viewNbr);
-        if (sofaAddr == 0 && fssInView.length == 0) {
+        final List<TOP> fssInView = byViewByTypeFSs[viewNbr - 1];
+        final Sofa sofa = cds.getSofa(viewNbr);
+        if (sofa == null && fssInView.size() == 0) {
           continue;  // skip non-existent initial view with no sofa and no elements                    
         }
         jch.writeNlJustBeforeNext();
-        String viewName = (0 == sofaAddr) ?  
-            CAS.NAME_DEFAULT_SOFA :
-            cds.cas.getStringValue(sofaAddr, cds.tsi.sofaIdFeatCode);
+        String viewName = (null == sofa) ? CAS.NAME_DEFAULT_SOFA : sofa.getSofaID();
         jg.writeFieldName(viewName);  // view namne
         jg.writeStartObject();
-        for (Integer fs : fssInView) {
+        for (TOP fs : fssInView) {
           cds.encodeFS(fs);
         }
         if (lastEncodedTypeCode != -1) {
@@ -586,24 +597,27 @@ public class JsonCasSerializer {
     }
    
     // sort the by-view by-type set
-    //   previously Serialized 
-    private Integer[][] sortByViewType() {
-      final Integer[] [] r = new Integer[cds.indexedFSs.length] [];
+    //   previously Serialized
+    /**
+     * @return the List<TOP>[] returned by cds.indexedFSs, but with each view sorted by type
+     */
+    private List<TOP>[] sortByViewType() {
+      
+      @SuppressWarnings("unchecked")
+      final List<TOP>[] r = new List[cds.indexedFSs.length]; 
+      
       int i = 0;
-      for (final IntVector fss : cds.indexedFSs) {
-        final Integer[] viewFSs = r[i++] = (null == fss) ? EMPTY_INTEGER_ARRAY : new Integer[fss.size()];
-        for (int j = 0; j < viewFSs.length; j++) {
-          viewFSs[j]  = fss.get(j);
-        }
-        Arrays.sort(viewFSs, cds.sortFssByType);
+      for (final List<TOP> fss : cds.indexedFSs) {
+        r[i] = (fss == null) ? Collections.EMPTY_LIST : (List<TOP>) ((ArrayList<TOP>)fss).clone();
+        Collections.sort(r[i++], cds.sortFssByType);
       }
       return r;
     }
     
     @Override
-    protected void writeView(int sofaAddr, int[] members) throws IOException {
+    protected void writeView(Sofa sofa, Collection<TOP> members) throws IOException {
       jch.writeNlJustBeforeNext();
-      String sofaXmiId = (0 == sofaAddr) ? "0" : cds.getXmiId(sofaAddr);
+      String sofaXmiId = (null == sofa) ? "0" : cds.getXmiId(sofa);
       jg.writeArrayFieldStart(sofaXmiId);
       writeViewMembers(members);
       //check for out-of-typesystem members
@@ -616,7 +630,7 @@ public class JsonCasSerializer {
       jg.writeEndArray();
     }
     
-    private void writeViewForDeltas(SerializedString kind, int[] deltaMembers) throws IOException {
+    private void writeViewForDeltas(SerializedString kind, Collection<TOP> deltaMembers) throws IOException {
       jg.writeFieldName(kind);
       jg.writeStartArray();
       writeViewMembers(deltaMembers);   
@@ -624,9 +638,9 @@ public class JsonCasSerializer {
     }
     
     @Override
-    protected void writeView(int sofaAddr, int[] added, int[] deleted, int[] reindexed) throws IOException {
+    protected void writeView(Sofa sofa, Collection<TOP> added, Collection<TOP> deleted, Collection<TOP> reindexed) throws IOException {
       jch.writeNlJustBeforeNext();
-      jg.writeFieldName(cds.getXmiId(sofaAddr));
+      jg.writeFieldName(cds.getXmiId(sofa));
       jg.writeStartObject();
       writeViewForDeltas(ADDED_MEMBERS_NAME, added);
       writeViewForDeltas(DELETED_MEMBERS_NAME, deleted);
@@ -634,10 +648,10 @@ public class JsonCasSerializer {
       jg.writeEndObject();
     }
     
-    private void writeViewMembers(int[] members) throws IOException {
+    private void writeViewMembers(Collection<TOP> members) throws IOException {
       int nextBreak = CasSerializerSupport.PP_ELEMENTS;
       int i = 0;
-      for (int member : members) {
+      for (TOP member : members) {
         int xmiId = cds.getXmiIdAsInt(member);
         if (xmiId == 0) {
           continue;
@@ -722,7 +736,7 @@ public class JsonCasSerializer {
       
       for (TypeImpl ti : cds.getSortedUsedTypes()) {
         jch.writeNlJustBeforeNext();      
-        jg.writeFieldName(getSerializedTypeName(ti.getCode()));
+        jg.writeFieldName(getSerializedTypeName(ti));
         jg.writeStartObject();
         if (isWithExpandedTypeNames) {
           jg.writeFieldName(ID_NAME);  // form for using SerializedString
@@ -736,20 +750,20 @@ public class JsonCasSerializer {
       }
       
       // write out contexts for types in the supertype chain which have no instances
-      for (final int typeCode : parentTypesWithNoInstances.toArray()) {
+      for (final TypeImpl ti : parentTypesWithNoInstances) {
         jch.writeNlJustBeforeNext();      
-        jg.writeFieldName(getSerializedTypeName(typeCode));
+        jg.writeFieldName(getSerializedTypeName(ti));
         jg.writeStartObject();
-        XmlElementName xe = cds.typeCode2namespaceNames[typeCode];
+        XmlElementName xe = cds.typeCode2namespaceNames[ti.getCode()];
 
         if (isWithExpandedTypeNames) {
           jg.writeFieldName(ID_NAME);  // form for using SerializedString
           jg.writeString(xe.nsUri);
         }
  
-        addJsonFeatContext(typeCode);
+        addJsonFeatContext(ti);
         if (isWithSubtypes) {
-          addJsonSubtypes(typeCode);
+          addJsonSubtypes(ti);
         }
         jg.writeEndObject();  // end of one type
         
@@ -767,19 +781,15 @@ public class JsonCasSerializer {
      * @throws IOException 
      */
     private void addJsonFeatContext(TypeImpl type) throws IOException {
-      addJsonFeatContext(type.getCode());
-    }
-    
-    private void addJsonFeatContext(final int typeCode) throws IOException {
-      final int[] feats = cds.tsi.ll_getAppropriateFeatures(typeCode);
+      final FeatureImpl[] feats = type.getFeatureImpls();
       startedFeatureTypes = false;
    
-      for (int featCode : feats) {
-        final int fsClass = cds.classifyType(cds.tsi.range(featCode));
-        SerializedString featKind = featureTypeLabel(fsClass, featCode);
+      for (FeatureImpl feat : feats) {
+        final int fsClass = CasSerializerSupport.classifyType(feat.getRangeImpl());
+        SerializedString featKind = featureTypeLabel(fsClass);
         if (null != featKind) {
           maybeDoStartFeatureTypes();
-          jg.writeFieldName(getShortFeatureName(featCode)); 
+          jg.writeFieldName(getSerializedString(feat.getShortName())); 
           jg.writeString(featKind);
         }  
       }
@@ -796,28 +806,21 @@ public class JsonCasSerializer {
         startedFeatureTypes = true;
       }
     }
-    
-    private SerializedString getShortFeatureName(int featCode) {
-      return getSerializedString(cds.tsi.ll_getFeatureForCode(featCode).getShortName());
-    }
-        
+            
     /**
      * Add subtype information for used types limited to used subtypes
      * @throws IOException 
      */
     private void addJsonSubtypes(TypeImpl ti) throws IOException {
-      addJsonSubtypes(ti.getCode());
-    }
-    
-    private void addJsonSubtypes(int aTypeCode) throws IOException {
-      IntVector iv = mapType2Subtypes.get(aTypeCode);
+      IntVector iv = mapType2Subtypes.get(ti.getCode());
       if (null != iv && iv.size() > 0) {
         jch.writeNlJustBeforeNext();
         jg.writeFieldName(SUB_TYPES_NAME);
         jg.writeStartArray();
         
+        TypeSystemImpl tsi = ti.getTypeSystem();
         for (int typeCode : iv.toArray()) {
-          jg.writeString(getSerializedTypeName(typeCode));
+          jg.writeString(getSerializedTypeName(tsi.getTypeForCode(typeCode)));
         }
         jg.writeEndArray();
       }
@@ -837,8 +840,8 @@ public class JsonCasSerializer {
              parent = (TypeImpl) parent.getSuperType()) {
           final int parentCode = parent.getCode();
           if (Arrays.binarySearch(tiArray,  parent) < 0 ) {  // if parentCode not contained in tiArray
-            if (!parentTypesWithNoInstances.contains(parentCode)) {
-              parentTypesWithNoInstances.add(parentCode);
+            if (!parentTypesWithNoInstances.contains(parent)) {
+              parentTypesWithNoInstances.add(parent);
             }
           }
           boolean wasAdded = mapType2Subtypes.addSubtype(parentCode, subtypeCode);
@@ -850,13 +853,13 @@ public class JsonCasSerializer {
       }
     }
     
-    private SerializedString getSerializedTypeName(int typeCode) {
-      XmlElementName xe = cds.typeCode2namespaceNames[typeCode];
+    private SerializedString getSerializedTypeName(TypeImpl ti) {
+      XmlElementName xe = cds.typeCode2namespaceNames[ti.getCode()];
       if (null == xe) {
         // happens for supertypes which have no instantiations
-        String typeName = cds.tsi.ll_getTypeForCode(typeCode).getName();
+        String typeName = ti.getName();
         xe = uimaTypeName2XmiElementName(typeName);
-        cds.typeCode2namespaceNames[typeCode] = xe;
+        cds.typeCode2namespaceNames[ti.getCode()] = xe;
       }
       return getSerializedString(xe.qName);
     }
@@ -889,7 +892,7 @@ public class JsonCasSerializer {
     }
     
     @Override
-    protected boolean writeFsStart(int addr, int typeCode) throws IOException {
+    protected boolean writeFsStart(TOP fs, int typeCode) throws IOException {
       if (isEmbedded) {
         if (!isEmbeddedFromFsFeature) {
           jch.writeNlJustBeforeNext();  // if from feature, already did nl
@@ -903,7 +906,7 @@ public class JsonCasSerializer {
           startedReferencedFSs = true;
         }
         jch.writeNlJustBeforeNext();
-        jg.writeFieldName(cds.getXmiId(addr));
+        jg.writeFieldName(cds.getXmiId(fs));
         jg.writeStartObject();  // start of feat : value
       } else { // fs's as arrays under typeName
         if (typeCode != lastEncodedTypeCode) {
@@ -913,13 +916,13 @@ public class JsonCasSerializer {
           }
           lastEncodedTypeCode = typeCode;
           jch.writeNlJustBeforeNext();
-          jg.writeFieldName(getSerializedTypeName(typeCode));
+          jg.writeFieldName(getSerializedTypeName(fs._getTypeImpl()));
           jg.writeStartArray();
         }
         // if we're not going to write the actual FS here, 
         //   and are just going to write the ref, 
         //   skip the start object
-        if (cds.multiRefFSs == null || !cds.multiRefFSs.contains(addr)) {         
+        if (cds.multiRefFSs == null || !cds.multiRefFSs.contains(fs)) {         
           jch.writeNlJustBeforeNext();
           jg.writeStartObject();  // start of feat : value
         }
@@ -928,8 +931,8 @@ public class JsonCasSerializer {
     }
     
     @Override
-    protected void writeFsRef(int addr) throws Exception {
-       jg.writeNumber(cds.getXmiIdAsInt(addr));      
+    protected void writeFsRef(TOP fs) throws Exception {
+       jg.writeNumber(cds.getXmiIdAsInt(fs));      
     }    
 
 //    private void maybeWriteIdFeat(int addr) throws IOException {
@@ -939,130 +942,140 @@ public class JsonCasSerializer {
 //      }
 //    }
     
-    private void maybeWriteTypeFeat(int typeCode) throws IOException {
+    private void maybeWriteTypeFeat(TypeImpl ti) throws IOException {
       if (indexId || isEmbedded) {
         jg.writeFieldName(TYPE_NAME);
-        jg.writeString(getSerializedTypeName(typeCode));
+        jg.writeString(getSerializedTypeName(ti));
       }
     }
 
     @Override
-    protected void writeFs(int addr, int typeCode) throws IOException {
-      writeFsOrLists(addr, typeCode, false);
+    protected void writeFs(TOP fs, int typeCode) throws IOException {
+      writeFsOrLists(fs, fs._getTypeImpl(), false);
     }
     
     @Override
-    protected void writeListsAsIndividualFSs(int addr, int typeCode) throws IOException {
-      writeFsOrLists(addr, typeCode, true);
+    protected void writeListsAsIndividualFSs(TOP fs, int typeCode) throws IOException {
+      writeFsOrLists(fs, fs._getTypeImpl(), true);
     }
     
-    private void writeFsOrLists(int addr, int typeCode, boolean isListAsFSs) throws IOException {
-      final int[] feats = cds.tsi.ll_getAppropriateFeatures(typeCode);
+    private void writeFsOrLists(TOP fs, TypeImpl ti, boolean isListAsFSs) throws IOException {
+      final FeatureImpl[] feats = ti.getFeatureImpls();
       
 //      maybeWriteIdFeat(addr);
-      maybeWriteTypeFeat(typeCode);
+      maybeWriteTypeFeat(ti);
       
-      for (final int featCode : feats) {
+      for (final FeatureImpl feat : feats) {
 
         if (cds.isFiltering) {
           // skip features that aren't in the target type system
-          String fullFeatName = cds.tsi.ll_getFeatureForCode(featCode).getName();
+          String fullFeatName = feat.getName();
           if (cds.filterTypeSystem.getFeatureByFullName(fullFeatName) == null) {
             continue;
           }
         }
         
-        final int featAddr = addr + cds.cas.getFeatureOffset(featCode);
-        final int featValRaw = cds.cas.getHeapValue(featAddr);
-        final int featureClass = cds.classifyType(cds.tsi.range(featCode));
+//        final int featAddr = addr + cds.cas.getAdjustedFeatureOffset(featCode);
+//        final int featValRaw = cds.cas.getHeapValue(featAddr);
+        final int featureClass = CasSerializerSupport.classifyType(feat.getRangeImpl());
+        final SerializedString shortName = getSerializedString(feat.getShortName());
                 
         switch (featureClass) {
         
-        case LowLevelCAS.TYPE_CLASS_BYTE:
-        case LowLevelCAS.TYPE_CLASS_SHORT:  
-        case LowLevelCAS.TYPE_CLASS_INT:
-          if (featValRaw == 0 && isOmitDefaultValues) continue;
-          jg.writeFieldName(getShortFeatureName(featCode));
-          jg.writeNumber(featValRaw);
-          break;
-
-        case LowLevelCAS.TYPE_CLASS_FS:
-          if (featValRaw == 0/* && isOmitDefaultValues*/) continue;
-          writeFsOrRef(featValRaw, featCode); // writes nl before embedded fs
-          break;
-  
-        case LowLevelCAS.TYPE_CLASS_LONG:
-          final long longVal = cds.cas.ll_getLongValue(featValRaw);
-          if (longVal == 0L && isOmitDefaultValues) continue;
-          jg.writeFieldName(getShortFeatureName(featCode));
-          jg.writeNumber(longVal);
+        case LowLevelCAS.TYPE_CLASS_BYTE:  writeNumeric(feat, fs._getByteValueNc (feat)); break;
+        case LowLevelCAS.TYPE_CLASS_SHORT: writeNumeric(feat, fs._getShortValueNc(feat)); break; 
+        case LowLevelCAS.TYPE_CLASS_INT:   writeNumeric(feat, fs._getIntValueNc  (feat)); break;  
+        case LowLevelCAS.TYPE_CLASS_LONG:  writeNumeric(feat, fs._getLongValueNc (feat)); break;  
+
+        case LowLevelCAS.TYPE_CLASS_FS: {
+          TOP ref = fs._getFeatureValueNc(feat);
+          if (ref == null /* && isOmitDefaultValues*/) continue;
+          writeFsOrRef(ref, feat); // writes nl before embedded fs
           break;
+        }
           
         case LowLevelCAS.TYPE_CLASS_FLOAT:
-          final float floatVal = CASImpl.int2float(featValRaw);
+          final float floatVal = fs._getFloatValueNc(feat);
           if (floatVal == 0.F && isOmitDefaultValues) continue;
-          jg.writeFieldName(getShortFeatureName(featCode));
+          jg.writeFieldName(shortName);
           jg.writeNumber(floatVal);
           break;
           
         case LowLevelCAS.TYPE_CLASS_DOUBLE:
-          final double doubleVal = cds.cas.ll_getDoubleValue(addr, featCode);
+          final double doubleVal = fs._getDoubleValueNc(feat);
           if (doubleVal == 0L && isOmitDefaultValues) continue;
-          jg.writeFieldName(getShortFeatureName(featCode));
+          jg.writeFieldName(shortName);
           jg.writeNumber(doubleVal);
           break;
           
         case LowLevelCAS.TYPE_CLASS_BOOLEAN:
-          jg.writeFieldName(getShortFeatureName(featCode));
-          jg.writeBoolean(cds.cas.ll_getBooleanValue(addr, featCode));           
+          jg.writeFieldName(shortName);
+          jg.writeBoolean(fs._getBooleanValueNc(feat));           
           break; 
         
-        case LowLevelCAS.TYPE_CLASS_STRING:
-          if (featValRaw == 0 /*&& isOmitDefaultValues*/) continue; 
-          jg.writeFieldName(getShortFeatureName(featCode));
-          jg.writeString(cds.cas.getStringForCode(featValRaw));
+        case LowLevelCAS.TYPE_CLASS_STRING: {
+          String s = fs._getStringValueNc(feat);
+          if (s == null /*&& isOmitDefaultValues*/) continue; 
+          jg.writeFieldName(shortName);
+          jg.writeString(s);
           break; 
-            
-        // all other fields (arrays, lists, fsRefs) can be null and are omitted if so  
-        default: 
-          if (featValRaw != CASImpl.NULL /*|| !isOmitDefaultValues*/) {
-            
-            jg.writeFieldName(getShortFeatureName(featCode));
-
-            if (featureClass == LowLevelCAS.TYPE_CLASS_INTARRAY ||
-                featureClass == LowLevelCAS.TYPE_CLASS_FLOATARRAY ||
-                featureClass == LowLevelCAS.TYPE_CLASS_BOOLEANARRAY ||
-                featureClass == LowLevelCAS.TYPE_CLASS_BYTEARRAY ||
-                featureClass == LowLevelCAS.TYPE_CLASS_SHORTARRAY ||
-                featureClass == LowLevelCAS.TYPE_CLASS_LONGARRAY ||
-                featureClass == LowLevelCAS.TYPE_CLASS_DOUBLEARRAY ||
-                featureClass == LowLevelCAS.TYPE_CLASS_STRINGARRAY ||
-                featureClass == LowLevelCAS.TYPE_CLASS_FSARRAY) {
-              
-              if (isDynamicOrStaticMultiRef(featCode, featValRaw)) {
-                jg.writeNumber(cds.getXmiIdAsInt(featValRaw));
-              } else {
-                writeJsonArrayValues(featValRaw, featureClass);
-              }
-              
-            } else if (featureClass == CasSerializerSupport.TYPE_CLASS_INTLIST ||
-                       featureClass == CasSerializerSupport.TYPE_CLASS_FLOATLIST ||
-                       featureClass == CasSerializerSupport.TYPE_CLASS_STRINGLIST ||
-                       featureClass == CasSerializerSupport.TYPE_CLASS_FSLIST) {
-
-              if (isDynamicOrStaticMultiRef(featCode, featValRaw, isListAsFSs)) {
-                jg.writeNumber(cds.getXmiIdAsInt(featValRaw));
-              } else {
-                writeJsonListValues(featValRaw);
-              }              
-            } else {  // is error
-              throw new RuntimeException("Invalid State, featureClass was "+ featureClass);
-            }
-          }  // end of default case with non-null values
+        }
+        
+        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_STRINGARRAY:
+        case LowLevelCAS.TYPE_CLASS_FSARRAY: 
+          writeArray(fs, feat, featureClass);
+          break;
+          
+        case CasSerializerSupport.TYPE_CLASS_INTLIST:
+        case CasSerializerSupport.TYPE_CLASS_FLOATLIST:
+        case CasSerializerSupport.TYPE_CLASS_STRINGLIST:
+        case CasSerializerSupport.TYPE_CLASS_FSLIST:
+          writeList(fs, feat, featureClass, isListAsFSs);
+          break;        
+        default: Misc.internalError(); 
         }  // end of switch
       } // end of loop over all features
     }
     
+    private void writeNumeric(FeatureImpl fi, long v) throws IOException {
+      if (v == 0 && isOmitDefaultValues) return;
+      jg.writeFieldName(fi.getShortName());
+      jg.writeNumber(v);
+    }
+    
+    private void writeArray(TOP fs, FeatureImpl fi, int featureClass) throws IOException {
+      assert(fs != null);      
+      TOP array = fs._getFeatureValueNc(fi);
+      if (array == null) return;
+      
+      jg.writeFieldName(fi.getShortName());
+      if (isDynamicOrStaticMultiRef(fi, array)) {
+        jg.writeNumber(cds.getXmiIdAsInt(array));
+      } else {
+        writeJsonArrayValues(array, featureClass);
+      }
+    }
+    
+    private void writeList(TOP fs, FeatureImpl fi, int featureClass, boolean isListAsFSs) throws IOException {
+      assert(fs != null); 
+      TOP list = fs._getFeatureValueNc(fi);
+      if (list == null) return;
+      
+      jg.writeFieldName(fi.getShortName());
+      if (isDynamicOrStaticMultiRef(fi, list, isListAsFSs)) {
+        jg.writeNumber(cds.getXmiIdAsInt(list));
+      } else {
+        writeJsonListValues(list);
+      }
+    }
+    
     /**
      * for arrays and lists,
      * recursively write one FS, 
@@ -1073,20 +1086,20 @@ public class JsonCasSerializer {
      * @param addr
      * @throws IOException
      */
-    private void writeFsOrRef(int addr) throws IOException {
-      if (addr == 0 || null == cds.multiRefFSs || cds.multiRefFSs.contains(addr)) {
-        jg.writeNumber(cds.getXmiIdAsInt(addr));
+    private void writeFsOrRef(TOP fs) throws IOException {
+      if (fs == null || null == cds.multiRefFSs || cds.multiRefFSs.contains(fs)) {
+        jg.writeNumber(cds.getXmiIdAsInt(fs));
       } else {
         isEmbeddedFromFsFeature = false;
-        writeEmbeddedFs(addr);
+        writeEmbeddedFs(fs);
       }
     }
         
-    private void writeEmbeddedFs(int addr) throws IOException {
+    private void writeEmbeddedFs(TOP fs) throws IOException {
       boolean savedEmbedded = isEmbedded;
       try {
         isEmbedded = true;
-        cds.encodeFS(addr);
+        cds.encodeFS(fs);
       } catch (Exception e) {
         if (e instanceof IOException) {
           throw (IOException) e;
@@ -1097,19 +1110,19 @@ public class JsonCasSerializer {
       }  // embed 
     }
     
-    private void writeFsOrRef(int addr, int featCode) throws IOException {
-      if (addr == 0 || null == cds.multiRefFSs || cds.multiRefFSs.contains(addr)) {
-        jg.writeFieldName(getShortFeatureName(featCode));
-        jg.writeNumber(cds.getXmiIdAsInt(addr));
+    private void writeFsOrRef(TOP fs, FeatureImpl fi) throws IOException {
+      if (fs == null || null == cds.multiRefFSs || cds.multiRefFSs.contains(fs)) {
+        jg.writeFieldName(fi.getShortName());
+        jg.writeNumber(cds.getXmiIdAsInt(fs));
       } else {
         jch.writeNlJustBeforeNext();
-        jg.writeFieldName(getShortFeatureName(featCode));
+        jg.writeFieldName(fi.getShortName());
         isEmbeddedFromFsFeature = true;
         //  Use cases:  can write embed, which has embed, which has non-embed
         //     once hit non-embed, this flag would be turned off,
         //     But it's only tested at the beginning of writeEmbeddedFs, so subsequent fields reset this
         //     This flag only used to control new lines for embedded case
-        writeEmbeddedFs(addr);
+        writeEmbeddedFs(fs);
         isEmbeddedFromFsFeature = false; // restore default
       }
     }
@@ -1118,12 +1131,12 @@ public class JsonCasSerializer {
      * Write FSArrays
      */
     @Override
-    protected void writeArrays(int addr, int typeCode, int typeClass) throws IOException {
+    protected void writeArrays(TOP fs, int typeCode, int typeClass) throws IOException {
 //      maybeWriteIdFeat(addr);
-      maybeWriteTypeFeat(typeCode);
+      maybeWriteTypeFeat(fs._getTypeImpl());
 
       jg.writeFieldName(COLLECTION_NAME);            
-      writeJsonArrayValues(addr, typeClass);
+      writeJsonArrayValues(fs, typeClass);
     }
     
     @Override
@@ -1135,92 +1148,125 @@ public class JsonCasSerializer {
     // or null if the reference to the UIMA array is actually null
     // 0 length arrays are written as []
     //   Note: FSs can be embedded for FS Arrays
-    private void writeJsonArrayValues(int addr, int arrayType) throws IOException {
-      if (addr == CASImpl.NULL) {
+    private void writeJsonArrayValues(TOP array, int arrayType) throws IOException {
+      if (array == null) {
         jg.writeNull();
         return;
       }
       
-      cds.visited_not_yet_written.remove(addr);
-      final int array_size = cds.cas.ll_getArraySize(addr);
+      cds.visited_not_yet_written.remove(array);
+      CommonArray ca = (CommonArray) array;
+      final int array_size = ca.size();
 
       if (arrayType == LowLevelCAS.TYPE_CLASS_BYTEARRAY) {
         // special case for byte arrays: 
         // serialize using standard JACKSON/JSON binary serialization
         // (doing extra copy to avoid figuring out the impl details)
-        ByteArrayFS byteArrayFS = new ByteArrayFSImpl(addr, cds.cas);
-        int length = byteArrayFS.size();
-        byte[] byteArray = new byte[length];
-        byteArrayFS.copyToArray(0, byteArray, 0, length);
-      
-        jg.writeBinary(byteArray);
+        ByteArray ba = (ByteArray) array;      
+        jg.writeBinary(ba._getTheArray());
         
       } else {
         jg.writeStartArray();
-        int pos = cds.cas.getArrayStartAddress(addr);
+//        int pos = cds.cas.getArrayStartAddress(addr);
         
-        if (arrayType == LowLevelCAS.TYPE_CLASS_FSARRAY) {
+        switch(arrayType) {
+        case LowLevelCAS.TYPE_CLASS_BOOLEANARRAY: {
+          boolean[] a = ((BooleanArray)array)._getTheArray();
+          writeArrayElements(array_size, i -> jg.writeBoolean(a[i]));
+          break;
+        }
+        case LowLevelCAS.TYPE_CLASS_BYTEARRAY: {
+          ByteArray ba = (ByteArray) array;      
+          jg.writeBinary(ba._getTheArray());
+          break;
+        }
+        case LowLevelCAS.TYPE_CLASS_SHORTARRAY: {
+          short[] a = ((ShortArray)array)._getTheArray();
+          writeArrayElements(array_size, i -> jg.writeNumber(a[i]));
+          break;
+        }
+        case LowLevelCAS.TYPE_CLASS_INTARRAY: {
+          int[] a = ((IntegerArray)array)._getTheArray();
+          writeArrayElements(array_size, i -> jg.writeNumber(a[i]));
+          break;
+        }
+        case LowLevelCAS.TYPE_CLASS_LONGARRAY: {
+          long[] a = ((LongArray)array)._getTheArray();
+          writeArrayElements(array_size, i -> jg.writeNumber(a[i]));
+          break;          
+        }
+        case LowLevelCAS.TYPE_CLASS_FLOATARRAY: {
+          float[] a = ((FloatArray)array)._getTheArray();
+          writeArrayElements(array_size, i -> jg.writeNumber(a[i]));
+          break;          
+        }
+        case LowLevelCAS.TYPE_CLASS_DOUBLEARRAY: {
+          double[] a = ((DoubleArray)array)._getTheArray();
+          writeArrayElements(array_size, i -> jg.writeNumber(a[i]));
+          break;          
+        }
+        case LowLevelCAS.TYPE_CLASS_STRINGARRAY: {
+          String[] a = ((StringArray)array)._getTheArray();
+          writeArrayElements(array_size, i -> jg.writeString(a[i]));
+          break;          
+        }
+        case LowLevelCAS.TYPE_CLASS_FSARRAY: writeFSArray(array, array_size); break;
+        default: Misc.internalError();
+        } // end of switch
         
-          List<XmiArrayElement> ootsArrayElementsList = cds.sharedData == null ? null : 
-            cds.sharedData.getOutOfTypeSystemArrayElements(addr);
-          int ootsIndex = 0;
-  
-          for (int j = 0; j < array_size; j++) {  // j used to id the oots things
-            int heapValue = cds.cas.getHeapValue(pos++);
-  
-            if (heapValue == CASImpl.NULL) {
-              // this null array element might have been a reference to an 
-              // out-of-typesystem FS, which, when deserialized, was replaced with NULL,
-              // so check the ootsArrayElementsList
-              boolean found = false;
-              if (ootsArrayElementsList != null) {
-                
-                while (ootsIndex < ootsArrayElementsList.size()) {
-                  XmiArrayElement arel = ootsArrayElementsList.get(ootsIndex++);
-                  if (arel.index == j) {
-                    jg.writeNumber(Integer.parseInt(arel.xmiId));
-                    found = true;
-                    break;
-                  }                
-                }
-              }
-              if (!found) {
-                jg.writeNumber(0);
-              }
-              
-            // else, not null FS ref  
-            } else {
-              if (cds.isFiltering) { // return as null any references to types not in target TS
-                String typeName = cds.tsi.ll_getTypeForCode(cds.cas.getHeapValue(addr)).getName();
-                if (cds.filterTypeSystem.getType(typeName) == null) {
-                  heapValue = CASImpl.NULL;
-                }
-              }
-              writeFsOrRef(heapValue);  // allow embedding in array
+        jg.writeEndArray();
+      }
+    }
+    
+    private void writeArrayElements(final int size, IntConsumer_withIOException ic) throws IOException {
+      for (int i = 0; i < size; i++) {
+        ic.accept(i);
+      }
+    }
+    
+    private void writeFSArray(TOP array, int array_size) throws NumberFormatException, IOException {
+      FSArray fsArray = (FSArray) array;
+      
+      List<XmiArrayElement> ootsArrayElementsList = cds.sharedData == null 
+                                                      ? null 
+                                                      : cds.sharedData.getOutOfTypeSystemArrayElements(fsArray);
+      int ootsIndex = 0;
+      TOP[] fsItems = fsArray._getTheArray();
+      
+      for (int j = 0; j < array_size; j++) {  // j used to id the oots things
+        TOP fsItem = fsItems[j];  // int heapValue = cds.cas.getHeapValue(pos++);
+
+        if (fsItem == null) {
+          // this null array element might have been a reference to an 
+          // out-of-typesystem FS, which, when deserialized, was replaced with NULL,
+          // so check the ootsArrayElementsList
+          boolean found = false;
+          if (ootsArrayElementsList != null) {
+            
+            while (ootsIndex < ootsArrayElementsList.size()) {
+              XmiArrayElement arel = ootsArrayElementsList.get(ootsIndex++);
+              if (arel.index == j) {
+                jg.writeNumber(Integer.parseInt(arel.xmiId));
+                found = true;
+                break;
+              }                
             }
-          } // end of loop over all refs in FS array
+          }
+          if (!found) {
+            jg.writeNumber(0);
+          }
           
+        // else, not null FS ref  
         } else {
-          for (int i = 0; i < array_size; i++) {
-            if (arrayType == LowLevelCAS.TYPE_CLASS_BOOLEANARRAY) {
-              jg.writeBoolean(cds.cas.ll_getBooleanArrayValue(addr, i));
-            } else if (arrayType == LowLevelCAS.TYPE_CLASS_STRINGARRAY) {
-              jg.writeString(cds.cas.ll_getStringArrayValue(addr, i));
-            } else if (arrayType == LowLevelCAS.TYPE_CLASS_SHORTARRAY) {
-              jg.writeNumber(cds.cas.ll_getShortArrayValue(addr, i));
-            } else if (arrayType == LowLevelCAS.TYPE_CLASS_INTARRAY) {
-              jg.writeNumber(cds.cas.ll_getIntArrayValue(addr, i));
-            } else if (arrayType == LowLevelCAS.TYPE_CLASS_LONGARRAY) {
-              jg.writeNumber(cds.cas.ll_getLongArrayValue(addr, i));
-            } else if (arrayType == LowLevelCAS.TYPE_CLASS_FLOATARRAY) {
-              jg.writeNumber(cds.cas.ll_getFloatArrayValue(addr, i));
-            } else {
-              jg.writeNumber(cds.cas.ll_getDoubleArrayValue(addr, i));
+          if (cds.isFiltering) { // return as null any references to types not in target TS
+            String typeName = fsItem._getTypeImpl().getName();
+            if (cds.filterTypeSystem.getType(typeName) == null) {
+              fsItem = null;
             }
           }
+          writeFsOrRef(fsItem);  // allow embedding in array
         }
-        jg.writeEndArray();
-      }
+      } // end of loop over all refs in FS array
     }
     
     // a null ref is written as null
@@ -1232,47 +1278,48 @@ public class JsonCasSerializer {
      * @param curNode the address of the start of the list
      * @throws IOException
      */
-    private void writeJsonListValues(int curNode) throws IOException {
-      if (curNode == CASImpl.NULL) {
-        throw new RuntimeException("never happen");
-      }
-      final ListUtils listUtils = cds.listUtils;
-      final int startNodeType = cds.cas.getHeapValue(curNode);
-
-      int headFeat = listUtils.getHeadFeatCode(startNodeType);
-      int tailFeat = listUtils.getTailFeatCode(startNodeType);
-      int neListType = listUtils.getNeListType(startNodeType);  // non-empty
+    private void writeJsonListValues(TOP curNode) throws IOException {
+      if (curNode == null) {
+        Misc.internalError();
+      }
+
       final PositiveIntSet visited = new PositiveIntSet_impl();
      
       jg.writeStartArray();
-      while (curNode != CASImpl.NULL) { 
+      FeatureStructure nextNode = null;
+      while (curNode != null) { 
 
         cds.visited_not_yet_written.remove(curNode);
-        final int curNodeType = cds.cas.getHeapValue(curNode);
-        if (curNodeType != neListType) { // if not "non-empty"
+        if (curNode instanceof EmptyList) { 
           break;  // would be the end element.  a 0 is also treated as an end element
         }
         
-        if (!visited.add(curNode)) {
+        if (!visited.add(curNode.id())) {
           break;  // loop detected, stop. no error report here, would be reported earlier during enqueue
         }
         
-        final int val = cds.cas.getHeapValue(curNode + cds.cas.getFeatureOffset(headFeat));
+//        final int val = cds.cas.getHeapValue(curNode + cds.cas.getAdjustedFeatureOffset(headFeat));
 
-        if (curNodeType == listUtils.neStringListType) {
-          jg.writeString(cds.cas.getStringForCode(val));
-        } else if (curNodeType == listUtils.neFloatListType) {
-          jg.writeNumber(CASImpl.int2float(val));
-        } else if (curNodeType == listUtils.neFsListType) {
-          writeFsOrRef(val);  // maybe embed
+        if (curNode instanceof NonEmptyStringList) {
+          NonEmptyStringList l = (NonEmptyStringList)curNode;
+          jg.writeString(l.getHead());
+          nextNode = l.getCommonTail();
+        } else if (curNode instanceof NonEmptyFloatList) {
+          NonEmptyFloatList l = (NonEmptyFloatList)curNode;
+          jg.writeNumber(l.getHead());
+          nextNode = l.getCommonTail();
+        } else if (curNode instanceof NonEmptyFSList) {
+          NonEmptyFSList l = (NonEmptyFSList)curNode;
+          writeFsOrRef(l);  // maybe embed
+          nextNode = l.getCommonTail();
         } else {  // for ints 
-          jg.writeNumber(val);
+          NonEmptyIntegerList l = (NonEmptyIntegerList)curNode;
+          jg.writeNumber(l.getHead());
+          nextNode = l.getCommonTail();
         }
-
-        curNode = cds.cas.getHeapValue(curNode + cds.cas.getFeatureOffset(tailFeat));
+        curNode = (TOP) nextNode;
       }
       jg.writeEndArray();
-    
     }
     
     /**
@@ -1284,7 +1331,7 @@ public class JsonCasSerializer {
      * @return _ref, _array, _byte_array, or null
      */
    
-    private SerializedString featureTypeLabel(int fsClass, int featCode) {
+    private SerializedString featureTypeLabel(int fsClass) {
       switch (fsClass) {
         case LowLevelCAS.TYPE_CLASS_FS: 
         case LowLevelCAS.TYPE_CLASS_FSARRAY: 
@@ -1358,16 +1405,16 @@ public class JsonCasSerializer {
       }
     }
     
-    private boolean isDynamicOrStaticMultiRef(int featCode, int addr) {
+    private boolean isDynamicOrStaticMultiRef(FeatureImpl fi, TOP fs) {
       return (cds.multiRefFSs == null) ? 
-                cds.isStaticMultiRef(featCode) : 
-                cds.multiRefFSs.contains(addr);
+                cds.isStaticMultiRef(fi) : 
+                cds.multiRefFSs.contains(fs);
     }
     
-    private boolean isDynamicOrStaticMultiRef(int featCode, int addr, boolean isListAsFSs) {
+    private boolean isDynamicOrStaticMultiRef(FeatureImpl fi, TOP fs, boolean isListAsFSs) {
       return (cds.multiRefFSs == null) ? 
-                (isListAsFSs || cds.isStaticMultiRef(featCode)) : 
-                cds.multiRefFSs.contains(addr);
+                (isListAsFSs || cds.isStaticMultiRef(fi)) : 
+                cds.multiRefFSs.contains(fs);
     }
 
   }