//Dstl (c) Crown Copyright 2017 package uk.gov.dstl.baleen.uima; import java.util.Collection; import org.apache.uima.UimaContext; import org.apache.uima.analysis_engine.AnalysisEngineProcessException; import org.apache.uima.fit.component.JCasAnnotator_ImplBase; import org.apache.uima.fit.descriptor.ExternalResource; import org.apache.uima.jcas.JCas; import org.apache.uima.jcas.tcas.Annotation; import org.apache.uima.jcas.tcas.DocumentAnnotation; import org.apache.uima.resource.ResourceInitializationException; import uk.gov.dstl.baleen.core.history.BaleenHistory; import uk.gov.dstl.baleen.core.pipelines.PipelineBuilder; import uk.gov.dstl.baleen.core.pipelines.orderers.AnalysisEngineAction; import uk.gov.dstl.baleen.core.pipelines.orderers.AnalysisEngineActionStore; import uk.gov.dstl.baleen.core.pipelines.orderers.IPipelineOrderer; import uk.gov.dstl.baleen.uima.utils.UimaUtils; /** * This class provides basic functionality for an annotator, such as metrics and * logging, so that we don't need to put it into every annotator manually. All * annotators in Baleen should inherit from this class and use any utility * methods it provides as required to ensure we standardise logging and metrics * as much as possible. * * */ public abstract class BaleenAnnotator extends JCasAnnotator_ImplBase { private UimaMonitor monitor; private UimaSupport support; /** * Baleen History resource * * @baleen.resource uk.gov.dstl.baleen.core.history.BaleenHistory */ public static final String KEY_HISTORY = PipelineBuilder.BALEEN_HISTORY; @ExternalResource(key = KEY_HISTORY, mandatory = false) private BaleenHistory history; @Override public void initialize(UimaContext context) throws ResourceInitializationException { // This will do initialization of resources, // but won't be included in the metrics super.initialize(context); String pipelineName = UimaUtils.getPipelineName(context); monitor = createMonitor(pipelineName); support = createSupport(pipelineName, context); monitor.startFunction("initialize"); doInitialize(context); monitor.finishFunction("initialize"); String uuid = (String) getContext().getConfigParameterValue(PipelineBuilder.ANNOTATOR_UUID); AnalysisEngineActionStore.getInstance().add(uuid, getAction()); } protected UimaSupport createSupport(String pipelineName, UimaContext context) { return new UimaSupport(pipelineName, this.getClass(), history, monitor, UimaUtils.isMergeDistinctEntities(context)); } protected UimaMonitor createMonitor(String pipelineName) { return new UimaMonitor(pipelineName, this.getClass()); } /** * Called when the analysis engine is being initialized. Any required * resources, for example, should be opened at this point. * * @param aContext * UimaContext object passed by the Collection Processing Engine */ public void doInitialize(UimaContext aContext) throws ResourceInitializationException{ // Do nothing - this should be overridden in most cases } @Override public void process(JCas aJCas) throws AnalysisEngineProcessException { monitor.startFunction("process"); doProcess(aJCas); monitor.finishFunction("process"); monitor.persistCounts(); } /** * Called when UIMA wants the annotator to process a document. The passed * JCas object contains information about the document and any existing * annotations. * * @param jCas * JCas object to process * @throws AnalysisEngineProcessException */ protected abstract void doProcess(JCas jCas) throws AnalysisEngineProcessException; @Override public void destroy() { monitor.startFunction("destroy"); doDestroy(); monitor.finishFunction("destroy"); } /** * Called when the analysis engine has finished and is closing down. Any * open resources, for example, should be closed at this point. */ protected void doDestroy(){ //Do nothing - this should be overridden in most cases } /** Get the UIMA monitor for this annotator. * @return the uima monitor */ protected UimaMonitor getMonitor() { return monitor; } /** Get the UIMA support for this annotator. * @return the uima support */ protected UimaSupport getSupport() { return support; } // Direct access to common support functions /** * Add an annotation to the JCas index, notifying UimaMonitor of the fact we * have done so * * @param annot * Annotation(s) to add */ protected void addToJCasIndex(Annotation... annotations) { getSupport().add(annotations); } /** * Add an annotation to the JCas index, notifying UimaMonitor of the fact we * have done so * * @param annot * Annotation(s) to add */ protected void addToJCasIndex(Collection<? extends Annotation> annotations) { getSupport().add(annotations); } /** * Remove an annotation to the JCas index, notifying UimaMonitor of the fact * we have done so * * @param annot * Annotation(s) to remove */ protected void removeFromJCasIndex(Collection<? extends Annotation> annotations) { getSupport().remove(annotations); } /** * Remove an annotation to the JCas index, notifying UimaMonitor of the fact * we have done so * * @param annot * Annotation(s) to remove */ protected void removeFromJCasIndex(Annotation... annotations) { getSupport().remove(annotations); } /** * Add a new annotation, which is merged from the old annotations, removing the old annotations. * * @param newAnnotation * The annotation which is to be added to the document as the merged result of the old annotations * @param annotations * Annotation(s) which have been merged and should be removed */ protected void mergeWithNew(Annotation newAnnotation, Annotation... annotations) { getSupport().mergeWithNew(newAnnotation, annotations); } /** * Add a new annotation, which is merged from the old annotations, removing the old annotations. * * @param newAnnotation * The annotation which is to be added to the document as the merged result of the old annotations * @param annotations * Annotation(s) which have been merged and should be removed */ protected void mergeWithNew(Annotation newAnnotation, Collection<? extends Annotation> annotations) { getSupport().mergeWithNew(newAnnotation, annotations); } /** * Merge an existing annotation with old annotations, removing the old annotations. * * @param existingAnnotation * The annotation which exists and is to be left in the document (merged) * @param annotations * Annotation(s) which have been merged wiht existingAnnotation and then removed */ protected void mergeWithExisting(Annotation existingAnnotation, Annotation... annotations) { getSupport().mergeWithExisting(existingAnnotation, annotations); } /** * Add a new annotation, which is merged from the old annotations, removing the old annotations. * * @param existingAnnotation * The annotation which exists and is to be left in the document (merged) * @param annotations * Annotation(s) which have been merged wiht existingAnnotation and then removed */ protected void mergeWithExisting(Annotation existingAnnotation, Collection<? extends Annotation> annotations) { getSupport().mergeWithExisting(existingAnnotation, annotations); } /** * Return the document annotation. * * @param jCas * @return the document annotation */ protected DocumentAnnotation getDocumentAnnotation(JCas jCas){ return getSupport().getDocumentAnnotation(jCas); } /** * Return an AnalysisEngineAction that programmatically describes * what the analysis engine is doing, such that it can be automatically * ordered by an {@link IPipelineOrderer} */ public abstract AnalysisEngineAction getAction(); }