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/23 22:32:16 UTC
svn commit: r1715964 [3/3] - in
/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl:
XmiCasDeserializer.java XmiCasSerializer.java XmiSerializationSharedData.java
Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiCasSerializer.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiCasSerializer.java?rev=1715964&r1=1715963&r2=1715964&view=diff
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiCasSerializer.java (original)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiCasSerializer.java Mon Nov 23 21:32:16 2015
@@ -21,6 +21,7 @@ package org.apache.uima.cas.impl;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -28,9 +29,7 @@ import java.util.Map;
import org.apache.uima.UIMAFramework;
import org.apache.uima.UIMARuntimeException;
import org.apache.uima.UimaContext;
-import org.apache.uima.cas.ByteArrayFS;
import org.apache.uima.cas.CAS;
-import org.apache.uima.cas.CommonArrayFS;
import org.apache.uima.cas.Marker;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
@@ -41,6 +40,14 @@ import org.apache.uima.cas.impl.XmiSeria
import org.apache.uima.internal.util.XmlAttribute;
import org.apache.uima.internal.util.XmlElementName;
import org.apache.uima.internal.util.XmlElementNameAndContents;
+import org.apache.uima.jcas.cas.ByteArray;
+import org.apache.uima.jcas.cas.CommonArray;
+import org.apache.uima.jcas.cas.CommonList;
+import org.apache.uima.jcas.cas.FSArray;
+import org.apache.uima.jcas.cas.Sofa;
+import org.apache.uima.jcas.cas.StringArray;
+import org.apache.uima.jcas.cas.StringList;
+import org.apache.uima.jcas.cas.TOP;
import org.apache.uima.util.XMLSerializer;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
@@ -126,6 +133,8 @@ public class XmiCasSerializer {
SYSTEM_LINE_FEED = (lf == null) ? "\n" : lf;
}
+ public final static char[] INT_TO_HEX = "0123456789ABCDEF".toCharArray();
+
private final CasSerializerSupport css = new CasSerializerSupport();
private Map<String, String> nsUriToSchemaLocationMap = null;
@@ -579,10 +588,10 @@ public class XmiCasSerializer {
}
@Override
- protected void writeView(int sofaAddr, int[] members) throws Exception {
+ protected void writeView(Sofa sofa, Collection<TOP> members) throws Exception {
workAttrs.clear();
// this call should never generate a new XmiId, it should just retrieve the existing one for the sofa
- String sofaXmiId = cds.getXmiId(sofaAddr);
+ String sofaXmiId = (sofa == null) ? null : cds.getXmiId(sofa);
if (sofaXmiId != null && sofaXmiId.length() > 0) {
addAttribute(workAttrs, "sofa", sofaXmiId);
}
@@ -618,7 +627,7 @@ public class XmiCasSerializer {
* @param isPastFirstElement -
* @return
*/
- private StringBuilder writeViewMembers(StringBuilder sb, List<String> members, boolean isPastFirstElement) {
+ private StringBuilder writeViewMembers(StringBuilder sb, Collection<String> members, boolean isPastFirstElement) {
if (members != null) {
for (String member : members) {
if (isPastFirstElement) {
@@ -633,10 +642,10 @@ public class XmiCasSerializer {
}
- private boolean writeViewMembers(StringBuilder sb, int[] members) throws SAXException {
+ private boolean writeViewMembers(StringBuilder sb, Collection<TOP> members) throws SAXException {
boolean isPastFirstElement = false;
int nextBreak = (((sb.length() - 1) / CasSerializerSupport.PP_LINE_LENGTH) + 1) * CasSerializerSupport.PP_LINE_LENGTH;
- for (int member : members) {
+ for (TOP member : members) {
int xmiId = cds.getXmiIdAsInt(member);
if (xmiId != 0) { // to catch filtered FS
if (isPastFirstElement) {
@@ -654,7 +663,7 @@ public class XmiCasSerializer {
return isPastFirstElement;
}
- private void writeViewForDeltas(String kind, int[] deltaMembers) throws SAXException {
+ private void writeViewForDeltas(String kind, Collection<TOP> deltaMembers) throws SAXException {
StringBuilder sb = new StringBuilder();
writeViewMembers(sb, deltaMembers);
if (sb.length() > 0) {
@@ -663,8 +672,8 @@ public class XmiCasSerializer {
}
@Override
- protected void writeView(int sofaAddr, int[] added, int[] deleted, int[] reindexed) throws SAXException {
- String sofaXmiId = cds.getXmiId(sofaAddr);
+ protected void writeView(Sofa sofa, Collection<TOP> added, Collection<TOP> deleted, Collection<TOP> reindexed) throws SAXException {
+ String sofaXmiId = cds.getXmiId(sofa);
workAttrs.clear();
if (sofaXmiId != null && sofaXmiId.length() > 0) {
addAttribute(workAttrs, "sofa", sofaXmiId);
@@ -693,20 +702,20 @@ public class XmiCasSerializer {
}
@Override
- protected void writeFs(int addr, int typeCode) throws SAXException {
- writeFsOrLists(addr, typeCode, false);
+ protected void writeFs(TOP fs, int typeCode) throws SAXException {
+ writeFsOrLists(fs, typeCode, false);
}
@Override
- protected void writeListsAsIndividualFSs(int addr, int typeCode) throws SAXException {
- writeFsOrLists(addr, typeCode, true);
+ protected void writeListsAsIndividualFSs(TOP fs, int typeCode) throws SAXException {
+ writeFsOrLists((TOP)fs, typeCode, true);
}
- private void writeFsOrLists(int addr, int typeCode, boolean isListAsFSs) throws SAXException {
+ private void writeFsOrLists(TOP fs, int typeCode, boolean isListAsFSs) throws SAXException {
// encode features. this populates the attributes (workAttrs). It also
// populates the child elements list with features that are to be encoded
// as child elements (currently required for string arrays).
- List<XmlElementNameAndContents> childElements = encodeFeatures(addr, workAttrs, isListAsFSs);
+ List<XmlElementNameAndContents> childElements = encodeFeatures(fs, workAttrs, isListAsFSs);
XmlElementName xmlElementName = cds.typeCode2namespaceNames[typeCode];
startElement(xmlElementName, workAttrs, childElements.size());
sendElementEvents(childElements);
@@ -714,21 +723,21 @@ public class XmiCasSerializer {
}
@Override
- protected void writeArrays(int addr, int typeCode, int typeClass) throws SAXException {
+ protected void writeArrays(TOP fsArray, int typeCode, int typeClass) throws SAXException {
XmlElementName xmlElementName = cds.typeCode2namespaceNames[typeCode];
- if (typeClass == LowLevelCAS.TYPE_CLASS_STRINGARRAY) {
+ if (fsArray instanceof StringArray) {
// string arrays are encoded as elements, in case they contain whitespace
List<XmlElementNameAndContents> childElements = new ArrayList<XmlElementNameAndContents>();
- stringArrayToElementList("elements", addr, childElements);
+ stringArrayToElementList("elements", (StringArray) fsArray, childElements);
startElement(xmlElementName, workAttrs, childElements.size());
sendElementEvents(childElements);
endElement(xmlElementName);
} else {
- workAttrs.addAttribute("", "", "elements", "CDATA", arrayToString(addr, typeClass));
+ workAttrs.addAttribute("", "", "elements", "CDATA", arrayToString(fsArray, typeClass));
startElement(xmlElementName, workAttrs, 0);
endElement(xmlElementName);
}
@@ -852,11 +861,11 @@ public class XmiCasSerializer {
* should be added as a child of the FS
* @throws SAXException passthru
*/
- private List<XmlElementNameAndContents> encodeFeatures(int addr, AttributesImpl attrs, boolean insideListNode)
+ private List<XmlElementNameAndContents> encodeFeatures(TOP fs, AttributesImpl attrs, boolean insideListNode)
throws SAXException {
List<XmlElementNameAndContents> childElements = new ArrayList<XmlElementNameAndContents>();
- int heapValue = cds.cas.getHeapValue(addr);
- int[] feats = cds.tsi.ll_getAppropriateFeatures(heapValue);
+// int heapValue = cds.cas.getHeapValue(addr);
+// int[] feats = cds.tsi.ll_getAppropriateFeatures(heapValue);
String attrValue;
// boolean isSofa = false;
@@ -865,20 +874,18 @@ public class XmiCasSerializer {
// // set isSofa flag to apply SofaID mapping and to store sofaNum->xmi:id mapping
// isSofa = true;
// }
- for (final int featCode : feats) {
+ for (final FeatureImpl fi : fs._typeImpl.getFeatureImpls()) {
if (cds.isFiltering) {
// skip features that aren't in the target type system
- String fullFeatName = cds.tsi.ll_getFeatureForCode(featCode).getName();
+ String fullFeatName = fi.getName();
if (cds.filterTypeSystem.getFeatureByFullName(fullFeatName) == null) {
continue;
}
}
- final String featName = cds.tsi.ll_getFeatureForCode(featCode).getShortName();
- final int featAddr = addr + cds.cas.getFeatureOffset(featCode);
- final int featValRaw = cds.cas.getHeapValue(featAddr);
- final int featureValueClass = cds.classifyType(cds.tsi.range(featCode));
+ final String featName = fi.getShortName();
+ final int featureValueClass = fi.rangeTypeClass;
switch (featureValueClass) {
@@ -889,11 +896,11 @@ public class XmiCasSerializer {
case LowLevelCAS.TYPE_CLASS_FLOAT:
case LowLevelCAS.TYPE_CLASS_DOUBLE:
case LowLevelCAS.TYPE_CLASS_BOOLEAN:
- attrValue = cds.cas.getFeatureValueAsString(addr, featCode);
+ attrValue = fs.getFeatureValueAsString(fi);
break;
case LowLevelCAS.TYPE_CLASS_STRING:
- attrValue = (featValRaw == CASImpl.NULL) ? null : cds.cas.getStringForCode(featValRaw);
+ attrValue = fs.getFeatureValueAsString(fi);
break;
// Arrays
@@ -905,20 +912,20 @@ public class XmiCasSerializer {
case LowLevelCAS.TYPE_CLASS_LONGARRAY:
case LowLevelCAS.TYPE_CLASS_DOUBLEARRAY:
case LowLevelCAS.TYPE_CLASS_FSARRAY:
- if (cds.isStaticMultiRef(featCode)) {
- attrValue = cds.getXmiId(featValRaw);
+ if (cds.isStaticMultiRef(fi.getCode())) {
+ attrValue = cds.getXmiId(fs.getFeatureValue(fi));
} else {
- attrValue = arrayToString(featValRaw, featureValueClass);
+ attrValue = arrayToString(fs.getFeatureValue(fi), featureValueClass);
}
break;
// special case for StringArrays, which stored values as child elements rather
// than attributes.
case LowLevelCAS.TYPE_CLASS_STRINGARRAY:
- if (cds.isStaticMultiRef(featCode)) {
- attrValue = cds.getXmiId(featValRaw);
+ if (cds.isStaticMultiRef(fi.getCode())) {
+ attrValue = cds.getXmiId(fs.getFeatureValue(fi));
} else {
- stringArrayToElementList(featName, featValRaw, childElements);
+ stringArrayToElementList(featName, (StringArray) fs.getFeatureValue(fi), childElements);
attrValue = null;
}
break;
@@ -927,41 +934,46 @@ public class XmiCasSerializer {
case CasSerializerSupport.TYPE_CLASS_INTLIST:
case CasSerializerSupport.TYPE_CLASS_FLOATLIST:
case CasSerializerSupport.TYPE_CLASS_FSLIST:
- if (insideListNode || cds.isStaticMultiRef(featCode)) {
+ TOP startNode = fs.getFeatureValue(fi);
+ if (insideListNode || cds.isStaticMultiRef(fi.getCode())) {
// If the feature has multipleReferencesAllowed = true OR if we're already
// inside another list node (i.e. this is the "tail" feature), serialize as a normal FS.
// Otherwise, serialize as a multi-valued property.
// if (cds.isStaticMultRef(feats[i]) ||
// cds.embeddingNotAllowed.contains(featVal) ||
// insideListNode) {
- attrValue = cds.getXmiId(featValRaw);
+
+ attrValue = cds.getXmiId(startNode);
} else {
- attrValue = listToString(featValRaw);
+ attrValue = listToString((CommonList) fs.getFeatureValue(fi));
}
break;
// special case for StringLists, which stored values as child elements rather
// than attributes.
case CasSerializerSupport.TYPE_CLASS_STRINGLIST:
- if (insideListNode || cds.isStaticMultiRef(featCode)) {
- attrValue = cds.getXmiId(featValRaw);
+ if (insideListNode || cds.isStaticMultiRef(fi.getCode())) {
+ attrValue = cds.getXmiId(fs.getFeatureValue(fi));
} else {
// it is not safe to use a space-separated attribute, which would
// break for strings containing spaces. So use child elements instead.
- List<String> listOfStrings = cds.listUtils.anyListToStringList(featValRaw, null, cds);
+ StringList stringList = (StringList) fs.getFeatureValue(fi);
+ if (stringList != null) {
+ List<String> listOfStrings = stringList.anyListToStringList(null, cds);
// if (array.length > 0 && !arrayAndListFSs.put(featVal, featVal)) {
// reportWarning("Warning: multiple references to a ListFS. Reference identity will not be preserved.");
// }
- for (String string : listOfStrings) {
- childElements.add(new XmlElementNameAndContents(new XmlElementName(null, featName,
- featName), string));
+ for (String string : listOfStrings) {
+ childElements.add(new XmlElementNameAndContents(new XmlElementName(null, featName,
+ featName), string));
+ }
}
attrValue = null;
}
break;
default: // Anything that's not a primitive type, array, or list.
- attrValue = cds.getXmiId(featValRaw);
+ attrValue = cds.getXmiId(fs.getFeatureValue(fi));
break;
} // end of switch
@@ -973,7 +985,7 @@ public class XmiCasSerializer {
//add out-of-typesystem features, if any
if (cds.sharedData != null) {
- OotsElementData oed = cds.sharedData.getOutOfTypeSystemFeatures(addr);
+ OotsElementData oed = cds.sharedData.getOutOfTypeSystemFeatures(fs);
if (oed != null) {
//attributes
Iterator<XmlAttribute> attrIter = oed.attributes.iterator();
@@ -990,30 +1002,32 @@ public class XmiCasSerializer {
/**
* Create a string to represent array values, embedded format
+ * Not called for StringArray
* @param addr
* @param arrayType
* @return
* @throws SAXException
*/
- private String arrayToString(int addr, int arrayType) throws SAXException {
- if (addr == CASImpl.NULL) {
+ private String arrayToString(TOP fsIn, int arrayType) throws SAXException {
+ if (fsIn == null) {
return null;
}
StringBuilder buf = new StringBuilder();
- final int size = cds.cas.ll_getArraySize(addr);
+ CommonArray fs = (CommonArray) fsIn;
+ final int size = fs.size();
String elemStr = null;
// FS arrays: handle shared data items
- if (arrayType == LowLevelCAS.TYPE_CLASS_FSARRAY) {
- int pos = cds.cas.getArrayStartAddress(addr);
+ if (fs instanceof FSArray) {
List<XmiArrayElement> ootsArrayElementsList = cds.sharedData == null ? null :
- cds.sharedData.getOutOfTypeSystemArrayElements(addr);
+ cds.sharedData.getOutOfTypeSystemArrayElements((FSArray) fs);
int ootsIndex = 0;
- for (int j = 0; j < size; j++) {
- int heapValue = cds.cas.getHeapValue(pos++);
-
- if (heapValue == 0) { // null case
+
+ int j = -1;
+ for (TOP elemFS : ((FSArray)fs)._getTheArray()) {
+ j++;
+ if (elemFS == null) { // null case
// special NULL object with xmi:id=0 is used to represent
// a null in an FSArray
elemStr = "0";
@@ -1031,9 +1045,9 @@ public class XmiCasSerializer {
}
} else { // not null
- String xmiId = cds.getXmiId(heapValue);
+ String xmiId = cds.getXmiId(elemFS);
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();
+ String typeName = elemFS._typeImpl.getName();
if (cds.filterTypeSystem.getType(typeName) == null) {
xmiId = "0";
}
@@ -1049,57 +1063,56 @@ public class XmiCasSerializer {
return buf.toString();
- } else if (arrayType == LowLevelCAS.TYPE_CLASS_BYTEARRAY) {
+ } else if (fs instanceof ByteArray) {
// special case for byte arrays: serialize as hex digits
- ByteArrayFS byteArrayFS = new ByteArrayFSImpl(addr, cds.cas);
- int len = byteArrayFS.size();
- for (int i = 0; i < len; i++) {
- byte b = byteArrayFS.get(i);
- // this test is necessary to generate a leading zero where necessary
- if ((b & 0xF0) == 0) {
- buf.append('0').append(Integer.toHexString(b).toUpperCase());
- } else {
- buf.append(Integer.toHexString(0xFF & b).toUpperCase());
- }
+ byte[] ba = ((ByteArray) fs)._getTheArray();
+
+ char[] r = new char[ba.length * 2];
+
+ int i = 0;
+ for (byte b : ba) {
+ r[i++] = INT_TO_HEX[(b & 0xF0) >>> 4];
+ r[i++] = INT_TO_HEX[b & 0x0F];
}
- return buf.toString();
+ return new String(r);
} else {
- CommonArrayFS fs;
- String[] fsvalues;
-
- switch (arrayType) {
- case LowLevelCAS.TYPE_CLASS_INTARRAY:
- fs = new IntArrayFSImpl(addr, cds.cas);
- break;
- case LowLevelCAS.TYPE_CLASS_FLOATARRAY:
- fs = new FloatArrayFSImpl(addr, cds.cas);
- break;
- case LowLevelCAS.TYPE_CLASS_BOOLEANARRAY:
- fs = new BooleanArrayFSImpl(addr, cds.cas);
- break;
- case LowLevelCAS.TYPE_CLASS_SHORTARRAY:
- fs = new ShortArrayFSImpl(addr, cds.cas);
- break;
- case LowLevelCAS.TYPE_CLASS_LONGARRAY:
- fs = new LongArrayFSImpl(addr, cds.cas);
- break;
- case LowLevelCAS.TYPE_CLASS_DOUBLEARRAY:
- fs = new DoubleArrayFSImpl(addr, cds.cas);
- break;
- case LowLevelCAS.TYPE_CLASS_BYTEARRAY:
- fs = new ByteArrayFSImpl(addr, cds.cas);
- break;
- default: {
- return "";
- }
- }
+ // is not FSarray, is not ByteArray, is not String Array
+// CommonArrayFS fs;
+// String[] fsvalues;
+//
+// switch (arrayType) {
+// case LowLevelCAS.TYPE_CLASS_INTARRAY:
+// fs = new IntArrayFSImpl(addr, cds.cas);
+// break;
+// case LowLevelCAS.TYPE_CLASS_FLOATARRAY:
+// fs = new FloatArrayFSImpl(addr, cds.cas);
+// break;
+// case LowLevelCAS.TYPE_CLASS_BOOLEANARRAY:
+// fs = new BooleanArrayFSImpl(addr, cds.cas);
+// break;
+// case LowLevelCAS.TYPE_CLASS_SHORTARRAY:
+// fs = new ShortArrayFSImpl(addr, cds.cas);
+// break;
+// case LowLevelCAS.TYPE_CLASS_LONGARRAY:
+// fs = new LongArrayFSImpl(addr, cds.cas);
+// break;
+// case LowLevelCAS.TYPE_CLASS_DOUBLEARRAY:
+// fs = new DoubleArrayFSImpl(addr, cds.cas);
+// break;
+// case LowLevelCAS.TYPE_CLASS_BYTEARRAY:
+// fs = new ByteArrayFSImpl(addr, cds.cas);
+// break;
+// default: {
+// return "";
+// }
+// }
// if (arrayType == LowLevelCAS.TYPE_CLASS_STRINGARRAY) { // this method never called for StringArrays
// StringArrayFS strFS = new StringArrayFSImpl(addr, cds.cas);
// fsvalues = strFS.toArray();
// } else {
- fsvalues = fs.toStringArray();
+ String[] fsvalues = fs.toStringArray();
// }
for (String s : fsvalues) {
@@ -1114,24 +1127,17 @@ public class XmiCasSerializer {
private void stringArrayToElementList(
String featName,
- int addr,
+ StringArray stringArray,
List<? super XmlElementNameAndContents> resultList) {
- if (addr == CASImpl.NULL) {
+ if (stringArray == null) {
return;
}
-
// it is not safe to use a space-separated attribute, which would
// break for strings containing spaces. So use child elements instead.
- final int size = cds.cas.ll_getArraySize(addr);
- // if (size > 0 && !arrayAndListFSs.put(addr, addr)) {
- // reportWarning("Warning: multiple references to a String array. Reference identity will not be preserved.");
- // }
- int pos = cds.cas.getArrayStartAddress(addr);
- for (int j = 0; j < size; j++) {
- String s = cds.cas.getStringForCode(cds.cas.getHeapValue(pos));
+
+ for (String s : stringArray._getTheArray()) {
resultList.add(new XmlElementNameAndContents(new XmlElementName(null, featName, featName),
- s));
- ++pos;
+ s));
}
}
@@ -1147,20 +1153,16 @@ public class XmiCasSerializer {
* @return String representation of the array, or null if passed in CASImpl.NULL
* @throws SAXException passthru
*/
- private String listToString(int curNode) throws SAXException {
- if (curNode == CASImpl.NULL) {
+ private String listToString(CommonList fs) throws SAXException {
+ if (fs == null) {
return null; // different from ""
}
final StringBuilder sb = new StringBuilder();
- cds.listUtils.anyListToOutput(curNode, cds.sharedData, cds, new ListUtils.ListOutput() {
- @Override
- void append(String item) {
- if (sb.length() > 0) {
- sb.append(' ');
- }
- sb.append(item);
- }
- });
+ fs.anyListToOutput(cds.sharedData, cds, s -> {if (sb.length() > 0) {
+ sb.append(' ').append(s);
+ } else {
+ sb.append(s);
+ }});
return sb.toString();
}
@@ -1232,9 +1234,9 @@ public class XmiCasSerializer {
protected void addNameSpace(XmlElementName xmlElementName) {};
@Override
- protected boolean writeFsStart(int addr, int typeCode /* ignored */) {
+ protected boolean writeFsStart(TOP fs, int typeCode /* ignored */) {
workAttrs.clear();
- addAttribute(workAttrs, ID_ATTR_NAME, cds.getXmiId(addr));
+ addAttribute(workAttrs, ID_ATTR_NAME, cds.getXmiId(fs));
return false; // ignored
}
@@ -1288,7 +1290,7 @@ public class XmiCasSerializer {
protected void writeEndOfIndividualFs() {}
@Override
- protected void writeFsRef(int addr) throws Exception {} // only for JSON, not used here
+ protected void writeFsRef(TOP fs) throws Exception {} // only for JSON, not used here
}
@@ -1297,5 +1299,4 @@ public class XmiCasSerializer {
// return new XmiDocSerializer(ch, cas, null);
// }
-
}
Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiSerializationSharedData.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiSerializationSharedData.java?rev=1715964&r1=1715963&r2=1715964&view=diff
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiSerializationSharedData.java (original)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/XmiSerializationSharedData.java Mon Nov 23 21:32:16 2015
@@ -20,18 +20,22 @@
package org.apache.uima.cas.impl;
import java.util.ArrayList;
-import java.util.BitSet;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import org.apache.uima.internal.util.Int2IntHashMap;
-import org.apache.uima.internal.util.IntListIterator;
+import org.apache.uima.internal.util.Int2ObjHashMap;
+import org.apache.uima.internal.util.Obj2IntIdentityHashMap;
import org.apache.uima.internal.util.XmlAttribute;
import org.apache.uima.internal.util.XmlElementName;
import org.apache.uima.internal.util.XmlElementNameAndContents;
+import org.apache.uima.jcas.cas.FSArray;
+import org.apache.uima.jcas.cas.TOP;
+import org.xml.sax.Attributes;
/**
* A container for data that is shared between the {@link XmiCasSerializer} and the {@link XmiCasDeserializer}.
@@ -51,25 +55,33 @@ import org.apache.uima.internal.util.Xml
* <li>After calling the XmiCasSerializer and passing an <code>XmiSerializationSharedData</code>, you can call the
* {@link #getMaxXmiId()} method to get the maximum xmi:id value in the serialized CAS. This feature, along with the consistency of
* xmi:id values, allows merging multiple XMI documents into a single CAS. See TODO.</li>
- * </ul>
+ * </ul>
+ *
+ * <p>Inner classes are used to hold information about Feature Structure elements, both for out-of-typesystem data, and also
+ * when deserializing pre V3 xmi serializations where the Sofa FS are not guaranteed to come before other Feature Structures that
+ * depend on them.</p>
*
*/
public class XmiSerializationSharedData {
/**
+ * V3: FSs have an id - use that. (Assumes id's are internal ones)
+ *
* A map from FeatureStructure address to xmi:id. This is populated whenever
* an XMI element is serialized or deserialized. It is used by the
* getXmiId() method, which is done to ensure a consistent ID for each FS
* address across multiple serializations.
*/
- private Int2IntHashMap fsAddrToXmiIdMap = new Int2IntHashMap();
+ private Obj2IntIdentityHashMap<TOP> fsToXmiId = new Obj2IntIdentityHashMap<>(TOP.class, TOP.singleton);
- /**
+ /**
+ * V3: use the cas's getFsFromId (Assumes id's are internal ones)
+ *
* A map from xmi:id to FeatureStructure address. This is populated whenever
* an XMI element is serialized or deserialized. It is used by the
* getFsAddrForXmiId() method, necessary to support merging multiple XMI
* CASes into the same CAS object.
**/
- private Int2IntHashMap xmiIdToFsAddrMap = new Int2IntHashMap();
+ private Int2ObjHashMap<TOP> xmiIdToFs = new Int2ObjHashMap<>(TOP.class);
/**
* List of OotsElementData objects, each of which captures information about
@@ -78,23 +90,25 @@ public class XmiSerializationSharedData
private List<OotsElementData> ootsFs = new ArrayList<OotsElementData>();
/**
- * Map that from the xmi:id (String) of a Sofa to a List of xmi:id's (Strings) for
+ * Map from the xmi:id (String) of a Sofa to a List of xmi:id's (Strings) for
* the out-of-typesystem FSs that are members of that Sofa's view.
*/
private Map<String, List<String>> ootsViewMembers = new HashMap<String, List<String>>();
- /** Map from Feature Structure address (Integer) to OotsElementData object, capturing information
+ /** Map from Feature Structures to OotsElementData object, capturing information
* about out-of-typesystem features that were part of an in-typesystem FS. These include both
* features not defined in the typesystem and features that are references to out-of-typesystem
* elements. This information needs to be included when the FS is subsequently serialized.
*/
- private Map<Integer, OotsElementData> ootsFeatures = new HashMap<Integer, OotsElementData>();
+ private Map<TOP, OotsElementData> ootsFeatures = new IdentityHashMap<>();
- /** Map from Feature Structure address (Integer) of an FSArray to a list of
+ /**
+ * V3: Key is FSArray
+ * Map from an FSArray to a list of
* {@link XmiArrayElement} objects, each of which holds an index and an xmi:id
* for an out-of-typesystem array element.
*/
- private Map<Integer, List<XmiArrayElement>> ootsArrayElements = new HashMap<Integer, List<XmiArrayElement>>();
+ private Map<FSArray, List<XmiArrayElement>> ootsArrayElements = new HashMap<>();
/**
* The maximum XMI ID used in the serialization. Used to generate unique IDs if needed.
@@ -103,31 +117,46 @@ public class XmiSerializationSharedData
/**
+ * V3: key is TOP, value is TOP
+ *
* Map from FS address of a non-shared multi-valued (Array/List) FS to the
* FS address of the encompassing FS which has a feature whose value is this multi-valued FS.
* Used when deserializing a Delta CAS to find and serialize the encompassing FS when
* the non-shared array/list FS is modified.
*/
- Int2IntHashMap nonsharedfeatureIdToFSId = new Int2IntHashMap();
+ Map<TOP, TOP> nonsharedfeatureIdToFSId = new IdentityHashMap<>();
+// Int2IntHashMap nonsharedfeatureIdToFSId = new Int2IntHashMap();
- void addIdMapping(int fsAddr, int xmiId) {
- fsAddrToXmiIdMap.put(fsAddr, xmiId);
- xmiIdToFsAddrMap.put(xmiId, fsAddr);
+ void addIdMapping(TOP fs, int xmiId) {
+ fsToXmiId.put(fs, xmiId);
+ xmiIdToFs.put(xmiId, fs);
if (xmiId > maxXmiId)
maxXmiId = xmiId;
}
- String getXmiId(int fsAddr) {
- return Integer.toString(getXmiIdAsInt(fsAddr));
+ public String getXmiId(TOP fs) {
+ return Integer.toString(getXmiIdAsInt(fs));
}
- int getXmiIdAsInt(int fsAddr) {
+ /**
+ * Gets the FS address that corresponds to the given xmi:id, in the most
+ * recent serialization or deserialization.
+ *
+ * @param xmiId an xmi:id from the most recent XMI CAS that was serialized
+ * or deserialized.
+ * @return the FeatureStructure corresponding to that xmi:id, null if none.
+ */
+ public TOP getFsForXmiId(int xmiId) {
+ return (TOP) xmiIdToFs.get(xmiId);
+ }
+
+ int getXmiIdAsInt(TOP fs) {
// see if we already have a mapping
- int xmiId = fsAddrToXmiIdMap.get(fsAddr);
+ int xmiId = fsToXmiId.get(fs);
if (xmiId == 0) {
// to be sure we get a unique Id, increment maxXmiId and use that
xmiId = ++maxXmiId;
- addIdMapping(fsAddr, xmiId);
+ addIdMapping(fs, xmiId);
}
return xmiId;
}
@@ -140,19 +169,19 @@ public class XmiSerializationSharedData
return maxXmiId;
}
- /**
- * Gets the FS address that corresponds to the given xmi:id, in the most
- * recent serialization or deserialization.
- *
- * @param xmiId an xmi:id from the most recent XMI CAS that was serialized
- * or deserialized.
- * @return the FS address of the FeatureStructure corresponding to that
- * xmi:id, -1 if none.
- */
- public int getFsAddrForXmiId(int xmiId) {
- final int addr = xmiIdToFsAddrMap.get(xmiId);
- return addr == 0 ? -1 : addr;
- }
+// /**
+// * Gets the FS address that corresponds to the given xmi:id, in the most
+// * recent serialization or deserialization.
+// *
+// * @param xmiId an xmi:id from the most recent XMI CAS that was serialized
+// * or deserialized.
+// * @return the FS address of the FeatureStructure corresponding to that
+// * xmi:id, -1 if none.
+// */
+// public int getFsAddrForXmiId(int xmiId) {
+// final int addr = xmiIdToFs.get(xmiId);
+// return addr == 0 ? -1 : addr;
+// }
/**
* Clears the ID mapping information that was populated in
@@ -160,8 +189,8 @@ public class XmiSerializationSharedData
* TODO: maybe a more general reset that resets other things?
*/
public void clearIdMap() {
- fsAddrToXmiIdMap.clear();
- xmiIdToFsAddrMap.clear();
+ fsToXmiId.clear();
+ xmiIdToFs.clear();
nonsharedfeatureIdToFSId.clear();
maxXmiId = 0;
}
@@ -221,12 +250,11 @@ public class XmiSerializationSharedData
* @param featName name of the feature
* @param featVal value of the feature, as a string
*/
- public void addOutOfTypeSystemAttribute(int addr, String featName, String featVal) {
- Integer key = Integer.valueOf(addr);
- OotsElementData oed = this.ootsFeatures.get(key);
+ public void addOutOfTypeSystemAttribute(TOP fs, String featName, String featVal) {
+ OotsElementData oed = this.ootsFeatures.get(fs);
if (oed == null) {
- oed = new OotsElementData();
- this.ootsFeatures.put(key, oed);
+ oed = new OotsElementData(null, null, -1, -1);
+ this.ootsFeatures.put(fs, oed);
}
oed.attributes.add(new XmlAttribute(featName, featVal));
}
@@ -238,12 +266,11 @@ public class XmiSerializationSharedData
* @param featName name of the feature (element tag name)
* @param featVals values of the feature, as a List of strings
*/
- public void addOutOfTypeSystemChildElements(int addr, String featName, List<String> featVals) {
- Integer key = Integer.valueOf(addr);
- OotsElementData oed = this.ootsFeatures.get(key);
+ public void addOutOfTypeSystemChildElements(TOP fs, String featName, List<String> featVals) {
+ OotsElementData oed = this.ootsFeatures.get(fs);
if (oed == null) {
- oed = new OotsElementData();
- this.ootsFeatures.put(key, oed);
+ oed = new OotsElementData(null, null, -1, -1);
+ this.ootsFeatures.put(fs, oed);
}
Iterator<String> iter = featVals.iterator();
XmlElementName elemName = new XmlElementName(null,featName,featName);
@@ -259,17 +286,18 @@ public class XmiSerializationSharedData
* @return object containing information about out-of-typesystem features
* (both attributes and child elements)
*/
- public OotsElementData getOutOfTypeSystemFeatures(int addr) {
- Integer key = Integer.valueOf(addr);
- return this.ootsFeatures.get(key);
+ public OotsElementData getOutOfTypeSystemFeatures(TOP fs) {
+ return this.ootsFeatures.get(fs);
}
/**
* Get all FS Addresses that have been added to the id map.
* @return an array containing all the FS addresses
*/
- public int[] getAllFsAddressesInIdMap() {
- return fsAddrToXmiIdMap.getSortedKeys();
+ public TOP[] getAndSortByIdAllFSsInIdMap() {
+ TOP[] keys= fsToXmiId.getKeys();
+ Arrays.sort(keys, (fs1, fs2) -> Integer.compare(fs1._id, fs2._id));
+ return keys;
}
/**
@@ -279,8 +307,8 @@ public class XmiSerializationSharedData
* holds the index and xmi:id of an array element that is a
* reference to an out-of-typesystem FS.
*/
- public List<XmiArrayElement> getOutOfTypeSystemArrayElements(int addr) {
- return this.ootsArrayElements.get(Integer.valueOf(addr));
+ public List<XmiArrayElement> getOutOfTypeSystemArrayElements(FSArray fsarray) {
+ return this.ootsArrayElements.get(fsarray);
}
public boolean hasOutOfTypeSystemArrayElements() {
@@ -294,12 +322,11 @@ public class XmiSerializationSharedData
* @param index index into array
* @param xmiId xmi:id of the out-of-typesystem element that is the value at the given index
*/
- public void addOutOfTypeSystemArrayElement(int addr, int index, int xmiId) {
- Integer key = Integer.valueOf(addr);
- List<XmiArrayElement> list = this.ootsArrayElements.get(key);
+ public void addOutOfTypeSystemArrayElement(FSArray fsarray, int index, int xmiId) {
+ List<XmiArrayElement> list = this.ootsArrayElements.get(fsarray);
if (list == null) {
list = new ArrayList<XmiArrayElement>();
- this.ootsArrayElements.put(key, list);
+ this.ootsArrayElements.put(fsarray, list);
}
list.add(new XmiArrayElement(index, Integer.toString(xmiId)));
}
@@ -311,82 +338,165 @@ public class XmiSerializationSharedData
* @param nonsharedFSAddr - fs address of non-shared multi-valued feature value
* @param fsAddr - fs address of encompassing featurestructure
*/
- public void addNonsharedRefToFSMapping(int nonsharedFSAddr, int fsAddr) {
- this.nonsharedfeatureIdToFSId.put(nonsharedFSAddr, fsAddr);
+ public void addNonsharedRefToFSMapping(TOP nonsharedFS, TOP fs) {
+ this.nonsharedfeatureIdToFSId.put(nonsharedFS, fs);
}
/**
*
* @return the non-shared featureId to FS Id key set
*/
- public int[] getNonsharedMulitValuedFSs() {
- return this.nonsharedfeatureIdToFSId.getSortedKeys();
+ public TOP[] getNonsharedMulitValuedFSs() {
+ return getSortedKeys(this.nonsharedfeatureIdToFSId);
+ }
+
+ private TOP[] getSortedKeys(Map<TOP, ?> map) {
+ TOP[] keys = map.keySet().toArray(new TOP[map.size()]);
+ Arrays.sort(keys, (fs1, fs2) -> Integer.compare(fs1._id, fs2._id));
+ return keys;
}
/**
*
- * @param nonsharedFS an id of a nonsharedFS
- * @return the int handle to the encompassing FS or -1 if not found
+ * @param nonsharedFS a nonsharedFS
+ * @return the encompassing FS or null if not found
*/
- public int getEncompassingFS(int nonsharedFS) {
- int addr = nonsharedfeatureIdToFSId.get(nonsharedFS);
- return addr == 0 ? -1 : addr;
+ public TOP getEncompassingFS(TOP nonsharedFS) {
+ return nonsharedfeatureIdToFSId.get(nonsharedFS);
}
/**
* For debugging purposes only.
*/
- void checkForDups() {
- BitSet ids = new BitSet();
- IntListIterator iter = fsAddrToXmiIdMap.keyIterator();
- while (iter.hasNext()) {
- int xmiId = iter.next();
- if (ids.get(xmiId)) {
- throw new RuntimeException("Duplicate ID " + xmiId + "!");
- }
- ids.set(xmiId);
- }
- }
+// void checkForDups() {
+// BitSet ids = new BitSet();
+// IntListIterator iter = fsToXmiId.keyIterator();
+// while (iter.hasNext()) {
+// int xmiId = iter.next();
+// if (ids.get(xmiId)) {
+// throw new RuntimeException("Duplicate ID " + xmiId + "!");
+// }
+// ids.set(xmiId);
+// }
+// }
/**
* For debugging purposes only.
*/
public String toString() {
- StringBuffer buf = new StringBuffer();
- int[] keys = fsAddrToXmiIdMap.getSortedKeys();
- for (int i = 0; i < keys.length; i++) {
- buf.append(keys[i]).append(": ").append(fsAddrToXmiIdMap.get(keys[i])).append('\n');
+ StringBuilder buf = new StringBuilder();
+ TOP[] keys = getAndSortByIdAllFSsInIdMap();
+ for (TOP fs : keys) {
+ buf.append(fs.id()).append(": ").append(fsToXmiId.get(fs)).append('\n');
}
return buf.toString();
}
/**
- * Data structure holding all information about an XMI element
- * containing an out-of-typesystem FS.
+ * <p>Data structure holding all information about an XMI element
+ * containing an out-of-typesystem FS.</p>
+ *
+ * <p>Also used to hold information for deferring deserialization of subtypes of AnnotationBase when the sofa
+ * is not yet known</p>
+ *
*/
- static class OotsElementData {
+ public static class OotsElementData {
/**
* xmi:id of the element
*/
- String xmiId;
+ final String xmiId;
/**
* Name of the element, including XML namespace.
*/
- XmlElementName elementName;
+ final XmlElementName elementName;
/**
* List of XmlAttribute objects each holding name and value of an attribute.
*/
- List<XmlAttribute> attributes = new ArrayList<XmlAttribute>();
+ final public List<XmlAttribute> attributes = new ArrayList<XmlAttribute>();
/**
* List of XmlElementNameAndContents objects each describing one of the
* child elements representing features of this out-of-typesystem element.
*/
- List<XmlElementNameAndContents> childElements = new ArrayList<XmlElementNameAndContents>();
+ final List<XmlElementNameAndContents> childElements = new ArrayList<XmlElementNameAndContents>();
+
+ final int lineNumber;
+
+ final int colNumber;
+
+ public OotsElementData(String xmiId, XmlElementName elementName) {
+ this(xmiId, elementName, -1, -1);
+ }
+
+ public OotsElementData(String xmiId, XmlElementName elementName, int lineNumber, int colNumber) {
+ this.xmiId = xmiId;
+ this.elementName = elementName;
+ this.lineNumber = lineNumber;
+ this.colNumber = colNumber;
+ }
+
+ public Attributes getAttributes() {
+ return new Attributes() {
+
+ @Override
+ public int getLength() { return attributes.size(); }
+
+ @Override
+ public String getURI(int index) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public String getLocalName(int index) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public String getQName(int index) { return attributes.get(index).name; }
+
+
+ @Override
+ public String getType(int index) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public String getValue(int index) { return attributes.get(index).value; }
+
+ @Override
+ public int getIndex(String uri, String localName) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public int getIndex(String qName) {
+ int i = 0;
+ for (XmlAttribute attr : attributes) {
+ if (attr.name.equals(qName)) {
+ return i;
+ }
+ i++;
+ }
+ return -1;
+ }
+
+ @Override
+ public String getType(String uri, String localName) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public String getType(String qName) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public String getValue(String uri, String localName) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public String getValue(String qName) {
+ for (XmlAttribute attr : attributes) {
+ if (attr.name.equals(qName)) {
+ return attr.value;
+ }
+ }
+ return null;
+ }
+ };
+ }
}
+
/**
* Data structure holding the index and the xmi:id of an array or list element that
* is a reference to an out-of-typesystem FS.