Author: schor Date: Wed Nov 4 14:45:42 2015 New Revision: 1712558 URL: http://svn.apache.org/viewvc?rev=1712558&view=rev Log: [UIMA-4687] impl static way to identify features in JCas cover classes, use for index corruption checking and journaling
Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FeatureImpl.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/JCasRegistry.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSArray.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFSList.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFloatList.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyIntegerList.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyStringList.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Sofa.java uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/tcas/Annotation.java Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/CASImpl.java Wed Nov 4 14:45:42 2015 @@ -28,6 +28,7 @@ import java.io.UnsupportedEncodingExcept import java.net.URL; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.BitSet; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -37,8 +38,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import java.util.function.IntSupplier; -import java.util.function.Supplier; import org.apache.uima.UIMAFramework; import org.apache.uima.UIMARuntimeException; @@ -258,7 +257,12 @@ public class CASImpl extends AbstractCas private FeatureStructure cache_not_in_index = null; // a one item cache of a FS guaranteed to not be in any index - private final PositiveIntSet_impl featureCodesInIndexKeys = new PositiveIntSet_impl(); + /** + * These fields are here, not in TypeSystemImpl, because different CASes may have different indexes but share the same type system + * They hold the same data (constant per CAS) but are accessed with different indexes + */ + private final BitSet featureCodesInIndexKeys = new BitSet(1024); // 128 bytes + private final BitSet featureJiInIndexKeys = new BitSet(1024); // indexed by JCas Feature Index, not feature code. // A map from Sofas to IndexRepositories. private Map<Integer, FSIndexRepository> sofa2indexMap; @@ -287,8 +291,6 @@ public class CASImpl extends AbstractCas // to load the CASImpl class. private ClassLoader jcasClassLoader = this.getClass().getClassLoader(); - private ClassLoader previousJCasClassLoader = this.jcasClassLoader; - // If this CAS can be flushed (reset) or not. // often, the framework disables this before calling users code private boolean flushEnabled = true; @@ -386,8 +388,12 @@ public class CASImpl extends AbstractCas return svd.fsTobeAddedbackSingle; } - void featureCodesInIndexKeysAdd(int featCode) { - svd.featureCodesInIndexKeys.add(featCode); + void featureCodes_inIndexKeysAdd(int featCode, int registryIndex) { + svd.featureCodesInIndexKeys.set(featCode); + // skip adding if no JCas registry entry for this feature + if (registryIndex >= 0) { + svd.featureJiInIndexKeys.set(registryIndex); + } } void maybeClearCacheNotInIndex(FeatureStructure fs) { @@ -813,7 +819,6 @@ public class CASImpl extends AbstractCas return this.svd.baseCAS; } - @SuppressWarnings("unchecked") public FSIterator<SofaFS> getSofaIterator() { FSIndex<SofaFS> sofaIndex = this.svd.baseCAS.indexRepository.getIndex(CAS.SOFA_INDEX_NAME); return sofaIndex.iterator(); @@ -1018,6 +1023,7 @@ public class CASImpl extends AbstractCas public void resetNoQuestions() { svd.casResets.incrementAndGet(); svd.fsIdGenerator.set(0); + svd.id2fs.clear(); if (trace) { System.out.println("CAS Reset in thread " + Thread.currentThread().getName() + " for CasId = " + getCasId() + ", new reset count = " + svd.casResets.get()); @@ -1209,32 +1215,28 @@ public class CASImpl extends AbstractCas /* * Support code for JCas setters + * Only called from JCasGen'd code + * */ - public void setWithCheckAndJournal(FeatureStructureImplC fs, int featCode, Runnable setter) { - boolean wasRemoved = checkForInvalidFeatureSetting(fs, featCode); + public void setWithCheckAndJournalJFRI(FeatureStructureImplC fs, int jcasFieldRegistryIndex, Runnable setter) { + boolean wasRemoved = checkForInvalidFeatureSettingJFRI(fs, jcasFieldRegistryIndex); setter.run(); if (wasRemoved) { maybeAddback(fs); } - maybeLogUpdate(fs, featCode); + maybeLogUpdateJFRI(fs, jcasFieldRegistryIndex); } - /** - * This method called by setters in JCas gen'd classes when - * the setter must check for journaling and index corruption - * @param fs - * @param featCode - * @param setter - */ - public void setWithCheckAndJournal(FeatureStructureImplC fs, IntSupplier featCodeSupplier, Runnable setter) { - boolean wasRemoved = checkForInvalidFeatureSetting(fs, featCodeSupplier); + public void setWithCheckAndJournal(FeatureStructureImplC fs, int featCode, Runnable setter) { + boolean wasRemoved = checkForInvalidFeatureSetting(fs, featCode); setter.run(); if (wasRemoved) { maybeAddback(fs); } - maybeLogUpdate(fs, featCodeSupplier.getAsInt()); + maybeLogUpdate(fs, featCode); } - + + // public void setWithCheck(FeatureStructureImplC fs, FeatureImpl feat, Runnable setter) { // boolean wasRemoved = checkForInvalidFeatureSetting(fs, feat); // setter.run(); @@ -1255,11 +1257,13 @@ public class CASImpl extends AbstractCas maybeLogUpdate(fs, fi); } - public void setWithJournal(FeatureStructureImplC fs, Supplier<FeatureImpl> fiSupplier, Runnable setter) { + public void setWithJournalJFRI(FeatureStructureImplC fs, int jcasFieldRegistryIndex, Runnable setter) { setter.run(); - maybeLogUpdate(fs, fiSupplier); + maybeLogUpdateJFRI(fs, jcasFieldRegistryIndex); } + + /** * * @param fs the Feature Structure being updated @@ -1278,9 +1282,9 @@ public class CASImpl extends AbstractCas } } - public void maybeLogUpdate(FeatureStructureImplC fs, Supplier<FeatureImpl> featSupplier) { + public void maybeLogUpdateJFRI(FeatureStructureImplC fs, int jcasFieldRegistryIndex) { if (this.svd.trackingMark != null) { - this.logFSUpdate(fs, featSupplier.get()); + this.logFSUpdate(fs, getFeatFromJCasFieldRegistryIndex(jcasFieldRegistryIndex)); } } @@ -1298,7 +1302,7 @@ public class CASImpl extends AbstractCas */ /** - * This is the common point where all operations to set features come through + * This is the common point where low-level operations to set features come through * It implements the check for invalid feature setting and potentially the addback. * * @param fs the feature structure @@ -2049,7 +2053,6 @@ public class CASImpl extends AbstractCas return ((FeatureStructureImplC)fs).id(); } - @SuppressWarnings("unchecked") public <T extends TOP> T ll_getFSForRef(int id) { return getFsFromId_checked(id); } @@ -2172,11 +2175,30 @@ public class CASImpl extends AbstractCas if (IS_DISABLED_PROTECT_INDEXES && ssz == 0) { return false; } + + if (!svd.featureCodesInIndexKeys.get(featCode)) { + return false; + } - return checkForInvalidFeatureSettingCommon(fs, featCode, ssz); + // next method skips if the fsRef is not in the index (cache) + final boolean wasRemoved = removeFromCorruptableIndexAnyView( + fs, + (ssz > 0) ? svd.fssTobeAddedback.get(ssz - 1) : + svd.fsTobeAddedbackSingle + ); + + svd.cache_not_in_index = fs; // speed up adds before add back + + // skip message if wasn't removed + // skip message if protected in explicit block + if (wasRemoved && IS_REPORT_FS_UPDATE_CORRUPTS_INDEX && ssz == 0) { + featModWhileInIndexReport(fs, featCode); + } + return wasRemoved; } - - private boolean checkForInvalidFeatureSetting(FeatureStructureImplC fs, IntSupplier featCodeSupplier) { + + // version of above, but using jcasFieldRegistryIndex + private boolean checkForInvalidFeatureSettingJFRI(FeatureStructureImplC fs, int jcasFieldRegistryIndex) { if (fs == svd.cache_not_in_index) { return false; } @@ -2186,30 +2208,39 @@ public class CASImpl extends AbstractCas if (IS_DISABLED_PROTECT_INDEXES && ssz == 0) { return false; } - - return checkForInvalidFeatureSettingCommon(fs, featCodeSupplier.getAsInt(), ssz); - } + + if (!svd.featureJiInIndexKeys.get(jcasFieldRegistryIndex)) { + return false; + } - private boolean checkForInvalidFeatureSettingCommon(FeatureStructureImplC fs, int featCode, int ssz) { // next method skips if the fsRef is not in the index (cache) final boolean wasRemoved = removeFromCorruptableIndexAnyView( fs, (ssz > 0) ? svd.fssTobeAddedback.get(ssz - 1) : - svd.fsTobeAddedbackSingle, - featCode); + svd.fsTobeAddedbackSingle + ); + + svd.cache_not_in_index = fs; // speed up adds before add back // skip message if wasn't removed // skip message if protected in explicit block if (wasRemoved && IS_REPORT_FS_UPDATE_CORRUPTS_INDEX && ssz == 0) { - featModWhileInIndexReport(fs, featCode); + featModWhileInIndexReport(fs, getFeatFromJCasFieldRegistryIndex(jcasFieldRegistryIndex)); } return wasRemoved; } + private FeatureImpl getFeatFromJCasFieldRegistryIndex(int jcasFieldRegistryIndex) { + return getFSClassRegistry().featuresFromJFRI[jcasFieldRegistryIndex]; + } + private void featModWhileInIndexReport(FeatureStructure fs, int featCode) { + featModWhileInIndexReport(fs, getTypeSystemImpl().getFeatureForCode(featCode)); + } + + private void featModWhileInIndexReport(FeatureStructure fs, FeatureImpl fi) { // prepare a message which includes the feature which is a key, the fs, and // the call stack. - Feature fi = getTypeSystemImpl().getFeatureForCode(featCode); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); new Throwable().printStackTrace(pw); @@ -2296,7 +2327,7 @@ public class CASImpl extends AbstractCas */ boolean removeFromCorruptableIndexAnyView(final FeatureStructureImplC fs, FSsTobeAddedback toBeAdded, int featCode) { - if (fs != svd.cache_not_in_index && svd.featureCodesInIndexKeys.contains(featCode)) { + if (fs != svd.cache_not_in_index && svd.featureCodesInIndexKeys.get(featCode)) { boolean wasRemoved = removeFromCorruptableIndexAnyView(fs, toBeAdded); svd.cache_not_in_index = fs; // because will remove it if its in the index. return wasRemoved; @@ -2332,15 +2363,7 @@ public class CASImpl extends AbstractCas } return wasRemoved; } - - boolean removeFromCorruptableIndexAnyViewSetCache(final FeatureStructureImplC fs, FSsTobeAddedback toBeAdded) { - if (fs != svd.cache_not_in_index) { - svd.cache_not_in_index = fs; - return removeFromCorruptableIndexAnyView(fs, toBeAdded); - } - return false; - } - + /** * remove a FS from corruptable indexes in this view * @param fs the fs to be removed @@ -2683,7 +2706,6 @@ public class CASImpl extends AbstractCas * @see org.apache.uima.cas.admin.CASMgr#setJCasClassLoader(java.lang.ClassLoader) */ public void setJCasClassLoader(ClassLoader classLoader) { - this.svd.previousJCasClassLoader = classLoader; this.svd.jcasClassLoader = classLoader; } @@ -3566,9 +3588,10 @@ public class CASImpl extends AbstractCas public int setId2fs(FeatureStructureImplC fs) { svd.id2fs.add(fs); - assert(!svd.id2fs.is_gc - ? svd.id2fs.size() == (1 + svd.fsIdGenerator.get()) - : true); + if (svd.id2fs.size() != (2 + svd.fsIdGenerator.get())) { + System.out.println("debug"); + } + assert(svd.id2fs.size() == (2 + svd.fsIdGenerator.get())); return getNextFsId(); } Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java Wed Nov 4 14:45:42 2015 @@ -179,6 +179,8 @@ public class FSClassRegistry { // the loaded JCas cover classes, generators, setters, and getters. index is typecode; value is JCas cover class which may belong to a supertype. private final JCasClassInfo[] jcasClassesInfo; + final FeatureImpl[] featuresFromJFRI; + /** * install the default (non-JCas) generator for all types in the type system and the * JCas style generators for the built-in types @@ -215,9 +217,45 @@ public class FSClassRegistry { maybeLoadJCasAndSubtypes(ts, ts.topType, jcasClassesInfo[TypeSystemImpl.topTypeCode]); } + // walk the type system and extract all the registry indexes + // While walking, update the FeatureImpl with the registry index + ArrayList<FeatureImpl> ffjfri = getFeatureFromJFRI(ts, ts.topType, new ArrayList<FeatureImpl>()); + + featuresFromJFRI = new FeatureImpl[ffjfri.size()]; + ffjfri.toArray(featuresFromJFRI); + reportErrors(); } + /** + * Walk type system from TOP, depth first + * - for each type, for all the features introduced, + * -- collect if exists the field registry # and also save in the FeatureImpl + * @param ts + * @param ti + * @param collector + * @return + */ + private ArrayList<FeatureImpl> getFeatureFromJFRI(TypeSystemImpl ts, TypeImpl ti, ArrayList<FeatureImpl> collector) { + Class<?> clazz = getJCasClass(ti.getCode()); + for (FeatureImpl fi : ti.getMergedStaticFeaturesIntroducedByThisType()) { + int indexJFRI = Misc.getStaticIntField(clazz, "_FI_" + fi.getShortName()); + if (indexJFRI != Integer.MIN_VALUE) { // that value is code for not found + fi.registryIndex = indexJFRI; + Misc.setWithExpand(collector, indexJFRI, fi); +// } else { +// System.out.println("debug: not found " + clazz.getName() + ", feature = " + fi.getShortName()); + } + } + + for (TypeImpl subtype : ti.getDirectSubtypes()) { + getFeatureFromJFRI(ts, subtype, collector); + } + return collector; + } + + + private void maybeLoadJCasAndSubtypes(TypeSystemImpl ts, TypeImpl ti, JCasClassInfo copyDownDefault_jcasClassInfo) { final int typecode = ti.getCode(); Class<?> clazz; @@ -238,7 +276,7 @@ public class FSClassRegistry { maybeLoadJCasAndSubtypes(ts, subtype, jcasClassesInfo[typecode]); } } - + private static Class<?> maybeLoadJCas(String typeName, ClassLoader cl) { Class<?> clazz = null; String className = typeName2ClassName(typeName); Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSIndexRepositoryImpl.java Wed Nov 4 14:45:42 2015 @@ -476,7 +476,8 @@ public class FSIndexRepositoryImpl imple if (!sii.isSetUpFromBaseCAS) { for (int i = 0, nKeys = comp.getNumberOfKeys(); i < nKeys; i++) { if (comp.getKeyType(i) == FSIndexComparator.FEATURE_KEY) { - cas.featureCodesInIndexKeysAdd(comp.getKeyFeature(i).getCode()); + FeatureImpl fi = comp.getKeyFeature(i); + cas.featureCodes_inIndexKeysAdd(fi.getCode(), fi.registryIndex); } } } Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FeatureImpl.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FeatureImpl.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FeatureImpl.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FeatureImpl.java Wed Nov 4 14:45:42 2015 @@ -36,6 +36,9 @@ public class FeatureImpl implements Feat private final int featureCode; // unique id for this feature, in this type system private int featureOffset = -1; // the offset in the storage array for this feature without regard to JCas implemented features; set at commit time private int adjustedFeatureOffset = -1; // the offset in the storage array for this feature, adjusted to exclude JCas implemented features; set at commit time + + int registryIndex = -1; // set from JCas classes feature registry + // used to setup index corruption bitset final boolean isInInt; // specifies which array the data is in private TypeImpl highestDefiningType; // not final, could change @@ -47,13 +50,10 @@ public class FeatureImpl implements Feat private final boolean isMultipleRefsAllowed; private final String shortName; // feat - - private final String getterName; // getFoo where "foo" is shortName - private final String setterName; // setFoo where "foo" is shortName - + protected Object jcasGetter; // null or the functional interface to call to get this feature protected Object jcasSetter; // null or the functional interface to call to set this feature - + private final SlotKind slotKind; @@ -67,9 +67,6 @@ public class FeatureImpl implements Feat this.slotKind = slotKind; this.shortName = shortName; this.isMultipleRefsAllowed = isMultipleRefsAllowed; - String shortName1stLetterUpperCase = Character.toUpperCase(this.shortName.charAt(0)) + ((shortName.length() == 1) ? "" : this.shortName.substring(1)); - this.getterName = "get" + shortName1stLetterUpperCase; - this.setterName = "set" + shortName1stLetterUpperCase; this.isInInt = tsi.isInInt(rangeType); typeImpl.addFeature(this); // might throw if existing feature with different range feats.add(this); @@ -128,22 +125,12 @@ public class FeatureImpl implements Feat } public String getGetterSetterName(boolean isGet) { - return isGet ? this.getterName : this.setterName; + String shortName1stLetterUpperCase = Character.toUpperCase(this.shortName.charAt(0)) + + ((shortName.length() == 1) ? "" : this.shortName.substring(1)); + + return (isGet ? "get" : "set") + shortName1stLetterUpperCase; } - public String getSetterName() { - return this.setterName; - } - -// /** -// * Get the type system that this feature belongs to. -// * -// * @return The type system. -// */ -// public TypeSystem getTypeSystem() { -// return this.ts; -// } - /** * Note: you can only compare features from the same type system. If you compare features from * different type systems, the result is undefined. Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java Wed Nov 4 14:45:42 2015 @@ -292,6 +292,7 @@ public class TypeSystemImpl implements T // private FeatureStructureClassGen featureStructureClassGen = new FeatureStructureClassGen(); private FSClassRegistry fsClassRegistry; // set at type system commit time. + /** * Map from built-in array name to component Type */ @@ -1320,26 +1321,13 @@ public class TypeSystemImpl implements T computeAdjustedFeatureOffsets(topType, 0, 0); } - - private void computeFeatureOffsets(TypeImpl ti, int nextI, int nextR) { - int iFeat = nextI; - int rFeat = nextR; - - for (FeatureImpl fi : ti.getMergedStaticFeaturesIntroducedByThisType()) { - fi.setOffset(fi.isInInt ? (iFeat ++) : (rFeat ++)); - if (((TypeImpl)fi.getRange()).isLongOrDouble) { - iFeat ++; - } - } - - ti.highestIntOffset = nextI; - ti.highestRefOffset = nextR; - - for (TypeImpl sub : ti.getDirectSubtypes()) { - computeFeatureOffsets(sub, iFeat, rFeat); - } - } - + /** + * This is the actual offset for the feature, only if it is not in the JCas class as a field + * Also sets the getter and setter items from the FSClassRegistry. + * @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) { int iFeat = nextI; int rFeat = nextR; @@ -1368,6 +1356,31 @@ public class TypeSystemImpl implements T } } + /** + * 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 + */ + private void computeFeatureOffsets(TypeImpl ti, int nextI, int nextR) { + int iFeat = nextI; + int rFeat = nextR; + + for (FeatureImpl fi : ti.getMergedStaticFeaturesIntroducedByThisType()) { + fi.setOffset(fi.isInInt ? (iFeat ++) : (rFeat ++)); + if (((TypeImpl)fi.getRange()).isLongOrDouble) { + iFeat ++; + } + } + + ti.highestIntOffset = nextI; + ti.highestRefOffset = nextR; + + for (TypeImpl sub : ti.getDirectSubtypes()) { + computeFeatureOffsets(sub, iFeat, rFeat); + } + } + private void decompile(Type t) { String name = t.getName(); if (name.endsWith(ARRAY_TYPE_SUFFIX)) return; @@ -1968,7 +1981,7 @@ public class TypeSystemImpl implements T return false; } // superType is null for TOP, which is a Ref type - if (superType != null && superType.getName().equals(CAS.TYPE_NAME_STRING)) { // cant compare to stringType - may not be set yet + if (superType != null && superType.getName().equals(CAS.TYPE_NAME_STRING)) { // can't compare to stringType - may not be set yet return false; } return true; Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/JCasRegistry.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/JCasRegistry.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/JCasRegistry.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/JCasRegistry.java Wed Nov 4 14:45:42 2015 @@ -20,30 +20,44 @@ package org.apache.uima.jcas; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Deque; +import org.apache.uima.internal.util.IntListIterator; +import org.apache.uima.internal.util.PositiveIntSet; +import org.apache.uima.internal.util.PositiveIntSet_impl; import org.apache.uima.jcas.cas.TOP; /** - * Maintains a registry of JCas cover classes that have been loaded. Methods on this - * class are called from JCas cover classes (that is, classes generated by JCasGen). - * They are not intended to be called directly from user-written code. + * Maintains a registry of JCas cover classes that have been loaded + * in order to be able to assign a unique low-value positive int index to each loaded + * JCas class. Note that the same JCas class loaded under two different class loaders + * will get two different numbers. * - * There are two kinds of JCasr classes: built-in and other. - * JCas "other" classes may have multiple versions for the same named class generated and loaded - * under different class loaders; + * The internals maintain a weak reference to the loaded class in order to allow the + * index value to be reused if the associated JCas class is garbaged collected. * - * This supports the use cases of - * - different type systems being used, either + * The register methods is called from JCas cover class static initialization and + * returns the unique index value for this class. + * + * The associated int index is used in a lookup on a jcas registry array associated with a particular + * type system, to get the associated Type. This supports the use cases of + * - different type systems being used with the same loaded JCas classes, either * -- sequentially by a single instance of UIMA or * -- multiple instances of pipelines running in one JVM each with different type systems * - * To avoid memory leaks, weak refs are used. + * A similar mechanism is provided for any features defined for this type. The index values there are + * similarly used in a table in the type system to get the associated Feature. This allows the feature + * info to be kept in static final fields in the JCas class, and yet reference multiple (by type system) + * FeatureImpl instances. + * */ public class JCasRegistry { private static class WeakRefInt<T> extends WeakReference<T> { int index; + PositiveIntSet featureIndexes = new PositiveIntSet_impl(); WeakRefInt(T item, ReferenceQueue<T> q, int index) { super(item, q); @@ -54,6 +68,9 @@ public class JCasRegistry { final private static ArrayList<WeakRefInt<Class<? extends TOP>>> loadedJCasClasses = new ArrayList<>(); final private static ReferenceQueue<Class<? extends TOP>> releasedQueue = new ReferenceQueue<>(); + + private static int nextFeatureIndex = 0; + final private static Deque<Integer> availableFeatureIndexes = new ArrayDeque<>(); /** * Registers a JCas cover class with this registry. The registry will assign * it a unique index, which is then used by the cover-class to identify itself @@ -67,7 +84,13 @@ public class JCasRegistry { WeakRefInt<Class<? extends TOP>> releasedWeakRef = (WeakRefInt<Class<? extends TOP>>) releasedQueue.poll(); if (releasedWeakRef != null) { - int i = ((WeakRefInt<Class<? extends TOP>>)releasedWeakRef).index; + int i = releasedWeakRef.index; + + IntListIterator it = releasedWeakRef.featureIndexes.iterator(); + while (it.hasNext()){ + availableFeatureIndexes.addLast(it.next()); + } + loadedJCasClasses.set(i, new WeakRefInt<Class<? extends TOP>>(aJCasCoverClass, releasedQueue, i)); return i; } @@ -77,6 +100,17 @@ public class JCasRegistry { return i; } + public static synchronized int registerFeature(int typeIndexID) { + Integer i = availableFeatureIndexes.poll(); + if (i == null) { + loadedJCasClasses.get(typeIndexID).featureIndexes.add(nextFeatureIndex); + return nextFeatureIndex ++; + } else { + loadedJCasClasses.get(typeIndexID).featureIndexes.add(i); + return i; + } + } + /** * For a particular type, return true if that type should have run-time checking for use of fields * defined in the JCas Model which are not present in the CAS. If false, all fields @@ -84,17 +118,19 @@ public class JCasRegistry { * this allows the runtime to skip this test. * <p> * This is reserved for future use; it currently always returns true. + * * @param fullyQualTypeName fully qualified type name * @return true if that type should have run-time checking for use of fields - * defined in the JCas Model which are not present in the CAS. If false, all fields - * in the JCas must be in the CAS type system at instantiation time, or an exception is thrown; - * this allows the runtime to skip this test. + * defined in the JCas Model which are not present in the CAS. If false, all fields + * in the JCas must be in the CAS type system at instantiation time, or an exception is thrown; + * this allows the runtime to skip this test. */ public static boolean getFeatOkTst(String fullyQualTypeName) { return true; } /** + * NOT CURRENTLY USED * Gets the number of cover classes that have been registered. * * @return the number of registered JCas cover classes @@ -104,6 +140,7 @@ public class JCasRegistry { } /** + * NOT CURRENTLY USED * Gets the JCas cover class for a given index. * * @param aIndex the index Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/AnnotationBase.java Wed Nov 4 14:45:42 2015 @@ -54,8 +54,11 @@ public class AnnotationBase extends TOP public int getTypeIndexID() { return typeIndexID; } + + // private final static int _FI_sofa = JCasRegistry.registerFeature(); // only for journal-able or corruptable feature slots /* local data */ + public final static int _FI_sofa = JCasRegistry.registerFeature(typeIndexID); private final Sofa _F_sofa; Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSArray.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSArray.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSArray.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/FSArray.java Wed Nov 4 14:45:42 2015 @@ -48,7 +48,7 @@ public final class FSArray extends TOP i return typeIndexID; } - private final FeatureStructureImplC[] theArray; + private final FeatureStructure[] theArray; // never called. Here to disable default constructor @SuppressWarnings("unused") @@ -144,7 +144,7 @@ public final class FSArray extends TOP i public void copyToArray(int srcPos, String[] dest, int destPos, int length) { _casView.checkArrayBounds(theArray.length, srcPos, length); for (int i = 0; i < length; i++) { - FeatureStructureImplC fs = theArray[i + srcPos]; + FeatureStructure fs = theArray[i + srcPos]; dest[i + destPos] = (fs == null) ? null : fs.toString(); } } @@ -157,7 +157,7 @@ public final class FSArray extends TOP i } // internal use - public FeatureStructureImplC[] _getTheArray() { + public FeatureStructure[] _getTheArray() { return theArray; } Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFSList.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFSList.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFSList.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFSList.java Wed Nov 4 14:45:42 2015 @@ -19,10 +19,8 @@ package org.apache.uima.jcas.cas; -import org.apache.uima.cas.CAS; import org.apache.uima.cas.impl.CASImpl; import org.apache.uima.cas.impl.TypeImpl; -import org.apache.uima.cas.impl.TypeSystemImpl; import org.apache.uima.jcas.JCas; import org.apache.uima.jcas.JCasRegistry; @@ -36,20 +34,8 @@ public class NonEmptyFSList extends FSLi return typeIndexID; } - // Offsets to use in accessing features - // For built-ins, these are static constants - - private final static int head_featCode; - private final static int tail_featCode; - - static { - TypeSystemImpl tsi = TypeSystemImpl.staticTsi; - TypeImpl listType = tsi.getType(CAS.TYPE_NAME_NON_EMPTY_FS_LIST); - - // makes assumption that all uima lists have the same head/tail offsets - head_featCode = listType.getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD).getCode(); - tail_featCode = listType.getFeatureByBaseName(CAS.FEATURE_BASE_NAME_TAIL).getCode(); - } + public static final int _FI_head = JCasRegistry.registerFeature(typeIndexID); + public static final int _FI_tail = JCasRegistry.registerFeature(typeIndexID); /* local data */ private TOP _F_head; @@ -83,7 +69,7 @@ public class NonEmptyFSList extends FSLi public void setHead(TOP v) { _F_head = v; // no corruption check - can't be a key - _casView.maybeLogUpdate(this, head_featCode); + _casView.maybeLogUpdateJFRI(this, _FI_head); } // *------------------* @@ -95,7 +81,7 @@ public class NonEmptyFSList extends FSLi public void setTail(FSList v) { _F_tail = v; // no corruption check - can't be a key - _casView.maybeLogUpdate(this, tail_featCode); + _casView.maybeLogUpdateJFRI(this, _FI_tail); } public void setTail(CommonList v) { Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFloatList.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFloatList.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFloatList.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyFloatList.java Wed Nov 4 14:45:42 2015 @@ -19,10 +19,8 @@ package org.apache.uima.jcas.cas; -import org.apache.uima.cas.CAS; import org.apache.uima.cas.impl.CASImpl; import org.apache.uima.cas.impl.TypeImpl; -import org.apache.uima.cas.impl.TypeSystemImpl; import org.apache.uima.jcas.JCas; import org.apache.uima.jcas.JCasRegistry; @@ -36,21 +34,9 @@ public class NonEmptyFloatList extends F return typeIndexID; } - // Offsets to use in accessing features - // For built-ins, these are static constants + public static final int _FI_head = JCasRegistry.registerFeature(typeIndexID); + public static final int _FI_tail = JCasRegistry.registerFeature(typeIndexID); - private final static int head_featCode; - private final static int tail_featCode; - - static { - TypeSystemImpl tsi = TypeSystemImpl.staticTsi; - TypeImpl listType = tsi.getType(CAS.TYPE_NAME_NON_EMPTY_FLOAT_LIST); - - // makes assumption that all uima lists have the same head/tail offsets - head_featCode = listType.getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD).getCode(); - tail_featCode = listType.getFeatureByBaseName(CAS.FEATURE_BASE_NAME_TAIL).getCode(); - } - /* local data */ private float _F_head; private FloatList _F_tail; @@ -83,7 +69,7 @@ public class NonEmptyFloatList extends F public void setHead(float v) { _F_head = v; // no corruption check - a list element can't be a key - _casView.maybeLogUpdate(this, head_featCode); + _casView.maybeLogUpdateJFRI(this, _FI_head); } // *------------------* @@ -95,7 +81,7 @@ public class NonEmptyFloatList extends F public void setTail(FloatList v) { _F_tail = v; // no corruption check - can't be a key - _casView.maybeLogUpdate(this, tail_featCode); + _casView.maybeLogUpdateJFRI(this, _FI_tail); } public void setTail(CommonList v) { Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyIntegerList.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyIntegerList.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyIntegerList.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyIntegerList.java Wed Nov 4 14:45:42 2015 @@ -21,10 +21,8 @@ package org.apache.uima.jcas.cas; import java.util.List; -import org.apache.uima.cas.CAS; import org.apache.uima.cas.impl.CASImpl; import org.apache.uima.cas.impl.TypeImpl; -import org.apache.uima.cas.impl.TypeSystemImpl; import org.apache.uima.jcas.JCas; import org.apache.uima.jcas.JCasRegistry; @@ -38,20 +36,8 @@ public class NonEmptyIntegerList extends return typeIndexID; } - // Offsets to use in accessing features - // For built-ins, these are static constants - - private final static int head_featCode; - private final static int tail_featCode; - - static { - TypeSystemImpl tsi = TypeSystemImpl.staticTsi; - TypeImpl listType = tsi.getType(CAS.TYPE_NAME_NON_EMPTY_INTEGER_LIST); - - // makes assumption that all uima lists have the same head/tail offsets - head_featCode = listType.getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD).getCode(); - tail_featCode = listType.getFeatureByBaseName(CAS.FEATURE_BASE_NAME_TAIL).getCode(); - } + public final static int _FI_head = JCasRegistry.registerFeature(typeIndexID); + public final static int _FI_tail = JCasRegistry.registerFeature(typeIndexID); /* local data */ private int _F_head; @@ -86,7 +72,7 @@ public class NonEmptyIntegerList extends public void setHead(int v) { _F_head = v; // no corruption check - can't be a key - _casView.maybeLogUpdate(this, head_featCode); + _casView.maybeLogUpdateJFRI(this, _FI_head); } // *------------------* @@ -98,7 +84,7 @@ public class NonEmptyIntegerList extends public void setTail(IntegerList v) { _F_tail = v; // no corruption check - can't be a key - _casView.maybeLogUpdate(this, tail_featCode); + _casView.maybeLogUpdateJFRI(this, _FI_tail); } public void setTail(CommonList v) { Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyStringList.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyStringList.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyStringList.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/NonEmptyStringList.java Wed Nov 4 14:45:42 2015 @@ -36,17 +36,9 @@ public class NonEmptyStringList extends return typeIndexID; } - private final static int head_featCode; - private final static int tail_featCode; + public static final int _FI_head = JCasRegistry.registerFeature(typeIndexID); + public static final int _FI_tail = JCasRegistry.registerFeature(typeIndexID); - static { - TypeSystemImpl tsi = TypeSystemImpl.staticTsi; - TypeImpl listType = tsi.getType(CAS.TYPE_NAME_NON_EMPTY_STRING_LIST); - - head_featCode = listType.getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD).getCode(); - tail_featCode = listType.getFeatureByBaseName(CAS.FEATURE_BASE_NAME_TAIL).getCode(); - } - /* local data */ private String _F_head; private StringList _F_tail; @@ -79,7 +71,7 @@ public class NonEmptyStringList extends public void setHead(String v) { _F_head = v; // no corruption check - can't be a key - _casView.maybeLogUpdate(this, head_featCode); + _casView.maybeLogUpdateJFRI(this, _FI_head); } // *------------------* @@ -91,7 +83,7 @@ public class NonEmptyStringList extends public void setTail(StringList v) { _F_tail = v; // no corruption check - can't be a key - _casView.maybeLogUpdate(this, tail_featCode); + _casView.maybeLogUpdateJFRI(this, _FI_tail); } public void setTail(CommonList v) { Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Sofa.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Sofa.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Sofa.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/cas/Sofa.java Wed Nov 4 14:45:42 2015 @@ -41,6 +41,13 @@ public class Sofa extends TOP implements /* local data */ + public final static int _FI_sofaNum = JCasRegistry.registerFeature(typeIndexID); + public final static int _FI_sofaID = JCasRegistry.registerFeature(typeIndexID); + public final static int _FI_mimeType = JCasRegistry.registerFeature(typeIndexID); + public final static int _FI_sofaArray = JCasRegistry.registerFeature(typeIndexID); + public final static int _FI_sofaString = JCasRegistry.registerFeature(typeIndexID); + public final static int _FI_sofaURI = JCasRegistry.registerFeature(typeIndexID); + private final int _F_sofaNum; private final String _F_sofaID; // view name or _InitialView private String _F_mimeType; // may be changed Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/tcas/Annotation.java URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/tcas/Annotation.java?rev=1712558&r1=1712557&r2=1712558&view=diff ============================================================================== --- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/tcas/Annotation.java (original) +++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/tcas/Annotation.java Wed Nov 4 14:45:42 2015 @@ -43,17 +43,9 @@ public class Annotation extends Annotati return typeIndexID; } - // static values OK for built-ins - private final static int begin_featCode; - private final static int end_featCode; - - static { - TypeSystemImpl tsi = TypeSystemImpl.staticTsi; - TypeImpl annotType = tsi.annotType; - begin_featCode = annotType.getFeatureByBaseName(CAS.FEATURE_BASE_NAME_BEGIN).getCode(); - end_featCode = annotType.getFeatureByBaseName(CAS.FEATURE_BASE_NAME_END ).getCode(); - } - + public final static int _FI_begin = JCasRegistry.registerFeature(typeIndexID); + public final static int _FI_end = JCasRegistry.registerFeature(typeIndexID); + /* local data */ private int _F_begin; private int _F_end; @@ -90,7 +82,7 @@ public class Annotation extends Annotati * setter for begin - sets beginning of span of annotation */ public void setBegin(int v) { - _casView.setWithCheckAndJournal(this, begin_featCode, () -> _F_begin = v); + _casView.setWithCheckAndJournalJFRI(this, _FI_begin , () -> _F_begin = v); } // *------------------* @@ -106,7 +98,7 @@ public class Annotation extends Annotati * setter for end - sets ending of span of annotation */ public void setEnd(int v) { - _casView.setWithCheckAndJournal(this, end_featCode, () -> _F_end = v); + _casView.setWithCheckAndJournalJFRI(this, _FI_end, () -> _F_end = v); } /**