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
}