//Dstl (c) Crown Copyright 2017 package uk.gov.dstl.baleen.uima.utils; import java.util.Iterator; import org.apache.uima.cas.Type; import org.apache.uima.cas.TypeSystem; import org.apache.uima.jcas.JCas; import org.apache.uima.jcas.cas.AnnotationBase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory; import com.googlecode.concurrenttrees.suffix.ConcurrentSuffixTree; import com.googlecode.concurrenttrees.suffix.SuffixTree; import uk.gov.dstl.baleen.exceptions.BaleenException; import uk.gov.dstl.baleen.types.semantic.Entity; /** A collection of utility to set bridge between Uima types and Java classes. * * */ public class TypeUtils { private static final Logger LOGGER = LoggerFactory.getLogger(TypeUtils.class); private TypeUtils(){ // Private constructor for Util class } /** * For a given type name, look through the type system and return the matching class. * If two types of the same name (but different packages) exist, then null will be returned and the package will need to be included in the typeName. * * @param typeName The name of the type, optionally including the package * @param jCas A JCas object containing the type system * @return The class associated with that type */ public static Class<? extends AnnotationBase> getType(String typeName, JCas jCas){ return getType(typeName, jCas.getTypeSystem()); } /** * For a given type name, look through the type system and return the matching class. * If two types of the same name (but different packages) exist, then null will be returned and the package will need to be included in the typeName. * * @param typeName The name of the type, optionally including the package * @param typeSystem The type system to search * @return The class associated with that type */ @SuppressWarnings("unchecked") public static Class<AnnotationBase> getType(String typeName, TypeSystem typeSystem){ SuffixTree<Class<AnnotationBase>> types = new ConcurrentSuffixTree<>(new DefaultByteArrayNodeFactory()); Iterator<Type> itTypes = typeSystem.getTypeIterator(); while(itTypes.hasNext()){ Type t = itTypes.next(); Class<AnnotationBase> c; try { String clazz = t.getName(); if(clazz.startsWith("uima.")){ continue; } else if(clazz.endsWith("[]")){ clazz = clazz.substring(0, clazz.length() - 2); } Class<?> unchecked = Class.forName(clazz); if(AnnotationBase.class.isAssignableFrom(unchecked)){ c = (Class<AnnotationBase>) unchecked; types.put(t.getName(), c); }else{ LOGGER.debug("Skipping class {} that doesn't inherit from AnnotationBase"); } } catch (ClassNotFoundException e) { LOGGER.warn("Unable to load class {} from type system", t.getName(), e); } } Class<AnnotationBase> ret = getClassFromType("."+typeName, types); if(ret == null){ ret = getClassFromType(typeName, types); } if(ret == null){ LOGGER.warn("No uniquely matching class found for type {}", typeName); } return ret; } private static Class<AnnotationBase> getClassFromType(String typeName, SuffixTree<Class<AnnotationBase>> types){ Iterator<CharSequence> itMatchedTypes = types.getKeysEndingWith(typeName).iterator(); if(!itMatchedTypes.hasNext()){ return null; //No match found } Class<AnnotationBase> ret = types.getValueForExactKey(itMatchedTypes.next()); if(itMatchedTypes.hasNext()){ return null; //More than one match found } return ret; } /** * Get the class of a specified type, that extends from the Entity base class * * @param typeName The name of the type, optionally including the package * @param jCas A JCas object containing the type system * @return The class associated with that type, which will extend from Entity * @throws BaleenException is thrown if a suitable class can't be found */ @SuppressWarnings("unchecked") public static Class<? extends Entity> getEntityClass(String typeName, JCas jCas) throws BaleenException{ Class<? extends AnnotationBase> at = getType(typeName, jCas); if(at == null){ throw new BaleenException("Couldn't find type '"+typeName+"'"); } if(!Entity.class.isAssignableFrom(at)){ throw new BaleenException("Entity type '"+typeName+"' does not inherit from Entity"); } return (Class<? extends Entity>) at; } }