blob: eb54fd464165094c3c76a8fb80f33d5d4d427e7b [file] [log] [blame]
/*
* 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.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.apache.uima.ResourceFactory;
import org.apache.uima.UIMAFramework;
import org.apache.uima.resource.Resource;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.ResourceSpecifier;
/**
* A simple implementation of a {@link org.apache.uima.ResourceFactory}. This implementation
* maintains a Map between the {@link ResourceSpecifier} sub-interface name (e.g.
* <code>AnalysisEngineDescription</code>) and the class name of the resource to be constructed
* from specifiers of that type.
* <p>
* UIMA developers who introduce new types of {@link Resource}s or {@link ResourceSpecifier}s may
* create an instance of this class and use the {@link #addMapping(Class,Class)} method to register
* a mapping between the ResourceSpecifier interface and the Class of the Resource that is to be
* constructed from it. The <code>SimpleResourceFactory</code> should then be registered with the
* framework by calling
* <code>{@link UIMAFramework#getResourceFactory()}.{@link org.apache.uima.CompositeResourceFactory#registerFactory(Class,ResourceFactory) registerFactory(Class,ResourceFactory)};</code>
*
*
*/
public class SimpleResourceFactory implements ResourceFactory {
/**
* resource bundle for log messages
*/
private static final String LOG_RESOURCE_BUNDLE = "org.apache.uima.impl.log_messages";
/**
* current class
*/
private static final Class CLASS_NAME = SimpleResourceFactory.class;
/**
* Map from ResourceSpecifier Class to List of Resource Classes. Resource initialization is
* attempted in reverse order through this List, so more recently registered classes are tried
* first.
*/
protected Map mClassMap = Collections.synchronizedMap(new HashMap());
/**
* Produces an appropriate <code>Resource</code> instance from a <code>ResourceSpecifier</code>.
*
* @param aResourceClass
* the interface of the resource to be produced. This is intended to be a standard UIMA
* interface such as <code>TextAnalysisEngine</code> or <code>ASB</code>.
* @param aSpecifier
* an object that specifies how to acquire an instance of a <code>Resource</code>.
* @param aAdditionalParams
* a Map containing additional parameters to pass to the
* {@link Resource#initialize(ResourceSpecifier,Map)} method. May be <code>null</code>
* if there are no parameters.
*
* @return a <code>Resource</code> instance. Returns <code>null</code> if this factory does
* not know how to create a Resource from the <code>ResourceSpecifier</code> provided.
*
* @throws ResourceInitializationException
* if a failure occurred during production of the resource
*
* @see org.apache.uima.ResourceFactory#produceResource(Class, ResourceSpecifier,Map)
*/
public Resource produceResource(Class aResourceClass, ResourceSpecifier aSpecifier,
Map aAdditionalParams) throws ResourceInitializationException {
ResourceInitializationException lastException = null;
// get all interfaces implemented by aSpecifier
Class[] interfaces = aSpecifier.getClass().getInterfaces();
// look up class mapping
List resourceClasses = null;
for (int i = 0; i < interfaces.length; i++) {
resourceClasses = (List) mClassMap.get(interfaces[i]);
if (resourceClasses != null)
break;
}
if (resourceClasses != null) {
// iterate backwards through the elements of the list, so that
// we attempt to initialize the most recently registered Resource
// classes first
ListIterator i = resourceClasses.listIterator(resourceClasses.size());
while (i.hasPrevious()) {
Class currentClass = (Class) i.previous();
ResourceInitializationException currentException = null;
try {
// check to see if this is a subclass of aResourceClass
if (aResourceClass.isAssignableFrom(currentClass)) {
// instantiate this Resource Class
Resource resource = (Resource) currentClass.newInstance();
// attempt to initialize it
UIMAFramework.getLogger(CLASS_NAME).logrb(Level.CONFIG, CLASS_NAME.getName(),
"produceResource", LOG_RESOURCE_BUNDLE, "UIMA_trying_resource_class__CONFIG",
currentClass.getName());
if (resource.initialize(aSpecifier, aAdditionalParams)) {
// success!
return resource;
}
}
}
// if an exception occurs, log it but do not throw it... yet
catch (IllegalAccessException e) {
currentException = new ResourceInitializationException(
ResourceInitializationException.COULD_NOT_INSTANTIATE, new Object[] {
currentClass.getName(), aSpecifier.getSourceUrlString() }, e);
} catch (InstantiationException e) {
currentException = new ResourceInitializationException(
ResourceInitializationException.COULD_NOT_INSTANTIATE, new Object[] {
currentClass.getName(), aSpecifier.getSourceUrlString() }, e);
} catch (Throwable t) {
currentException = new ResourceInitializationException(
ResourceInitializationException.ERROR_INITIALIZING_FROM_DESCRIPTOR, new Object[] {
currentClass.getName(), aSpecifier.getSourceUrlString() }, t);
} finally {
if (currentException != null) {
currentException.fillInStackTrace();
// UIMAFramework.getLogger().logException(currentException);
// store this exception
lastException = currentException;
}
}
// try again
}
}
// No resource could be created. If an exception occurred,
// throw it. Otherwise, return null.
if (lastException != null) {
throw lastException;
} else {
return null;
}
}
/**
* Configures this <code>SimpleResourceFactory</code> by adding a new mapping between a
* <code>ResourceSpecifier</code> class and a <code>Resource</code> class.
*
* @param aSpecifierInterface
* the subinterface of <code>ResourceSpecifier</code>.
* @param aResourceClass
* a subclass of <code>Resource</code> that is to be instantiated from resource
* specifiers of the given class.
*/
public void addMapping(Class aSpecifierInterface, Class aResourceClass) {
List mappingList = (List) mClassMap.get(aSpecifierInterface);
if (mappingList == null) {
// No mapping exists. Create a new list and put it in the map.
mappingList = new ArrayList();
mClassMap.put(aSpecifierInterface, mappingList);
}
// add the new Resource Class to the end of the mapping list
mappingList.add(aResourceClass);
}
/**
* Configures this <code>SimpleResourceFactory</code> by adding a new mapping between a
* <code>ResourceSpecifier</code> class and a <code>Resource</code> class.
*
* @param aSpecifierInterfaceName
* name of the subinterface of <code>ResourceSpecifier</code>.
* @param aResourceClassName
* the name of a subclass of <code>Resource</code> that is to be instantiated from
* resource specifiers of the given class.
*/
public void addMapping(String aSpecifierInterfaceName, String aResourceClassName)
throws ClassNotFoundException {
addMapping(Class.forName(aSpecifierInterfaceName), Class.forName(aResourceClassName));
}
}