Author: schor Date: Tue Jan 23 21:02:30 2018 New Revision: 1822059 URL: http://svn.apache.org/viewvc?rev=1822059&view=rev Log: [UIMA-5698] support JCas imputed features, fix test case
Modified: uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeImpl.java uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties uima/uv3/uimaj-v3/trunk/uimaj-core/src/test/java/org/apache/uima/cas/impl/JCasReinitTest.java Modified: uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java URL: http://svn.apache.org/viewvc/uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java?rev=1822059&r1=1822058&r2=1822059&view=diff ============================================================================== --- uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java (original) +++ uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java Tue Jan 23 21:02:30 2018 @@ -34,13 +34,11 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Parameter; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import org.apache.uima.UIMAFramework; import org.apache.uima.UIMARuntimeException; @@ -111,7 +109,9 @@ import org.apache.uima.util.Logger; */ public abstract class FSClassRegistry { // abstract to prevent instantiating; this class only has static methods - + +// private static final boolean IS_TRACE_AUGMENT_TS = false; +// private static final boolean IS_TIME_AUGMENT_FEATURES = false; /* ========================================================= */ /* This class has only static methods and fields */ /* To allow multi-threaded use, some fields are */ @@ -242,6 +242,10 @@ public abstract class FSClassRegistry { boolean isPearOverride(ClassLoader cl) { return jcasClass.getClassLoader().equals(cl); } + + TypeImpl getUimaType(TypeSystemImpl tsi) { + return tsi.getType(Misc.javaClassName2UimaTypeName(jcasClass.getName())); + } } /** @@ -249,7 +253,7 @@ public abstract class FSClassRegistry { * Used to expand the type system when the JCas defines more features * than the type system declares. */ - private static class JCasClassFeatureInfo { + static class JCasClassFeatureInfo { final String shortName; // rangename is byte.class, etc // or x.y.z.JCasClassName @@ -259,6 +263,17 @@ public abstract class FSClassRegistry { this.shortName = shortName; this.uimaRangeName = uimaRangeName; } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.format("JCasClassFeatureInfo feature: %s, range: %s", (shortName == null) ? "<null>" : shortName, + (uimaRangeName == null) ? "<null>" : uimaRangeName); + } + + } @@ -519,7 +534,7 @@ public abstract class FSClassRegistry { maybeLoadJCasAndSubtypes(tsi, subtype, jcci_or_copyDown, cl, type2jcci, callSites_toSync, lookup); } } - + /** * For a particular type name, get the JCasClassInfo * - by fetching the cached value @@ -540,21 +555,8 @@ public abstract class FSClassRegistry { JCasClassInfo jcci = type2jcci.get(ti.getJCasClassName()); if (jcci == null) { - // first time encountering this typename. Attempt to load a jcas class for this - // - if none, the next call returns null. - jcci = createJCasClassInfo(ti, cl, lookup); // does update of callsites if was able find JCas class - - if (null != jcci) { - // not done here, needs to be done additionally with different type systems - // done as part of conformance check -// if (!ti.isBuiltIn) { -// validateSuperClass(jcci, ti); -// } - type2jcci.put(ti.getJCasClassName(), jcci); - // non-creatable JCas types (e.g. FSList) do not have a valid jcasType - - } - } + jcci = maybeCreateJCasClassInfo(ti, cl, type2jcci, lookup); + } // do this setup for new type systems using previously loaded jcci, as well as // for new jccis @@ -564,6 +566,15 @@ public abstract class FSClassRegistry { return jcci; } + static JCasClassInfo maybeCreateJCasClassInfo(TypeImpl ti, ClassLoader cl, Map<String, JCasClassInfo> type2jcci, Lookup lookup) { + JCasClassInfo jcci = createJCasClassInfo(ti, cl, lookup); // does update of callsites if was able find JCas class + + if (null != jcci) { + type2jcci.put(ti.getJCasClassName(), jcci); + // non-creatable JCas types (e.g. FSList) do not have a valid jcasType + } + return jcci; + } public static JCasClassInfo createJCasClassInfo( TypeImpl ti, @@ -587,67 +598,133 @@ public abstract class FSClassRegistry { return null; } } -// if (ti.getTypeSystem().isCommitted()) { -// try { -// updateOrValidateAllCallSitesForJCasClass(clazz, ti, callSites_toSync); -// } finally { -// TypeSystemImpl.typeBeingLoadedThreadLocal.set(null); -// } -// } return createJCasClassInfo(clazz, ti, jcasType, lookup); } - static void augmentFeaturesFromJCas( - TypeImpl type, - ClassLoader cl, - TypeSystemImpl tsi, - Map<String, JCasClassInfo> type2jcci, - Lookup lookup) { - - if (type.isBuiltIn) { - return; - } - - /************************************************************************************** - * N O T E : * - * fixup the ordering of staticMergedFeatures: * - * - supers, then features introduced by this type. * - * - order may be "bad" if later feature merge introduced an additional feature * - **************************************************************************************/ - type.getFeatureImpls(); // done to reorder the features if needed, see above comment block - - if ( ! type.isTopType()) { - // skip for top level; no features there, but no super type either - type.getFeatureImpls(); // done for side effect of computingcomputeStaticMergedFeaturesList(); - - TypeSystemImpl.typeBeingLoadedThreadLocal.set(type); // only for supporting previous version of v3 jcas - - JCasClassInfo jcci = getOrCreateJCasClassInfo(type, cl, type2jcci, lookup); // no call site sync - if (jcci != null) { - for (JCasClassFeatureInfo f : jcci.features) { - FeatureImpl fi = type.getFeatureByBaseName(f.shortName); - if (fi == null) { - // feature is missing in the type, add it - // Range is either one of the uima primitives, or - // a fs reference. FS References could be to "unknown" types in this type system. - // If so, use TOP - TypeImpl rangeType = tsi.getType(f.uimaRangeName); - if (rangeType == null) { - rangeType = tsi.topType; - } - tsi.addFeature(f.shortName, type, rangeType); - } - } - } - } - - - for (TypeImpl subti : type.getDirectSubtypes()) { - augmentFeaturesFromJCas(subti, cl, tsi, type2jcci, lookup); - } - } +// static AtomicLong time = IS_TIME_AUGMENT_FEATURES ? new AtomicLong(0) : null; +// +// static { +// if (IS_TIME_AUGMENT_FEATURES) { +// Runtime.getRuntime().addShutdownHook(new Thread(null, () -> { +// System.out.format("Augment features from JCas time: %,d ms%n", +// time.get() / 1000000L); +// }, "show augment feat from jcas time")); +// } +// } +// +// static void augmentFeaturesFromJCas( +// TypeImpl type, +// ClassLoader cl, +// TypeSystemImpl tsi, +// Map<String, JCasClassInfo> type2jcci, +// Lookup lookup) { +// +// long startTime = 0; +// if (type.isTopType()) { +// if (IS_TIME_AUGMENT_FEATURES) { +// startTime = System.nanoTime(); +// } +// } else { +// /************************************************************************************** +// * N O T E : * +// * fixup the ordering of staticMergedFeatures: * +// * - supers, then features introduced by this type. * +// * - order may be "bad" if later feature merge introduced an additional feature * +// **************************************************************************************/ +// // skip for top level; no features there, but no super type either +// type.getFeatureImpls(); // done for side effect of computingcomputeStaticMergedFeaturesList(); +// } +// +// if ( //false && // debugging +// ! type.isBuiltIn) { +// +// if (IS_TRACE_AUGMENT_TS) System.out.println("trace Augment TS from JCas, for type " + type.getName()); +// +// +// TypeSystemImpl.typeBeingLoadedThreadLocal.set(type); // only for supporting previous version of v3 jcas +// +// JCasClassInfo jcci = getOrCreateJCasClassInfo(type, cl, type2jcci, lookup); // no call site sync +// if (jcci != null) { +// +// if (IS_TRACE_AUGMENT_TS) System.out.println(" trace Augment TS from JCas, adding features: " + Misc.ppList(Arrays.asList(jcci.features))); +// +// type.jcci = jcci; +// // also recurse for supertypes to load jcci's (in case some don't have uima type) +// // recursion stops when have jcci already +// jcci = type2jcci.get(jcci.jcasClass.getSuperclass()); +// if (null == jcci) { +// +// } +// +//// for (JCasClassFeatureInfo f : jcci.features) { +//// FeatureImpl fi = type.getFeatureByBaseName(f.shortName); +//// if (fi == null) { +//// +//// /* ********************************************************************************* +//// * feature is missing in the type, a pseudo feature for it * +//// * *********************************************************************************/ +//// +//// /* Range is either one of the uima primitives, or * +//// * a fs reference. FS References could be to "unknown" types in this type system. * +//// * If so, use TOP */ +//// TypeImpl rangeType = tsi.getType(f.uimaRangeName); +//// if (rangeType == null) { +//// rangeType = tsi.topType; +//// } +//// +//// /** Can't add feature to type "{0}" since it is feature final. */ +//// if (type.isFeatureFinal()) { +//// throw new CASAdminException(CASAdminException.TYPE_IS_FEATURE_FINAL, type.getName()); +//// } +//// +//// if (IS_TRACE_AUGMENT_TS) System.out.println(" trace Augment TS from JCas, for feature: " + f.shortName ); +//// +//// if (tsi.isInInt(rangeType)) { +//// type.jcas_added_int_slots.add(new FeatureImpl_jcas_only(f.shortName, rangeType)); +//// } else { +//// type.jcas_added_ref_slots.add(new FeatureImpl_jcas_only(f.shortName, rangeType)); +//// } +//// } +//// } +// } +// } +// +// if (IS_TRACE_AUGMENT_TS) System.out.println("trace Augment TS from JCas, for subtypes of type " + type.getName() + ", " + Misc.ppList(type.getDirectSubtypes())); +// for (TypeImpl subti : type.getDirectSubtypes()) { +// augmentFeaturesFromJCas(subti, cl, tsi, type2jcci, lookup); +// } +// +// if (IS_TIME_AUGMENT_FEATURES && type.isTopType()) { +// time.addAndGet(System.nanoTime() - startTime); +// } +// } - +// private void setTypeJcci(TypeImpl type, ClassLoader cl, Lookup lookup, Map<String, JCasClassInfo> type2jcci) { +// if (IS_TRACE_AUGMENT_TS) System.out.println("trace Augment TS from JCas, for type " + type.getName()); +// +// TypeSystemImpl.typeBeingLoadedThreadLocal.set(type); // only for supporting previous version of v3 jcas +// +// JCasClassInfo jcci = getOrCreateJCasClassInfo(type, cl, type2jcci, lookup); // no call site sync +// if (jcci != null) { +// +// if (IS_TRACE_AUGMENT_TS) System.out.println(" trace Augment TS from JCas, adding features: " + Misc.ppList(Arrays.asList(jcci.features))); +// +// type.jcci = jcci; +// // also recurse for supertypes to load jcci's (in case some don't have uima type) +// // recursion stops when have jcci already +// Class<?> superClass = jcci.jcasClass.getSuperclass(); +// String superClassName = superClass.getName(); +// jcci = type2jcci.get(superClassName); +// +// if (null == jcci) { +// TypeSystemImpl tsi = type.getTypeSystem(); +// TypeImpl ti = tsi.getType(Misc.javaClassName2UimaTypeName(superClassName)); +// +// +// setTypeJcci() +// } +// +// } // private static String superTypeJCasName(TypeImpl ti) { // return Misc.typeName2ClassName(ti.getSuperType().getName()); @@ -758,13 +835,15 @@ public abstract class FSClassRegistry { String className = ti.getJCasClassName(); try { + TypeSystemImpl.typeBeingLoadedThreadLocal.set(ti); // only for backwards compat with alpha02 release clazz = (Class<? extends TOP>) Class.forName(className, true, cl); } catch (ClassNotFoundException e) { // Class not found is normal, if there is no JCas for this class return clazz; - } catch (Throwable e) { - e.printStackTrace(System.err); + } finally { + TypeSystemImpl.typeBeingLoadedThreadLocal.set(null); } + return clazz; } @@ -1150,8 +1229,12 @@ public abstract class FSClassRegistry { FeatureImpl fi = ti.getFeatureByBaseName(featName); if (fi == null) { add2errors(errorSet, + /** JCAS class "{0}" defines a UIMA field "{1}" but the UIMA type doesn''t define that field. */ new CASRuntimeException(CASRuntimeException.JCAS_FIELD_MISSING_IN_TYPE_SYSTEM, clazz.getName(), featName), - false); // don't throw on this error, field is set to -1 and will throw if trying to use it + false); // don't throw on this error, field is still set up +// //debug +// System.out.format("debug JCAS field not in ts: type: %s, field: %s %n%s%n", +// clazz.getName(), featName, Misc.getCallers(1, 30)); } else { Field mhf = clazz.getDeclaredField("_FH_" + featName); mhf.setAccessible(true); @@ -1333,6 +1416,13 @@ public abstract class FSClassRegistry { // System.out.println("debug " + fieldName); String featureName = fieldName.substring("_FC_".length()); final int index = TypeSystemImpl.getAdjustedFeatureOffset(type, featureName); +// //debug +// if (type.getShortName().equals("Split") && featureName.equals("splits") +// ) { +// System.out.println("debug attempting to set offset for splits in Splits to " + index); +// System.out.println(type.toString(2)); +// System.out.println(Misc.getCallers(1, 32)); +// } if (index == -1) { continue; // a feature defined in the JCas class doesn't exist in the currently loaded type } // skip setting it. If code uses this, a runtime error will happen. Modified: uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeImpl.java URL: http://svn.apache.org/viewvc/uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeImpl.java?rev=1822059&r1=1822058&r2=1822059&view=diff ============================================================================== --- uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeImpl.java (original) +++ uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeImpl.java Tue Jan 23 21:02:30 2018 @@ -164,7 +164,7 @@ public class TypeImpl implements Type, C // for journalling allocation: This is a 0-based offset for all features in feature order int highestOffset = -1; - + // FeatureImpl featUimaUID = null; // null or the feature named uimaUID with range type long private TypeImpl() { @@ -423,7 +423,7 @@ public class TypeImpl implements Type, C public FeatureImpl getFeatureByBaseName(String featureShortName) { return staticMergedFeatures.get(featureShortName); } - + /** * @see org.apache.uima.cas.Type#getShortName() */ @@ -914,31 +914,7 @@ public class TypeImpl implements Type, C ? ((CommonArrayFS)fs).size() : 0); } - - - void setOffset2Feat(List<FeatureImpl> tempIntFis, - List<FeatureImpl> tempRefFis, - List<FeatureImpl> tempNsr, - FeatureImpl fi, - int next) { - if (fi.isInInt) { - assert tempIntFis.size() == next; - tempIntFis.add(fi); - if (fi.getRangeImpl().isLongOrDouble) { - tempIntFis.add(null); - } - } else { - assert tempRefFis.size() == next; - tempRefFis.add(fi); - TypeImpl range = fi.getRangeImpl(); - - if (range.isRefType && - range.typeCode != TypeSystemConstants.sofaTypeCode) { - tempNsr.add(fi); - } - } - } - + void initAdjOffset2FeatureMaps(List<FeatureImpl> tmpIntFis, List<FeatureImpl> tmpRefFis, List<FeatureImpl> tmpNsr) { tmpIntFis.addAll(Arrays.asList(superType.staticMergedIntFeaturesList)); tmpRefFis.addAll(Arrays.asList(superType.staticMergedRefFeaturesList)); Modified: uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java URL: http://svn.apache.org/viewvc/uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java?rev=1822059&r1=1822058&r2=1822059&view=diff ============================================================================== --- uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java (original) +++ uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java Tue Jan 23 21:02:30 2018 @@ -123,6 +123,8 @@ import org.apache.uima.util.impl.Constan */ public class TypeSystemImpl implements TypeSystem, TypeSystemMgr, LowLevelTypeSystem { + private static final boolean IS_TRACE_JCAS_EXPAND = false; // set to show jcas expands of types + /** * Define this JVM property to disable equal type system consolidation. * When a type system is committed, it normally is compared with other committed type systems @@ -441,6 +443,12 @@ public class TypeSystemImpl implements T * */ private final Map<ClassLoader, FsGenerator3[]> generators4pearsByClassLoader = new IdentityHashMap<>(); + + private int nextI; // temp value used in computing adjusted offsets + private int nextR; // temp value used in computing adjusted offsets + private Map<String, JCasClassInfo> type2jcci; // temp value used in computing adjusted offsets + private Lookup lookup; + private ClassLoader cl_for_commit; public TypeSystemImpl() { @@ -909,7 +917,9 @@ public class TypeSystemImpl implements T public boolean isInInt(Type rangeType) { - return rangeType.isPrimitive() && !subsumes(stringType, rangeType); + return (rangeType == null) + ? false + : (rangeType.isPrimitive() && !subsumes(stringType, rangeType)); } @Override @@ -1368,12 +1378,6 @@ public class TypeSystemImpl implements T // because it will call the type system iterator // this.casMetadata.setupFeaturesAndCreatableTypes(); - // Augment (if called for) the features for the types, based on features defined in the JCas classes (if they exist) - // - also does feature reordering if necessary so subtype added features follow super type added ones. - Map<String, JCasClassInfo> type2jcci = FSClassRegistry.get_className_to_jcci(cl, false); // is not pear - Lookup lookup = FSClassRegistry.getLookup(cl); - FSClassRegistry.augmentFeaturesFromJCas(this.topType, cl, this, type2jcci, lookup); - if (!IS_DISABLE_TYPESYSTEM_CONSOLIDATION) { WeakReference<TypeSystemImpl> prevWr = committedTypeSystems.get(this); if (null != prevWr) { @@ -1398,8 +1402,12 @@ public class TypeSystemImpl implements T // } // } // } - - computeAdjustedFeatureOffsets(topType, 0, 0); // must preceed the FSClassRegistry JCas stuff below + + type2jcci = FSClassRegistry.get_className_to_jcci(cl, false); // is not pear + lookup = FSClassRegistry.getLookup(cl); + cl_for_commit = cl; + + computeAdjustedFeatureOffsets(topType); // must preceed the FSClassRegistry JCas stuff below // Load all the available JCas classes (if not already loaded). // Has to follow above, because information computed above is used when @@ -1428,27 +1436,68 @@ public class TypeSystemImpl implements T /** * This is the actual offset for the feature, in either the int or ref array + * + * Offsets for super types come before types, because + * multiple subtypes can share the same super type + * + * Offsets due to JCas defined features are set before those from type systems, because + * the same JCas class might be used with different type system, + * and this increases the chance that the assignment is still valid. * + * Special handling for JCas defined features which are missing in the type system. + * - these are allocated artificial "feature impls", which participate in the offset + * setting, but not in anything else (like serialization) + * + * Special handling for JCas super types which have no corresponding uima types + * - features inferred from these are incorporated for purposes of computing offsets (only), because + * some later type system might have these. + * + * Sets offset into 2 places: + * - the FeatureImpl + * - a set of arrays in the type: + * one mapping offset to featureImpl for refs + * one mapping offset to featureImpl for ints + * one mapping offset to non-fs-refs (for efficiency in enquing these before refs) + * + * also sets the number-of-used slots (int / ref) for allocating, in the type + * * @param ti - the type - * @param nextI - the next available slot to use - for int style items - * @param nextR - the next available slot to use - for ref style items */ - private void computeAdjustedFeatureOffsets(TypeImpl ti, int nextI, int nextR) { + private void computeAdjustedFeatureOffsets(TypeImpl ti) { + List<FeatureImpl> tempIntFis = new ArrayList<>(); List<FeatureImpl> tempRefFis = new ArrayList<>(); - List<FeatureImpl> tempNsr = new ArrayList<>(); + List<FeatureImpl> tempNsr = new ArrayList<>(); + if (ti != topType) { + // initialize these offset -> fi maps from supertype ti.initAdjOffset2FeatureMaps(tempIntFis, tempRefFis, tempNsr); + nextI = ti.getSuperType().nbrOfUsedIntDataSlots; + nextR = ti.getSuperType().nbrOfUsedRefDataSlots; + } else { + nextI = 0; + nextR = 0; } + + // all the JCas slots come first, because their offsets can't easily change + // this includes any superClass of a jcas class which is not in this type system + JCasClassInfo jcci = getJcci(ti); + + if (jcci != null) { + addJCasOffsetsWithSupers(jcci.jcasClass, tempIntFis, tempRefFis, tempNsr); +// addJCasOffsets(ti.jcci, tempIntFis, tempRefFis, tempNsr); // already done by above + } + for (final FeatureImpl fi : ti.getMergedStaticFeaturesIntroducedByThisType()) { - fi.setAdjustedOffset(fi.isInInt ? nextI : nextR); - ti.setOffset2Feat(tempIntFis, tempRefFis, tempNsr, fi, fi.isInInt ? (nextI++) : (nextR++)); - if (((TypeImpl)fi.getRange()).isLongOrDouble) { - nextI ++; - } + if (fi.getAdjustedOffset() == -1) { + // wasn't set due to jcas class, above + setFeatureAdjustedOffset(fi, tempIntFis, tempRefFis, tempNsr); + } else { + + } } - + ti.nbrOfUsedIntDataSlots = nextI; ti.nbrOfUsedRefDataSlots = nextR; @@ -1467,15 +1516,166 @@ public class TypeSystemImpl implements T // ti.hasNoSlots = ti.nbrOfUsedIntDataSlots == 0 && ti.nbrOfUsedRefDataSlots == 0; for (TypeImpl sub : ti.getDirectSubtypes()) { - computeAdjustedFeatureOffsets(sub, nextI, nextR); + computeAdjustedFeatureOffsets(sub); } } + + /** + * Insures that any super class jcas-defined features, + * not already defined (due to having a corresponding type in this + * type system) + * get their features done first + * + * Walking up the super chain: + * - could encounter a class which has no jcci (it's not a jcas class) + * but has a super class which is one) - so don't stop the up walk. + * + * Stop the up walk when + * - reach the TOP or Object + * - reach a class which has a corresponding uima type (the assumption is that + * this type is a super type + * + * @param ti the type associated with clazz, or null, if none + * @param clazz the class whose supertypes are being scanned. May not be a JCas class + * @param tempIntFis the array of int offsets (refs to feature impls (maybe jcas-only) + * @param tempRefFis the array of ref offsets (refs to feature impls (maybe jcas-only) + * @param tempNsrFis a list of non fs-ref ref values + */ + private void addJCasOffsetsWithSupers(Class<?> clazz, + List<FeatureImpl> tempIntFis, + List<FeatureImpl> tempRefFis, + List<FeatureImpl> tempNsrFis) { + + Class<?> superClass = clazz.getSuperclass(); + /* ********************** + * STOP if get to top * + * **********************/ + if (superClass == Object.class) { + return; + } + + String superClassName = superClass.getName(); + String uimaSuperTypeName = Misc.javaClassName2UimaTypeName(superClassName); + if (this.getType(uimaSuperTypeName) != null) { + + /* **************************** + * STOP if get to UIMA type * + * ****************************/ + + // But process this jcas class level + // then return to recursively process other jcas class levels. + String className = clazz.getName(); + String uimaTypeName = Misc.javaClassName2UimaTypeName(className); + TypeImpl ti = this.getType(uimaTypeName); + if (ti != null) { + maybeAddJCasOffsets(ti, tempIntFis, tempRefFis, tempNsrFis); + } + return; + } + + // recurse up the superclass chain for all jcci's not having UIMA types + // If they exist, they will have been loaded/created by FSClassRegistry.augmentFeaturesFromJCas + // some intermediate superclasses may not have jccis, just skip over them. + + addJCasOffsetsWithSupers(superClass, tempIntFis, tempRefFis, tempNsrFis); +// maybeAddJCasOffsets(clazz, tempIntFis, tempRefFis, tempNsrFis); // already done by above statement + } + + + /** + * + * @param ti the type having offsets set up for + * @param jcci a corresponding jcci, either for this type or for a super type + * when the super type is not in this uima type system + * @param tempIntFis list to augment with additional slots + * @param tempRefFis list to augment with additional slots + */ + private void maybeAddJCasOffsets(TypeImpl ti, + List<FeatureImpl> tempIntFis, + List<FeatureImpl> tempRefFis, + List<FeatureImpl> tempNsrFis) { + + JCasClassInfo jcci = getJcci(ti); + if (null != jcci) { // could be null if class is not a JCas class + addJCasOffsets(jcci, tempIntFis, tempRefFis, tempNsrFis); + } + } + + private void addJCasOffsets(JCasClassInfo jcci, + List<FeatureImpl> tempIntFis, + List<FeatureImpl> tempRefFis, + List<FeatureImpl> tempNsrFis) { + + List<FeatureImpl> added = IS_TRACE_JCAS_EXPAND ? (new ArrayList<>(0)) : null; + for (FSClassRegistry.JCasClassFeatureInfo jcci_feat : jcci.features) { + TypeImpl rangeType = getType(jcci_feat.uimaRangeName); // could be null + TypeImpl ti = jcci.getUimaType(this); // could be null + FeatureImpl fi = null; + if (ti != null) { + fi = ti.getFeatureByBaseName(jcci_feat.shortName); // could be null + } + if (fi == null) { // + // no feature for this type in this type system, but in the JCas. + // create a FeatureImpl_jcas_only, to hold the offset info to use for + // later in the + // update of the CallSites to install the offsets + fi = new FeatureImpl_jcas_only(jcci_feat.shortName, rangeType); + if (IS_TRACE_JCAS_EXPAND) { + added.add(fi); + } + } + assert fi.getAdjustedOffset() == -1; + setFeatureAdjustedOffset(fi, tempIntFis, tempRefFis, tempNsrFis); + } + + if (IS_TRACE_JCAS_EXPAND && added.size() > 0) { + System.out.format("debug trace jcas added: %d slots, %s%n", added.size(), + Misc.ppList(added)); + } + } + + void setFeatureAdjustedOffset(FeatureImpl fi, List<FeatureImpl> tmpIntFis, List<FeatureImpl> tmpRefFis, List<FeatureImpl> tmpNsr) { + boolean isInt = fi.isInInt; + fi.setAdjustedOffset(isInt ? nextI : nextR); + setOffset2Feat(tmpIntFis, tmpRefFis, tmpNsr, fi, isInt ? (nextI++) : (nextR++)); + if (fi.isLongOrDouble) { + nextI ++; + } + } + + void setOffset2Feat( + List<FeatureImpl> tempIntFis, + List<FeatureImpl> tempRefFis, + List<FeatureImpl> tempNsr, + FeatureImpl fi, + int next) { + boolean is_jcas_only = fi instanceof FeatureImpl_jcas_only; + if (fi.isInInt) { + // assert tempIntFis.size() == next; // could have added slots from JCas + tempIntFis.add(is_jcas_only ? null : fi); + if (fi.getRangeImpl().isLongOrDouble) { + tempIntFis.add(null); + } + } else { + // assert tempRefFis.size() == next; // could have added slots from JCas + tempRefFis.add(is_jcas_only ? null : fi); + TypeImpl range = fi.getRangeImpl(); + + if (!is_jcas_only && range.isRefType && range != sofaType) { + tempNsr.add(fi); + } + } + } + + private JCasClassInfo getJcci(TypeImpl ti) { + return FSClassRegistry.getOrCreateJCasClassInfo(ti, cl_for_commit, type2jcci, lookup); + } + /** * Feature "ids" - offsets without adjusting for whether or not they're in the class itself * @param ti a type to compute these for - * @param nextI - the next available int offset - * @param nextR - the next available ref offset + * @param next - the next offset */ private void computeFeatureOffsets(TypeImpl ti, int next) { @@ -2619,6 +2819,7 @@ public class TypeSystemImpl implements T // return jcasClassesInfo[typecode].jcasClass; // } /** + * ******** OBSOLETE - only left in for supporting some jcas style in alpha level ************* * This code is run when a JCas class is loaded and resolved, for the first time, as part of type system commit, or * as part of statically loading the FSClassRegister class (where this is done for all the built-ins, once). * It looks up the offset value in the type system (via a thread-local) @@ -2627,6 +2828,7 @@ public class TypeSystemImpl implements T * @param featName - * @return the offset in the int or ref data arrays for the named feature */ + // ******** OBSOLETE - only left in for supporting some jcas style in alpha level ************* public static synchronized int getAdjustedFeatureOffset(String featName) { TypeImpl type = typeBeingLoadedThreadLocal.get(); if (null == type) { @@ -2648,7 +2850,12 @@ public class TypeSystemImpl implements T static int getAdjustedFeatureOffset(TypeImpl type, String featName) { FeatureImpl fi = type.getFeatureByBaseName(featName); - return (fi == null) ? -1 : fi.getAdjustedOffset(); + return (fi == null) ? -1 : fi.getAdjustedOffset(); +// if (fi == null) { +// FeatureImpl_jcas_only fi_j = type.getJcasAddedFeature(featName); +// return (fi_j == null) ? -1 : fi_j.getAdjustedOffset(); +// } +// return fi.getAdjustedOffset(); } /** Modified: uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties URL: http://svn.apache.org/viewvc/uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties?rev=1822059&r1=1822058&r2=1822059&view=diff ============================================================================== --- uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties (original) +++ uima/uv3/uimaj-v3/trunk/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties Tue Jan 23 21:02:30 2018 @@ -558,7 +558,7 @@ JCAS_UNKNOWN_TYPE_NOT_IN_CAS = Unknown J JCAS_FIELD_MISSING_IN_TYPE_SYSTEM = JCAS class "{0}" defines a UIMA field "{1}" but the UIMA type doesn''t define that field. JCAS_FIELD_ADJ_OFFSET_CHANGED = In JCAS class "{0}", UIMA field "{1}" was set up when this class was previously loaded and initialized, to have an adjusted offset of "{2}" but now the feature has a different adjusted offset of "{3}"; this may be due to something else other than type system commit actions loading and initializing the JCas class, or to having a different non-compatible type system for this class, trying to use a common JCas cover class, which is not supported. JCAS_CAS_MISMATCH_SUPERTYPE = JCas Class's supertypes for "{0}", "{1}" and the corresponding UIMA Supertypes for "{2}", "{3}" don't have an intersection. -JCAS_MISMATCH_SUPERTYPE = The JCas class: "{0}" has supertype: "{1}" which doesn''t match the UIMA type "{2}"''s supertype "{3}". +JCAS_MISMATCH_SUPERTYPE = The JCas class: "{0}" has supertypes: "{1}" which do not match the UIMA type "{2}"''s supertypes "{3}". JCAS_TYPE_RANGE_MISMATCH = CAS type system type "{0}" defines field "{1}" with range "{2}", but JCas getter method is returning "{3}" which is not a subtype of the declared range. JCAS_GET_NTH_ON_EMPTY_LIST = JCas getNthElement method called via invalid object - an empty list: {0}. JCAS_GET_NTH_NEGATIVE_INDEX = JCas getNthElement method called with index "{0}" which is negative. Modified: uima/uv3/uimaj-v3/trunk/uimaj-core/src/test/java/org/apache/uima/cas/impl/JCasReinitTest.java URL: http://svn.apache.org/viewvc/uima/uv3/uimaj-v3/trunk/uimaj-core/src/test/java/org/apache/uima/cas/impl/JCasReinitTest.java?rev=1822059&r1=1822058&r2=1822059&view=diff ============================================================================== --- uima/uv3/uimaj-v3/trunk/uimaj-core/src/test/java/org/apache/uima/cas/impl/JCasReinitTest.java (original) +++ uima/uv3/uimaj-v3/trunk/uimaj-core/src/test/java/org/apache/uima/cas/impl/JCasReinitTest.java Tue Jan 23 21:02:30 2018 @@ -62,12 +62,23 @@ public class JCasReinitTest extends Test public void testReinit() throws Throwable { File typeSystemFile1; - typeSystemFile1 = JUnitExtension.getFile("ExampleCas/testTypeSystem_token_no_features.xml"); +// // x.y.z.Token with no features +// typeSystemFile1 = JUnitExtension.getFile("ExampleCas/testTypeSystem_token_no_features.xml"); +// typeSystemDescription = UIMAFramework.getXMLParser().parseTypeSystemDescription( +// new XMLInputSource(typeSystemFile1)); +// +// cas = (CASImpl) CasCreationUtils.createCas(typeSystemDescription, new TypePriorities_impl(), null); +// T.dumpOffset(); +// + + typeSystemFile1 = JUnitExtension.getFile("ExampleCas/testTypeSystem_t_nofeatures.xml"); typeSystemDescription = UIMAFramework.getXMLParser().parseTypeSystemDescription( new XMLInputSource(typeSystemFile1)); - - cas = (CASImpl) CasCreationUtils.createCas(typeSystemDescription, new TypePriorities_impl(), null); + cas_no_features = (CASImpl) CasCreationUtils.createCas(typeSystemDescription, new TypePriorities_impl(), null); + + T.dumpOffset(); + typeSystemFile1 = JUnitExtension.getFile("ExampleCas/testTypeSystem_t_1_feature.xml"); typeSystemDescription = UIMAFramework.getXMLParser().parseTypeSystemDescription( new XMLInputSource(typeSystemFile1)); @@ -77,13 +88,6 @@ public class JCasReinitTest extends Test T.dumpOffset(); - typeSystemFile1 = JUnitExtension.getFile("ExampleCas/testTypeSystem_t_nofeatures.xml"); - typeSystemDescription = UIMAFramework.getXMLParser().parseTypeSystemDescription( - new XMLInputSource(typeSystemFile1)); - - cas_no_features = (CASImpl) CasCreationUtils.createCas(typeSystemDescription, new TypePriorities_impl(), null); - - T.dumpOffset(); }