| /* |
| * 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.util; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.Set; |
| import java.util.TreeSet; |
| |
| import org.apache.uima.UIMAFramework; |
| import org.apache.uima.analysis_engine.AnalysisEngineDescription; |
| import org.apache.uima.analysis_engine.metadata.AnalysisEngineMetaData; |
| import org.apache.uima.cas.CAS; |
| import org.apache.uima.cas.CASException; |
| import org.apache.uima.cas.FSIndex; |
| import org.apache.uima.cas.Feature; |
| import org.apache.uima.cas.Type; |
| import org.apache.uima.cas.TypeSystem; |
| import org.apache.uima.cas.admin.CASFactory; |
| import org.apache.uima.cas.admin.CASMgr; |
| import org.apache.uima.cas.admin.FSIndexComparator; |
| import org.apache.uima.cas.admin.FSIndexRepositoryMgr; |
| import org.apache.uima.cas.admin.LinearTypeOrderBuilder; |
| import org.apache.uima.cas.admin.TypeSystemMgr; |
| import org.apache.uima.cas.impl.CASImpl; |
| import org.apache.uima.cas_data.CasData; |
| import org.apache.uima.cas_data.FeatureStructure; |
| import org.apache.uima.cas_data.PrimitiveValue; |
| import org.apache.uima.collection.CasConsumerDescription; |
| import org.apache.uima.collection.CasInitializerDescription; |
| import org.apache.uima.collection.CollectionReaderDescription; |
| import org.apache.uima.flow.FlowControllerDescription; |
| import org.apache.uima.resource.CasDefinition; |
| import org.apache.uima.resource.Resource; |
| import org.apache.uima.resource.ResourceInitializationException; |
| import org.apache.uima.resource.ResourceManager; |
| import org.apache.uima.resource.ResourceSpecifier; |
| import org.apache.uima.resource.URISpecifier; |
| import org.apache.uima.resource.impl.ResourceManager_impl; |
| import org.apache.uima.resource.metadata.AllowedValue; |
| import org.apache.uima.resource.metadata.FeatureDescription; |
| import org.apache.uima.resource.metadata.FsIndexCollection; |
| import org.apache.uima.resource.metadata.FsIndexDescription; |
| import org.apache.uima.resource.metadata.FsIndexKeyDescription; |
| import org.apache.uima.resource.metadata.ProcessingResourceMetaData; |
| import org.apache.uima.resource.metadata.ResourceMetaData; |
| import org.apache.uima.resource.metadata.TypeDescription; |
| import org.apache.uima.resource.metadata.TypePriorities; |
| import org.apache.uima.resource.metadata.TypePriorityList; |
| import org.apache.uima.resource.metadata.TypeSystemDescription; |
| import org.apache.uima.resource.metadata.impl.ProcessingResourceMetaData_impl; |
| |
| /** |
| * Utilities for creating and setting up CASes. Also includes utilities for merging CAS type |
| * systems. |
| * |
| * |
| */ |
| public class CasCreationUtils { |
| |
| /** |
| * Creates a new CAS instance. Note this method does not work for Aggregate Analysis Engine |
| * descriptors -- use {@link #createCas(AnalysisEngineDescription)} instead. |
| * |
| * @param aMetaData |
| * metadata for the analysis engine that will process this CAS. This is used to set up |
| * the CAS's type system and indexes. |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(AnalysisEngineMetaData aMetaData) |
| throws ResourceInitializationException { |
| List list = new ArrayList(); |
| list.add(aMetaData); |
| return createCas(list); |
| } |
| |
| /** |
| * Creates a new CAS instance. |
| * |
| * @param aMetaData |
| * metadata for the resource that will process this CAS. This is used to set up the CAS's |
| * type system and indexes. |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(ProcessingResourceMetaData aMetaData) |
| throws ResourceInitializationException { |
| List list = new ArrayList(); |
| list.add(aMetaData); |
| return createCas(list); |
| } |
| |
| /** |
| * Creates a new CAS instance for an Analysis Engine. This works for both primitive and aggregate |
| * analysis engines. |
| * |
| * @param aDescription |
| * description of the anlaysis engine that will process this CAS. This is used to set up |
| * the CAS's type system and indexes. |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(AnalysisEngineDescription aDescription) |
| throws ResourceInitializationException { |
| return createCas(aDescription, UIMAFramework.getDefaultPerformanceTuningProperties()); |
| } |
| |
| /** |
| * Creates a new CAS instance for an Analysis Engine. This works for both primitive and aggregate |
| * analysis engines. |
| * |
| * @param aDescription |
| * description of the anlaysis engine that will process this CAS. This is used to set up |
| * the CAS's type system and indexes. |
| * @param aPerformanceTuningSettings |
| * Properties object containing framework performance tuning settings using key names |
| * defined on {@link UIMAFramework} interface |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(AnalysisEngineDescription aDescription, |
| Properties aPerformanceTuningSettings) throws ResourceInitializationException { |
| List list = new ArrayList(); |
| list.add(aDescription); |
| return createCas(list, aPerformanceTuningSettings); |
| } |
| |
| /** |
| * Creates a new CAS instance for a collection of CAS Processors. This method correctly handles |
| * aggregate as well as primitive analysis engines |
| * <p> |
| * If you pass this method objects of type {@link AnalysisEngineDescription}, |
| * {@link CollectionReaderDescription}, {@link CasInitializerDescription}, or |
| * {@link CasConsumerDescription}, it will not instantiate the components. It will just extract |
| * the type system information from the descriptor. For any other kind of |
| * {@link ResourceSpecifier}, it will call |
| * {@link UIMAFramework#produceResource(org.apache.uima.resource.ResourceSpecifier, Map)}. For |
| * example, if a {@link URISpecifier} is passed, a remote connection will be established and the |
| * service will be queries for its metadata. An exception will be thrown if the connection can not |
| * be opened. |
| * |
| * @param aComponentDescriptionsOrMetaData |
| * a collection of {@link ResourceSpecifier}, {@link ProcessingResourceMetaData}, |
| * {@link TypeSystemDescription}, {@link FsIndexCollection}, or {@link TypePriorities} |
| * objects. |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(Collection aComponentDescriptionsOrMetaData) |
| throws ResourceInitializationException { |
| return createCas(aComponentDescriptionsOrMetaData, UIMAFramework |
| .getDefaultPerformanceTuningProperties()); |
| } |
| |
| /** |
| * Creates a new CAS instance for a collection of CAS Processors. This method correctly handles |
| * aggregate as well as primitive analysis engines |
| * <p> |
| * If you pass this method objects of type {@link AnalysisEngineDescription}, |
| * {@link CollectionReaderDescription}, {@link CasInitializerDescription}, or |
| * {@link CasConsumerDescription}, it will not instantiate the components. It will just extract |
| * the type system information from the descriptor. For any other kind of |
| * {@link ResourceSpecifier}, it will call |
| * {@link UIMAFramework#produceResource(org.apache.uima.resource.ResourceSpecifier, Map)}. For |
| * example, if a {@link URISpecifier} is passed, a remote connection will be established and the |
| * service will be queries for its metadata. An exception will be thrown if the connection can not |
| * be opened. |
| * |
| * @param aComponentDescriptionsOrMetaData |
| * a collection of {@link ResourceSpecifier}, {@link ProcessingResourceMetaData}, |
| * {@link TypeSystemDescription}, {@link FsIndexCollection}, or {@link TypePriorities} |
| * objects. |
| * @param aPerformanceTuningSettings |
| * Properties object containing framework performance tuning settings using key names |
| * defined on {@link UIMAFramework} interface |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(Collection aComponentDescriptionsOrMetaData, |
| Properties aPerformanceTuningSettings) throws ResourceInitializationException { |
| return createCas(aComponentDescriptionsOrMetaData, aPerformanceTuningSettings, UIMAFramework |
| .newDefaultResourceManager()); |
| } |
| |
| /** |
| * Creates a new CAS instance for a collection of CAS Processors. This method correctly handles |
| * aggregate as well as primitive analysis engines |
| * <p> |
| * If you pass this method objects of type {@link AnalysisEngineDescription}, |
| * {@link CollectionReaderDescription}, {@link CasInitializerDescription}, or |
| * {@link CasConsumerDescription}, it will not instantiate the components. It will just extract |
| * the type system information from the descriptor. For any other kind of |
| * {@link ResourceSpecifier}, it will call |
| * {@link UIMAFramework#produceResource(org.apache.uima.resource.ResourceSpecifier, Map)}. For |
| * example, if a {@link URISpecifier} is passed, a remote connection will be established and the |
| * service will be queries for its metadata. An exception will be thrown if the connection can not |
| * be opened. |
| * |
| * @param aComponentDescriptionsOrMetaData |
| * a collection of {@link ResourceSpecifier}, {@link ProcessingResourceMetaData}, |
| * {@link TypeSystemDescription}, {@link FsIndexCollection}, or {@link TypePriorities} |
| * objects. |
| * @param aPerformanceTuningSettings |
| * Properties object containing framework performance tuning settings using key names |
| * defined on {@link UIMAFramework} interface |
| * @param aResourceManager |
| * the resource manager to use to resolve import declarations within the metadata |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(Collection aComponentDescriptionsOrMetaData, |
| Properties aPerformanceTuningSettings, ResourceManager aResourceManager) |
| throws ResourceInitializationException { |
| // build a list of metadata objects |
| List mdList = getMetaDataList(aComponentDescriptionsOrMetaData, aResourceManager); |
| |
| // extract TypeSystems, TypePriorities, and FsIndexes from metadata |
| List typeSystems = new ArrayList(); |
| List typePriorities = new ArrayList(); |
| List fsIndexes = new ArrayList(); |
| Iterator it = mdList.iterator(); |
| while (it.hasNext()) { |
| ProcessingResourceMetaData md = (ProcessingResourceMetaData) it.next(); |
| if (md.getTypeSystem() != null) |
| typeSystems.add(md.getTypeSystem()); |
| if (md.getTypePriorities() != null) |
| typePriorities.add(md.getTypePriorities()); |
| if (md.getFsIndexCollection() != null) |
| fsIndexes.add(md.getFsIndexCollection()); |
| } |
| |
| // merge |
| TypeSystemDescription aggTypeDesc = mergeTypeSystems(typeSystems, aResourceManager); |
| TypePriorities aggTypePriorities = mergeTypePriorities(typePriorities, aResourceManager); |
| FsIndexCollection aggIndexColl = mergeFsIndexes(fsIndexes, aResourceManager); |
| |
| return createCas(aggTypeDesc, aggTypePriorities, aggIndexColl.getFsIndexes(), |
| aPerformanceTuningSettings, aResourceManager); |
| } |
| |
| /** |
| * Creates a new CAS instance. |
| * |
| * @param aTypeSystem |
| * type system to install in the CAS |
| * @param aTypePriorities |
| * type priorities to install in the CAS |
| * @param aFsIndexes |
| * indexes to install in the CAS |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(TypeSystemDescription aTypeSystem, TypePriorities aTypePriorities, |
| FsIndexDescription[] aFsIndexes) throws ResourceInitializationException { |
| return createCas(aTypeSystem, aTypePriorities, aFsIndexes, null, null); |
| } |
| |
| /** |
| * Creates a new CAS instance. |
| * |
| * @param aTypeSystem |
| * type system to install in the CAS |
| * @param aTypePriorities |
| * type priorities to install in the CAS |
| * @param aFsIndexes |
| * indexes to install in the CAS |
| * @param aPerformanceTuningSettings |
| * Properties object containing framework performance tuning settings using key names |
| * defined on {@link UIMAFramework} interface |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(TypeSystemDescription aTypeSystem, TypePriorities aTypePriorities, |
| FsIndexDescription[] aFsIndexes, Properties aPerformanceTuningSettings) |
| throws ResourceInitializationException { |
| return createCas(aTypeSystem, aTypePriorities, aFsIndexes, aPerformanceTuningSettings, null); |
| } |
| |
| /** |
| * Creates a new CAS instance. |
| * |
| * @param aTypeSystem |
| * type system to install in the CAS |
| * @param aTypePriorities |
| * type priorities to install in the CAS |
| * @param aFsIndexes |
| * indexes to install in the CAS |
| * @param aPerformanceTuningSettings |
| * Properties object containing framework performance tuning settings using key names |
| * defined on {@link UIMAFramework} interface |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(TypeSystemDescription aTypeSystem, TypePriorities aTypePriorities, |
| FsIndexDescription[] aFsIndexes, Properties aPerformanceTuningSettings, |
| ResourceManager aResourceManager) throws ResourceInitializationException { |
| return doCreateCas(null, aTypeSystem, aTypePriorities, aFsIndexes, aPerformanceTuningSettings, |
| aResourceManager); |
| } |
| |
| /** |
| * Creates a new CAS instance for a collection of CAS Processors, which. reuses an existing type |
| * system. Using this method allows several CASes to all share the exact same type system object. |
| * This method correctly handles aggregate as well as primitive analysis engines. |
| * <p> |
| * If you pass this method objects of type {@link AnalysisEngineDescription}, |
| * {@link CollectionReaderDescription}, {@link CasInitializerDescription}, or |
| * {@link CasConsumerDescription}, it will not instantiate the components. It will just extract |
| * the type system information from the descriptor. For any other kind of |
| * {@link ResourceSpecifier}, it will call |
| * {@link UIMAFramework#produceResource(org.apache.uima.resource.ResourceSpecifier, Map)}. For |
| * example, if a {@link URISpecifier} is passed, a remote connection will be established and the |
| * service will be queries for its metadata. An exception will be thrown if the connection can not |
| * be opened. |
| * |
| * @param aComponentDescriptionsOrMetaData |
| * a collection of {@link ResourceSpecifier}, {@link ProcessingResourceMetaData}, |
| * {@link TypeSystemDescription}, {@link FsIndexCollection}, or {@link TypePriorities} |
| * objects. |
| * @param aTypeSystem |
| * type system to install in the CAS, null if none |
| * @param aPerformanceTuningSettings |
| * Properties object containing framework performance tuning settings using key names |
| * defined on {@link UIMAFramework} interface |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(Collection aComponentDescriptionsOrMetaData, TypeSystem aTypeSystem, |
| Properties aPerformanceTuningSettings) throws ResourceInitializationException { |
| return createCas(aComponentDescriptionsOrMetaData, aTypeSystem, aPerformanceTuningSettings, |
| UIMAFramework.newDefaultResourceManager()); |
| } |
| |
| /** |
| * Creates a new CAS instance for a collection of CAS Processors, which. reuses an existing type |
| * system. Using this method allows several CASes to all share the exact same type system object. |
| * This method correctly handles aggregate as well as primitive analysis engines. |
| * <p> |
| * If you pass this method objects of type {@link AnalysisEngineDescription}, |
| * {@link CollectionReaderDescription}, {@link CasInitializerDescription}, or |
| * {@link CasConsumerDescription}, it will not instantiate the components. It will just extract |
| * the type system information from the descriptor. For any other kind of |
| * {@link ResourceSpecifier}, it will call |
| * {@link UIMAFramework#produceResource(org.apache.uima.resource.ResourceSpecifier, Map)}. For |
| * example, if a {@link URISpecifier} is passed, a remote connection will be established and the |
| * service will be queries for its metadata. An exception will be thrown if the connection can not |
| * be opened. |
| * |
| * @param aComponentDescriptionsOrMetaData |
| * a collection of {@link ResourceSpecifier}, {@link ProcessingResourceMetaData}, |
| * {@link TypeSystemDescription}, {@link FsIndexCollection}, or {@link TypePriorities} |
| * objects. |
| * @param aTypeSystem |
| * type system to install in the CAS, null if none |
| * @param aPerformanceTuningSettings |
| * Properties object containing framework performance tuning settings using key names |
| * defined on {@link UIMAFramework} interface |
| * @param aResourceManager |
| * the resource manager to use to resolve import declarations within the metadata, and |
| * also to set the JCas ClassLoader for the new CAS |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(Collection aComponentDescriptionsOrMetaData, TypeSystem aTypeSystem, |
| Properties aPerformanceTuningSettings, ResourceManager aResourceManager) |
| throws ResourceInitializationException { |
| // build a list of metadata objects |
| List mdList = getMetaDataList(aComponentDescriptionsOrMetaData, aResourceManager); |
| |
| // extract TypeSystems, TypePriorities, and FsIndexes from metadata |
| List typeSystems = new ArrayList(); |
| List typePriorities = new ArrayList(); |
| List fsIndexes = new ArrayList(); |
| Iterator it = mdList.iterator(); |
| while (it.hasNext()) { |
| ProcessingResourceMetaData md = (ProcessingResourceMetaData) it.next(); |
| if (md.getTypeSystem() != null) |
| typeSystems.add(md.getTypeSystem()); |
| if (md.getTypePriorities() != null) |
| typePriorities.add(md.getTypePriorities()); |
| if (md.getFsIndexCollection() != null) |
| fsIndexes.add(md.getFsIndexCollection()); |
| } |
| |
| // merge TypePriorities and FsIndexes |
| TypePriorities aggTypePriorities = mergeTypePriorities(typePriorities, aResourceManager); |
| FsIndexCollection aggIndexColl = mergeFsIndexes(fsIndexes, aResourceManager); |
| |
| if (aTypeSystem != null) // existing type system object was specified; use that |
| { |
| return createCas(aTypeSystem, aggTypePriorities, aggIndexColl.getFsIndexes(), |
| aPerformanceTuningSettings, aResourceManager); |
| } else { |
| // no type system object specified; merge type system descriptions in metadata |
| TypeSystemDescription aggTypeDesc = mergeTypeSystems(typeSystems); |
| return createCas(aggTypeDesc, aggTypePriorities, aggIndexColl.getFsIndexes(), |
| aPerformanceTuningSettings, aResourceManager); |
| } |
| } |
| |
| /** |
| * Creates a new CAS instance that reuses an existing type system. Using this method allows |
| * several CASes to all share the exact same type system object. |
| * |
| * @param aTypeSystem |
| * type system to install in the CAS |
| * @param aTypePriorities |
| * type priorities to install in the CAS |
| * @param aFsIndexes |
| * indexes to install in the CAS |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(TypeSystem aTypeSystem, TypePriorities aTypePriorities, |
| FsIndexDescription[] aFsIndexes, Properties aPerformanceTuningSettings) |
| throws ResourceInitializationException { |
| return createCas(aTypeSystem, aTypePriorities, aFsIndexes, aPerformanceTuningSettings, null); |
| } |
| |
| /** |
| * Creates a new CAS instance that reuses an existing type system. Using this method allows |
| * several CASes to all share the exact same type system object. |
| * |
| * @param aTypeSystem |
| * type system to install in the CAS |
| * @param aTypePriorities |
| * type priorities to install in the CAS |
| * @param aFsIndexes |
| * indexes to install in the CAS |
| * @param aResourceManager |
| * resource manager, which is used to set the JCas ClassLoader for the new CAS |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| public static CAS createCas(TypeSystem aTypeSystem, TypePriorities aTypePriorities, |
| FsIndexDescription[] aFsIndexes, Properties aPerformanceTuningSettings, |
| ResourceManager aResourceManager) throws ResourceInitializationException { |
| return doCreateCas(aTypeSystem, null, aTypePriorities, aFsIndexes, aPerformanceTuningSettings, |
| aResourceManager); |
| } |
| |
| /** |
| * Method that does the work for creating a new CAS instance. Other createCas methods in this |
| * class should all eventually call this method, so that the critical code is not duplicated in |
| * more than one place. |
| * |
| * @param aTypeSystem |
| * an existing type sytsem to reuse in this CAS, null if none. |
| * @param aTypeSystemDescription |
| * description of type system to use for this CAS. This is only used if aTypeSystem is |
| * null. |
| * @param aTypePriorities |
| * type priorities to install in the CAS |
| * @param aFsIndexes |
| * indexes to install in the CAS |
| * @param aPerformanceTuningSettings |
| * Properties object containing framework performance tuning settings using key names |
| * defined on {@link UIMAFramework} interface |
| * |
| * @return a new CAS instance |
| * |
| * @throws ResourceInitializationException |
| * if CAS creation fails |
| */ |
| private static CAS doCreateCas(TypeSystem aTypeSystem, TypeSystemDescription aTypeSystemDesc, |
| TypePriorities aTypePriorities, FsIndexDescription[] aFsIndexes, |
| Properties aPerformanceTuningSettings, ResourceManager aResourceManager) |
| throws ResourceInitializationException { |
| if (aResourceManager == null) { |
| aResourceManager = UIMAFramework.newDefaultResourceManager(); |
| } |
| |
| // resolve imports |
| try { |
| if (aTypeSystemDesc != null) { |
| aTypeSystemDesc.resolveImports(aResourceManager); |
| } |
| if (aTypePriorities != null) { |
| aTypePriorities.resolveImports(aResourceManager); |
| } |
| } catch (InvalidXMLException e) { |
| throw new ResourceInitializationException(e); |
| } |
| |
| // get initial heap size |
| String initialHeapSizeStr = null; |
| if (aPerformanceTuningSettings != null) { |
| initialHeapSizeStr = aPerformanceTuningSettings |
| .getProperty(UIMAFramework.CAS_INITIAL_HEAP_SIZE); |
| } |
| |
| // create CAS using either aTypeSystem or aTypeSystemDesc |
| CASMgr casMgr; |
| if (aTypeSystem != null) { |
| if (initialHeapSizeStr != null) { |
| casMgr = CASFactory.createCAS(Integer.parseInt(initialHeapSizeStr), aTypeSystem); |
| } else { |
| casMgr = CASFactory.createCAS(aTypeSystem); |
| } |
| } else // no TypeSystem to reuse - create a new one |
| { |
| if (initialHeapSizeStr != null) { |
| casMgr = CASFactory.createCAS(Integer.parseInt(initialHeapSizeStr)); |
| } else { |
| casMgr = CASFactory.createCAS(); |
| } |
| // install type system |
| setupTypeSystem(casMgr, aTypeSystemDesc); |
| // Commit the type system |
| ((CASImpl) casMgr).commitTypeSystem(); |
| } |
| |
| try { |
| // install TypePriorities into CAS |
| setupTypePriorities(casMgr, aTypePriorities); |
| |
| // install Built-in indexes into CAS |
| casMgr.initCASIndexes(); |
| } catch (CASException e) { |
| throw new ResourceInitializationException(e); |
| } |
| |
| // install AnalysisEngine's custom indexes into CAS |
| setupIndexes(casMgr, aFsIndexes); |
| |
| // Commit the index repository |
| casMgr.getIndexRepositoryMgr().commit(); |
| |
| // Set JCas ClassLoader |
| if (aResourceManager.getExtensionClassLoader() != null) { |
| casMgr.setJCasClassLoader(aResourceManager.getExtensionClassLoader()); |
| } |
| |
| return casMgr.getCAS().getView(CAS.NAME_DEFAULT_SOFA); |
| } |
| |
| /** |
| * Create a CAS from a CAS Definition. |
| * |
| * @param casDef |
| * completely describes the CAS to be created |
| * @param performanceTuningSettings |
| * Properties object containing framework performance tuning settings using key names |
| * defined on {@link UIMAFramework} interface |
| * |
| * @return a new CAS matching the given CasDefinition |
| */ |
| public static CAS createCas(CasDefinition casDef, Properties performanceTuningSettings) |
| throws ResourceInitializationException { |
| return createCas(casDef.getTypeSystemDescription(), casDef.getTypePriorities(), casDef |
| .getFsIndexDescriptions(), performanceTuningSettings, casDef.getResourceManager()); |
| } |
| |
| /** |
| * Create a CAS from a CAS Definition, but reuse the provided TypeSystem object. |
| * |
| * @param casDef |
| * completely describes the CAS to be created |
| * @param performanceTuningSettings |
| * Properties object containing framework performance tuning settings using key names |
| * defined on {@link UIMAFramework} interface |
| * @param typeSystem |
| * type system object to reuse |
| * |
| * @return a new CAS matching the given CasDefinition |
| */ |
| public static CAS createCas(CasDefinition casDef, Properties performanceTuningSettings, |
| TypeSystem typeSystem) throws ResourceInitializationException { |
| return createCas(typeSystem, casDef.getTypePriorities(), casDef.getFsIndexDescriptions(), |
| performanceTuningSettings, casDef.getResourceManager()); |
| } |
| |
| /** |
| * Installs a TypeSystem in a CAS. |
| * |
| * @param aCASMgr |
| * the <code>CASMgr</code> object whose type system is to be modified. |
| * @param aTypeSystem |
| * desription of type system to install |
| * |
| * @throws ResourceInitializationException |
| * if an error occurs during modification of the type system |
| */ |
| 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 guarnanteed 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 typeList = new LinkedList(); |
| typeList.addAll(Arrays.asList(types)); |
| int numTypes = typeList.size(); |
| int lastNumTypes; |
| LinkedList typesInOrderOfCreation = new LinkedList(); |
| do { |
| lastNumTypes = numTypes; |
| Iterator it = typeList.iterator(); |
| while (it.hasNext()) { |
| TypeDescription curTypeDesc = (TypeDescription) 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() }); |
| } |
| 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 |
| if (numTypes > 0) { |
| TypeDescription firstFailed = (TypeDescription) 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 typeIter = typesInOrderOfCreation.iterator(); |
| while (typeIter.hasNext()) { |
| TypeDescription typeDesc = (TypeDescription) 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.booleanValue()); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Adds TypePriorities to a CAS. |
| * |
| * @param aCASMgr |
| * the <code>CASMgr</code> object to be modified |
| * @param aTypePriorities |
| * description of the type priorities to add |
| * |
| * @throws CASException |
| * if an error occurs during type priority setup |
| */ |
| public static void setupTypePriorities(CASMgr aCASMgr, TypePriorities aTypePriorities) |
| throws ResourceInitializationException { |
| if (aTypePriorities != null) { |
| LinearTypeOrderBuilder typeOrderBuilder = aCASMgr.getIndexRepositoryMgr() |
| .getDefaultOrderBuilder(); |
| TypePriorityList[] priorityLists = aTypePriorities.getPriorityLists(); |
| for (int i = 0; i < priorityLists.length; i++) { |
| // check that all types exist. This error would be caught in |
| // typeOrderBuilder.getOrder(), but that's too late to indicate |
| // the location of the faulty descriptor in the error message. |
| String[] typeList = priorityLists[i].getTypes(); |
| for (int j = 0; j < typeList.length; j++) { |
| if (aCASMgr.getTypeSystemMgr().getType(typeList[j]) == null) { |
| throw new ResourceInitializationException( |
| ResourceInitializationException.UNDEFINED_TYPE_FOR_PRIORITY_LIST, new Object[] { |
| typeList[j], priorityLists[i].getSourceUrlString() }); |
| } |
| } |
| try { |
| typeOrderBuilder.add(priorityLists[i].getTypes()); |
| } catch (CASException e) { |
| // typically caused by a cycle in the priorities - the caused-by message |
| // will clarify. |
| throw new ResourceInitializationException( |
| ResourceInitializationException.INVALID_TYPE_PRIORITIES, |
| new Object[] { priorityLists[i].getSourceUrlString() }, e); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Adds FeatureStructure indexes to a CAS. |
| * |
| * @param aCASMgr |
| * the <code>CASMgr</code> object to be modified |
| * @param aIndexes |
| * descriptions of the indexes to add |
| * |
| * @throws ResourceInitializationException |
| * if an error occurs during index creation |
| */ |
| public static void setupIndexes(CASMgr aCASMgr, FsIndexDescription[] aIndexes) |
| throws ResourceInitializationException { |
| if (aIndexes != null) { |
| TypeSystemMgr tsm = aCASMgr.getTypeSystemMgr(); |
| FSIndexRepositoryMgr irm = aCASMgr.getIndexRepositoryMgr(); |
| |
| for (int i = 0; i < aIndexes.length; i++) { |
| int kind = FSIndex.SORTED_INDEX; |
| String kindStr = aIndexes[i].getKind(); |
| if (kindStr != null) { |
| if (kindStr.equals(FsIndexDescription.KIND_BAG)) |
| kind = FSIndex.BAG_INDEX; |
| else if (kindStr.equals(FsIndexDescription.KIND_SET)) |
| kind = FSIndex.SET_INDEX; |
| else if (kindStr.equals(FsIndexDescription.KIND_SORTED)) |
| kind = FSIndex.SORTED_INDEX; |
| } |
| |
| Type type = tsm.getType(aIndexes[i].getTypeName()); |
| if (type == null) { |
| throw new ResourceInitializationException( |
| ResourceInitializationException.UNDEFINED_TYPE_FOR_INDEX, new Object[] { |
| aIndexes[i].getTypeName(), aIndexes[i].getLabel(), |
| aIndexes[i].getSourceUrlString() }); |
| } |
| FSIndexComparator comparator = irm.createComparator(); |
| comparator.setType(type); |
| |
| FsIndexKeyDescription[] keys = aIndexes[i].getKeys(); |
| if (keys != null) { |
| for (int j = 0; j < keys.length; j++) { |
| if (keys[j].isTypePriority()) { |
| comparator.addKey(irm.getDefaultTypeOrder(), FSIndexComparator.STANDARD_COMPARE); |
| } else { |
| Feature feature = type.getFeatureByBaseName(keys[j].getFeatureName()); |
| if (feature == null) { |
| throw new ResourceInitializationException( |
| ResourceInitializationException.INDEX_KEY_FEATURE_NOT_FOUND, new Object[] { |
| keys[j].getFeatureName(), aIndexes[i].getLabel(), |
| aIndexes[i].getSourceUrlString() }); |
| } |
| comparator.addKey(feature, keys[j].getComparator()); |
| } |
| } |
| } |
| |
| irm.createIndex(comparator, aIndexes[i].getLabel(), kind); |
| } |
| } |
| } |
| |
| /** |
| * Extracts a TypeSystem definition from a CasData. |
| * |
| * @param aCasData |
| * the CAS Data from which to extract the type system |
| * |
| * @return a description of a TypeSystem to which the CAS Data conforms |
| */ |
| public static TypeSystemDescription convertData2TypeSystem(CasData aCasData) { |
| TypeSystemDescription result = UIMAFramework.getResourceSpecifierFactory() |
| .createTypeSystemDescription(); |
| Iterator iter = aCasData.getFeatureStructures(); |
| ArrayList typesArr = new ArrayList(); |
| while (iter.hasNext()) { |
| FeatureStructure casFS = (FeatureStructure) iter.next(); |
| TypeDescription newType = UIMAFramework.getResourceSpecifierFactory().createTypeDescription(); |
| newType.setName(casFS.getType()); |
| newType.setSupertypeName("uima.tcas.annotation"); |
| newType.setDescription("CasData Type"); |
| String features[] = casFS.getFeatureNames(); |
| if (features != null) { |
| for (int i = 0; i < features.length; i++) { |
| String featName = features[i]; |
| String rangeName = ""; |
| String description = ""; |
| PrimitiveValue pVal = (PrimitiveValue) casFS.getFeatureValue(featName); |
| if (pVal.get().getClass().getName().equals("java.lang.String")) { |
| System.out.println(" the feature is a String "); |
| rangeName = "uima.cas.String"; |
| description = " featue of the casDataType"; |
| } |
| newType.addFeature(featName, description, rangeName); |
| } |
| } |
| typesArr.add(newType); |
| } |
| TypeDescription td[] = new TypeDescription[typesArr.size()]; |
| for (int j = 0; j < typesArr.size(); j++) { |
| td[j] = (TypeDescription) typesArr.get(j); |
| } |
| result.setTypes(td); |
| return result; |
| } |
| |
| /** |
| * Merges several TypeSystemDescriptions into one. Also resolves imports in the |
| * TypeSystemDescription objects. |
| * |
| * @param aTypeSystems |
| * a collection of TypeSystems to be merged |
| * |
| * @return a new TypeSystemDescription that is the result of merging all of the type systems |
| * together |
| * |
| * @throws ResourceInitializationException |
| * if an incompatibiliy exists or if an import could not be resolved |
| */ |
| public static TypeSystemDescription mergeTypeSystems(Collection aTypeSystems) |
| throws ResourceInitializationException { |
| return mergeTypeSystems(aTypeSystems, UIMAFramework.newDefaultResourceManager()); |
| } |
| |
| /** |
| * Merges several TypeSystemDescriptions into one. Also resolves imports in the |
| * TypeSystemDescription objects. |
| * |
| * @param aTypeSystems |
| * a collection of TypeSystems to be merged |
| * @param aResourceManager |
| * Resource Manager to use to locate type systems imported by name |
| * |
| * @return a new TypeSystemDescription that is the result of merging all of the type systems |
| * together |
| * |
| * @throws ResourceInitializationException |
| * if an incompatibiliy exists or if an import could not be resolved |
| */ |
| public static TypeSystemDescription mergeTypeSystems(Collection aTypeSystems, |
| ResourceManager aResourceManager) throws ResourceInitializationException { |
| return mergeTypeSystems(aTypeSystems, aResourceManager, null); |
| } |
| |
| /** |
| * Merges several TypeSystemDescriptions into one. Also resolves imports in the |
| * TypeSystemDescription objects. |
| * <p> |
| * This version of this method takes an argument <code>aOutputMergedTypes</code>, which |
| * this method will populate with the names and descriptor locations of any types whose definitions |
| * have been merged from multiple non-identical sources. That is, types that are declared |
| * more than once, with different (but compatible) sets of features in each declaration, |
| * or with different (but compatible) supertypes. |
| * |
| * @param aTypeSystems |
| * a collection of TypeSystems to be merged |
| * @param aResourceManager |
| * Resource Manager to use to locate type systems imported by name |
| * @param aOutputMergedTypes |
| * A Map that this method will populate with information about the set of types |
| * whose definitions were merged from multiple non-identical sources. The keys in |
| * the Map will be the type names (Strings) and the values will be |
| * {link Set}s containing Descriptor URLs (Strings) where those types are |
| * declared. You may pass null if you are not interested in this information. |
| * |
| * @return a new TypeSystemDescription that is the result of merging all of the type systems |
| * together |
| * |
| * @throws ResourceInitializationException |
| * if an incompatibiliy exists or if an import could not be resolved |
| */ |
| public static TypeSystemDescription mergeTypeSystems(Collection aTypeSystems, |
| ResourceManager aResourceManager, Map aOutputMergedTypes) |
| throws ResourceInitializationException { |
| // create the type system into which we are merging |
| TypeSystemDescription result = UIMAFramework.getResourceSpecifierFactory() |
| .createTypeSystemDescription(); |
| // also build a Map from Type names to Types |
| Map typeNameMap = new HashMap(); |
| |
| // Now iterate through all type systems - if a new type is found, add it. |
| // If an existing type is found, merge features. |
| Iterator it = aTypeSystems.iterator(); |
| while (it.hasNext()) { |
| TypeSystemDescription ts = (TypeSystemDescription) it.next(); |
| if (ts != null) { |
| try { |
| ts.resolveImports(aResourceManager); |
| } catch (InvalidXMLException e) { |
| throw new ResourceInitializationException(e); |
| } |
| TypeDescription[] types = ts.getTypes(); |
| if (types != null) { |
| for (int i = 0; i < types.length; i++) { |
| String typeName = types[i].getName(); |
| TypeDescription existingType = (TypeDescription) typeNameMap.get(typeName); |
| if (existingType == null) { |
| // create new type |
| existingType = result.addType(types[i].getName(), types[i].getDescription(), types[i] |
| .getSupertypeName()); |
| existingType.setAllowedValues(types[i].getAllowedValues()); |
| existingType.setSourceUrl(types[i].getSourceUrl()); |
| typeNameMap.put(types[i].getName(), existingType); |
| FeatureDescription[] features = types[i].getFeatures(); |
| if (features != null) { |
| mergeFeatures(existingType, types[i].getFeatures()); |
| } |
| } else { |
| // type already existed - check that supertypes are compatible |
| String supertypeName = types[i].getSupertypeName(); |
| String existingSupertypeName = existingType.getSupertypeName(); |
| if (!existingSupertypeName.equals(supertypeName)) { |
| // supertypes are not identical - check if one subsumes the other |
| if (subsumes(existingSupertypeName, supertypeName, typeNameMap)) { |
| // existing supertype subsumes newly specified supertype - |
| // reset supertype to the new, more specific type |
| existingType.setSupertypeName(supertypeName); |
| // report that a merge occurred |
| reportMerge(aOutputMergedTypes, types[i], existingType); |
| } else if (subsumes(supertypeName, existingSupertypeName, typeNameMap)) { |
| // newly specified supertype subsumes old type, this is OK and we don't |
| // need to do anything except report this |
| reportMerge(aOutputMergedTypes, types[i], existingType); |
| } else { |
| // error |
| throw new ResourceInitializationException( |
| ResourceInitializationException.INCOMPATIBLE_SUPERTYPES, new Object[] { |
| typeName, supertypeName, existingSupertypeName, |
| types[i].getSourceUrlString() }); |
| } |
| |
| } |
| // merge features |
| int prevNumFeatures = existingType.getFeatures().length; |
| FeatureDescription[] features = types[i].getFeatures(); |
| if (features != null) { |
| mergeFeatures(existingType, types[i].getFeatures()); |
| // if feature-merged occurred, the number of features on the type will have |
| // changed. Report this by adding to the aOutputMergedTypeNames collection. |
| if (existingType.getFeatures().length != prevNumFeatures) { |
| reportMerge(aOutputMergedTypes, types[i], existingType); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Utility method for populating the aOutputMergedTypes argument in the |
| * mergeTypeSystems method. |
| * @param aOutputMergedTypes Map to populate |
| * @param currentType TypeDescription currently being processed |
| * @param existingType TypeDescription that already existed for the same name |
| */ |
| private static void reportMerge(Map aOutputMergedTypes, TypeDescription currentType, |
| TypeDescription existingType) { |
| if (aOutputMergedTypes != null) { |
| String typeName = currentType.getName(); |
| Set descriptorUrls = (Set)aOutputMergedTypes.get(typeName); |
| if (descriptorUrls == null) { |
| descriptorUrls = new TreeSet(); |
| descriptorUrls.add(existingType.getSourceUrlString()); |
| descriptorUrls.add(currentType.getSourceUrlString()); |
| aOutputMergedTypes.put(typeName, descriptorUrls); |
| } |
| else { |
| descriptorUrls.add(currentType.getSourceUrlString()); |
| } |
| } |
| } |
| |
| /** |
| * Merges the Type Systems of each component within an aggregate Analysis Engine, producing a |
| * single combined Type System. |
| * |
| * @param aAggregateDescription |
| * an aggregate Analysis Engine description |
| * |
| * @return a new TypeSystemDescription that is the result of merging all of the delegate AE type |
| * systems together |
| * |
| * @throws ResourceInitializationException |
| * if an incompatibiliy exists or if an import could not be resolved |
| */ |
| public static TypeSystemDescription mergeDelegateAnalysisEngineTypeSystems( |
| AnalysisEngineDescription aAggregateDescription) throws ResourceInitializationException { |
| return mergeDelegateAnalysisEngineTypeSystems(aAggregateDescription, UIMAFramework |
| .newDefaultResourceManager()); |
| } |
| |
| /** |
| * Merges the Type Systems of each component within an aggregate Analysis Engine, producing a |
| * single combined Type System. |
| * <p> |
| * This version of this method takes an argument <code>aOutputMergedTypeNames</code>, to which |
| * this method will add the names of any types whose definitions have been merged from multiple |
| * non-identical sources. That is, types that are declared more than once, with different (but |
| * compatible) sets of features in each declaration, or with different (but compatible) |
| * supertypes. |
| * |
| * @param aAggregateDescription |
| * an aggregate Analysis Engine description |
| * @param aResourceManager |
| * ResourceManager instance used to resolve imports |
| * |
| * @return a new TypeSystemDescription that is the result of merging all of the delegate AE type |
| * systems together |
| * |
| * @throws ResourceInitializationException |
| * if an incompatibiliy exists or if an import could not be resolved |
| */ |
| public static TypeSystemDescription mergeDelegateAnalysisEngineTypeSystems( |
| AnalysisEngineDescription aAggregateDescription, ResourceManager aResourceManager) |
| throws ResourceInitializationException { |
| return mergeDelegateAnalysisEngineTypeSystems(aAggregateDescription, aResourceManager, null); |
| } |
| |
| /** |
| * Merges the Type Systems of each component within an aggregate Analysis Engine, producing a |
| * single combined Type System. |
| * <p> |
| * This version of this method takes an argument <code>aOutputMergedTypes</code>, which |
| * this method will populate with the names and descriptor locations of any types whose definitions |
| * have been merged from multiple non-identical sources. That is, types that are declared |
| * more than once, with different (but compatible) sets of features in each declaration, |
| * or with different (but compatible) supertypes. |
| * |
| * @param aAggregateDescription |
| * an aggregate Analysis Engine description |
| * @param aResourceManager |
| * ResourceManager instance used to resolve imports |
| * @param aOutputMergedTypes |
| * A Map that this method will populate with information about the set of types |
| * whose definitions were merged from multiple non-identical sources. The keys in |
| * the Map will be the type names (Strings) and the values will be |
| * {link Set}s containing Descriptor URLs (Strings) where those types are |
| * declared. You may pass null if you are not interested in this information. |
| * * |
| * @return a new TypeSystemDescription that is the result of merging all of the delegate AE type |
| * systems together |
| * |
| * @throws ResourceInitializationException |
| * if an incompatibiliy exists or if an import could not be resolved |
| */ |
| public static TypeSystemDescription mergeDelegateAnalysisEngineTypeSystems( |
| AnalysisEngineDescription aAggregateDescription, ResourceManager aResourceManager, |
| Map aOutputMergedTypes) throws ResourceInitializationException { |
| // expand the aggregate AE description into the individual delegates |
| ArrayList l = new ArrayList(); |
| l.add(aAggregateDescription); |
| List mdList = getMetaDataList(l, aResourceManager); |
| |
| // extract type systems and merge |
| List typeSystems = new ArrayList(); |
| Iterator it = mdList.iterator(); |
| while (it.hasNext()) { |
| ProcessingResourceMetaData md = (ProcessingResourceMetaData) it.next(); |
| if (md.getTypeSystem() != null) |
| typeSystems.add(md.getTypeSystem()); |
| } |
| return mergeTypeSystems(typeSystems, aResourceManager, aOutputMergedTypes); |
| } |
| |
| /** |
| * Merges a List of FsIndexCollections into a single FsIndexCollection object. |
| * |
| * @param aFsIndexCollections |
| * list of FsIndexCollection objects |
| * @param aResourceManager |
| * ResourceManager instance to use to resolve imports |
| * |
| * @return a merged FsIndexCollection object |
| * @throws ResourceInitializationException |
| * if an incompatibiliy exists or if an import could not be resolved |
| */ |
| public static FsIndexCollection mergeFsIndexes(List aFsIndexCollections, |
| ResourceManager aResourceManager) throws ResourceInitializationException { |
| Map aggIndexes = new HashMap(); |
| Iterator it = aFsIndexCollections.iterator(); |
| while (it.hasNext()) { |
| FsIndexCollection indexColl = (FsIndexCollection) it.next(); |
| |
| if (indexColl != null) { |
| try { |
| indexColl.resolveImports(aResourceManager); |
| } catch (InvalidXMLException e) { |
| throw new ResourceInitializationException(e); |
| } |
| FsIndexDescription[] indexes = indexColl.getFsIndexes(); |
| for (int i = 0; i < indexes.length; i++) { |
| // does an index with this label already exist? |
| FsIndexDescription duplicateIndex = (FsIndexDescription) aggIndexes.get(indexes[i] |
| .getLabel()); |
| if (duplicateIndex == null) { |
| // no, so add it |
| aggIndexes.put(indexes[i].getLabel(), indexes[i]); |
| } else if (!duplicateIndex.equals(indexes[i])) { |
| // index with same label exists, they better be equal! |
| throw new ResourceInitializationException( |
| ResourceInitializationException.DUPLICATE_INDEX_NAME, new Object[] { |
| duplicateIndex.getLabel(), duplicateIndex.getSourceUrlString(), |
| indexes[i].getSourceUrlString() }); |
| } |
| } |
| } |
| } |
| |
| // convert index map to FsIndexCollection |
| FsIndexCollection aggIndexColl = UIMAFramework.getResourceSpecifierFactory() |
| .createFsIndexCollection(); |
| Collection indexes = aggIndexes.values(); |
| FsIndexDescription[] indexArray = new FsIndexDescription[indexes.size()]; |
| indexes.toArray(indexArray); |
| aggIndexColl.setFsIndexes(indexArray); |
| return aggIndexColl; |
| } |
| |
| /** |
| * Merges the FS Index Collections of each component within an aggregate Analysis Engine, |
| * producing a single combined FS Index Collection. |
| * |
| * @param aAggregateDescription |
| * an aggregate Analysis Engine description |
| * |
| * @return a new FsIndexCollection that is the result of merging all of the delegate AE |
| * FsIndexCollections together |
| * |
| * @throws ResourceInitializationException |
| * if an incompatibiliy exists or if an import could not be resolved |
| */ |
| public static FsIndexCollection mergeDelegateAnalysisEngineFsIndexCollections( |
| AnalysisEngineDescription aAggregateDescription) throws ResourceInitializationException { |
| return mergeDelegateAnalysisEngineFsIndexCollections(aAggregateDescription, UIMAFramework |
| .newDefaultResourceManager()); |
| } |
| |
| /** |
| * Merges the FS Index Collections of each component within an aggregate Analysis Engine, |
| * producing a single combined FS Index Collection. |
| * |
| * @param aAggregateDescription |
| * an aggregate Analysis Engine description |
| * @param aResourceManager |
| * ResourceManager instance used to resolve imports |
| * |
| * @return a new FsIndexCollection that is the result of merging all of the delegate AE |
| * FsIndexCollections together |
| * |
| * @throws ResourceInitializationException |
| * if an incompatibiliy exists or if an import could not be resolved |
| */ |
| public static FsIndexCollection mergeDelegateAnalysisEngineFsIndexCollections( |
| AnalysisEngineDescription aAggregateDescription, ResourceManager aResourceManager) |
| throws ResourceInitializationException { |
| // expand the aggregate AE description into the individual delegates |
| ArrayList l = new ArrayList(); |
| l.add(aAggregateDescription); |
| List mdList = getMetaDataList(l, aResourceManager); |
| |
| // extract FsIndexCollections and merge |
| List fsIndexes = new ArrayList(); |
| Iterator it = mdList.iterator(); |
| while (it.hasNext()) { |
| ProcessingResourceMetaData md = (ProcessingResourceMetaData) it.next(); |
| if (md.getFsIndexCollection() != null) |
| fsIndexes.add(md.getFsIndexCollection()); |
| } |
| return mergeFsIndexes(fsIndexes, aResourceManager); |
| } |
| |
| /** |
| * Merges a List of TypePriorities into a single TypePriorities object. |
| * |
| * @param aTypePriorities |
| * list of TypePriorities objects |
| * @param aResourceManager |
| * ResourceManager instance to use to resolve imports |
| * |
| * @return a merged TypePriorities object |
| * @throws ResourceInitializationException |
| * if an import could not be resolved |
| */ |
| public static TypePriorities mergeTypePriorities(List aTypePriorities, |
| ResourceManager aResourceManager) throws ResourceInitializationException { |
| TypePriorities aggTypePriorities = UIMAFramework.getResourceSpecifierFactory() |
| .createTypePriorities(); |
| Iterator it = aTypePriorities.iterator(); |
| while (it.hasNext()) { |
| TypePriorities tp = (TypePriorities) it.next(); |
| try { |
| tp.resolveImports(aResourceManager); |
| } catch (InvalidXMLException e) { |
| throw new ResourceInitializationException(e); |
| } |
| TypePriorityList[] pls = tp.getPriorityLists(); |
| if (pls != null) { |
| for (int i = 0; i < pls.length; i++) { |
| aggTypePriorities.addPriorityList(pls[i]); |
| } |
| } |
| } |
| return aggTypePriorities; |
| } |
| |
| /** |
| * Merges the Type Priorities of each component within an aggregate Analysis Engine, producing a |
| * single combined TypePriorities object. |
| * |
| * @param aAggregateDescription |
| * an aggregate Analysis Engine description |
| * |
| * @return a new TypePriorities object that is the result of merging all of the delegate AE |
| * TypePriorities together |
| * |
| * @throws ResourceInitializationException |
| * if an incompatibility exists |
| */ |
| public static TypePriorities mergeDelegateAnalysisEngineTypePriorities( |
| AnalysisEngineDescription aAggregateDescription) throws ResourceInitializationException { |
| return mergeDelegateAnalysisEngineTypePriorities(aAggregateDescription, UIMAFramework |
| .newDefaultResourceManager()); |
| } |
| |
| /** |
| * Merges the Type Priorities of each component within an aggregate Analysis Engine, producing a |
| * single combined TypePriorities object. |
| * |
| * @param aAggregateDescription |
| * an aggregate Analysis Engine description |
| * @param aResourceManager |
| * ResourceManager instance used to resolve imports |
| * |
| * @return a new TypePriorities object that is the result of merging all of the delegate AE |
| * TypePriorities together |
| * |
| * @throws ResourceInitializationException |
| * if an incompatibility exists |
| */ |
| public static TypePriorities mergeDelegateAnalysisEngineTypePriorities( |
| AnalysisEngineDescription aAggregateDescription, ResourceManager aResourceManager) |
| throws ResourceInitializationException { |
| // expand the aggregate AE description into the individual delegates |
| ArrayList l = new ArrayList(); |
| l.add(aAggregateDescription); |
| List mdList = getMetaDataList(l, aResourceManager); |
| |
| // extract TypePriorities and merge |
| List typePriorities = new ArrayList(); |
| Iterator it = mdList.iterator(); |
| while (it.hasNext()) { |
| ProcessingResourceMetaData md = (ProcessingResourceMetaData) it.next(); |
| if (md.getTypePriorities() != null) |
| typePriorities.add(md.getTypePriorities()); |
| } |
| return mergeTypePriorities(typePriorities, aResourceManager); |
| } |
| |
| /** |
| * Merges the Type Systems, Type Priorities, and FS Indexes of each component within an |
| * aggregate Analysis Engine. |
| * <p> |
| * This version of this method takes an argument <code>aOutputMergedTypes</code>, which |
| * this method will populate with the names and descriptor locations of any types whose definitions |
| * have been merged from multiple non-identical sources. That is, types that are declared |
| * more than once, with different (but compatible) sets of features in each declaration, |
| * or with different (but compatible) supertypes. |
| * |
| * @param aAggregateDescription |
| * an aggregate Analysis Engine description |
| * @param aResourceManager |
| * ResourceManager instance used to resolve imports |
| * @param aOutputMergedTypes |
| * A Map that this method will populate with information about the set of types |
| * whose definitions were merged from multiple non-identical sources. That is, |
| * types that are declared more than once, with different (but compatible) sets |
| * of features in each declaration, or with different (but compatible) supertypes. |
| * The keys in the Map will be the type names (Strings) and the values will be |
| * {link Set}s containing Descriptor URLs (Strings) where those types are |
| * declared. You may pass null if you are not interested in this information. |
| * @param aOutputFailedRemotes |
| * If this paramter is non-null, and if a remote AE could not be contacted, then |
| * an entry will be added to this map. The key will be the context name (e.g., |
| * /myDelegate1/nestedRemoteDelegate) of the failed remote, and the value will be |
| * the Exception that occurred. If this parameter is null, an exception will be thrown |
| * if a remote AE could not be contacted. |
| * |
| * @return an object containing the merged TypeSystem, TypePriorities, and FS Index definitions. |
| * |
| * @throws ResourceInitializationException |
| * if an incompatibiliy exists or if an import could not be resolved |
| */ |
| public static ProcessingResourceMetaData mergeDelegateAnalysisEngineMetaData( |
| AnalysisEngineDescription aAggregateDescription, ResourceManager aResourceManager, |
| Map aOutputMergedTypes, Map aOutputFailedRemotes) throws ResourceInitializationException { |
| // expand the aggregate AE description into the individual delegates |
| ArrayList l = new ArrayList(); |
| l.add(aAggregateDescription); |
| List mdList = getMetaDataList(l, aResourceManager, aOutputFailedRemotes); |
| |
| ProcessingResourceMetaData result = |
| UIMAFramework.getResourceSpecifierFactory().createProcessingResourceMetaData(); |
| |
| // extract type systems and merge |
| List typeSystems = new ArrayList(); |
| Iterator it = mdList.iterator(); |
| while (it.hasNext()) { |
| ProcessingResourceMetaData md = (ProcessingResourceMetaData) it.next(); |
| if (md.getTypeSystem() != null) |
| typeSystems.add(md.getTypeSystem()); |
| } |
| result.setTypeSystem(mergeTypeSystems(typeSystems, aResourceManager, aOutputMergedTypes)); |
| |
| // extract TypePriorities and merge |
| List typePriorities = new ArrayList(); |
| it = mdList.iterator(); |
| while (it.hasNext()) { |
| ProcessingResourceMetaData md = (ProcessingResourceMetaData) it.next(); |
| if (md.getTypePriorities() != null) |
| typePriorities.add(md.getTypePriorities()); |
| } |
| result.setTypePriorities(mergeTypePriorities(typePriorities, aResourceManager)); |
| |
| // extract FsIndexCollections and merge |
| List fsIndexes = new ArrayList(); |
| it = mdList.iterator(); |
| while (it.hasNext()) { |
| ProcessingResourceMetaData md = (ProcessingResourceMetaData) it.next(); |
| if (md.getFsIndexCollection() != null) |
| fsIndexes.add(md.getFsIndexCollection()); |
| } |
| result.setFsIndexCollection(mergeFsIndexes(fsIndexes, aResourceManager)); |
| |
| return result; |
| } |
| |
| /** |
| * Determines whether one type subsumes another. |
| * |
| * @param aType1Name |
| * name of first type |
| * @param aType2Name |
| * name of second type |
| * @param aNameMap |
| * Map from type names to TypeDescriptions |
| * |
| * @return true if and only if the type named <code>aType1Name</code> subsumes the type named |
| * <code>aType2Name</code> according to the information given in the |
| * <code>aNameMap</code>. |
| */ |
| protected static boolean subsumes(String aType1Name, String aType2Name, Map aNameMap) { |
| // Top type subsumes everything |
| if (CAS.TYPE_NAME_TOP.equals(aType1Name)) { |
| return true; |
| } |
| |
| // "walk up the tree" from aType2Name until we reach aType1Name or null |
| String current = aType2Name; |
| while (current != null && !current.equals(aType1Name)) { |
| TypeDescription curType = (TypeDescription) aNameMap.get(current); |
| if (curType == null) |
| current = null; |
| else |
| current = curType.getSupertypeName(); |
| } |
| |
| return (current != null); |
| } |
| |
| /** |
| * Merges features into a TypeDescription. |
| * |
| * @param aType |
| * TypeDescription into which to merge the features |
| * @param aFeatures |
| * array of features to merge |
| * |
| * @throws ResourceInitializationException |
| * if an incompatibility exists |
| */ |
| protected static void mergeFeatures(TypeDescription aType, FeatureDescription[] aFeatures) |
| throws ResourceInitializationException { |
| FeatureDescription[] existingFeatures = aType.getFeatures(); |
| if (existingFeatures == null) { |
| existingFeatures = new FeatureDescription[0]; |
| } |
| |
| for (int i = 0; i < aFeatures.length; i++) { |
| String featName = aFeatures[i].getName(); |
| String rangeTypeName = aFeatures[i].getRangeTypeName(); |
| String elementTypeName = aFeatures[i].getElementType(); |
| Boolean multiRefsAllowed = aFeatures[i].getMultipleReferencesAllowed(); |
| |
| // see if a feature already exists with this name |
| FeatureDescription feat = null; |
| for (int j = 0; j < existingFeatures.length; j++) { |
| if (existingFeatures[j].getName().equals(featName)) { |
| feat = existingFeatures[j]; |
| break; |
| } |
| } |
| |
| if (feat == null) { |
| // doesn't exist; add it |
| FeatureDescription featDesc = aType.addFeature(featName, aFeatures[i].getDescription(), |
| rangeTypeName, elementTypeName, multiRefsAllowed); |
| featDesc.setSourceUrl(aFeatures[i].getSourceUrl()); |
| } else // feature does exist |
| { |
| // check that the range types match |
| if (!feat.getRangeTypeName().equals(rangeTypeName)) { |
| throw new ResourceInitializationException( |
| ResourceInitializationException.INCOMPATIBLE_RANGE_TYPES, new Object[] { |
| aType.getName() + ":" + feat.getName(), rangeTypeName, |
| feat.getRangeTypeName(), aType.getSourceUrlString() }); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Gets a list of ProcessingResourceMetadata objects from a list containing either |
| * ResourceSpecifiers, ProcessingResourceMetadata objects, or subparts of |
| * ProcessingResourceMetadata objects (type sypstems, indexes, or type priorities). Subparts will |
| * be wrapped inside a ProcessingResourceMetadata object. All objects will be cloned, so that |
| * further processing (such as import resolution) does not affect the caller. |
| * <p> |
| * If you pass this method objects of type {@link AnalysisEngineDescription}, |
| * {@link CollectionReaderDescription}, {@link CasInitializerDescription}, or |
| * {@link CasConsumerDescription}, it will not instantiate the components. It will just extract |
| * the type system information from the descriptor. For any other kind of |
| * {@link ResourceSpecifier}, it will call |
| * {@link UIMAFramework#produceResource(org.apache.uima.resource.ResourceSpecifier, Map)}. For |
| * example, if a {@link URISpecifier} is passed, a remote connection will be established and the |
| * service will be queries for its metadata. An exception will be thrown if the connection can not |
| * be opened. |
| * |
| * @param aComponentDescriptionsOrMetaData |
| * a collection of {@link ResourceSpecifier}, {@link ProcessingResourceMetaData}, |
| * {@link TypeSystemDescription}, {@link FsIndexCollection}, or {@link TypePriorities} |
| * objects. |
| * @param aResourceManager |
| * used to resolve delegate analysis engine imports |
| * @param aOutputFailedRemotes |
| * If this paramter is non-null, and if a remote AE could not be contacted, then |
| * the context name (e.g. /myDelegate1/nestedRemoteDelegate) of the failed remote will |
| * be added to this collection. If this parameter is null, an exception will be thrown |
| * if a remote AE could not be contacted. |
| * |
| * @return a List containing the ProcessingResourceMetaData objects containing all of the |
| * information in all of the objects in <code>aComponentDescriptionOrMetaData</code> |
| * (including all components of aggregate AnalysisEngines) |
| * |
| * @throws ResourceInitialziationException |
| * if a failure occurs because an import could not be resolved |
| */ |
| public static List getMetaDataList(Collection aComponentDescriptionOrMetaData, |
| ResourceManager aResourceManager, Map aOutputFailedRemotes) throws ResourceInitializationException { |
| return getMetaDataList(aComponentDescriptionOrMetaData, aResourceManager, aOutputFailedRemotes, ""); |
| } |
| |
| private static List getMetaDataList(Collection aComponentDescriptionOrMetaData, |
| ResourceManager aResourceManager, Map aOutputFailedRemotes, String aContextName) throws ResourceInitializationException { |
| |
| List mdList = new ArrayList(); |
| if (null == aComponentDescriptionOrMetaData) { |
| return mdList; |
| } |
| Iterator iter = aComponentDescriptionOrMetaData.iterator(); |
| while (iter.hasNext()) { |
| Object current = iter.next(); |
| if (current instanceof ProcessingResourceMetaData) { |
| mdList.add(((ProcessingResourceMetaData) current).clone()); |
| } else if (current instanceof AnalysisEngineDescription) { |
| AnalysisEngineDescription aeDesc = (AnalysisEngineDescription) current; |
| mdList.add(aeDesc.getMetaData().clone()); |
| // expand aggregate |
| if (!aeDesc.isPrimitive()) { |
| Map delegateMap; |
| try { |
| delegateMap = aeDesc.getAllComponentSpecifiers(aResourceManager); |
| } catch (InvalidXMLException e) { |
| throw new ResourceInitializationException(e); |
| } |
| Iterator delIter = delegateMap.entrySet().iterator(); |
| while(delIter.hasNext()) { |
| Map.Entry delEntry = (Map.Entry)delIter.next(); |
| List tempList = new ArrayList(); |
| tempList.add(delEntry.getValue()); |
| mdList.addAll(getMetaDataList(tempList, aResourceManager, aOutputFailedRemotes, aContextName + "/" + delEntry.getKey())); |
| } |
| } |
| } else if (current instanceof CollectionReaderDescription) { |
| mdList.add(((CollectionReaderDescription) current).getMetaData().clone()); |
| } else if (current instanceof CasInitializerDescription) { |
| mdList.add(((CasInitializerDescription) current).getMetaData().clone()); |
| } else if (current instanceof CasConsumerDescription) { |
| mdList.add(((CasConsumerDescription) current).getMetaData().clone()); |
| } else if (current instanceof FlowControllerDescription) { |
| mdList.add(((FlowControllerDescription) current).getMetaData().clone()); |
| } else if (current instanceof TypeSystemDescription) { |
| ProcessingResourceMetaData md = new ProcessingResourceMetaData_impl(); |
| md.setTypeSystem((TypeSystemDescription) current); |
| mdList.add(md); |
| } else if (current instanceof FsIndexCollection) { |
| ProcessingResourceMetaData md = new ProcessingResourceMetaData_impl(); |
| md.setFsIndexCollection((FsIndexCollection) current); |
| mdList.add(md); |
| } else if (current instanceof TypePriorities) { |
| ProcessingResourceMetaData md = new ProcessingResourceMetaData_impl(); |
| md.setTypePriorities((TypePriorities) current); |
| mdList.add(md); |
| } else if (current instanceof ResourceSpecifier) { |
| //try to instantiate the resource |
| Resource resource = null; |
| Map resourceMgrInMap = new HashMap(); |
| resourceMgrInMap.put(Resource.PARAM_RESOURCE_MANAGER, aResourceManager); |
| try { |
| resource = UIMAFramework.produceResource((ResourceSpecifier) current, |
| (null == aResourceManager) ? Collections.EMPTY_MAP : resourceMgrInMap); |
| } catch (Exception e) { |
| //failed. If aOutputFailedRemotes is non-null, add an entry to it to it, else throw the exception. |
| if (aOutputFailedRemotes != null) { |
| aOutputFailedRemotes.put(aContextName,e); |
| } |
| else { |
| if (e instanceof ResourceInitializationException) |
| throw (ResourceInitializationException)e; |
| else if (e instanceof RuntimeException) |
| throw (RuntimeException)e; |
| else |
| throw new RuntimeException(e); |
| } |
| } |
| if (resource != null) { |
| ResourceMetaData metadata = resource.getMetaData(); |
| if (metadata instanceof ProcessingResourceMetaData) { |
| mdList.add(metadata); |
| } |
| resource.destroy(); |
| } |
| } else { |
| throw new ResourceInitializationException( |
| ResourceInitializationException.UNSUPPORTED_OBJECT_TYPE_IN_CREATE_CAS, |
| new Object[] { current.getClass().getName() }); |
| } |
| } |
| |
| return mdList; |
| } |
| |
| |
| /** |
| * Gets a list of ProcessingResourceMetadata objects from a list containing either |
| * ResourceSpecifiers, ProcessingResourceMetadata objects, or subparts of |
| * ProcessingResourceMetadata objects (type sypstems, indexes, or type priorities). Subparts will |
| * be wrapped inside a ProcessingResourceMetadata object. All objects will be cloned, so that |
| * further processing (such as import resolution) does not affect the caller. |
| * <p> |
| * If you pass this method objects of type {@link AnalysisEngineDescription}, |
| * {@link CollectionReaderDescription}, {@link CasInitializerDescription}, or |
| * {@link CasConsumerDescription}, it will not instantiate the components. It will just extract |
| * the type system information from the descriptor. For any other kind of |
| * {@link ResourceSpecifier}, it will call |
| * {@link UIMAFramework#produceResource(org.apache.uima.resource.ResourceSpecifier, Map)}. For |
| * example, if a {@link URISpecifier} is passed, a remote connection will be established and the |
| * service will be queries for its metadata. An exception will be thrown if the connection can not |
| * be opened. |
| * |
| * @param aComponentDescriptionsOrMetaData |
| * a collection of {@link ResourceSpecifier}, {@link ProcessingResourceMetaData}, |
| * {@link TypeSystemDescription}, {@link FsIndexCollection}, or {@link TypePriorities} |
| * objects. |
| * @param aResourceManager |
| * used to resolve delegate analysis engine imports |
| * |
| * @return a List containing the ProcessingResourceMetaData objects containing all of the |
| * information in all of the objects in <code>aComponentDescriptionOrMetaData</code> |
| * (including all components of aggregate AnalysisEngines) |
| * |
| * @throws ResourceInitialziationException |
| * if a failure occurs because an import could not be resolved |
| */ |
| public static List getMetaDataList(Collection aComponentDescriptionOrMetaData, |
| ResourceManager aResourceManager) throws ResourceInitializationException { |
| return getMetaDataList(aComponentDescriptionOrMetaData, aResourceManager, null); |
| } |
| |
| } |