You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by sc...@apache.org on 2016/01/04 03:08:40 UTC
svn commit: r1722785 -
/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/cas_data/impl/CasComparer.java
Author: schor
Date: Mon Jan 4 02:08:40 2016
New Revision: 1722785
URL: http://svn.apache.org/viewvc?rev=1722785&view=rev
Log:
[UIMA-4674] update cas compare - more specific generics, identity hashmaps for FSs
Modified:
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/cas_data/impl/CasComparer.java
Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/cas_data/impl/CasComparer.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/cas_data/impl/CasComparer.java?rev=1722785&r1=1722784&r2=1722785&view=diff
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/cas_data/impl/CasComparer.java (original)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/test/java/org/apache/uima/cas_data/impl/CasComparer.java Mon Jan 4 02:08:40 2016
@@ -23,15 +23,15 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.ConcurrentModificationException;
-import java.util.HashSet;
+import java.util.IdentityHashMap;
import java.util.List;
import java.util.Set;
+import java.util.function.IntUnaryOperator;
import org.apache.uima.cas.ArrayFS;
import org.apache.uima.cas.BooleanArrayFS;
import org.apache.uima.cas.ByteArrayFS;
import org.apache.uima.cas.CAS;
-import org.apache.uima.cas.CommonArrayFS;
import org.apache.uima.cas.DoubleArrayFS;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.cas.Feature;
@@ -44,7 +44,24 @@ import org.apache.uima.cas.SofaFS;
import org.apache.uima.cas.StringArrayFS;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
+import org.apache.uima.cas.impl.FeatureImpl;
+import org.apache.uima.cas.impl.SlotKinds.SlotKind;
+import org.apache.uima.cas.impl.TypeImpl;
import org.apache.uima.internal.util.IntVector;
+import org.apache.uima.jcas.cas.BooleanArray;
+import org.apache.uima.jcas.cas.ByteArray;
+import org.apache.uima.jcas.cas.CommonArray;
+import org.apache.uima.jcas.cas.DoubleArray;
+import org.apache.uima.jcas.cas.EmptyList;
+import org.apache.uima.jcas.cas.FSArray;
+import org.apache.uima.jcas.cas.FloatArray;
+import org.apache.uima.jcas.cas.IntegerArray;
+import org.apache.uima.jcas.cas.LongArray;
+import org.apache.uima.jcas.cas.ShortArray;
+import org.apache.uima.jcas.cas.Sofa;
+import org.apache.uima.jcas.cas.StringArray;
+import org.apache.uima.jcas.cas.TOP;
+import org.apache.uima.util.Misc;
import junit.framework.Assert;
@@ -61,21 +78,29 @@ public class CasComparer {
enum ARRAY_TYPE {
FS, STRING, BOOLEAN, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE,
}
+
+ final private Set<TOP> sortCompareSeen = Collections.newSetFromMap(new IdentityHashMap<>());
+ final private Set<TOP> alreadyCompared = Collections.newSetFromMap(new IdentityHashMap<>());
public static void assertEquals(CAS c1, CAS c2) {
+ new CasComparer().assertEqualsInner(c1, c2);
+ }
+
+ public void assertEqualsInner(CAS c1, CAS c2) {
+ alreadyCompared.clear();
// this code handles initial views with no SofaFS
CAS initialView1 = c1.getView(CAS.NAME_DEFAULT_SOFA);
CAS initialView2 = c2.getView(CAS.NAME_DEFAULT_SOFA);
- assertEqualViews(initialView1, initialView2);
+ assertEqualViewsInner(initialView1, initialView2);
// this code skips the initial view, if it doesn't have a sofa FS
- FSIterator<SofaFS> sofaIter = c1.getSofaIterator();
+ FSIterator<Sofa> sofaIter = c1.getSofaIterator();
int c1Sofas = 0;
while (sofaIter.hasNext()) {
SofaFS sofa = sofaIter.next();
CAS tcas1 = c1.getView(sofa);
CAS tcas2 = c2.getView(tcas1.getViewName());
- assertEqualViews(tcas1, tcas2);
+ assertEqualViewsInner(tcas1, tcas2);
c1Sofas++;
}
sofaIter = c2.getSofaIterator();
@@ -89,25 +114,25 @@ public class CasComparer {
public static void assertEqualViews(CAS c1, CAS c2) {
CasComparer instance = new CasComparer();
- instance.assertEqualViews(c1, c2, new HashSet<FeatureStructure>());
+ instance.assertEqualViewsInner(c1, c2);
}
public static void assertEquals(FeatureStructure fs1, FeatureStructure fs2) {
CasComparer instance = new CasComparer();
- Assert.assertTrue(0 == instance.compare1(fs1, fs2));
+ instance.assertEqualsInner((TOP)fs1, (TOP)fs2);
}
- private void assertEqualViews(CAS c1, CAS c2, Set<FeatureStructure> visited) {
+ private void assertEqualViewsInner(CAS c1, CAS c2) {
// allow for different ordering in the getAllIndexedFSs
- List<FeatureStructure> list1 = populate(c1.getIndexRepository().getAllIndexedFS(c1.getTypeSystem().getTopType()), visited);
- List<FeatureStructure> list2 = populate(c2.getIndexRepository().getAllIndexedFS(c2.getTypeSystem().getTopType()), visited);
+ List<TOP> list1 = populate(c1.getIndexRepository().getAllIndexedFS(c1.getTypeSystem().getTopType()), alreadyCompared);
+ List<TOP> list2 = populate(c2.getIndexRepository().getAllIndexedFS(c2.getTypeSystem().getTopType()), alreadyCompared);
Assert.assertEquals(list1.size(), list2.size());
- isSortUse = true; // while sorting
+ isSortUse = true; // while sorting; i.e., for next two calls. Affects how visited is used
Collections.sort(list1, fsComparator);
Collections.sort(list2, fsComparator);
@@ -115,7 +140,7 @@ public class CasComparer {
int i = 0;
try {
for (; i < list1.size(); i++) {
- compare1(list1.get(i), list2.get(i), visited);
+ compare1(list1.get(i), list2.get(i), alreadyCompared);
}
} catch (ConcurrentModificationException e) {
Assert.fail();
@@ -127,14 +152,9 @@ public class CasComparer {
*/
private boolean isSortUse = true;
private TypeSystem ts;
- private Type casStringType;
+// private Type casStringType;
- private Comparator<FeatureStructure> fsComparator = new Comparator<FeatureStructure>() {
- @Override
- public int compare(FeatureStructure o1, FeatureStructure o2) {
- return compare1(o1, o2);
- }
- };
+ private Comparator<TOP> fsComparator = (o1, o2) -> compare1(o1, o2);
/**
* Comparator that establishes an ordering among all FSs in a view.
@@ -144,41 +164,114 @@ public class CasComparer {
* @param fs2
*/
- public int compare1(FeatureStructure fs1, FeatureStructure fs2) {
- return compare1(fs1, fs2, new HashSet<FeatureStructure>());
+ public int compare1(TOP fs1, TOP fs2) {
+ sortCompareSeen.clear();
+ return compare1(fs1, fs2, sortCompareSeen);
}
- private int compare1(FeatureStructure fs1, FeatureStructure fs2, Set<FeatureStructure> visited) {
- if (fs1 == null && fs2 == null) {
- return 0;
+ private void assertEqualsInner(TOP fs1, TOP fs2) {
+ alreadyCompared.clear();
+ chkEqual(compare1(fs1, fs2, alreadyCompared), "Feature Structures not equal: %n%s%n%s", fs1, fs2);
+ }
+
+ /**
+ *
+ * @param fs1
+ * @param fs2
+ * @param visited when called for sorting FSs, is sortCompareSeen(cleared);
+ * when called for comparing for equality, holds FSs already compared in other views
+ * @return
+ */
+ private int compare1(TOP fs1, TOP fs2, Set<TOP> visited) {
+ if (!isSortUse) { // only do null check for non- sort use
+ if (fs1 == null && fs2 == null) {
+ return 0;
+ }
+ if (fs1 == null) return chkEqual(-1, "fs1 was null and fs2 was not");
+ if (fs2 == null) return chkEqual(1, "fs2 was null and fs1 was not");
}
- if (fs1 == null) return chkEqual(-1, "fs1 was null and fs2 was not");
- if (fs2 == null) return chkEqual(1, "fs2 was null and fs1 was not");
- if (!visited.add(fs1)) {
+ boolean wasPresent1 = !visited.add(fs1);
+ boolean wasPresent2 = !visited.add(fs2);
+
+ if (wasPresent1 && wasPresent2) {
return 0; // already checked and found equal
}
+
+ if (!wasPresent1 && !wasPresent2) {
+ int r;
+ TypeImpl t1, t2;
+ if (0 != (r = compStr((t1 = (TypeImpl) fs1.getType()).getName(), (t2 = (TypeImpl) fs2.getType()).getName()))) {
+ return chkEqual(r, "Types of FSs are different: Type1 = %s, Type2 = %s", t1, t2);
+ }
+ // types are the same
+
+ if (CAS.TYPE_NAME_SOFA.equals(t1.getName())) {
+ if (isSortUse) {
+ return Integer.compare(((Sofa)fs1).getSofaNum(), ((Sofa)fs2).getSofaNum());
+ }
+ return 0; // skip comparing sofa so this routine can be used for cas copier testing
+ }
+
+ if (t1.isArray()) {
+ final int len1 = ((CommonArray)fs1).size();
+ if (0 != (r = Integer.compare(len1, ((CommonArray)fs2).size()))) {
+ return r;
+ }
+
+ SlotKind kind = t1.getComponentSlotKind();
- int r;
- Type t1, t2;
- if (0 != (r = compStr((t1 = fs1.getType()).getName(), (t2 = fs2.getType()).getName()))) {
- return chkEqual(r, "Types of FSs are different: Type1 = %s, Type2 = %s", t1, t2);
+ switch(kind) {
+ case Slot_BooleanRef: return compareAllArrayElements(len1, i -> Boolean.compare(((BooleanArray )fs1).get(i), ((BooleanArray)fs2).get(i)), "Miscompare Boolean Arrays %n%s%n%s", fs1, fs2);
+ case Slot_ByteRef: return compareAllArrayElements(len1, i -> Byte .compare(((ByteArray )fs1).get(i), ((ByteArray )fs2).get(i)), "Miscompare Byte Arrays %n%s%n%s" , fs1, fs2);
+ case Slot_ShortRef: return compareAllArrayElements(len1, i -> Short .compare(((ShortArray )fs1).get(i), ((ShortArray )fs2).get(i)), "Miscompare Short Arrays %n%s%n%s" , fs1, fs2);
+ case Slot_Int: return compareAllArrayElements (len1, i -> Integer.compare(((IntegerArray )fs1).get(i), ((IntegerArray)fs2).get(i)), "Miscompare Integer Arrays %n%s%n%s", fs1, fs2);
+ case Slot_LongRef: return compareAllArrayElements(len1, i -> Long .compare(((LongArray )fs1).get(i), ((LongArray )fs2).get(i)), "Miscompare Long Arrays %n%s%n%s", fs1, fs2);
+ case Slot_Float: return compareAllArrayElements (len1, i -> Integer.compare(Float.floatToRawIntBits (((FloatArray )fs1).get(i)),
+ Float.floatToRawIntBits (((FloatArray )fs2).get(i))), "Miscompare Float Arrays %n%s%n%s", fs1, fs2);
+ case Slot_DoubleRef: return compareAllArrayElements(len1, i -> Long .compare(Double.doubleToRawLongBits(((DoubleArray)fs1).get(i)),
+ Double.doubleToRawLongBits(((DoubleArray)fs2).get(i))), "Miscompare Double Arrays %n%s%n%s", fs1, fs2);
+ case Slot_HeapRef: return compareAllArrayElements(len1, i -> compare1(((FSArray )fs1).get(i), ((FSArray )fs2).get(i), visited), "Miscompare FS Arrays %n%s%n%s", fs1, fs2);
+ case Slot_StrRef: return compareAllArrayElements(len1, i -> Misc.compareStrings(((StringArray )fs1).get(i), ((StringArray )fs2).get(i)), "Miscompare String Arrays %n%s%n%s", fs1, fs2);
+ default:
+ assert(false); return 0; // only to avoid a compile error
+ }
+ }
+
+ ts = fs1.getCAS().getTypeSystem();
+ return compareFeatures(fs1, fs2, t1.getFeatureImpls(), t2.getFeatureImpls(), visited);
}
- // types are the same
- if (CAS.TYPE_NAME_SOFA.equals(t1.getName())) {
- return 0; // skip comparing sofa so this routine can be used for cas copier testing
+ // getting here: one was already traversed, the other not. Possible use case:
+ // fs1 is a list with a loop; fs2 is a list without a loop
+ // arbitrarily return the one with a loop first
+
+ if (fs1 instanceof EmptyList) {
+ return 0; // allow different or shared EmptyList instances to compare equal
+ // because some deserializers or user code can create them as shared or not
}
-
- ts = fs1.getCAS().getTypeSystem();
- casStringType = ts.getType(CAS.TYPE_NAME_STRING);
- return compareFeatures(fs1, fs2, t1.getFeatures(), t2.getFeatures(), visited);
+ if (wasPresent1) {
+ return chkEqual(-1, "First element had a ref loop %s%n, second didn't so far %s", fs1, fs2);
+ }
+ return chkEqual(-1, "Second element had a ref loop %s%n, first didn't so far %s", fs2, fs1);
+
+ }
+
+ private int compareAllArrayElements(final int len, IntUnaryOperator c, String msg, TOP fs1, TOP fs2) {
+ for (int i = 0; i < len; i++) {
+ int r = chkEqual(c.applyAsInt(i), String.format(msg, fs1, fs2));
+ if (0 != r) {
+ return r;
+ }
+ }
+ return 0;
}
+
private int compareFeatures(
- FeatureStructure fs1, FeatureStructure fs2,
- List<Feature> feats1, List<Feature> feats2,
- Set<FeatureStructure> visited) {
+ TOP fs1, TOP fs2,
+ List<FeatureImpl> feats1, List<FeatureImpl> feats2,
+ Set<TOP> visited) {
IntVector fsCompares = new IntVector(2);
for (int i = 0; i < feats1.size(); i++) {
@@ -193,7 +286,7 @@ public class CasComparer {
// range types are the same
//String or subtypes of it
- if (ts.subsumes(casStringType, rangeType)) {
+ if (rangeType.isStringOrStringSubtype()) {
if (0 != (r = compStr(fs1.getStringValue(feat1), fs2.getStringValue(feat2)))) {
return chkEqual(r, "String features miscompare, s1 = %s, s2 = %s", fs1.getStringValue(feat1), fs2.getStringValue(feat2));
}
@@ -257,7 +350,7 @@ public class CasComparer {
}
private int compLong(long v1, long v2) {
- return chkEqual(Long.compare(v1, v2), "Intregal format number miscompare, v1 = %,d v2 = %,d", v1, v2);
+ return chkEqual(Long.compare(v1, v2), "Integral format number miscompare, v1 = %,d v2 = %,d", v1, v2);
}
private int compDouble(double v1, double v2) {
@@ -275,13 +368,13 @@ public class CasComparer {
}
/*
- * When populating, skip items already visted and compared in other views
+ * When populating, skip items already visted and compared in other views (but always include sofas)
*/
- private static List<FeatureStructure> populate(FSIterator<FeatureStructure> it, Set<FeatureStructure> visited) {
- List<FeatureStructure> s = new ArrayList<FeatureStructure>();
+ private static List<TOP> populate(FSIterator<TOP> it, Set<TOP> visited) {
+ List<TOP> s = new ArrayList<TOP>();
while (it.hasNext()) {
- FeatureStructure fs = it.next();
- if (!(fs instanceof SofaFS) && !visited.contains(fs)) {
+ TOP fs = it.next();
+ if (!(fs instanceof Sofa) && !visited.contains(fs)) {
s.add(fs);
}
}
@@ -289,17 +382,17 @@ public class CasComparer {
}
// returns true if the items were arrays
- private int compareArrayFSs(FeatureStructure arrayFS1fs, Feature feat1, FeatureStructure arrayFS2fs, Feature feat2, Set<FeatureStructure> visited) {
+ private int compareArrayFSs(TOP arrayFS1fs, Feature feat1, TOP arrayFS2fs, Feature feat2, Set<TOP> visited) {
- CommonArrayFS arrayFS1 = (CommonArrayFS)arrayFS1fs.getFeatureValue(feat1);
- CommonArrayFS arrayFS2 = (CommonArrayFS)arrayFS2fs.getFeatureValue(feat2);
+ CommonArray arrayFS1 = (CommonArray)arrayFS1fs.getFeatureValue(feat1);
+ CommonArray arrayFS2 = (CommonArray)arrayFS2fs.getFeatureValue(feat2);
if (null == arrayFS1 && null == arrayFS2)return 0; // are equal
if (null == arrayFS1) return chkEqual(-1, "Array FS1 is null, but Array FS2 is not");
if (null == arrayFS2) return chkEqual(-1, "Array FS2 is null, but Array FS1 is not");
int r, len;
- if (0 != (r = compLong(len = arrayFS1.size(), arrayFS2.size()))) {
+ if (0 != (r = Integer.compare(len = arrayFS1.size(), arrayFS2.size()))) {
return chkEqual(r, "ArrayFSs are different sizes, fs1 size is %d, fs2 size is %d", arrayFS1.size(), arrayFS2.size());
}
// are same size
@@ -309,7 +402,7 @@ public class CasComparer {
switch(getArrayType(arrayFS1)) {
case FS:
for (int j = 0; j < len; j++) {
- if (0 != (r = compare1(((ArrayFS)arrayFS1).get(j), ((ArrayFS)arrayFS2).get(j), visited))) return r;
+ if (0 != (r = compare1(((FSArray)arrayFS1).get(j), ((FSArray)arrayFS2).get(j), visited))) return r;
}
break;
case BOOLEAN:
@@ -358,7 +451,7 @@ public class CasComparer {
return 0; // all were equal
}
- private ARRAY_TYPE getArrayType(CommonArrayFS c) {
+ private ARRAY_TYPE getArrayType(CommonArray c) {
if (c instanceof ArrayFS) return ARRAY_TYPE.FS;
if (c instanceof StringArrayFS) return ARRAY_TYPE.STRING;
if (c instanceof BooleanArrayFS) return ARRAY_TYPE.BOOLEAN;
@@ -371,7 +464,7 @@ public class CasComparer {
return null;
}
- private int validateSameType(CommonArrayFS a1, CommonArrayFS a2) {
+ private int validateSameType(CommonArray a1, CommonArray a2) {
if (a1.getClass() == a2.getClass()) {
return 0;
}