public static void setupTypeSystem()

in uimaj-core/src/main/java/org/apache/uima/util/CasCreationUtils.java [726:891]


  public static void setupTypeSystem(CASMgr aCASMgr, TypeSystemDescription aTypeSystem)
          throws ResourceInitializationException {
    TypeSystemMgr typeSystemMgr = aCASMgr.getTypeSystemMgr();
    if (aTypeSystem != null) {
      TypeDescription[] types = aTypeSystem.getTypes();
      if (types != null) {
        // add all Types first (so that we can handle forward references) - note
        // that it isn't guaranteed that a supertype will occur in the Types list
        // before its subtype.

        // Build a linked list of type descriptions. We will make multiple passes
        // over this, adding types to the CAS and removing them from the linked
        // list. We continue until the list is empty or we cannot make any
        // progress.
        LinkedList<TypeDescription> typeList = new LinkedList<>();
        typeList.addAll(Arrays.asList(types));
        int numTypes = typeList.size();
        int lastNumTypes;
        List<TypeDescription> typesInOrderOfCreation = new LinkedList<>();
        do {
          lastNumTypes = numTypes;
          Iterator<TypeDescription> it = typeList.iterator();
          while (it.hasNext()) {
            TypeDescription curTypeDesc = it.next();
            String typeName = curTypeDesc.getName();
            // type does not exist - add it under the appropriate supertype
            String superTypeName = curTypeDesc.getSupertypeName();
            if (superTypeName == null) {
              throw new ResourceInitializationException(
                      ResourceInitializationException.NO_SUPERTYPE,
                      new Object[] { typeName, curTypeDesc.getSourceUrlString() });
            }
            // Check if it's a built-in type: must not change supertype!
            Type builtIn = typeSystemMgr.getType(typeName);
            if (builtIn != null) {
              if (!superTypeName.equals(typeSystemMgr.getParent(builtIn).getName())) {
                throw new ResourceInitializationException(
                        ResourceInitializationException.REDEFINING_BUILTIN_TYPE,
                        new Object[] { typeSystemMgr.getParent(builtIn), typeName, superTypeName,
                            curTypeDesc.getSourceUrlString() });
              }
            }
            Type supertype = typeSystemMgr.getType(superTypeName);
            if (supertype != null) {
              // supertype is defined, so add to CAS type system
              // check for special "enumerated types" that extend String
              if (curTypeDesc.getSupertypeName().equals(CAS.TYPE_NAME_STRING)) {
                AllowedValue[] vals = curTypeDesc.getAllowedValues();
                if (vals == null) {
                  throw new ResourceInitializationException(
                          ResourceInitializationException.MISSING_ALLOWED_VALUES,
                          new Object[] { typeName, curTypeDesc.getSourceUrlString() });
                }
                String[] valStrs = new String[vals.length];
                for (int i = 0; i < valStrs.length; i++) {
                  valStrs[i] = vals[i].getString();
                }
                typeSystemMgr.addStringSubtype(typeName, valStrs);
              } else // a "normal" type
              {
                // make sure that allowed values are NOT specified for non-string subtypes
                if (curTypeDesc.getAllowedValues() != null
                        && curTypeDesc.getAllowedValues().length > 0) {
                  throw new ResourceInitializationException(
                          ResourceInitializationException.ALLOWED_VALUES_ON_NON_STRING_TYPE,
                          new Object[] { typeName, curTypeDesc.getSourceUrlString() });
                }
                typeSystemMgr.addType(typeName, supertype);
              }
              // remove from list of type descriptions and add it to the typesInOrderOfCreation list
              // for later processing
              it.remove();
              typesInOrderOfCreation.add(curTypeDesc);
            }
          }
          numTypes = typeList.size();
        } while (numTypes > 0 && numTypes != lastNumTypes);
        // we quit the above loop either when we've added all types or when
        // we went through the entire list without successfully finding any
        // supertypes. In the latter case, throw an exception. Since there
        // can be more than one such type, we look for one that does not have
        // ancestor in the list as it is the likely cause of the issue. The
        // implementation of this is not as efficient as it could be but avoids
        // issues with cyclic definitions.
        for (int i = 0; i < typeList.size(); i++) {
          TypeDescription td_i = typeList.get(i);
          boolean foundSuperType = false;
          for (int j = 0; j < typeList.size(); j++) {
            if (i == j) {
              continue;
            }
            TypeDescription td_j = typeList.get(j);
            if (td_j.getName().equals(td_i.getSupertypeName())) {
              foundSuperType = true;
              break;
            }
          }
          if (!foundSuperType) {
            throw new ResourceInitializationException(
                    ResourceInitializationException.UNDEFINED_SUPERTYPE, new Object[] {
                        td_i.getSupertypeName(), td_i.getName(), td_i.getSourceUrlString() });
          }
        }

        if (numTypes > 0) {
          // We get here in either of two cases: there was only one problematic
          // type definition, or there was a cycle.
          TypeDescription firstFailed = typeList.getFirst();
          throw new ResourceInitializationException(
                  ResourceInitializationException.UNDEFINED_SUPERTYPE,
                  new Object[] { firstFailed.getSupertypeName(), firstFailed.getName(),
                      firstFailed.getSourceUrlString() });
        }

        // now for each type, add its features. We add features to supertypes before subtypes. This
        // is done so that
        // if we have a duplicate feature name on both a supertype and a subtype, it is added to the
        // supertype and then
        // ignored when we get to the subtype. Although this is a dubious type system, we support it
        // for backwards
        // compatibility (but we might want to think about generating a warning).
        Iterator<TypeDescription> typeIter = typesInOrderOfCreation.iterator();
        while (typeIter.hasNext()) {
          TypeDescription typeDesc = typeIter.next();
          Type type = typeSystemMgr.getType(typeDesc.getName());
          // assert type != null;

          FeatureDescription[] features = typeDesc.getFeatures();
          if (features != null) {
            for (int j = 0; j < features.length; j++) {
              String featName = features[j].getName();
              String rangeTypeName = features[j].getRangeTypeName();
              Type rangeType = typeSystemMgr.getType(rangeTypeName);
              if (rangeType == null) {
                throw new ResourceInitializationException(
                        ResourceInitializationException.UNDEFINED_RANGE_TYPE,
                        new Object[] { rangeTypeName, featName, typeDesc.getName(),
                            features[j].getSourceUrlString() });
              }
              if (rangeType.isArray()) // TODO: also List?
              {
                // if an element type is specified, get the specific
                // array subtype for that element type
                String elementTypeName = features[j].getElementType();
                if (elementTypeName != null && elementTypeName.length() > 0) {
                  Type elementType = typeSystemMgr.getType(elementTypeName);
                  if (elementType == null) {
                    throw new ResourceInitializationException(
                            ResourceInitializationException.UNDEFINED_RANGE_TYPE,
                            new Object[] { elementTypeName, featName, typeDesc.getName(),
                                features[j].getSourceUrlString() });
                  }
                  rangeType = typeSystemMgr.getArrayType(elementType);
                }
              }
              Boolean multiRefAllowed = features[j].getMultipleReferencesAllowed();
              if (multiRefAllowed == null) {
                multiRefAllowed = Boolean.FALSE; // default to false if unspecified
              }
              typeSystemMgr.addFeature(featName, type, rangeType, multiRefAllowed);
            }
          }
        }
      }
    }
  }