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 2015/11/09 20:46:46 UTC
svn commit: r1713525 - in
/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl:
XCASDeserializer.java XCASSerializer.java
Author: schor
Date: Mon Nov 9 19:46:45 2015
New Revision: 1713525
URL: http://svn.apache.org/viewvc?rev=1713525&view=rev
Log:
[UIMA-4663] fix XCAS de/serialization for Java object formats
Modified:
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XCASDeserializer.java
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XCASSerializer.java
Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XCASDeserializer.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XCASDeserializer.java?rev=1713525&r1=1713524&r2=1713525&view=diff
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XCASDeserializer.java (original)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XCASDeserializer.java Mon Nov 9 19:46:45 2015
@@ -27,13 +27,17 @@ import java.util.Map;
import org.apache.uima.UimaContext;
import org.apache.uima.cas.CAS;
+import org.apache.uima.cas.CASRuntimeException;
import org.apache.uima.cas.FSIndexRepository;
-import org.apache.uima.cas.SofaFS;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.internal.util.IntVector;
import org.apache.uima.internal.util.StringUtils;
import org.apache.uima.internal.util.rb_trees.RedBlackTree;
+import org.apache.uima.jcas.cas.CommonPrimitiveArray;
+import org.apache.uima.jcas.cas.FSArray;
+import org.apache.uima.jcas.cas.Sofa;
+import org.apache.uima.jcas.cas.TOP;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
@@ -49,20 +53,26 @@ import org.xml.sax.helpers.XMLReaderFact
*/
public class XCASDeserializer {
+ /**
+ * Feature Structure plus all the indexes it is indexed in
+ * indexRep -> indexMap -> indexRepositories -> indexRepository or
+ * indexRep -> indexRepositories -> indexRepository
+ *
+ * (2nd if indexMap size == 1)
+ */
private static class FSInfo {
- final private int addr;
+ final private TOP fs;
final private IntVector indexRep;
- private FSInfo(int addr, IntVector indexRep) {
- super();
- this.addr = addr;
+ private FSInfo(TOP fs, IntVector indexRep) {
+ this.fs = fs;
this.indexRep = indexRep;
}
}
-
+
private class XCASDeserializerHandler extends DefaultHandler {
// ///////////////////////////////////////////////////////////////////////
@@ -112,6 +122,9 @@ public class XCASDeserializer {
// of XML input.
private static final String unknownXMLSource = "<unknown>";
+ // SofaFS type
+ static final private int sofaTypeCode = TypeSystemImpl.sofaTypeCode;
+
// private long time;
// SAX locator. Used for error message generation.
@@ -121,20 +134,25 @@ public class XCASDeserializer {
final private CASImpl cas;
// Store FSs with ID in a search tree (for later reference resolution).
+ /**
+ * Map from extId to FSInfo (including fs)
+ */
final private RedBlackTree<FSInfo> fsTree;
// Store IDless FSs in a vector;
final private List<FSInfo> idLess;
+ final private List<Runnable> fixupToDos = new ArrayList<>();
+
// What we expect next.
private int state;
// StringBuffer to accumulate text.
private StringBuffer buffer;
- // The address of the most recently created FS. Needed for array elements
+ // The most recently created FS. Needed for array elements
// and embedded feature values.
- private int currentAddr;
+ private TOP currentFs;
// The name of the content feature, if we've seen one.
private String currentContentFeat = DEFAULT_CONTENT_FEATURE;
@@ -148,23 +166,25 @@ public class XCASDeserializer {
// Current out of type system FS
private FSData currentOotsFs;
- // SofaFS type
- final private int sofaTypeCode;
// AnnotationBase type
final private Type annotBaseType;
- // Store IndexRepositories in a vector;
+ /** map from index -> indexRepository, [0] = base view, [1] initial view, [2 +] other views */
final private List<FSIndexRepository> indexRepositories;
- // and Views too
+ /** map for index -> cas views, */
final private List<CAS> views;
// for processing v1.x format XCAS
- // map from sofa int values to id references
+ // map from sofaNum int values to external id references
final private IntVector sofaRefMap;
// map incoming _indexed values
+ /**
+ * Map external SofaNum -> internal sofaNum
+ * internal sofaNums also used to index indexRepositories -> ref to FsIndexRepositoryImpl
+ */
final private IntVector indexMap;
// working with initial view
@@ -185,8 +205,6 @@ public class XCASDeserializer {
indexRepositories.add(this.cas.getBaseIndexRepository());
// There should always be another index for the Initial View
indexRepositories.add(this.cas.getView(CAS.NAME_DEFAULT_SOFA).getIndexRepository());
- this.sofaTypeCode = cas.ll_getTypeSystem().ll_getCodeForType(
- cas.getTypeSystem().getType(CAS.TYPE_NAME_SOFA));
this.annotBaseType = this.cas.getAnnotationType();
this.sofaRefMap = new IntVector();
this.indexMap = new IntVector();
@@ -275,14 +293,13 @@ public class XCASDeserializer {
// Create a new FS.
private void readFS(String qualifiedName, Attributes attrs) throws SAXParseException {
+ if (qualifiedName.equals("uima.cas.SofA")) {
+ qualifiedName = "uima.cas.Sofa"; // fix for XCAS written with pre-public version of Sofas
+ }
+
String typeName = getCasTypeName(qualifiedName);
TypeImpl type = (TypeImpl) ts.getType(typeName);
- if (type == null) {
- if (typeName.equals("uima.cas.SofA")) {
- // temporary fix for XCAS written with pre-public version of Sofas
- type = (TypeImpl) ts.getType("uima.cas.Sofa");
- }
- }
+
if (type == null) {
if (this.outOfTypeSystemData == null) {
throw createException(XCASParsingException.UNKNOWN_TYPE, typeName);
@@ -292,12 +309,11 @@ public class XCASDeserializer {
addToOutOfTypeSystemData(typeName, attrs);
}
} else {
- if (cas.isArrayType(type.getCode())) {
+ if (type.isArray()) {
readArray(type, attrs);
return;
}
- final int addr = cas.ll_createFS(type.getCode());
- readFS(addr, attrs, true);
+ readFS(type, attrs, true);
}
}
@@ -309,39 +325,30 @@ public class XCASDeserializer {
* Special hack to accommodate document annotation, which is already in the index.
* @throws SAXParseException passthru
*/
- private void readFS(final int addr, Attributes attrs, boolean toIndex) throws SAXParseException {
- // Hang on address for setting content feature
- this.currentAddr = addr;
- int id = -1;
- IntVector indexRep = new IntVector(1); // empty means not indexed
- String attrName, attrValue;
- final int heapValue = cas.getHeapValue(addr);
- final Type type = cas.ll_getTypeSystem().ll_getTypeForCode(cas.ll_getFSRefType(addr));
-
- // Special handling for Sofas
- if (sofaTypeCode == heapValue) {
- // create some maps to handle v1 format XCAS ...
- // ... where the sofa feature of annotations was an int not a ref
-
- // determine if this is the one and only initial view Sofa
- boolean isInitialView = false;
+ private void readFS(final TypeImpl type, Attributes attrs, boolean toIndex) throws SAXParseException {
+ final int typecode = type.getCode();
+ final TOP fs;
+
+ if (sofaTypeCode == typecode) {
+ // Special handling for Sofas
+
+ // get SofaID - the view name or the string _InitialView
String sofaID = attrs.getValue(CAS.FEATURE_BASE_NAME_SOFAID);
if (sofaID.equals("_DefaultTextSofaName")) {
sofaID = CAS.NAME_DEFAULT_SOFA;
}
-// if (uimaContext != null) {
-// // Map incoming SofaIDs
-// sofaID = uimaContext.mapToSofaID(sofaID).getSofaID();
-// }
- if (sofaID.equals(CAS.NAME_DEFAULT_SOFA)) {
- isInitialView = true;
- }
- // get the sofaNum
+ final boolean isInitialView = sofaID.equals(CAS.NAME_DEFAULT_SOFA);
+
+ // get sofaNum
String sofaNum = attrs.getValue(CAS.FEATURE_BASE_NAME_SOFANUM);
- int thisSofaNum = Integer.parseInt(sofaNum);
-
+ final int extSofaNum = Integer.parseInt(sofaNum);
+
// get the sofa's FeatureStructure id
- int sofaFsId = Integer.parseInt(attrs.getValue(XCASSerializer.ID_ATTR_NAME));
+ final int sofaExtId = Integer.parseInt(attrs.getValue(XCASSerializer.ID_ATTR_NAME));
+
+
+ // create some maps to handle v1 format XCAS ...
+ // ... where the sofa feature of annotations was an int not a ref
// for v1 and v2 formats, create the index map
// ***we assume Sofas are always received in Sofanum order***
@@ -351,7 +358,7 @@ public class XCASDeserializer {
if (this.indexMap.size() == 1) {
if (isInitialView) {
// the first Sofa an initial view
- if (thisSofaNum == 2) {
+ if (extSofaNum == 2) {
// this sofa was mapped to the initial view
this.indexMap.add(-1); // for this CAS, there should not be a sofanum = 1
this.indexMap.add(1); // map 2 to 1
@@ -361,11 +368,11 @@ public class XCASDeserializer {
this.nextIndex = 2;
}
} else {
- if (thisSofaNum > 1) {
+ if (extSofaNum > 1) {
// the first Sofa not initial, but sofaNum > 1
// must be a v2 format, and sofaNum better be 2
this.indexMap.add(1);
- assert (thisSofaNum == 2);
+ assert (extSofaNum == 2);
this.indexMap.add(2);
this.nextIndex = 3;
} else {
@@ -375,11 +382,12 @@ public class XCASDeserializer {
}
}
} else {
+ // this is the case for the 2nd and subsequent Sofas
// if the new Sofa is the initial view, always map to 1
if (isInitialView) {
// the initial view is not the first
// if v2 format, space already reserved in mapping
- if (this.indexMap.size() == thisSofaNum) {
+ if (this.indexMap.size() == extSofaNum) {
// v1 format, add mapping for initial view
this.indexMap.add(1);
}
@@ -387,30 +395,74 @@ public class XCASDeserializer {
this.indexMap.add(this.nextIndex);
this.nextIndex++;
}
+
}
// Now update the mapping from annotation int to ref values
- if (this.sofaRefMap.size() == thisSofaNum) {
+ if (this.sofaRefMap.size() == extSofaNum) {
// Sofa received in sofaNum order, add new one
- this.sofaRefMap.add(sofaFsId);
- } else if (this.sofaRefMap.size() > thisSofaNum) {
+ this.sofaRefMap.add(sofaExtId);
+ } else if (this.sofaRefMap.size() > extSofaNum) {
// new Sofa has lower sofaNum than last one
- this.sofaRefMap.set(thisSofaNum, sofaFsId);
+ this.sofaRefMap.set(extSofaNum, sofaExtId);
} else {
// new Sofa has skipped ahead more than 1
- this.sofaRefMap.setSize(thisSofaNum + 1);
- this.sofaRefMap.set(thisSofaNum, sofaFsId);
+ this.sofaRefMap.setSize(extSofaNum + 1);
+ this.sofaRefMap.set(extSofaNum, sofaExtId);
}
- }
+ // get the sofa's mimeType
+ String sofaMimeType = attrs.getValue(CAS.FEATURE_BASE_NAME_SOFAMIME);
+ fs = cas.createSofa(this.indexMap.get(extSofaNum), sofaID, sofaMimeType);
+ } else {
+ if (type.isAnnotationBaseType()) {
+
+ // take pains to create FS in the right view.
+ // the XCAS external form sometimes uses "sofa" and sometimes uses "_ref_sofa"
+ // - these have different semantics:
+ // -- sofa = value is the sofaNum
+ // -- _ref_sofa = value is the external ID of the associated sofa feature structure
+ String extSofaNum = attrs.getValue(CAS.FEATURE_BASE_NAME_SOFA);
+ CAS casView;
+ if (extSofaNum != null) {
+ casView = cas.getView( (this.indexMap.size() == 1)
+ ? 1 // case of no Sofa, but view ref = 1 = _InitialView
+ : this.indexMap.get(Integer.parseInt(extSofaNum)));
+ } else {
+ String extSofaRefString = attrs.getValue(XCASSerializer.REF_PREFIX + CAS.FEATURE_BASE_NAME_SOFA);
+ if (null == extSofaRefString || extSofaRefString.length() == 0) {
+ throw createException(XCASParsingException.SOFA_REF_MISSING);
+ }
+ casView = cas.getView((Sofa) (fsTree.get(Integer.parseInt(extSofaRefString)).fs));
+ }
+ fs = (ts.docType.subsumes(type))
+ ? casView.getDocumentAnnotation()
+ : casView.createFS(type);
+ } else {
+ fs = cas.createFS(type);
+ }
+ }
+
+ // Hang on address for setting content feature
+ this.currentFs = fs;
+ int extId = -1;
+ IntVector indexRep = new IntVector(1); // empty means not indexed
+
+
+ /****************************************************************
+ * Loop for all feature specs *
+ * - handle features with _ reserved prefix, including _ref_ *
+ * - handle features without "_" prefix: *
+ * - if not Sofa *
+ ****************************************************************/
for (int i = 0; i < attrs.getLength(); i++) {
- attrName = attrs.getQName(i);
- attrValue = attrs.getValue(i);
+ final String attrName = attrs.getQName(i);
+ String attrValue = attrs.getValue(i);
if (attrName.startsWith(reservedAttrPrefix)) {
if (attrName.equals(XCASSerializer.ID_ATTR_NAME)) {
try {
- id = Integer.parseInt(attrValue);
+ extId = Integer.parseInt(attrValue);
} catch (NumberFormatException e) {
throw createException(XCASParsingException.ILLEGAL_ID, attrValue);
}
@@ -424,31 +476,29 @@ public class XCASDeserializer {
indexRep.add(Integer.parseInt(arrayvals[s]));
}
} else {
- handleFeature(type, addr, attrName, attrValue, false);
+ handleFeature(type, fs, attrName, attrValue, false);
}
} else {
- if (sofaTypeCode == heapValue) {
- if (attrName.equals(CAS.FEATURE_BASE_NAME_SOFAID)) {
- if (attrValue.equals("_DefaultTextSofaName")) {
- // First change old default Sofa name into the new one
+ if (sofaTypeCode == typecode) {
+ if (attrName.equals(CAS.FEATURE_BASE_NAME_SOFAID) && attrValue.equals("_DefaultTextSofaName")) {
+ // fixup old default Sofa name to new one
attrValue = CAS.NAME_DEFAULT_SOFA;
- }
-// if (uimaContext != null) {
-// // Map incoming SofaIDs
-// attrValue = uimaContext.mapToSofaID(attrValue).getSofaID();
-// }
}
}
- handleFeature(type, addr, attrName, attrValue, false);
+
+ if (!type.isAnnotationBaseType() || !attrName.equals(CAS.FEATURE_BASE_NAME_SOFA)) {
+ // skip the setting the sofa feature for Annotation base subtypes - this is set from the view
+ // otherwise handle the feature
+ handleFeature(type, fs, attrName, attrValue, false);
+ }
}
}
- if (sofaTypeCode == heapValue) {
- // If a Sofa, create CAS view to get new indexRepository
- SofaFS sofa = (SofaFS) cas.createFS(addr);
- // also add to indexes so we can retrieve the Sofa later
+ if (sofaTypeCode == typecode) {
+ Sofa sofa = (Sofa) fs;
cas.getBaseIndexRepository().addFS(sofa);
CAS view = cas.getView(sofa);
+ // internal sofaNum == 1 always means initial sofa
if (sofa.getSofaRef() == 1) {
cas.registerInitialSofa();
} else {
@@ -458,11 +508,11 @@ public class XCASDeserializer {
((CASImpl) view).registerView(sofa);
views.add(view);
}
- FSInfo fsInfo = new FSInfo(addr, indexRep);
- if (id < 0) {
+ FSInfo fsInfo = new FSInfo(fs, indexRep);
+ if (extId < 0) {
idLess.add(fsInfo);
} else {
- fsTree.put(id, fsInfo);
+ fsTree.put(extId, fsInfo);
}
// Set the state; we're either expecting features, or _content.
// APL - 6/28/04 - even if _content attr is not specified, we can still have content, which
@@ -510,36 +560,35 @@ public class XCASDeserializer {
throw createException(XCASParsingException.ILLEGAL_ARRAY_ATTR, attrName);
}
}
- FeatureStructureImpl fs;
+ TOP fs;
if (cas.isIntArrayType(type)) {
- fs = (FeatureStructureImpl) cas.createIntArrayFS(size);
+ fs = (TOP) cas.createIntArrayFS(size);
} else if (cas.isFloatArrayType(type)) {
- fs = (FeatureStructureImpl) cas.createFloatArrayFS(size);
+ fs = (TOP) cas.createFloatArrayFS(size);
} else if (cas.isStringArrayType(type)) {
- fs = (FeatureStructureImpl) cas.createStringArrayFS(size);
+ fs = (TOP) cas.createStringArrayFS(size);
} else if (cas.isBooleanArrayType(type)) {
- fs = (FeatureStructureImpl) cas.createBooleanArrayFS(size);
+ fs = (TOP) cas.createBooleanArrayFS(size);
} else if (cas.isByteArrayType(type)) {
- fs = (FeatureStructureImpl) cas.createByteArrayFS(size);
+ fs = (TOP) cas.createByteArrayFS(size);
} else if (cas.isShortArrayType(type)) {
- fs = (FeatureStructureImpl) cas.createShortArrayFS(size);
+ fs = (TOP) cas.createShortArrayFS(size);
} else if (cas.isLongArrayType(type)) {
- fs = (FeatureStructureImpl) cas.createLongArrayFS(size);
+ fs = (TOP) cas.createLongArrayFS(size);
} else if (cas.isDoubleArrayType(type)) {
- fs = (FeatureStructureImpl) cas.createDoubleArrayFS(size);
+ fs = (TOP) cas.createDoubleArrayFS(size);
} else {
- fs = (FeatureStructureImpl) cas.createArrayFS(size);
+ fs = (TOP) cas.createArrayFS(size);
}
- final int addr = fs.getAddress();
- FSInfo fsInfo = new FSInfo(addr, indexRep);
+ FSInfo fsInfo = new FSInfo(fs, indexRep);
if (id >= 0) {
fsTree.put(id, fsInfo);
} else {
idLess.add(fsInfo);
}
// Hang on to those for setting array values.
- this.currentAddr = addr;
+ this.currentFs = fs;
this.arrayPos = 0;
this.state = ARRAY_ELE_STATE;
@@ -552,65 +601,73 @@ public class XCASDeserializer {
}
// Create a feature value from a string representation.
- private void handleFeature(int addr, String featName, String featVal, boolean lenient)
+ private void handleFeature(TOP fs, String featName, String featVal, boolean lenient)
throws SAXParseException {
- int typeCode = cas.ll_getFSRefType(addr);
- Type type = cas.ll_getTypeSystem().ll_getTypeForCode(typeCode);
- handleFeature(type, addr, featName, featVal, lenient);
+ Type type = fs._typeImpl;
+ handleFeature(type, fs, featName, featVal, lenient);
}
- private void handleFeature(final Type type, int addr, String featName, String featVal,
+ private void handleFeature(final Type type, TOP fs, String featName, String featValIn,
boolean lenient) throws SAXParseException {
// The FeatureMap approach is broken because it assumes feature short names
// are unique. This is my quick fix. -APL
// final FeatureImpl feat = (FeatureImpl) featureMap.get(featName);
// handle v1.x format annotations, mapping int to ref values
- if (featName.equals("sofa") && ts.subsumes(this.annotBaseType, type)) {
- featVal = Integer.toString(this.sofaRefMap.get(Integer.parseInt(featVal)));
- }
+ final String featVal = (featName.equals("sofa") && ((TypeImpl)type).isAnnotationBaseType())
+ ? Integer.toString(this.sofaRefMap.get(
+ ((Sofa)fsTree.get(Integer.parseInt(featValIn)).fs).getSofaNum()))
+ : featValIn;
+// // can't do this in v3, dropping support
// handle v1.x sofanum values, remapping so that _InitialView always == 1
- if (featName.equals(CAS.FEATURE_BASE_NAME_SOFAID)
- && this.sofaTypeCode == cas.getHeapValue(addr)) {
- Type sofaType = ts.ll_getTypeForCode(this.sofaTypeCode);
- final FeatureImpl sofaNumFeat = (FeatureImpl) sofaType
- .getFeatureByBaseName(CAS.FEATURE_BASE_NAME_SOFANUM);
- int sofaNum = cas.getFeatureValue(addr, sofaNumFeat.getCode());
- cas.setFeatureValue(addr, sofaNumFeat.getCode(), this.indexMap.get(sofaNum));
- }
+// if (featName.equals(CAS.FEATURE_BASE_NAME_SOFAID) && (fs instanceof Sofa)) {
+// Sofa sofa = (Sofa) fs;
+// int sofaNum = sofa.getSofaNum();
+// sofa. --- oops, not possible to update the sofanum - it's final
+//
+// Type sofaType = ts.sofaType;
+// final FeatureImpl sofaNumFeat = (FeatureImpl) sofaType
+// .getFeatureByBaseName(CAS.FEATURE_BASE_NAME_SOFANUM);
+// int sofaNum = cas.getFeatureValue(addr, sofaNumFeat.getCode());
+// cas.setFeatureValue(addr, sofaNumFeat.getCode(), this.indexMap.get(sofaNum));
+// }
- String realFeatName;
- if (featName.startsWith(XCASSerializer.REF_PREFIX)) {
- realFeatName = featName.substring(XCASSerializer.REF_PREFIX.length());
- } else {
- realFeatName = featName;
- }
+ String realFeatName = getRealFeatName(featName);
+
final FeatureImpl feat = (FeatureImpl) type.getFeatureByBaseName(realFeatName);
- // System.out.println("DEBUG - Feature map result: " + featName + " = " + feat.getName());
if (feat == null) { // feature does not exist in typesystem
if (outOfTypeSystemData != null) {
// Add to Out-Of-Typesystem data (APL)
- Integer addrInteger = Integer.valueOf(addr);
- List<String[]> ootsAttrs = outOfTypeSystemData.extraFeatureValues.get(addrInteger);
+ List<String[]> ootsAttrs = outOfTypeSystemData.extraFeatureValues.get(fs);
if (ootsAttrs == null) {
ootsAttrs = new ArrayList<String[]>();
- outOfTypeSystemData.extraFeatureValues.put(addrInteger, ootsAttrs);
+ outOfTypeSystemData.extraFeatureValues.put(fs, ootsAttrs);
}
ootsAttrs.add(new String[] { featName, featVal });
} else if (!lenient) {
throw createException(XCASParsingException.UNKNOWN_FEATURE, featName);
}
} else {
- if (cas.ll_isRefType(ts.range(feat.getCode()))) {
- cas.setFeatureValue(addr, feat.getCode(), Integer.parseInt(featVal));
- } else {
- cas.setFeatureValueFromString(addr, feat.getCode(), featVal);
+ // feature is not null
+ if (feat.getRangeImpl().isRefType) {
+ // queue up a fixup action to be done
+ // after the external ids get properly associated with
+ // internal ones.
+
+ fixupToDos.add( () -> finalizeRefValue(Integer.parseInt(featVal), fs, feat));
+ } else { // is not a ref type.
+ cas.setFeatureValueFromString(fs, feat, featVal);
}
}
}
+ private String getRealFeatName(String featName) {
+ return featName.startsWith(XCASSerializer.REF_PREFIX)
+ ? featName.substring(XCASSerializer.REF_PREFIX.length())
+ : featName;
+ }
/*
* (non-Javadoc)
*
@@ -664,7 +721,7 @@ public class XCASDeserializer {
// Set the value of the content feature.
if (!isAllWhitespace(buffer)) {
try {
- handleFeature(currentAddr, currentContentFeat, buffer.toString(), true);
+ handleFeature(currentFs, currentContentFeat, buffer.toString(), true);
} catch (XCASParsingException x) {
// Not sure why we are calling handleFeature for WF content
}
@@ -674,7 +731,7 @@ public class XCASDeserializer {
}
case FEAT_CONTENT_STATE: {
// Create a feature value from an element.
- handleFeature(currentAddr, qualifiedName, buffer.toString(), false);
+ handleFeature(currentFs, qualifiedName, buffer.toString(), false);
this.state = FEAT_STATE;
break;
}
@@ -690,19 +747,18 @@ public class XCASDeserializer {
}
case DOC_TEXT_STATE: {
// Assume old style CAS with one text Sofa
- SofaFS newSofa = cas.createInitialSofa("text");
- CASImpl tcas = (CASImpl) cas.getInitialView();
- tcas.registerView(newSofa);
+ Sofa newSofa = cas.createInitialSofa("text");
+ CASImpl initialView = (CASImpl) cas.getInitialView();
+ initialView.registerView(newSofa);
// Set the document text without creating a documentAnnotation
- tcas.setDocTextFromDeserializtion(buffer.toString());
+ initialView.setDocTextFromDeserializtion(buffer.toString());
// and assume the new Sofa is at location 1!
- int addr = 1;
int id = 1;
this.sofaRefMap.add(id);
// and register the id for this Sofa
- FSInfo fsInfo = new FSInfo(addr, new IntVector());
+ FSInfo fsInfo = new FSInfo(newSofa, new IntVector());
fsTree.put(id, fsInfo);
this.state = FS_STATE;
@@ -725,21 +781,28 @@ public class XCASDeserializer {
}
private void addArrayElement(String content) throws SAXParseException {
- if (arrayPos >= cas.ll_getArraySize(currentAddr)) {
- throw createException(XCASParsingException.EXCESS_ARRAY_ELE);
- }
- try {
- if (!emptyVal(content)) {
- if (cas.isArrayType(cas.getHeap().heap[currentAddr])) {
- cas.setArrayValueFromString(currentAddr, arrayPos, content);
- } else {
- System.out.println(" not a known array type ");
+ if (currentFs instanceof CommonPrimitiveArray) {
+ CommonPrimitiveArray fsa = (CommonPrimitiveArray) currentFs;
+ if (arrayPos >= fsa.size()) {
+ throw createException(XCASParsingException.EXCESS_ARRAY_ELE);
+ }
+ try {
+ if (!emptyVal(content)) {
+ fsa.setArrayValueFromString(arrayPos, content);
}
+ } catch (NumberFormatException e) {
+ throw createException(XCASParsingException.INTEGER_EXPECTED, content);
+ }
+ } else {
+ // is ref array (FSArray)
+ if (content != null && content.length() > 0) {
+ final FSArray fsa = (FSArray) currentFs;
+ final int pos = arrayPos;
+ final int extId = Integer.parseInt(content);
+
+ fixupToDos.add( () -> finalizeArrayRefValue(extId, pos, fsa));
}
- } catch (NumberFormatException e) {
- throw createException(XCASParsingException.INTEGER_EXPECTED, content);
}
-
++arrayPos;
}
@@ -755,6 +818,9 @@ public class XCASDeserializer {
// "Resolving references for id data (" + fsTree.size() + ").");
// time = System.currentTimeMillis();
// Resolve references, index.
+ for (Runnable fixup : fixupToDos) {
+ fixup.run();
+ }
for (FSInfo fsInfo : fsTree) {
finalizeFS(fsInfo);
}
@@ -795,92 +861,97 @@ public class XCASDeserializer {
}
private void finalizeFS(FSInfo fsInfo) {
- final int addr = fsInfo.addr;
- final int type = cas.getHeapValue(addr);
- if (cas.isArrayType(type)) {
- finalizeArray(type, addr, fsInfo);
- finalizeAddToIndexes(fsInfo, addr);
- return;
- }
-
- int[] feats = cas.getTypeSystemImpl().ll_getAppropriateFeatures(type);
- int feat;
- FSInfo fsValInfo;
- for (int i = 0; i < feats.length; i++) {
- feat = feats[i];
- if (cas.ll_isRefType(ts.range(feats[i]))) {
- int featVal = cas.getFeatureValue(addr, feat);
- fsValInfo = fsTree.get(featVal);
- if (fsValInfo == null) {
- cas.setFeatureValue(addr, feat, CASImpl.NULL);
- // this feature may be a ref to an out-of-typesystem FS.
- // add it to the Out-of-typesystem features list (APL)
- if (featVal != 0 && outOfTypeSystemData != null) {
- Integer addrInteger = Integer.valueOf(addr);
- List<String[]> ootsAttrs = outOfTypeSystemData.extraFeatureValues.get(addrInteger);
- if (ootsAttrs == null) {
- ootsAttrs = new ArrayList<String[]>();
- outOfTypeSystemData.extraFeatureValues.put(addrInteger, ootsAttrs);
- }
- String featFullName = ts.ll_getFeatureForCode(feat).getName();
- int separatorOffset = featFullName.indexOf(TypeSystem.FEATURE_SEPARATOR);
- String featName = "_ref_" + featFullName.substring(separatorOffset + 1);
- ootsAttrs.add(new String[] { featName, Integer.toString(featVal) });
+ finalizeAddToIndexes(fsInfo); // must be done after fixes the sofa refs
+ }
+
+ /**
+ * Common code run at finalize time, to set ref values and handle out-of-typesystem data
+ *
+ * @param extId the external ID identifying either a deserialized FS or an out-of-typesystem instance
+ * @param fs Feature Structure whose fi reference feature is to be set with a value derived from extId and FSinfo
+ * @param fi the featureImpl
+ */
+ private void finalizeRefValue(int extId, TOP fs, FeatureImpl fi) {
+ FSInfo fsInfo = fsTree.get(extId);
+ if (fsInfo == null) {
+
+ // this feature may be a ref to an out-of-typesystem FS.
+ // add it to the Out-of-typesystem features list (APL)
+ if (extId != 0 && outOfTypeSystemData != null) {
+ List<String[]> ootsAttrs = outOfTypeSystemData.extraFeatureValues.get(extId);
+ if (ootsAttrs == null) {
+ ootsAttrs = new ArrayList<String[]>();
+ outOfTypeSystemData.extraFeatureValues.put(fs, ootsAttrs);
+ }
+ String featFullName = fi.getName();
+ int separatorOffset = featFullName.indexOf(TypeSystem.FEATURE_SEPARATOR);
+ String featName = "_ref_" + featFullName.substring(separatorOffset + 1);
+ ootsAttrs.add(new String[] { featName, Integer.toString(extId) });
+ }
+ fs.setFeatureValue(fi, null);
+ } else {
+ // the sofa ref in annotationBase is set when the fs is created, not here
+ if (fi.getCode() != TypeSystemImpl.annotSofaFeatCode) {
+ if (fs instanceof Sofa) {
+ // special setters for sofa values
+ Sofa sofa = (Sofa) fs;
+ switch (fi.getRangeImpl().getCode()) {
+ case TypeSystemImpl.sofaArrayFeatCode: sofa.setLocalSofaData(fsInfo.fs); break;
+ default: throw new CASRuntimeException(CASRuntimeException.INTERNAL_ERROR);
}
- } else {
- cas.setFeatureValue(addr, feat, fsValInfo.addr);
+ return;
}
+ fs.setFeatureValue(fi, fsInfo.fs);
}
}
- finalizeAddToIndexes(fsInfo, addr); // must be done after above fixes the sofa refs
}
-
- private void finalizeAddToIndexes(final FSInfo fsInfo, final int addr) {
+
+ /**
+ * Same as above, but specialized for array values, not feature slot values
+ * @param extId
+ * @param extId the external ID identifying either a deserialized FS or an out-of-typesystem instance
+ * @param pos the index in the array
+ * @return the TOP instance to be set as the value in an array or as the value of a feature.
+ * @return
+ */
+ private void finalizeArrayRefValue(int extId, int pos, FSArray fs) {
+ FSInfo fsInfo = fsTree.get(extId);
+
+ if (fsInfo == null) {
+
+ // this element may be a ref to an out-of-typesystem FS.
+ // add it to the Out-of-typesystem array elements list (APL)
+ if (extId != 0 && outOfTypeSystemData != null) {
+ List<ArrayElement> ootsElements = outOfTypeSystemData.arrayElements.get(extId);
+ if (ootsElements == null) {
+ ootsElements = new ArrayList<ArrayElement>();
+ outOfTypeSystemData.arrayElements.put(extId, ootsElements);
+ }
+ // the "value" of the reference is the ID, but we prefix with a letter to indicate
+ // that this ID refers to an array OOTS FS
+ ArrayElement ootsElem = new ArrayElement(pos, "a" + Integer.toString(extId));
+ ootsElements.add(ootsElem);
+ }
+ fs.set(pos, null);
+ } else {
+ fs.set(pos, fsInfo.fs);
+ }
+ }
+
+ private void finalizeAddToIndexes(final FSInfo fsInfo) {
if (fsInfo.indexRep.size() >= 0) {
// Now add FS to all specified index repositories
for (int i = 0; i < fsInfo.indexRep.size(); i++) {
if (indexMap.size() == 1) {
- ((FSIndexRepositoryImpl) indexRepositories.get(fsInfo.indexRep.get(i))).addFS(addr);
+ ((FSIndexRepositoryImpl) indexRepositories.get(fsInfo.indexRep.get(i))).addFS(fsInfo.fs);
} else {
((FSIndexRepositoryImpl) indexRepositories.get(indexMap.get(fsInfo.indexRep.get(i))))
- .addFS(addr);
+ .addFS(fsInfo.fs);
}
}
}
}
- private void finalizeArray(int type, int addr, FSInfo fsInfo) {
- if (!cas.isFSArrayType(type)) {
- // Nothing to do.
- return;
- }
- final int size = cas.ll_getArraySize(addr);
- FSInfo fsValInfo;
- for (int i = 0; i < size; i++) {
- int arrayVal = cas.getArrayValue(addr, i);
- fsValInfo = fsTree.get(arrayVal);
- if (fsValInfo == null) {
- cas.setArrayValue(addr, i, CASImpl.NULL);
- // this element may be a ref to an out-of-typesystem FS.
- // add it to the Out-of-typesystem array elements list (APL)
- if (arrayVal != 0 && outOfTypeSystemData != null) {
- Integer arrayAddrInteger = Integer.valueOf(addr);
- List<ArrayElement> ootsElements = outOfTypeSystemData.arrayElements.get(arrayAddrInteger);
- if (ootsElements == null) {
- ootsElements = new ArrayList<ArrayElement>();
- outOfTypeSystemData.arrayElements.put(arrayAddrInteger, ootsElements);
- }
- // the "value" of the refrence is the ID, but we prefix with a letter to indicate
- // that this ID refers to an OOTS FS
- ArrayElement ootsElem = new ArrayElement(i, "a" + Integer.toString(arrayVal));
- ootsElements.add(ootsElem);
- }
- } else {
- cas.setArrayValue(addr, i, fsValInfo.addr);
- }
- }
- }
-
/*
* Finalizes an Out Of Type System FS by assigning a unique ID (prepending a letter) and
* remapping ID references appropriately (both In-Type-System and Out-Of-TypeSystem refs).
@@ -898,7 +969,7 @@ public class XCASDeserializer {
// attempt to locate target in type system
FSInfo fsValInfo = fsTree.get(val);
if (fsValInfo != null) {
- entry.setValue(Integer.toString(fsValInfo.addr));
+ entry.setValue(Integer.toString(fsValInfo.fs._id));
} else
// out of type system - remap by prepending letter
{
@@ -924,7 +995,7 @@ public class XCASDeserializer {
// attempt to locate target in type system
FSInfo fsValInfo = fsTree.get(val);
if (fsValInfo != null) {
- attr[1] = Integer.toString(fsValInfo.addr);
+ attr[1] = Integer.toString(fsValInfo.fs._id);
} else
// out of type system - remap by prepending letter
{
@@ -1012,35 +1083,35 @@ public class XCASDeserializer {
}
/*
- * Adds a feature sturcture to the out-of-typesystem data, and sets the parser's state
+ * Adds a feature structure to the out-of-typesystem data, and sets the parser's state
* appropriately. (APL)
*/
private void addToOutOfTypeSystemData(String typeName, Attributes attrs)
throws XCASParsingException {
if (this.outOfTypeSystemData != null) {
- FSData fs = new FSData();
- fs.type = typeName;
- fs.indexRep = null; // not indexed
+ FSData fsData = new FSData();
+ fsData.type = typeName;
+ fsData.indexRep = null; // not indexed
String attrName, attrValue;
for (int i = 0; i < attrs.getLength(); i++) {
attrName = attrs.getQName(i);
attrValue = attrs.getValue(i);
if (attrName.startsWith(reservedAttrPrefix)) {
if (attrName.equals(XCASSerializer.ID_ATTR_NAME)) {
- fs.id = attrValue;
+ fsData.id = attrValue;
} else if (attrName.equals(XCASSerializer.CONTENT_ATTR_NAME)) {
this.currentContentFeat = attrValue;
} else if (attrName.equals(XCASSerializer.INDEXED_ATTR_NAME)) {
- fs.indexRep = attrValue;
+ fsData.indexRep = attrValue;
} else {
- fs.featVals.put(attrName, attrValue);
+ fsData.featVals.put(attrName, attrValue);
}
} else {
- fs.featVals.put(attrName, attrValue);
+ fsData.featVals.put(attrName, attrValue);
}
}
- this.outOfTypeSystemData.fsList.add(fs);
- this.currentOotsFs = fs;
+ this.outOfTypeSystemData.fsList.add(fsData);
+ this.currentOotsFs = fsData;
// Set the state; we're ready to accept the "content" feature,
// if one is specified
this.state = OOTS_CONTENT_STATE;
Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XCASSerializer.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XCASSerializer.java?rev=1713525&r1=1713524&r2=1713525&view=diff
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XCASSerializer.java (original)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XCASSerializer.java Mon Nov 9 19:46:45 2015
@@ -21,19 +21,37 @@ package org.apache.uima.cas.impl;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.Vector;
import org.apache.uima.UimaContext;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.Feature;
+import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.internal.util.IntStack;
import org.apache.uima.internal.util.IntVector;
import org.apache.uima.internal.util.StringUtils;
import org.apache.uima.internal.util.rb_trees.IntRedBlackTree;
+import org.apache.uima.jcas.cas.BooleanArray;
+import org.apache.uima.jcas.cas.ByteArray;
+import org.apache.uima.jcas.cas.DoubleArray;
+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.ShortArray;
+import org.apache.uima.jcas.cas.StringArray;
+import org.apache.uima.jcas.cas.TOP;
import org.apache.uima.util.XMLSerializer;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
@@ -42,9 +60,7 @@ import org.xml.sax.helpers.AttributesImp
/**
* XCAS serializer. Create a serializer from a type system, then encode individual CASes by writing
- * to a SAX content handler. This class is thread safe.
- *
- *
+ * to a SAX content handler. This class is thread safe. *
*/
public class XCASSerializer {
@@ -70,7 +86,7 @@ public class XCASSerializer {
private CASImpl cas;
// Any FS reference we've touched goes in here.
- private IntRedBlackTree queued;
+ final private Map<TOP, Integer> queued = new IdentityHashMap<TOP, Integer>();
private static final int NOT_INDEXED = -1;
@@ -79,25 +95,22 @@ public class XCASSerializer {
private static final int INVALID_INDEX = -3;
// Any FS indexed in more than one IR goes in here
- private IntRedBlackTree duplicates;
+ final private Map<TOP, Integer> duplicates = new IdentityHashMap<>();
// Number of FS indexed in more than one IR
int numDuplicates;
// Vector of IntVectors for duplicates
- Vector<IntVector> dupVectors;
+ final List<IntVector> dupVectors = new ArrayList<>();
// All FSs that are in an index somewhere.
- private IntVector indexedFSs;
+ final private List<TOP> indexedFSs = new ArrayList<>();
// Specific IndexRepository for indexed FSs
- private IntVector indexReps;
+ final private IntVector indexReps = new IntVector();
// The current queue for FSs to write out.
- private IntStack queue;
-
- // SofaFS type
- private int sofaTypeCode;
+ final private Deque<TOP> queue = new ArrayDeque<>();
private final AttributesImpl emptyAttrs = new AttributesImpl();
@@ -117,40 +130,32 @@ public class XCASSerializer {
super();
this.ch = ch;
this.cas = cas;
- this.queued = new IntRedBlackTree();
- this.duplicates = new IntRedBlackTree();
this.numDuplicates = 0;
- this.dupVectors = new Vector<IntVector>();
- this.queue = new IntStack();
- this.indexedFSs = new IntVector();
- this.indexReps = new IntVector();
- this.sofaTypeCode = cas.ll_getTypeSystem().ll_getCodeForType(
- cas.getTypeSystem().getType(CAS.TYPE_NAME_SOFA));
}
/**
* Add an address to the queue.
*
- * @param addr
+ * @param fs_id
* The address.
* @return <code>false</code> iff we've seen this address before.
*/
- private boolean enqueue(int addr) {
- if (KEY_ONLY_MATCH == isQueued(addr, INVALID_INDEX)) {
+ private boolean enqueue(TOP fs) {
+ if (KEY_ONLY_MATCH == isQueued(fs, INVALID_INDEX)) {
return false;
}
- int heapVal = cas.getHeapValue(addr);
+ int typeCode = fs._getTypeCode();
// at this point we don't know if this FS is indexed
- queued.put(addr, NOT_INDEXED);
- queue.push(addr);
- final int typeClass = classifyType(heapVal);
+ queued.put(fs, NOT_INDEXED);
+ queue.push(fs);
+ final int typeClass = classifyType(typeCode);
if (typeClass == LowLevelCAS.TYPE_CLASS_FS) {
if (mOutOfTypeSystemData != null) {
- enqueueOutOfTypeSystemFeatures(addr);
+ enqueueOutOfTypeSystemFeatures(fs);
}
- enqueueFeatures(addr, heapVal);
+ enqueueFeatures(fs, typeCode);
} else if (typeClass == LowLevelCAS.TYPE_CLASS_FSARRAY) {
- enqueueFSArray(addr);
+ enqueueFSArray((FSArray) fs);
}
return true;
}
@@ -158,40 +163,40 @@ public class XCASSerializer {
/**
* Same as enqueue, but for indexed FSs.
*
- * @param addr
+ * @param fs_id
* The address to enqueue.
*/
- private void enqueueIndexed(int addr, int indexRep) {
- int status = isQueued(addr, indexRep);
+ private void enqueueIndexed(TOP fs, int indexRep) {
+ int status = isQueued(fs, indexRep);
switch (status) {
case KEY_NOT_FOUND: // most common case, key not found
- queued.put(addr, indexRep);
- indexedFSs.add(addr);
+ queued.put(fs, indexRep);
+ indexedFSs.add(fs);
indexReps.add(indexRep);
break;
case KEY_AND_VALUE_MATCH: // next most common, FS already queued
break;
case KEY_ONLY_MATCH: // key is there, indexRep not
- int prevIndex = queued.get(addr);
+ int prevIndex = queued.get(fs);
if (NOT_INDEXED == prevIndex) {
- // this addr added from a previously found reference
- queued.put(addr, indexRep); // set with given index
+ // this fs_id added from a previously found reference
+ queued.put(fs, indexRep); // set with given index
break;
}
if (MULTIPLY_INDEXED == prevIndex) {
- // this addr already indexed more than once
- int thisDup = duplicates.get(addr);
+ // this fs already indexed more than once
+ int thisDup = duplicates.get(fs);
dupVectors.get(thisDup).add(indexRep);
break;
}
// duplicate index detected!
- duplicates.put(addr, numDuplicates);
+ duplicates.put(fs, numDuplicates);
dupVectors.add(new IntVector());
dupVectors.get(numDuplicates).add(prevIndex);
dupVectors.get(numDuplicates).add(indexRep);
numDuplicates++;
- queued.put(addr, MULTIPLY_INDEXED); // mark this addr as multiply indexed
+ queued.put(fs, MULTIPLY_INDEXED); // mark this fs_id as multiply indexed
break;
}
return;
@@ -200,7 +205,7 @@ public class XCASSerializer {
/**
* Bad name; check if we've seen this (address, value) before.
*
- * @param addr
+ * @param fs_id
* The address.
* @param value
* The index repository
@@ -214,22 +219,9 @@ public class XCASSerializer {
private static final int KEY_NOT_FOUND = 0;
- private int isQueued(int addr, int value) {
- return containsKeyValuePair(this.queued, addr, value);
- }
-
- // returns
- // KEY_AND_VALUE_MATCH = 1;
- // KEY_ONLY_MATCH = -1;
- // KEY_NOT_FOUND = 0;
- private final int containsKeyValuePair(IntRedBlackTree rbt, int key, int value) {
- if (rbt.containsKey(key)) {
- if (rbt.get(key) == value) {
- return KEY_AND_VALUE_MATCH;
- }
- return KEY_ONLY_MATCH;
- }
- return KEY_NOT_FOUND;
+ private int isQueued(TOP fs, int value) {
+ Integer v = this.queued.get(fs);
+ return (null == v) ? KEY_NOT_FOUND : (value == v.intValue()) ? KEY_AND_VALUE_MATCH : KEY_ONLY_MATCH;
}
/*
@@ -247,7 +239,7 @@ public class XCASSerializer {
enqueueFeaturesOfIndexed();
if (outOfTypeSystemData != null) {
// Queues out of type system data.
- int nextId = cas.getHeap().getCellsUsed();
+ int nextId = cas.getNextFsIdNoIncrement() + 1;
Iterator<FSData> it = outOfTypeSystemData.fsList.iterator();
while (it.hasNext()) {
FSData fs = it.next();
@@ -350,39 +342,41 @@ public class XCASSerializer {
* Push the indexed FSs onto the queue.
*/
private void enqueueIndexed() {
- FSIndexRepositoryImpl ir = (FSIndexRepositoryImpl) cas.getBaseCAS().getBaseIndexRepository();
- int[] fsarray = ir.getIndexedFSs();
- for (int k = 0; k < fsarray.length; k++) {
- enqueueIndexed(fsarray[k], 0);
- }
+ List<TOP> allSofas = cas.getBaseIndexRepositoryImpl().getIndexedFSs();
+
+ // XCAS requires sofas in order of id
+ Collections.sort(allSofas, (fs1, fs2) -> Integer.compare(fs1._id, fs2._id) );
+ enqueueList(allSofas, 0);
+
// Get indexes for each SofaFS in the CAS
- int numViews = cas.getBaseSofaCount();
- for (int sofaNum = 1; sofaNum <= numViews; sofaNum++) {
- FSIndexRepositoryImpl loopIR = (FSIndexRepositoryImpl) cas.getBaseCAS()
- .getSofaIndexRepository(sofaNum);
- if (loopIR != null) {
- fsarray = loopIR.getIndexedFSs();
- for (int k = 0; k < fsarray.length; k++) {
- enqueueIndexed(fsarray[k], sofaNum);
- }
+ for (int sofaNum = 1, numViews = cas.getBaseSofaCount(); sofaNum <= numViews; sofaNum++) {
+ FSIndexRepositoryImpl viewIR = (FSIndexRepositoryImpl) cas.getBaseCAS().getSofaIndexRepository(sofaNum);
+ if (viewIR != null) {
+ enqueueList(viewIR.getIndexedFSs(), sofaNum);
}
}
}
+
+ private void enqueueList(List<TOP> fss, int sofaNum) {
+ for (TOP fs : fss) { // enqueues the Sofas
+ enqueueIndexed(fs, sofaNum);
+ }
+ }
private void enqueueFeaturesOfIndexed() {
final int max = indexedFSs.size();
for (int i = 0; i < max; i++) {
- int addr = indexedFSs.get(i);
- int heapVal = cas.getHeapValue(addr);
- final int typeClass = classifyType(heapVal);
+ TOP fs = indexedFSs.get(i);
+ int typeCode = fs._getTypeCode();
+ final int typeClass = classifyType(typeCode);
if (typeClass == LowLevelCAS.TYPE_CLASS_FS) {
if (mOutOfTypeSystemData != null) {
- enqueueOutOfTypeSystemFeatures(addr);
+ enqueueOutOfTypeSystemFeatures(fs);
}
- enqueueFeatures(addr, heapVal);
+ enqueueFeatures(fs, typeCode);
} else if (typeClass == LowLevelCAS.TYPE_CLASS_FSARRAY) {
- enqueueFSArray(addr);
+ enqueueFSArray((FSArray) fs);
}
}
}
@@ -392,31 +386,30 @@ public class XCASSerializer {
*
*/
private void encodeQueued() throws IOException, SAXException {
- int addr;
- while (!queue.empty()) {
- addr = queue.pop();
- encodeFS(addr, null);
+ for (TOP item : queue) {
+ encodeFS(item, null);
}
}
/**
* Encode an individual FS.
*
- * @param addr
+ * @param fs_id
* The address to be encoded.
* @param isIndexed
* If the FS is indexed or not.
* @throws IOException passthru
* @throws SAXException passthru
*/
- private void encodeFS(int addr, IntVector indexRep) throws IOException, SAXException {
+ private void encodeFS(TOP fs, IntVector indexRep) throws IOException, SAXException {
++fsCount;
+
workAttrs.clear();
// Create an element with the type name as tag.
- // xmlStack.pushElementNode(getTypeName(addr));
+ // xmlStack.pushElementNode(getTypeName(fs_id));
// Add indexed info.
- // if (sofaTypeCode == cas.getHeapValue(addr) &&
+ // if (sofaTypeCode == cas.getHeapValue(fs_id) &&
// cas.isBackwardCompatibleCas()) {
// // Don't encode sofaFS if old style application
// return;
@@ -440,87 +433,70 @@ public class XCASSerializer {
// have to do a complete traversal of the heap to find out which FSs
// is
// actually referenced.
- // xmlStack.addAttribute(ID_ATTR_NAME, Integer.toString(addr));
- addAttribute(workAttrs, ID_ATTR_NAME, Integer.toString(addr));
- final int typeClass = classifyType(cas.getHeapValue(addr));
+ // xmlStack.addAttribute(ID_ATTR_NAME, Integer.toString(fs_id));
+ addAttribute(workAttrs, ID_ATTR_NAME, Integer.toString(fs._id));
+ final int typeClass = classifyType(fs._getTypeCode());
// Call special code according to the type of the FS (special
// treatment
// for arrays).
+ String[] data = null;
+ String typeName = getTypeName(fs);
switch (typeClass) {
case LowLevelCAS.TYPE_CLASS_FS: {
- String typeName = getTypeName(addr);
- encodeFeatures(addr, workAttrs);
+ encodeFeatures(fs, workAttrs);
if (mOutOfTypeSystemData != null) {
- encodeOutOfTypeSystemFeatures(addr, workAttrs); // APL
+ encodeOutOfTypeSystemFeatures(fs, workAttrs); // APL
}
String xcasElementName = getXCasElementName(typeName);
startElement(xcasElementName, workAttrs, 0);
// xmlStack.commitNode();
endElement(xcasElementName);
- break;
+ return;
}
case LowLevelCAS.TYPE_CLASS_INTARRAY: {
- IntArrayFSImpl fs = new IntArrayFSImpl(addr, cas);
- String[] data = fs.toStringArray();
- encodePrimitiveTypeArrayFS(data, getTypeName(addr), workAttrs);
- // encodeIntArray(addr, workAttrs);
+ data = ((IntegerArray)fs).toStringArray();
break;
}
case LowLevelCAS.TYPE_CLASS_FLOATARRAY: {
- FloatArrayFSImpl fs = new FloatArrayFSImpl(addr, cas);
- String[] data = fs.toStringArray();
- encodePrimitiveTypeArrayFS(data, getTypeName(addr), workAttrs);
- // encodeFloatArray(addr, workAttrs);
+ data = ((FloatArray)fs).toStringArray();
break;
}
case LowLevelCAS.TYPE_CLASS_STRINGARRAY: {
- StringArrayFSImpl fs = new StringArrayFSImpl(addr, cas);
- String[] data = fs.toArray();
- encodePrimitiveTypeArrayFS(data, getTypeName(addr), workAttrs);
- // encodeStringArray(addr, workAttrs);
+ data = ((StringArray)fs).toArray();
break;
}
case LowLevelCAS.TYPE_CLASS_FSARRAY: {
- encodeFSArray(addr, workAttrs);
- break;
+ encodeFSArray((FSArray) fs, workAttrs);
+ return;
}
case LowLevelCAS.TYPE_CLASS_BOOLEANARRAY: {
- BooleanArrayFSImpl fs = new BooleanArrayFSImpl(addr, cas);
- String[] data = fs.toStringArray();
- encodePrimitiveTypeArrayFS(data, getTypeName(addr), workAttrs);
+ data = ((BooleanArray)fs).toStringArray();
break;
}
case LowLevelCAS.TYPE_CLASS_BYTEARRAY: {
- ByteArrayFSImpl fs = new ByteArrayFSImpl(addr, cas);
- String[] data = fs.toStringArray();
- encodePrimitiveTypeArrayFS(data, getTypeName(addr), workAttrs);
+ data = ((ByteArray)fs).toStringArray();
break;
}
case LowLevelCAS.TYPE_CLASS_SHORTARRAY: {
- ShortArrayFSImpl fs = new ShortArrayFSImpl(addr, cas);
- String[] data = fs.toStringArray();
- encodePrimitiveTypeArrayFS(data, getTypeName(addr), workAttrs);
+ data = ((ShortArray)fs).toStringArray();
break;
}
case LowLevelCAS.TYPE_CLASS_LONGARRAY: {
- LongArrayFSImpl fs = new LongArrayFSImpl(addr, cas);
- String[] data = fs.toStringArray();
- encodePrimitiveTypeArrayFS(data, getTypeName(addr), workAttrs);
+ data = ((LongArray)fs).toStringArray();
break;
}
case LowLevelCAS.TYPE_CLASS_DOUBLEARRAY: {
- DoubleArrayFSImpl fs = new DoubleArrayFSImpl(addr, cas);
- String[] data = fs.toStringArray();
- encodePrimitiveTypeArrayFS(data, getTypeName(addr), workAttrs);
+ data = ((DoubleArray)fs).toStringArray();
break;
}
default: {
// Internal error.
System.err.println("Error classifying FS type.");
}
- }
+ } // end of switch
+ // common code for most of the cases
+ encodePrimitiveTypeArrayFS(data, typeName, workAttrs);
// xmlStack.popNode();
-
}
private void encodePrimitiveTypeArrayFS(String[] data, String typeName, AttributesImpl attrs)
@@ -537,10 +513,10 @@ public class XCASSerializer {
endElement(typeName);
}
- private void encodeFSArray(int addr, AttributesImpl attrs) throws SAXException {
- final String typeName = getTypeName(addr);
- final int size = cas.ll_getArraySize(addr);
- int pos = cas.getArrayStartAddress(addr);
+ private void encodeFSArray(FSArray fs, AttributesImpl attrs) throws SAXException {
+ final String typeName = fs._typeImpl.getName();
+ final int size = fs.size();
+// int pos = cas.getArrayStartAddress(fs_id);
// xmlStack.addAttribute(ARRAY_SIZE_ATTR, Integer.toString(size));
// xmlStack.commitNode();
addAttribute(attrs, ARRAY_SIZE_ATTR, Integer.toString(size));
@@ -549,11 +525,10 @@ public class XCASSerializer {
String val = null;
// xmlStack.pushTextNode(ARRAY_ELEMENT_TAG);
// xmlStack.commitNode();
- int heapVal = cas.getHeapValue(pos);
- if (heapVal == CASImpl.NULL && mOutOfTypeSystemData != null) {
- // This array element may have been a reference to an OOTS
- // FS.
- List<ArrayElement> ootsElems = mOutOfTypeSystemData.arrayElements.get(Integer.valueOf(addr));
+ TOP element = fs.get(i);
+ if (null == element && mOutOfTypeSystemData != null) {
+ // This array element may have been a reference to an OOTS FS.
+ List<ArrayElement> ootsElems = mOutOfTypeSystemData.arrayElements.get(fs);
if (ootsElems != null) {
Iterator<ArrayElement> iter = ootsElems.iterator();
// TODO: iteration could be slow for large arrays
@@ -566,8 +541,8 @@ public class XCASSerializer {
}
}
}
- } else if (heapVal != CASImpl.NULL) {
- val = Integer.toString(heapVal);
+ } else if (null != element) {
+ val = Integer.toString(element.id());
}
if (val != null) {
@@ -578,77 +553,49 @@ public class XCASSerializer {
}
// xmlStack.popNode();
endElement(ARRAY_ELEMENT_TAG);
- ++pos;
}
endElement(typeName);
}
- private void enqueueFSArray(int addr) {
- final int size = cas.ll_getArraySize(addr);
- int pos = cas.getArrayStartAddress(addr);
- int val;
- for (int i = 0; i < size; i++) {
- val = cas.getHeapValue(pos);
- if (val != CASImpl.NULL) {
- enqueue(val);
+ private void enqueueFSArray(FSArray fs) {
+ TOP[] theArray = fs._getTheArray();
+ for (TOP element : theArray) {
+ if (element != null) {
+ enqueue(element);
}
- ++pos;
}
}
/*
* Encode features of a regular (non-array) FS.
*/
- private void encodeFeatures(int addr, AttributesImpl attrs) {
- int heapValue = cas.getHeapValue(addr);
- int[] feats = ts.ll_getAppropriateFeatures(heapValue);
- int featAddr, featVal;
- String featName, attrValue;
-// boolean nameMapping = false;
-// if (sofaTypeCode == heapValue) {
-// // set flag for SofaID mapping
-// nameMapping = true;
-// }
-
- for (int i = 0; i < feats.length; i++) {
- featAddr = addr + cas.getFeatureOffset(feats[i]);
- featVal = cas.getHeapValue(featAddr);
- featName = featureNames[feats[i]];
- if (!cas.ll_isRefType(ts.range(feats[i]))) {
- attrValue = cas.getFeatureValueAsString(addr, feats[i]);
-// if (nameMapping && featName.equals(CAS.FEATURE_BASE_NAME_SOFAID) && uimaContext != null) {
-// // map absolute SofaID to that expected by Component
-// attrValue = uimaContext.mapSofaIDToComponentSofaName(attrValue);
-// }
+ private void encodeFeatures(TOP fs, AttributesImpl attrs) {
+ TypeImpl ti = fs._typeImpl;
+
+ for (FeatureImpl fi : ti.getFeatureImpls()) {
+ String attrValue;
+ if (fi.getRangeImpl().isRefType) {
+ TOP v = fs.getFeatureValue(fi);
+ attrValue = (null == v) ? null : Integer.toString(v._id);
} else {
- if (featVal == CASImpl.NULL) {
- attrValue = null;
- } else {
- attrValue = Integer.toString(featVal);
- }
+ attrValue = fs.getFeatureValueAsString(fi);
}
-
- if (attrValue != null && featName != null) {
- addAttribute(attrs, featName, attrValue);
+ if (attrValue != null) {
+ addAttribute(attrs, featureNames[fi.getCode()], attrValue);
}
}
}
- private void enqueueFeatures(int addr, int heapValue) {
- int[] feats = ts.ll_getAppropriateFeatures(heapValue);
- int featAddr, featVal;
-
- for (int i = 0; i < feats.length; i++) {
- featAddr = addr + cas.getFeatureOffset(feats[i]);
- featVal = cas.getHeapValue(featAddr);
- if (cas.ll_isRefType(ts.range(feats[i]))) {
- if (featVal == CASImpl.NULL) {
- // break;
- } else {
- enqueue(featVal);
+ private void enqueueFeatures(TOP fs, int heapValue) {
+ TypeImpl ti = fs._typeImpl;
+
+ for (FeatureImpl fi : ti.getFeatureImpls()) {
+ if (fi.getRangeImpl().isRefType) {
+ TOP v = fs.getFeatureValue(fi);
+ if (null != v) {
+ enqueue(v);
}
-
}
}
}
@@ -656,8 +603,8 @@ public class XCASSerializer {
/*
* Encode Out-Of-TypeSystem Features.
*/
- private void encodeOutOfTypeSystemFeatures(int addr, AttributesImpl attrs) {
- List<String[]> attrList = mOutOfTypeSystemData.extraFeatureValues.get(Integer.valueOf(addr));
+ private void encodeOutOfTypeSystemFeatures(TOP fs, AttributesImpl attrs) {
+ List<String[]> attrList = mOutOfTypeSystemData.extraFeatureValues.get(fs);
if (attrList != null) {
for (String[] attr : attrList) {
// remap ID if necessary
@@ -675,8 +622,8 @@ public class XCASSerializer {
/*
* Encode Out-Of-TypeSystem Features.
*/
- private void enqueueOutOfTypeSystemFeatures(int addr) {
- List<String[]> attrList = mOutOfTypeSystemData.extraFeatureValues.get(Integer.valueOf(addr));
+ private void enqueueOutOfTypeSystemFeatures(TOP fs) {
+ List<String[]> attrList = mOutOfTypeSystemData.extraFeatureValues.get(fs);
if (attrList != null) {
Iterator<String[]> it = attrList.iterator();
while (it.hasNext()) {
@@ -687,15 +634,15 @@ public class XCASSerializer {
// system FS. All other references should be to in-typesystem FS, which we need to
// enqueue.
if (!attr[1].startsWith("a")) {
- enqueue(Integer.parseInt(attr[1]));
+ enqueue(cas.getFsFromId_checked(Integer.parseInt(attr[1])));
}
}
}
}
}
- private final String getTypeName(int addr) {
- return ts.ll_getTypeForCode(cas.getHeapValue(addr)).getName();
+ private final String getTypeName(TOP fs) {
+ return fs.getType().getName();
}
private final int classifyType(int type) {
@@ -715,7 +662,7 @@ public class XCASSerializer {
// system FS. All other references should be to in-typesystem FS, which we need to
// enqueue.
if (!attrVal.startsWith("a")) {
- enqueue(Integer.parseInt(attrVal));
+ enqueue(cas.getFsFromId_checked(Integer.parseInt(attrVal)));
}
}
}