private void enqueueFeatures()

in uimaj-core/src/main/java/org/apache/uima/cas/impl/CasSerializerSupport.java [992:1123]


    private void enqueueFeatures(TOP fs) throws SAXException {

      /**
       * Handle FSArrays
       */
      if (fs instanceof FSArray) {
        TOP[] theArray = ((FSArray) fs)._getTheArray();

        for (TOP elem : theArray) {
          if (isFiltering
                  && (null == filterTypeSystem_inner.getType(elem._getTypeImpl().getName()))) {
            continue; // skip because not in filter type system
          }
          if (elem != null) {
            enqueueFsAndMaybeFeatures(elem);
          }
        }
        return;
      }

      boolean insideListNode = fs instanceof CommonList;

      if (fs instanceof UimaSerializable) {
        ((UimaSerializable) fs)._save_to_cas_data();
      }

      for (FeatureImpl fi : fs._getTypeImpl().getFeatureImpls()) {
        if (isFiltering && filterTypeSystem_inner.getFeatureByFullName(fi.getName()) == null) {
          // skip features that aren't in the target type system
          continue;
        }
        // final int featAddr = addr + cas.getFeatureOffset(feat);
        // final int featVal = cas.getHeapValue(featAddr);
        // if (featVal == CASImpl.NULL) { // null feature values do not refer to any other FS
        // continue;
        // }

        // enqueue behavior depends on range type of feature
        final int fsClass = fi.rangeTypeClass;
        switch (fsClass) {
          case LowLevelCAS.TYPE_CLASS_FS: {
            enqueueFsAndMaybeFeatures(fs.getFeatureValue(fi));
            break;
          }
          case LowLevelCAS.TYPE_CLASS_INTARRAY:
          case LowLevelCAS.TYPE_CLASS_FLOATARRAY:
          case LowLevelCAS.TYPE_CLASS_STRINGARRAY:
          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: {
            TOP array = fs.getFeatureValue(fi); // can be null
            if (null == array) {
              continue;
            }
            // we enqueue arrays if:
            // when statically using multipleReferencesAllowed flag:
            // when that says it's multiply referenced;
            // otherwise, we skip enqueueing it because it will
            // be picked up when serializing the feature
            // when dynamically computing multiple-refs: we enqueue it
            // unless already enqueued, in order to pick up any multiple refs
            final boolean alreadyVisited = visited_not_yet_written.contains(array);
            if (isMultiRef_enqueue(fi, array, alreadyVisited, false, false)) {
              if (enqueued_multiRef_arrays_or_lists.add(array)) { // only do this once per item
                enqueueFsAndMaybeFeatures(array); // will add to queue list 1st time multi-ref
                                                  // detected
                // or JSON isDynamicEmbedding is on (whether or not multi-ref)
              } else {
                // for isDynamicMultiRef, this is the first time we detect multiple refs
                // do this here, because the enqueued_multiRef_arrays_or_lists.add above makes
                // the 2nd and subsequent multi-ref things bypass the enqueue call.
                // - only needed for isDynamicMultiRef, because only that returns true for
                // isMultiRef_enqueue
                // for the "first" instance, when it isn't yet known.
                if (isDynamicMultiRef) {
                  multiRefFSs.add(array);
                }
              }
              // otherwise, it is singly referenced (so far) and will be embedded
              // (or has already been enqueued, in dynamic embedding mode), so don't enqueue
            } else if (array instanceof FSArray && !alreadyVisited) {
              // enqueue any FSs reachable from an FSArray
              enqueueFSArrayElements((FSArray) array);
            }
            break;
          }
          case TYPE_CLASS_INTLIST:
          case TYPE_CLASS_FLOATLIST:
          case TYPE_CLASS_STRINGLIST:
          case TYPE_CLASS_FSLIST: {
            // we enqueue lists if:
            // when statically using multipleReferencesAllowed flag:
            // when that says it's multiply referenced or
            // we're inside a list which was earlier multiply referenced
            // otherwise, we skip enqueueing it because it will
            // be picked up when serializing the feature
            // when dynamically computing multiple-refs: we enqueue it
            // unless already enqueued, in order to pick up any multiple refs
            TOP startOfList_node = fs.getFeatureValue(fi);
            if (null == startOfList_node) {
              // the feature, whose type is one of the lists, has a null value, so there's nothing
              // to enqueue
              continue;
            }
            final boolean alreadyVisited = visited_not_yet_written.contains(startOfList_node);
            if (isMultiRef_enqueue(fi, startOfList_node, alreadyVisited, insideListNode, true)) {
              if (enqueued_multiRef_arrays_or_lists.add(startOfList_node)) { // only do this once
                                                                             // per item
                enqueueFsAndMaybeFeatures(startOfList_node);
              } else {
                // for isDynamicMultiRef, this is the first time we detect multiple refs
                // do this here, because the enqueued_multiRef_arrays_or_lists.add above makes
                // the 2nd and subsequent multi-ref things bypass the enqueue call.
                // - only needed for isDynamicMultiRef, because only that returns true for
                // isMultiRef_enqueue
                // for the "first" instance, when it isn't yet known.
                if (isDynamicMultiRef) {
                  multiRefFSs.add(startOfList_node);
                }
              }
            } else if (startOfList_node instanceof FSList && !alreadyVisited) {
              // also, we need to enqueue any FSs reachable from an FSList
              enqueueFSListElements((FSList<?>) startOfList_node);
            }
            break;
          }
        }
      } // end of loop over all features
    }