| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.uima.cas.impl; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.BitSet; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.NoSuchElementException; |
| import java.util.Vector; |
| |
| import org.apache.uima.cas.CAS; |
| import org.apache.uima.cas.Feature; |
| import org.apache.uima.cas.Type; |
| import org.apache.uima.cas.TypeNameSpace; |
| import org.apache.uima.cas.TypeSystem; |
| import org.apache.uima.cas.admin.CASAdminException; |
| import org.apache.uima.cas.admin.TypeSystemMgr; |
| import org.apache.uima.internal.util.IntVector; |
| import org.apache.uima.internal.util.StringToIntMap; |
| import org.apache.uima.internal.util.SymbolTable; |
| import org.apache.uima.internal.util.rb_trees.IntRedBlackTree; |
| import org.apache.uima.internal.util.rb_trees.RedBlackTree; |
| |
| /** |
| * Type system implementation. |
| * |
| */ |
| public class TypeSystemImpl implements TypeSystemMgr, LowLevelTypeSystem { |
| |
| private static class ListIterator<T> implements Iterator<T> { |
| |
| private final List<T> list; |
| |
| private final int len; |
| |
| private int pos = 0; |
| |
| private ListIterator(List<T> list, int max) { |
| this.list = list; |
| this.len = (max < list.size()) ? max : list.size(); |
| } |
| |
| public boolean hasNext() { |
| return this.pos < this.len; |
| } |
| |
| public T next() { |
| if (!hasNext()) { |
| throw new NoSuchElementException(); |
| } |
| T o = this.list.get(this.pos); |
| ++this.pos; |
| return o; |
| } |
| |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| } |
| |
| // static maps ok for now - only built-in mappings stored here |
| // which are the same for all type system instances |
| private static Map<String, String> arrayComponentTypeNameMap = new HashMap<String, String>(); |
| |
| private static Map<String, String> arrayTypeComponentNameMap = new HashMap<String, String>(); |
| |
| private static final String arrayTypeSuffix = "[]"; |
| |
| static { |
| arrayComponentTypeNameMap.put(CAS.TYPE_NAME_TOP, CAS.TYPE_NAME_FS_ARRAY); |
| arrayComponentTypeNameMap.put(CAS.TYPE_NAME_BOOLEAN, CAS.TYPE_NAME_BOOLEAN_ARRAY); |
| arrayComponentTypeNameMap.put(CAS.TYPE_NAME_BYTE, CAS.TYPE_NAME_BYTE_ARRAY); |
| arrayComponentTypeNameMap.put(CAS.TYPE_NAME_SHORT, CAS.TYPE_NAME_SHORT_ARRAY); |
| arrayComponentTypeNameMap.put(CAS.TYPE_NAME_INTEGER, CAS.TYPE_NAME_INTEGER_ARRAY); |
| arrayComponentTypeNameMap.put(CAS.TYPE_NAME_FLOAT, CAS.TYPE_NAME_FLOAT_ARRAY); |
| arrayComponentTypeNameMap.put(CAS.TYPE_NAME_LONG, CAS.TYPE_NAME_LONG_ARRAY); |
| arrayComponentTypeNameMap.put(CAS.TYPE_NAME_DOUBLE, CAS.TYPE_NAME_DOUBLE_ARRAY); |
| arrayComponentTypeNameMap.put(CAS.TYPE_NAME_STRING, CAS.TYPE_NAME_STRING_ARRAY); |
| } |
| |
| static { |
| arrayTypeComponentNameMap.put(CAS.TYPE_NAME_FS_ARRAY, CAS.TYPE_NAME_TOP); |
| arrayTypeComponentNameMap.put(CAS.TYPE_NAME_BOOLEAN_ARRAY, CAS.TYPE_NAME_BOOLEAN); |
| arrayTypeComponentNameMap.put(CAS.TYPE_NAME_BYTE_ARRAY, CAS.TYPE_NAME_BYTE); |
| arrayTypeComponentNameMap.put(CAS.TYPE_NAME_SHORT_ARRAY, CAS.TYPE_NAME_SHORT); |
| arrayTypeComponentNameMap.put(CAS.TYPE_NAME_INTEGER_ARRAY, CAS.TYPE_NAME_INTEGER); |
| arrayTypeComponentNameMap.put(CAS.TYPE_NAME_FLOAT_ARRAY, CAS.TYPE_NAME_FLOAT); |
| arrayTypeComponentNameMap.put(CAS.TYPE_NAME_LONG_ARRAY, CAS.TYPE_NAME_LONG); |
| arrayTypeComponentNameMap.put(CAS.TYPE_NAME_DOUBLE_ARRAY, CAS.TYPE_NAME_DOUBLE); |
| arrayTypeComponentNameMap.put(CAS.TYPE_NAME_STRING_ARRAY, CAS.TYPE_NAME_STRING); |
| } |
| |
| // Current implementation has online update. Look-up could be made |
| // more efficient by computing some tables, but the assumption is |
| // that the type system will not be queried often enough to justify |
| // the effort. |
| |
| private SymbolTable typeNameST; // Symbol table of type names |
| |
| // Symbol table of feature names, containing only one entry per feature, |
| // i.e., |
| // its normal form. |
| private SymbolTable featureNameST; |
| |
| // A map from the full space of feature names to feature codes. A feature |
| // may |
| // be know by many different names (one for each subtype of the type the |
| // feature is declared on). |
| private StringToIntMap featureMap; |
| |
| private List<IntVector> tree; // Collection of IntVectors encoding type tree |
| |
| private List<BitSet> subsumes; // Collection of BitSets for subsumption relation |
| |
| private IntVector intro; |
| |
| // Indicates which type introduces a feature (domain) |
| private IntVector featRange; // Indicates range type of features |
| |
| private ArrayList<IntVector> approp; // For each type, an IntVector of appropriate |
| |
| // features |
| |
| // Code of root of hierarchy (will be 1 with current implementation) |
| private int top; |
| |
| // An ArrayList (unsynchronized) of TypeImpl objects. |
| private List<Type> types; |
| |
| // An ArrayList (unsynchronized) of FeatureImpl objects. |
| private List<Feature> features; |
| |
| // List of parent types. |
| private final IntVector parents; |
| |
| // String sets for string subtypes. |
| private final List<String[]> stringSets; |
| |
| // This map contains an entry for every subtype of the string type. The value is a pointer into |
| // the stringSets array list. |
| private final IntRedBlackTree stringSetMap; |
| |
| // For each type, remember if an array of this component type has already |
| // been created. |
| private final IntRedBlackTree componentToArrayTypeMap; |
| |
| // A mapping from array types to their component types. |
| private final IntRedBlackTree arrayToComponentTypeMap; |
| |
| // A mapping from array type codes to array type objects. |
| private final RedBlackTree<TypeImpl> arrayCodeToTypeMap; |
| |
| // Is the type system locked? |
| private boolean locked = false; |
| |
| private static final int LEAST_TYPE_CODE = 1; |
| |
| // private static final int INVALID_TYPE_CODE = 0; |
| private static final int LEAST_FEATURE_CODE = 1; |
| |
| private int numCommittedTypes = 0; |
| |
| final CASMetadata casMetadata; // needs to be visible in package |
| |
| boolean areBuiltInTypesSetup = false; |
| |
| TypeImpl intType; |
| |
| TypeImpl stringType; |
| |
| TypeImpl floatType; |
| |
| TypeImpl arrayBaseType; |
| |
| TypeImpl intArrayType; |
| |
| TypeImpl floatArrayType; |
| |
| TypeImpl stringArrayType; |
| |
| TypeImpl fsArrayType; |
| |
| TypeImpl sofaType; |
| |
| TypeImpl annotType; |
| |
| TypeImpl annotBaseType; |
| |
| TypeImpl docType; |
| |
| FeatureImpl startFeat; |
| |
| FeatureImpl endFeat; |
| |
| FeatureImpl langFeat; |
| |
| FeatureImpl sofaNum; |
| |
| TypeImpl byteType; |
| |
| TypeImpl byteArrayType; |
| |
| TypeImpl booleanType; |
| |
| TypeImpl booleanArrayType; |
| |
| TypeImpl shortType; |
| |
| TypeImpl shortArrayType; |
| |
| TypeImpl longType; |
| |
| TypeImpl longArrayType; |
| |
| TypeImpl doubleType; |
| |
| TypeImpl doubleArrayType; |
| |
| // int topTypeCode; |
| int intTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int stringTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int floatTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int arrayBaseTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int intArrayTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int floatArrayTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int stringArrayTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int fsArrayTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int sofaTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int annotTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int annotBaseTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int byteTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int booleanTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int shortTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int longTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int doubleTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int byteArrayTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int booleanArrayTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int shortArrayTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int longArrayTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int doubleArrayTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| public int sofaNumFeatCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; // ref from another pkg |
| |
| int sofaIdFeatCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int sofaMimeFeatCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int sofaUriFeatCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int sofaArrayFeatCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| public int annotSofaFeatCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; // ref from another pkg |
| |
| int startFeatCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int endFeatCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| int langFeatCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE; |
| |
| /** |
| * Default constructor. |
| * |
| * @deprecated Use 0 arg constructor. Type Systems are shared by many CASes, and can't point to |
| * one. Change also your possible calls to ts.commit() - see comment on that method. |
| */ |
| @Deprecated |
| public TypeSystemImpl(CASImpl cas) { |
| this(); |
| } |
| |
| public TypeSystemImpl() { |
| // Changed numbering to start at 1. Hope this doesn't break |
| // anything. If it does, I know who's fault it is... |
| this.typeNameST = new SymbolTable(1); |
| this.featureNameST = new SymbolTable(1); |
| this.featureMap = new StringToIntMap(); |
| // In each Vector, add null as first element, since we start |
| // counting at 1. |
| this.tree = new ArrayList<IntVector>(); |
| this.tree.add(null); |
| this.subsumes = new ArrayList<BitSet>(); |
| this.subsumes.add(null); |
| this.intro = new IntVector(); |
| this.intro.add(0); |
| this.featRange = new IntVector(); |
| this.featRange.add(0); |
| this.approp = new ArrayList<IntVector>(); |
| this.approp.add(null); |
| this.types = new ArrayList<Type>(); |
| this.types.add(null); |
| this.features = new ArrayList<Feature>(); |
| this.features.add(null); |
| this.stringSets = new ArrayList<String[]>(); |
| this.stringSetMap = new IntRedBlackTree(); |
| this.componentToArrayTypeMap = new IntRedBlackTree(); |
| this.arrayToComponentTypeMap = new IntRedBlackTree(); |
| this.arrayCodeToTypeMap = new RedBlackTree<TypeImpl>(); |
| this.parents = new IntVector(); |
| this.parents.add(0); |
| |
| this.casMetadata = new CASMetadata(this); |
| // load in built-in types |
| CASImpl.setupTSDefault(this); |
| initTypeVariables(); |
| } |
| |
| // only built-in types here; can be called before |
| // type system is committed, as long as the built-in ones |
| // are defined. |
| final void initTypeVariables() { |
| // Type objects. |
| // this.ts.topType = (TypeImpl) this.ts.getTopType(); // never used |
| this.intType = (TypeImpl) getType(CAS.TYPE_NAME_INTEGER); |
| this.stringType = (TypeImpl) getType(CAS.TYPE_NAME_STRING); |
| this.floatType = (TypeImpl) getType(CAS.TYPE_NAME_FLOAT); |
| this.arrayBaseType = (TypeImpl) getType(CAS.TYPE_NAME_ARRAY_BASE); |
| this.intArrayType = (TypeImpl) getType(CAS.TYPE_NAME_INTEGER_ARRAY); |
| this.floatArrayType = (TypeImpl) getType(CAS.TYPE_NAME_FLOAT_ARRAY); |
| this.stringArrayType = (TypeImpl) getType(CAS.TYPE_NAME_STRING_ARRAY); |
| this.fsArrayType = (TypeImpl) getType(CAS.TYPE_NAME_FS_ARRAY); |
| this.sofaType = (TypeImpl) getType(CAS.TYPE_NAME_SOFA); |
| this.annotType = (TypeImpl) getType(CAS.TYPE_NAME_ANNOTATION); |
| this.sofaNum = (FeatureImpl) getFeatureByFullName(CAS.FEATURE_FULL_NAME_SOFANUM); |
| this.annotBaseType = (TypeImpl) getType(CAS.TYPE_NAME_ANNOTATION_BASE); |
| this.startFeat = (FeatureImpl) getFeatureByFullName(CAS.FEATURE_FULL_NAME_BEGIN); |
| this.endFeat = (FeatureImpl) getFeatureByFullName(CAS.FEATURE_FULL_NAME_END); |
| this.langFeat = (FeatureImpl) getFeatureByFullName(CAS.FEATURE_FULL_NAME_LANGUAGE); |
| this.docType = (TypeImpl) getType(CAS.TYPE_NAME_DOCUMENT_ANNOTATION); |
| |
| this.byteType = (TypeImpl) getType(CAS.TYPE_NAME_BYTE); |
| this.byteArrayType = (TypeImpl) getType(CAS.TYPE_NAME_BYTE_ARRAY); |
| this.booleanType = (TypeImpl) getType(CAS.TYPE_NAME_BOOLEAN); |
| this.booleanArrayType = (TypeImpl) getType(CAS.TYPE_NAME_BOOLEAN_ARRAY); |
| this.shortType = (TypeImpl) getType(CAS.TYPE_NAME_SHORT); |
| this.shortArrayType = (TypeImpl) getType(CAS.TYPE_NAME_SHORT_ARRAY); |
| this.longType = (TypeImpl) getType(CAS.TYPE_NAME_LONG); |
| this.longArrayType = (TypeImpl) getType(CAS.TYPE_NAME_LONG_ARRAY); |
| this.doubleType = (TypeImpl) getType(CAS.TYPE_NAME_DOUBLE); |
| this.doubleArrayType = (TypeImpl) getType(CAS.TYPE_NAME_DOUBLE_ARRAY); |
| |
| // Type codes. |
| initTypeCodeVars(); |
| } |
| |
| private final void initTypeCodeVars() { |
| this.intTypeCode = this.intType.getCode(); |
| this.stringTypeCode = this.stringType.getCode(); |
| this.floatTypeCode = this.floatType.getCode(); |
| // this.arrayBaseTypeCode = arrayBaseType.getCode(); |
| this.intArrayTypeCode = this.intArrayType.getCode(); |
| this.floatArrayTypeCode = this.floatArrayType.getCode(); |
| this.stringArrayTypeCode = this.stringArrayType.getCode(); |
| this.fsArrayTypeCode = this.fsArrayType.getCode(); |
| this.sofaTypeCode = this.sofaType.getCode(); |
| this.annotTypeCode = this.annotType.getCode(); |
| this.annotBaseTypeCode = this.annotBaseType.getCode(); |
| |
| this.byteArrayTypeCode = this.byteArrayType.getCode(); |
| this.byteTypeCode = this.byteType.getCode(); |
| this.booleanTypeCode = this.booleanType.getCode(); |
| this.booleanArrayTypeCode = this.booleanArrayType.getCode(); |
| this.shortTypeCode = this.shortType.getCode(); |
| this.shortArrayTypeCode = this.shortArrayType.getCode(); |
| this.longTypeCode = this.longType.getCode(); |
| this.longArrayTypeCode = this.longArrayType.getCode(); |
| this.doubleTypeCode = this.doubleType.getCode(); |
| this.doubleArrayTypeCode = this.doubleArrayType.getCode(); |
| |
| this.arrayBaseTypeCode = this.arrayBaseType.getCode(); |
| |
| final Type sofaT = this.sofaType; |
| this.sofaNumFeatCode = ll_getCodeForFeature(sofaT |
| .getFeatureByBaseName(CAS.FEATURE_BASE_NAME_SOFANUM)); |
| this.sofaIdFeatCode = ll_getCodeForFeature(sofaT |
| .getFeatureByBaseName(CAS.FEATURE_BASE_NAME_SOFAID)); |
| this.sofaMimeFeatCode = ll_getCodeForFeature(sofaT |
| .getFeatureByBaseName(CAS.FEATURE_BASE_NAME_SOFAMIME)); |
| this.sofaUriFeatCode = ll_getCodeForFeature(sofaT |
| .getFeatureByBaseName(CAS.FEATURE_BASE_NAME_SOFAURI)); |
| this.sofaArrayFeatCode = ll_getCodeForFeature(sofaT |
| .getFeatureByBaseName(CAS.FEATURE_BASE_NAME_SOFAARRAY)); |
| this.annotSofaFeatCode = ll_getCodeForFeature(this.annotBaseType |
| .getFeatureByBaseName(CAS.FEATURE_BASE_NAME_SOFA)); |
| this.startFeatCode = ll_getCodeForFeature(this.annotType |
| .getFeatureByBaseName(CAS.FEATURE_BASE_NAME_BEGIN)); |
| this.endFeatCode = ll_getCodeForFeature(this.annotType |
| .getFeatureByBaseName(CAS.FEATURE_BASE_NAME_END)); |
| this.langFeatCode = ll_getCodeForFeature(this.docType |
| .getFeatureByBaseName(CAS.FEATURE_BASE_NAME_LANGUAGE)); |
| } |
| |
| // Some implementation helpers for users of the type system. |
| final int getSmallestType() { |
| return LEAST_TYPE_CODE; |
| } |
| |
| final int getSmallestFeature() { |
| return LEAST_FEATURE_CODE; |
| } |
| |
| final int getTypeArraySize() { |
| return getNumberOfTypes() + getSmallestType(); |
| } |
| |
| public Vector<Feature> getIntroFeatures(Type type) { |
| Vector<Feature> feats = new Vector<Feature>(); |
| List<Feature> appropFeats = type.getFeatures(); |
| final int max = appropFeats.size(); |
| Feature feat; |
| for (int i = 0; i < max; i++) { |
| feat = appropFeats.get(i); |
| if (feat.getDomain() == type) { |
| feats.add(feat); |
| } |
| } |
| return feats; |
| } |
| |
| public Type getParent(Type t) { |
| return ((TypeImpl) t).getSuperType(); |
| } |
| |
| public int ll_getParentType(int typeCode) { |
| return this.parents.get(typeCode); |
| } |
| |
| int ll_computeArrayParentFromComponentType(int componentType) { |
| if (ll_isPrimitiveType(componentType) || |
| // note: not using this.top - until we can confirm this is set |
| // in all cases |
| (ll_getTypeForCode(componentType).getName().equals(CAS.TYPE_NAME_TOP))) { |
| return this.arrayBaseTypeCode; |
| } |
| // is a subtype of FSArray. |
| // note: not using this.fsArray - until we can confirm this is set in |
| // all cases |
| return this.fsArrayTypeCode; |
| // return ll_getArrayType(ll_getParentType(componentType)); |
| } |
| |
| /** |
| * Check if feature is appropriate for type (i.e., type is subsumed by domain type of feature). |
| */ |
| public boolean isApprop(int type, int feat) { |
| return subsumes(intro(feat), type); |
| } |
| |
| public final int getLargestTypeCode() { |
| return getNumberOfTypes(); |
| } |
| |
| public boolean isType(int type) { |
| return ((type > 0) && (type <= getLargestTypeCode())); |
| } |
| |
| /** |
| * Get a type object for a given name. |
| * |
| * @param typeName |
| * The name of the type. |
| * @return A type object, or <code>null</code> if no such type exists. |
| */ |
| public Type getType(String typeName) { |
| final int typeCode = ll_getCodeForTypeName(typeName); |
| if (typeCode < LEAST_TYPE_CODE) { |
| return null; |
| } |
| return this.types.get(typeCode); |
| } |
| |
| /** |
| * Get an feature object for a given code. |
| * |
| * @param featCode |
| * The code of the feature. |
| * @return A feature object, or <code>null</code> if no such feature exists. |
| */ |
| // public Feature getFeature(int featCode) { |
| // return (Feature) this.features.get(featCode); |
| // } |
| |
| /** |
| * Get an feature object for a given name. |
| * |
| * @param featureName |
| * The name of the feature. |
| * @return An feature object, or <code>null</code> if no such feature exists. |
| */ |
| public Feature getFeatureByFullName(String featureName) { |
| // if (!this.featureMap.containsKey(featureName)) { |
| // return null; |
| // } |
| // final int featCode = this.featureMap.get(featureName); |
| // return (Feature) this.features.get(featCode); |
| // will return null if feature not present because |
| // the featureMap.get will return 0, and |
| // getFeature returns null for code of 0 |
| return ll_getFeatureForCode(this.featureMap.get(featureName)); |
| } |
| |
| private static final String getArrayTypeName(String typeName) { |
| final String arrayTypeName = arrayComponentTypeNameMap.get(typeName); |
| return (null == arrayTypeName) ? typeName + arrayTypeSuffix : arrayTypeName; |
| // if (arrayComponentTypeNameMap.containsKey(typeName)) { |
| // return (String) arrayComponentTypeNameMap.get(typeName); |
| // } |
| // return typeName + arrayTypeSuffix; |
| } |
| |
| static final String getArrayComponentName(String arrayTypeName) { |
| return arrayTypeName.substring(0, arrayTypeName.length() - 2); |
| } |
| |
| static boolean isArrayTypeNameButNotBuiltIn(String typeName) { |
| return typeName.endsWith(arrayTypeSuffix); |
| } |
| |
| private static final String getBuiltinArrayComponent(String typeName) { |
| // if typeName is not contained in the map, the "get" returns null |
| // if (arrayTypeComponentNameMap.containsKey(typeName)) { |
| return arrayTypeComponentNameMap.get(typeName); |
| // } |
| // return null; |
| } |
| |
| /** |
| * Add a new type to the type system. |
| * |
| * @param typeName |
| * The name of the new type. |
| * @param mother |
| * The type node under which the new type should be attached. |
| * @return The new type, or <code>null</code> if <code>typeName</code> is already in use. |
| */ |
| public Type addType(String typeName, Type mother) throws CASAdminException { |
| if (this.locked) { |
| throw new CASAdminException(CASAdminException.TYPE_SYSTEM_LOCKED); |
| } |
| if (mother.isInheritanceFinal()) { |
| CASAdminException e = new CASAdminException(CASAdminException.TYPE_IS_INH_FINAL); |
| e.addArgument(mother.getName()); |
| throw e; |
| } |
| // Check type name syntax. |
| // Handle the built-in array types, like BooleanArray, FSArray, etc. |
| String componentTypeName = getBuiltinArrayComponent(typeName); |
| if (componentTypeName != null) { |
| return getArrayType(getType(componentTypeName)); |
| } |
| checkTypeSyntax(typeName); |
| final int typeCode = this.addType(typeName, ((TypeImpl) mother).getCode()); |
| if (typeCode < this.typeNameST.getStart()) { |
| return null; |
| } |
| return this.types.get(typeCode); |
| } |
| |
| /** |
| * Method checkTypeSyntax. |
| * |
| * @param typeName |
| */ |
| private void checkTypeSyntax(String name) throws CASAdminException { |
| if (!TypeSystemUtils.isTypeName(name)) { |
| CASAdminException e = new CASAdminException(CASAdminException.BAD_TYPE_SYNTAX); |
| e.addArgument(name); |
| throw e; |
| } |
| } |
| |
| int addType(String name, int superType) { |
| return addType(name, superType, false); |
| } |
| |
| /** |
| * Internal code for adding a new type. Warning: no syntax check on type name, must be done by |
| * caller. This method is not private because it's used by the serialization code. |
| */ |
| int addType(String name, int superType, boolean isStringType) { |
| if (this.typeNameST.contains(name)) { |
| return -1; |
| } |
| // assert (isType(superType)); //: "Supertype is not a known type: |
| // "+superType; |
| // Add the new type to the symbol table. |
| final int type = this.typeNameST.set(name); |
| // Create space for new type. |
| newType(); |
| // Add an edge to the tree. |
| (this.tree.get(superType)).add(type); |
| // Update subsumption relation. |
| updateSubsumption(type, superType); |
| // Add inherited features. |
| final IntVector superApprop = this.approp.get(superType); |
| // superApprop.add(0); |
| final IntVector typeApprop = this.approp.get(type); |
| // typeApprop.add(0); |
| final int max = superApprop.size(); |
| int featCode; |
| for (int i = 0; i < max; i++) { |
| featCode = superApprop.get(i); |
| typeApprop.add(featCode); |
| // Add inherited feature names. |
| String feat = name + TypeSystem.FEATURE_SEPARATOR + ll_getFeatureForCode(featCode).getShortName(); |
| // System.out.println("Adding name: " + feat); |
| this.featureMap.put(feat, featCode); |
| } |
| TypeImpl t; |
| if (isStringType) { |
| final int stringSetCode = this.stringSets.size(); |
| this.stringSetMap.put(type, stringSetCode); |
| t = new StringTypeImpl(name, type, this); |
| } else { |
| t = new TypeImpl(name, type, this); |
| } |
| this.types.add(t); |
| this.parents.add(superType); |
| this.numCommittedTypes = this.types.size(); |
| return type; |
| } |
| |
| public Feature addFeature(String featureName, Type domainType, Type rangeType) |
| throws CASAdminException { |
| return addFeature(featureName, domainType, rangeType, true); |
| } |
| |
| /** |
| * @see TypeSystemMgr#addFeature(String, Type, Type) |
| */ |
| public Feature addFeature(String featureName, Type domainType, Type rangeType, |
| boolean multipleReferencesAllowed) throws CASAdminException { |
| // assert(featureName != null); |
| // assert(domainType != null); |
| // assert(rangeType != null); |
| if (this.locked) { |
| throw new CASAdminException(CASAdminException.TYPE_SYSTEM_LOCKED); |
| } |
| Feature f = domainType.getFeatureByBaseName(featureName); |
| if (f != null && f.getRange().equals(rangeType)) { |
| return f; |
| } |
| if (domainType.isFeatureFinal()) { |
| CASAdminException e = new CASAdminException(CASAdminException.TYPE_IS_FEATURE_FINAL); |
| e.addArgument(domainType.getName()); |
| throw e; |
| } |
| checkFeatureNameSyntax(featureName); |
| final int featCode = this.addFeature(featureName, ((TypeImpl) domainType).getCode(), |
| ((TypeImpl) rangeType).getCode(), multipleReferencesAllowed); |
| if (featCode < this.featureNameST.getStart()) { |
| return null; |
| } |
| return this.features.get(featCode); |
| } |
| |
| /** |
| * Method checkFeatureNameSyntax. |
| */ |
| private void checkFeatureNameSyntax(String name) throws CASAdminException { |
| if (!TypeSystemUtils.isIdentifier(name)) { |
| CASAdminException e = new CASAdminException(CASAdminException.BAD_FEATURE_SYNTAX); |
| e.addArgument(name); |
| throw e; |
| } |
| } |
| |
| /** |
| * Get an iterator over all types, in no particular order. |
| * |
| * @return The iterator. |
| */ |
| public Iterator<Type> getTypeIterator() { |
| Iterator<Type> it = new ListIterator<Type>(this.types, this.numCommittedTypes); |
| // The first element is null, so skip it. |
| it.next(); |
| return it; |
| } |
| |
| public Iterator<Feature> getFeatures() { |
| Iterator<Feature> it = this.features.iterator(); |
| // The first element is null, so skip it. |
| it.next(); |
| return it; |
| } |
| |
| /** |
| * Get the top type, i.e., the root of the type system. |
| * |
| * @return The top type. |
| */ |
| public Type getTopType() { |
| return this.types.get(this.top); |
| } |
| |
| /** |
| * Return the list of all types subsumed by the input type. Note: the list does not include the |
| * type itself. |
| * |
| * @param type |
| * Input type. |
| * @return The list of types subsumed by <code>type</code>. |
| */ |
| public List<Type> getProperlySubsumedTypes(Type type) { |
| List<Type> subList = new ArrayList<Type>(); |
| Iterator<Type> typeIt = getTypeIterator(); |
| while (typeIt.hasNext()) { |
| Type t = typeIt.next(); |
| if (type != t && subsumes(type, t)) { |
| subList.add(t); |
| } |
| } |
| |
| return subList; |
| } |
| |
| /** |
| * Get a vector of the types directly subsumed by a given type. |
| * |
| * @param type |
| * The input type. |
| * @return A vector of the directly subsumed types. |
| */ |
| public Vector<Type> getDirectlySubsumedTypes(Type type) { |
| return new Vector<Type>(getDirectSubtypes(type)); |
| } |
| |
| public List<Type> getDirectSubtypes(Type type) { |
| if (type.isArray()) { |
| return new ArrayList<Type>(); |
| } |
| List<Type> list = new ArrayList<Type>(); |
| IntVector sub = this.tree.get(((TypeImpl) type).getCode()); |
| final int max = sub.size(); |
| for (int i = 0; i < max; i++) { |
| list.add(this.types.get(sub.get(i))); |
| } |
| return list; |
| } |
| |
| public boolean directlySubsumes(int t1, int t2) { |
| IntVector sub = this.tree.get(t1); |
| return sub.contains(t2); |
| } |
| |
| /** |
| * Does one type inherit from the other? |
| * |
| * @param superType |
| * Supertype. |
| * @param subType |
| * Subtype. |
| * @return <code>true</code> iff <code>sub</code> inherits from <code>super</code>. |
| */ |
| public boolean subsumes(Type superType, Type subType) { |
| // assert(superType != null); |
| // assert(subType != null); |
| return this.subsumes(((TypeImpl) superType).getCode(), ((TypeImpl) subType).getCode()); |
| } |
| |
| /** |
| * Get an array of the appropriate features for this type. |
| */ |
| public int[] ll_getAppropriateFeatures(int type) { |
| if (type < LEAST_TYPE_CODE || type > getNumberOfTypes()) { |
| return null; |
| } |
| // We have to copy the array since we don't have const. |
| return (this.approp.get(type)).toArrayCopy(); |
| } |
| |
| /** |
| * @return An offset <code>>0</code> if <code>feat</code> exists; <code>0</code>, else. |
| */ |
| int getFeatureOffset(int feat) { |
| return (this.approp.get(this.intro.get(feat))).position(feat) + 1; |
| } |
| |
| /** |
| * Get the overall number of features defined in the type system. |
| */ |
| public int getNumberOfFeatures() { |
| return this.featureNameST.size(); |
| } |
| |
| /** |
| * Get the overall number of types defined in the type system. |
| */ |
| public int getNumberOfTypes() { |
| return this.typeNameST.size(); |
| } |
| |
| /** |
| * Get the domain type for a feature. |
| */ |
| public int intro(int feat) { |
| return this.intro.get(feat); |
| } |
| |
| /** |
| * Get the range type for a feature. |
| */ |
| public int range(int feat) { |
| return this.featRange.get(feat); |
| } |
| |
| // Unification is trivial, since we don't have multiple inheritance. |
| public int unify(int t1, int t2) { |
| if (this.subsumes(t1, t2)) { |
| return t2; |
| } else if (this.subsumes(t2, t1)) { |
| return t1; |
| } else { |
| return -1; |
| } |
| } |
| |
| int addFeature(String shortName, int domain, int range) { |
| return addFeature(shortName, domain, range, true); |
| } |
| |
| /** |
| * Add a new feature to the type system. |
| */ |
| int addFeature(String shortName, int domain, int range, boolean multiRefsAllowed) { |
| // Since we just looked up the domain in the symbol table, we know it |
| // exists. |
| String name = this.typeNameST.getSymbol(domain) + TypeSystem.FEATURE_SEPARATOR + shortName; |
| // Create a list of the domain type and all its subtypes. |
| // Type t = getType(domain); |
| // if (t == null) { |
| // System.out.println("Type is null"); |
| // } |
| List<Type> typesLocal = getProperlySubsumedTypes(ll_getTypeForCode(domain)); |
| typesLocal.add(ll_getTypeForCode(domain)); |
| // For each type, check that the feature doesn't already exist. |
| int max = typesLocal.size(); |
| for (int i = 0; i < max; i++) { |
| String featureName = (typesLocal.get(i)).getName() + FEATURE_SEPARATOR + shortName; |
| if (this.featureMap.containsKey(featureName)) { |
| // We have already added this feature. If the range of the |
| // duplicate |
| // feature is identical, we don't do anything and just return. |
| // Else, |
| // we throw an exception. |
| Feature oldFeature = getFeatureByFullName(featureName); |
| Type oldDomain = oldFeature.getDomain(); |
| Type oldRange = oldFeature.getRange(); |
| if (range == ll_getCodeForType(oldRange)) { |
| return -1; |
| } |
| CASAdminException e = new CASAdminException(CASAdminException.DUPLICATE_FEATURE); |
| e.addArgument(shortName); |
| e.addArgument(ll_getTypeForCode(domain).getName()); |
| e.addArgument(ll_getTypeForCode(range).getName()); |
| e.addArgument(oldDomain.getName()); |
| e.addArgument(oldRange.getName()); |
| throw e; |
| } |
| } // Add name to symbol table. |
| int feat = this.featureNameST.set(name); |
| // Add entries for all subtypes. |
| for (int i = 0; i < max; i++) { |
| this.featureMap.put((typesLocal.get(i)).getName() + FEATURE_SEPARATOR + shortName, |
| feat); |
| } |
| this.intro.add(domain); |
| this.featRange.add(range); |
| max = this.typeNameST.size(); |
| for (int i = 1; i <= max; i++) { |
| if (subsumes(domain, i)) { |
| (this.approp.get(i)).add(feat); |
| } |
| } |
| this.features.add(new FeatureImpl(feat, name, this, multiRefsAllowed)); |
| return feat; |
| } |
| |
| /** |
| * Add a top type to the (empty) type system. |
| */ |
| public Type addTopType(String name) { |
| final int code = this.addTopTypeInternal(name); |
| if (code < 1) { |
| return null; |
| } |
| return this.types.get(code); |
| } |
| |
| private int addTopTypeInternal(String name) { |
| if (this.typeNameST.size() > 0) { |
| // System.out.println("Size of type table > 0."); |
| return 0; |
| } // Add name of top type to symbol table. |
| this.top = this.typeNameST.set(name); |
| // System.out.println("Size of name table is: " + typeNameST.size()); |
| // assert (typeNameST.size() == 1); |
| // System.out.println("Code of top type is: " + this.top); |
| // Create space for top type. |
| newType(); |
| // Make top subsume itself. |
| addSubsubsumption(this.top, this.top); |
| this.types.add(new TypeImpl(name, this.top, this)); |
| this.parents.add(LowLevelTypeSystem.UNKNOWN_TYPE_CODE); |
| this.numCommittedTypes = this.types.size(); |
| return this.top; |
| } |
| |
| /** |
| * Check if the first argument subsumes the second |
| */ |
| public boolean subsumes(int superType, int type) { |
| return this.ll_subsumes(superType, type); |
| } |
| |
| private boolean ll_isPrimitiveArrayType(int type) { |
| return type == this.floatArrayTypeCode || type == this.intArrayTypeCode |
| || type == this.booleanArrayTypeCode || type == this.shortArrayTypeCode |
| || type == this.byteArrayTypeCode || type == this.longArrayTypeCode |
| || type == this.doubleArrayTypeCode || type == this.stringArrayTypeCode; |
| } |
| |
| public boolean ll_subsumes(int superType, int type) { |
| // Add range check. |
| // assert (isType(superType)); |
| // assert (isType(type)); |
| |
| // Need special handling for arrays, as they're generated on the fly and |
| // not added to the subsumption table. |
| |
| // speedup code. |
| if (superType == type) |
| return true; |
| |
| // Yes, the code below is intentional. Until we actually support real |
| // arrays of some |
| // particular fs, |
| // we have FSArray is the supertype of xxxx[] AND |
| // xxx[] is the supertype of FSArray |
| // (this second relation because all we can generate are instances of |
| // FSArray |
| // and we must be able to assign them to xxx[] ) |
| if (superType == this.fsArrayTypeCode) { |
| return !ll_isPrimitiveArrayType(type) && ll_isArrayType(type); |
| } |
| |
| if (type == this.fsArrayTypeCode) { |
| return superType == this.top || superType == this.arrayBaseTypeCode |
| || (!ll_isPrimitiveArrayType(superType) && ll_isArrayType(superType)); |
| } |
| |
| // at this point, we could have arrays of other primitive types, or |
| // arrays of specific types: xxx[] |
| |
| final boolean isSuperArray = ll_isArrayType(superType); |
| final boolean isSubArray = ll_isArrayType(type); |
| if (isSuperArray) { |
| if (isSubArray) { |
| // If both types are arrays, simply compare the components. |
| return ll_subsumes(ll_getComponentType(superType), ll_getComponentType(type)); |
| } |
| // An array can never subsume a non-array. |
| return false; |
| } else if (isSubArray) { |
| // If the subtype is an array, and the supertype is not, then the |
| // supertype must be top, or the abstract array base. |
| return ((superType == this.top) || (superType == this.arrayBaseTypeCode)); |
| } |
| return this.subsumes.get(superType).get(type); |
| } |
| |
| private void updateSubsumption(int type, int superType) { |
| final int max = this.typeNameST.size(); |
| for (int i = 1; i <= max; i++) { |
| if (subsumes(i, superType)) { |
| addSubsubsumption(i, type); |
| } |
| } |
| addSubsubsumption(type, type); |
| } |
| |
| private void addSubsubsumption(int superType, int type) { |
| (this.subsumes.get(superType)).set(type); |
| } |
| |
| private void newType() { |
| // The assumption for the implementation is that new types will |
| // always be added at the end. |
| this.tree.add(new IntVector()); |
| this.subsumes.add(new BitSet()); |
| this.approp.add(new IntVector()); |
| } |
| |
| // Only used for serialization code. |
| SymbolTable getTypeNameST() { |
| return this.typeNameST; |
| } |
| |
| private final String getTypeString(Type t) { |
| return t.getName() + " (" + ll_getCodeForType(t) + ")"; |
| } |
| |
| private final String getFeatureString(Feature f) { |
| return f.getName() + " (" + ll_getCodeForFeature(f) + ")"; |
| } |
| |
| /** |
| * This writes out the type hierarchy in a human-readable form. |
| */ |
| public String toString() { |
| // This code is maximally readable, not maximally efficient. |
| StringBuffer buf = new StringBuffer(); |
| // Print top type. |
| buf.append("~" + getTypeString(this.getTopType()) + ";\n"); |
| // Iterate over types and print declarations. |
| final int numTypes = this.typeNameST.size(); |
| Type t; |
| for (int i = 2; i <= numTypes; i++) { |
| t = this.ll_getTypeForCode(i); |
| buf.append(getTypeString(t) + " < " + getTypeString(this.getParent(t)) + ";\n"); |
| } // Print feature declarations. |
| final int numFeats = this.featureNameST.size(); |
| Feature f; |
| for (int i = 1; i <= numFeats; i++) { |
| f = this.ll_getFeatureForCode(i); |
| buf.append(getFeatureString(f) + ": " + getTypeString(f.getDomain()) + " > " |
| + getTypeString(f.getRange()) + ";\n"); |
| } |
| return buf.toString(); |
| } |
| |
| /** |
| * @see org.apache.uima.cas.admin.TypeSystemMgr#commit() |
| */ |
| public void commit() { |
| if (this.locked == true) { |
| return; // might be called multiple times, but only need to do once |
| } |
| this.locked = true; |
| // because subsumes depends on it |
| // and generator initialization uses subsumes |
| this.numCommittedTypes = this.types.size(); // do before |
| // cas.commitTypeSystem - |
| // because it will call the type system iterator |
| this.casMetadata.setupFeaturesAndCreatableTypes(); |
| // ts should never point to a CAS. Many CASes can share one ts. |
| // if (this.cas != null) { |
| // this.cas.commitTypeSystem(); |
| // } |
| } |
| |
| /** |
| * @see org.apache.uima.cas.admin.TypeSystemMgr#isCommitted() |
| */ |
| public boolean isCommitted() { |
| return this.locked; |
| } |
| |
| // dangerous, and not needed, not in any interface |
| // public void setCommitted(boolean b) { |
| // this.locked = b; |
| // } |
| |
| /** |
| * @deprecated |
| */ |
| @Deprecated |
| public Feature getFeature(String featureName) { |
| return getFeatureByFullName(featureName); |
| } |
| |
| /** |
| * @see org.apache.uima.cas.admin.TypeSystemMgr#setFeatureFinal(org.apache.uima.cas.Type) |
| */ |
| public void setFeatureFinal(Type type) { |
| ((TypeImpl) type).setFeatureFinal(); |
| } |
| |
| /** |
| * @see org.apache.uima.cas.admin.TypeSystemMgr#setInheritanceFinal(org.apache.uima.cas.Type) |
| */ |
| public void setInheritanceFinal(Type type) { |
| ((TypeImpl) type).setInheritanceFinal(); |
| } |
| |
| /** |
| * @see org.apache.uima.cas.admin.TypeSystemMgr#addStringSubtype |
| */ |
| public Type addStringSubtype(String typeName, String[] stringList) throws CASAdminException { |
| // final int stringSetCode = this.stringSets.size(); |
| Type mother = this.stringType; |
| // Check type name syntax. |
| checkTypeSyntax(typeName); |
| // Create the type. |
| final int typeCode = this.addType(typeName, ((TypeImpl) mother).getCode(), true); |
| // If the type code is less than 1, it means that a type of that name |
| // already exists. |
| if (typeCode < this.typeNameST.getStart()) { |
| return null; |
| } // Get the created type. |
| StringTypeImpl type = (StringTypeImpl) this.types.get(typeCode); |
| type.setFeatureFinal(); |
| type.setInheritanceFinal(); |
| // Sort the String array. |
| Arrays.sort(stringList); |
| // Add the string array to the string sets. |
| this.stringSets.add(stringList); |
| return type; |
| } |
| |
| // public for ref from JCas TOP type, |
| // impl FeatureStructureImpl |
| public String[] getStringSet(int i) { |
| return this.stringSets.get(i); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.uima.cas.TypeSystem#getTypeNameSpace(java.lang.String) |
| */ |
| public TypeNameSpace getTypeNameSpace(String name) { |
| if (!TypeSystemUtils.isTypeNameSpaceName(name)) { |
| return null; |
| } |
| return new TypeNameSpaceImpl(name, this); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.uima.cas.impl.LowLevelTypeSystem#ll_getCodeForTypeName(java.lang.String) |
| */ |
| public int ll_getCodeForTypeName(String typeName) { |
| if (typeName == null) { |
| throw new NullPointerException(); |
| } |
| return this.typeNameST.get(typeName); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.uima.cas.impl.LowLevelTypeSystem#ll_getCodeForType(org.apache.uima.cas.Type) |
| */ |
| public int ll_getCodeForType(Type type) { |
| return ((TypeImpl) type).getCode(); |
| } |
| |
| public int ll_getCodeForFeatureName(String featureName) { |
| if (featureName == null) { |
| throw new NullPointerException(); |
| } |
| if (!this.featureMap.containsKey(featureName)) { |
| return UNKNOWN_FEATURE_CODE; |
| } |
| return this.featureMap.get(featureName); |
| } |
| |
| public int ll_getCodeForFeature(Feature feature) { |
| return ((FeatureImpl) feature).getCode(); |
| } |
| |
| public Type ll_getTypeForCode(int typeCode) { |
| if (isType(typeCode)) { |
| return this.types.get(typeCode); |
| } |
| return null; |
| } |
| |
| private final int getLargestFeatureCode() { |
| return this.getNumberOfFeatures(); |
| } |
| |
| final boolean isFeature(int featureCode) { |
| return ((featureCode > UNKNOWN_FEATURE_CODE) && (featureCode <= getLargestFeatureCode())); |
| } |
| |
| public Feature ll_getFeatureForCode(int featureCode) { |
| if (isFeature(featureCode)) { |
| return this.features.get(featureCode); |
| } |
| return null; |
| } |
| |
| public int ll_getDomainType(int featureCode) { |
| return intro(featureCode); |
| } |
| |
| public int ll_getRangeType(int featureCode) { |
| return range(featureCode); |
| } |
| |
| public LowLevelTypeSystem getLowLevelTypeSystem() { |
| return this; |
| } |
| |
| public boolean ll_isStringSubtype(int type) { |
| return this.stringSetMap.containsKey(type); |
| } |
| |
| public boolean ll_isRefType(int typeCode) { |
| final int typeClass = ll_getTypeClass(typeCode); |
| switch (typeClass) { |
| case LowLevelCAS.TYPE_CLASS_BOOLEAN: |
| case LowLevelCAS.TYPE_CLASS_BYTE: |
| case LowLevelCAS.TYPE_CLASS_SHORT: |
| case LowLevelCAS.TYPE_CLASS_INT: |
| case LowLevelCAS.TYPE_CLASS_FLOAT: |
| case LowLevelCAS.TYPE_CLASS_LONG: |
| case LowLevelCAS.TYPE_CLASS_DOUBLE: |
| case LowLevelCAS.TYPE_CLASS_STRING: { |
| return false; |
| } |
| default: { |
| return true; |
| } |
| } |
| } |
| |
| public Type getArrayType(Type componentType) { |
| final int arrayTypeCode = ll_getArrayType(ll_getCodeForType(componentType)); |
| if (arrayTypeCode == UNKNOWN_TYPE_CODE) { |
| return null; |
| } |
| return this.types.get(arrayTypeCode); |
| } |
| |
| public final int ll_getTypeClass(int typeCode) { |
| if (typeCode == this.booleanTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_BOOLEAN; |
| } |
| if (typeCode == this.byteTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_BYTE; |
| } |
| if (typeCode == this.shortTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_SHORT; |
| } |
| if (typeCode == this.intTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_INT; |
| } |
| if (typeCode == this.floatTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_FLOAT; |
| } |
| if (typeCode == this.longTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_LONG; |
| } |
| if (typeCode == this.doubleTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_DOUBLE; |
| } |
| // false if string type code not yet set up (during initialization) |
| // need this to avoid NPE in subsumes |
| if ((this.stringTypeCode != LowLevelTypeSystem.UNKNOWN_TYPE_CODE) && |
| ll_subsumes(this.stringTypeCode, typeCode)) { |
| return LowLevelCAS.TYPE_CLASS_STRING; |
| } |
| if (typeCode == this.booleanArrayTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_BOOLEANARRAY; |
| } |
| if (typeCode == this.byteArrayTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_BYTEARRAY; |
| } |
| if (typeCode == this.shortArrayTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_SHORTARRAY; |
| } |
| if (typeCode == this.intArrayTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_INTARRAY; |
| } |
| if (typeCode == this.floatArrayTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_FLOATARRAY; |
| } |
| if (typeCode == this.longArrayTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_LONGARRAY; |
| } |
| if (typeCode == this.doubleArrayTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_DOUBLEARRAY; |
| } |
| if (typeCode == this.stringArrayTypeCode) { |
| return LowLevelCAS.TYPE_CLASS_STRINGARRAY; |
| } |
| if (ll_isArrayType(typeCode)) { |
| return LowLevelCAS.TYPE_CLASS_FSARRAY; |
| } |
| return LowLevelCAS.TYPE_CLASS_FS; |
| } |
| |
| public int ll_getArrayType(int componentTypeCode) { |
| if (this.componentToArrayTypeMap.containsKey(componentTypeCode)) { |
| return this.componentToArrayTypeMap.get(componentTypeCode); |
| } |
| return addArrayType(ll_getTypeForCode(componentTypeCode), |
| ll_getTypeForCode(ll_computeArrayParentFromComponentType(componentTypeCode))); |
| } |
| |
| int addArrayType(Type componentType, Type mother) { |
| return ll_addArrayType(ll_getCodeForType(componentType), ll_getCodeForType(mother)); |
| } |
| |
| int ll_addArrayType(int componentTypeCode, int motherCode) { |
| |
| if (!ll_isValidTypeCode(componentTypeCode)) { |
| return UNKNOWN_TYPE_CODE; |
| } |
| // The array type is new and needs to be created. |
| String arrayTypeName = getArrayTypeName(ll_getTypeForCode(componentTypeCode).getName()); |
| int arrayTypeCode = this.typeNameST.set(arrayTypeName); |
| this.componentToArrayTypeMap.put(componentTypeCode, arrayTypeCode); |
| this.arrayToComponentTypeMap.put(arrayTypeCode, componentTypeCode); |
| // Dummy call to keep the counts ok. Will never use these data |
| // structures for array types. |
| newType(); |
| TypeImpl arrayType = new TypeImpl(arrayTypeName, arrayTypeCode, this); |
| this.types.add(arrayType); |
| this.parents.add(motherCode); |
| if (!isCommitted()) |
| this.numCommittedTypes = this.types.size(); |
| this.arrayCodeToTypeMap.put(arrayTypeCode, arrayType); |
| // System.out.println("*** adding to arrayCodeToTypeMap: " + arrayType.getName() + ", committed=" + isCommitted()); |
| // For built-in arrays, we need to add the abstract base array as parent |
| // to the inheritance tree. This sucks. Assumptions about the base |
| // array are all over the place. Would be nice to just remove it. |
| // Add an edge to the tree. |
| if (!isCommitted() && motherCode != fsArrayTypeCode ) { |
| final int arrayBaseTypeCodeBeforeCommitted = this.arrayBaseTypeCode; |
| (this.tree.get(arrayBaseTypeCodeBeforeCommitted)).add(arrayTypeCode); |
| // Update subsumption relation. |
| updateSubsumption(arrayTypeCode, this.arrayBaseTypeCode); |
| } |
| return arrayTypeCode; |
| } |
| |
| public boolean ll_isValidTypeCode(int typeCode) { |
| return (this.typeNameST.getSymbol(typeCode) != null) |
| || this.arrayToComponentTypeMap.containsKey(typeCode); |
| } |
| |
| public boolean ll_isArrayType(int typeCode) { |
| // if (!ll_isValidTypeCode(typeCode)) { |
| // return false; |
| // } |
| return this.arrayCodeToTypeMap.containsKey(typeCode); |
| } |
| |
| public int ll_getComponentType(int arrayTypeCode) { |
| if (ll_isArrayType(arrayTypeCode)) { |
| return this.arrayToComponentTypeMap.get(arrayTypeCode); |
| } |
| return UNKNOWN_TYPE_CODE; |
| } |
| |
| /* note that subtypes of String are considered primitive */ |
| public boolean ll_isPrimitiveType(int typeCode) { |
| return !ll_isRefType(typeCode); |
| } |
| |
| public String[] ll_getStringSet(int typeCode) { |
| // if (!ll_isValidTypeCode(typeCode)) { |
| // return null; |
| // } |
| if (!ll_isStringSubtype(typeCode)) { |
| return null; |
| } |
| return this.stringSets.get(this.stringSetMap.get(typeCode)); |
| } |
| |
| } |