AbstractSemanticAnnotationHelper.java

  1. /*
  2.  *  AbstractSemanticAnnotationHelper.java
  3.  *
  4.  *  Copyright (c) 2007-2011, The University of Sheffield.
  5.  *
  6.  *  This file is part of GATE Mímir (see http://gate.ac.uk/family/mimir.html),
  7.  *  and is free software, licenced under the GNU Lesser General Public License,
  8.  *  Version 3, June 2007 (also included with this distribution as file
  9.  *  LICENCE-LGPL3.html).
  10.  *
  11.  *  Valentin Tablan, 5 Aug 2009
  12.  *
  13.  *  $Id: AbstractSemanticAnnotationHelper.java 17261 2014-01-30 14:05:14Z valyt $
  14.  */
  15. package gate.mimir;

  16. import gate.Document;
  17. import gate.mimir.index.AtomicAnnotationIndex;
  18. import gate.mimir.index.Mention;
  19. import gate.mimir.search.QueryEngine;
  20. import gate.mimir.util.DefaultMentionDescriber;

  21. import java.io.Serializable;
  22. import java.util.ArrayList;
  23. import java.util.Collections;
  24. import java.util.List;
  25. import java.util.Map;
  26. import java.util.Map.Entry;


  27. /**
  28.  * Simple abstract class that provides:
  29.  * <ul>
  30.  *   <li>an empty implementation for {@link #documentStart(Document)}</li>
  31.  *   <li>an empty implementation for {@link #documentEnd()}</li>
  32.  *   <li>an implementation for {@link #getMentions(String, Map, QueryEngine)},
  33.  *   which simply calls {@link #getMentions(String, List, QueryEngine)} after
  34.  *   creating the appropriate constraints.</li>
  35.  * </ul>
  36.  *
  37.  * Subclasses are required to provide a no-argument constructor. When
  38.  * implementing the {@link #init(Indexer)} and {@link #init(QueryEngine)}
  39.  * methods, they must first call super.init(...).
  40.  *
  41.  * <p>If a particular helper does not support certain feature types it should
  42.  * use the {@link #concatenateArrays} method to combine those features with
  43.  * another kind that it can support, during the init(Indexer) call.  For example,
  44.  * helpers that do not have access to a full semantic repository may choose to
  45.  * treat URI features as if they were simply text features with no semantics.</p>
  46.  */
  47. public abstract class AbstractSemanticAnnotationHelper implements
  48.     SemanticAnnotationHelper {
  49.    
  50.   /**
  51.    * Interface for supporting classes used by
  52.    * {@link AbstractSemanticAnnotationHelper} and its sub-classes to provide a
  53.    * pluggable implementation for
  54.    * {@link SemanticAnnotationHelper#describeMention(String)}.
  55.    */
  56.   public static interface MentionDescriber extends Serializable {
  57.     public String describeMention(AbstractSemanticAnnotationHelper helper,
  58.         String mentionUri, String[] descriptiveFeatureNames,
  59.         String[] descriptiveFeatureValues);
  60.   }
  61.  
  62.     private static final long serialVersionUID = -5432862771431426914L;

  63.   private transient boolean isInited = false;
  64.  
  65.  
  66.   protected final boolean isInited() {
  67.     return isInited;
  68.   }

  69.   /**
  70.    * The list of names for the nominal features.
  71.    */
  72.   protected String[] nominalFeatureNames;

  73.   /**
  74.    * The list of names for the numeric features.
  75.    */
  76.   protected String[] integerFeatureNames;

  77.   /**
  78.    * The list of names for the numeric features.
  79.    */
  80.   protected String[] floatFeatureNames;
  81.  
  82.   /**
  83.    * The list of names for the text features.
  84.    */
  85.   protected String[] textFeatureNames;
  86.    
  87.   /**
  88.    * The list of names for the URI features.
  89.    */
  90.   protected String[] uriFeatureNames;
  91.  
  92.   /**
  93.    * The type of the annotations handled by this helper.
  94.    */
  95.   protected String annotationType;
  96.    
  97.   /**
  98.    * The list of names for all the features that should be used when describing
  99.    * an annotation mention (see {@link #describeMention(String)}).
  100.    */
  101.   protected String[] descriptiveFeatures;
  102.  
  103.   protected MentionDescriber mentionDescriber;
  104.  
  105.  
  106.   /**
  107.    * The working mode for this helper (defaults to {@link Mode#ANNOTATION}).
  108.    */
  109.   protected Mode mode = Mode.ANNOTATION;
  110.  
  111.   public Mode getMode() {
  112.     return mode;
  113.   }

  114.   public void setMode(Mode mode) {
  115.     this.mode = mode;
  116.   }

  117.   public String getAnnotationType() {
  118.     return annotationType;
  119.   }

  120.   public void setAnnotationType(String annotationType) {
  121.     this.annotationType = annotationType;
  122.   }  
  123.  
  124.   public void setAnnType(String annotationType) {
  125.     setAnnotationType(annotationType);
  126.   }

  127.   public String[] getNominalFeatures() {
  128.     return nominalFeatureNames;
  129.   }

  130.   public void setNominalFeatures(String[] nominalFeatureNames) {
  131.     this.nominalFeatureNames = nominalFeatureNames;
  132.   }

  133.   public String[] getIntegerFeatures() {
  134.     return integerFeatureNames;
  135.   }



  136.   public void setIntegerFeatures(String[] integerFeatureNames) {
  137.     this.integerFeatureNames = integerFeatureNames;
  138.   }
  139.  
  140.   public String[] getFloatFeatures() {
  141.     return floatFeatureNames;
  142.   }

  143.   public void setFloatFeatures(String[] floatFeatureNames) {
  144.     this.floatFeatureNames = floatFeatureNames;
  145.   }

  146.  
  147.   public String[] getTextFeatures() {
  148.     return textFeatureNames;
  149.   }

  150.   public void setTextFeatures(String[] textFeatureNames) {
  151.     this.textFeatureNames = textFeatureNames;
  152.   }
  153.  
  154.   /**
  155.    * @return the uriFeatureNames
  156.    */
  157.   public String[] getUriFeatures() {
  158.     return uriFeatureNames;
  159.   }

  160.   public void setUriFeatures(String[] uriFeatureNames) {
  161.     this.uriFeatureNames = uriFeatureNames;
  162.   }
  163.  
  164.   /**
  165.    * Gets the names of features that should be used when describing an
  166.    * annotation mention.
  167.    *  
  168.    * @return the descriptiveFeatures
  169.    */
  170.   protected String[] getDescriptiveFeatures() {
  171.     return descriptiveFeatures;
  172.   }

  173.   /**
  174.    * Sets the names of features that should be used when describing an
  175.    * annotation mention. This should be called <strong>before</strong> the
  176.    * helper is initialised (i.e. before calling {@link #init(QueryEngine)}).
  177.    *
  178.    * If no custom value has been set before {@link #init(QueryEngine)} is
  179.    * called, then all features are used as descriptive features.
  180.    *
  181.    * @param descriptiveFeatures the descriptiveFeatures to set
  182.    */
  183.   public void setDescriptiveFeatures(String[] descriptiveFeatures) {
  184.     this.descriptiveFeatures = descriptiveFeatures;
  185.   }

  186.  
  187.  
  188.   /**
  189.    * @return the mentionDescriber
  190.    */
  191.   public MentionDescriber getMentionDescriber() {
  192.     return mentionDescriber;
  193.   }

  194.   /**
  195.    * Sets the {@link MentionDescriber} to be used as the implementation of
  196.    * {@link SemanticAnnotationHelper#describeMention(String)}.
  197.    * If set to <code>null</code>, then an instance of
  198.    * {@link DefaultMentionDescriber} is automatically created and used.
  199.    *  
  200.    * @param mentionDescriber the custom mentionDescriber to use
  201.    */
  202.   public void setMentionDescriber(MentionDescriber mentionDescriber) {
  203.     this.mentionDescriber = mentionDescriber;
  204.   }

  205.   /* (non-Javadoc)
  206.    * @see gate.mimir.SemanticAnnotationHelper#documentEnd()
  207.    */
  208.   public void documentEnd() {}

  209.   public void documentStart(Document document) { }


  210.   /* (non-Javadoc)
  211.    * @see gate.mimir.SemanticAnnotationHelper#getMentions(java.lang.String, java.util.Map, gate.mimir.search.QueryEngine)
  212.    */
  213.   public List<Mention> getMentions(String annotationType,
  214.           Map<String, String> constraints, QueryEngine engine) {
  215.     //convert the simple constraints to actual implementations.
  216.     List<Constraint> predicates = new ArrayList<Constraint>(constraints.size());
  217.     for(Entry<String, String> entry : constraints.entrySet()){
  218.       predicates.add(new Constraint(ConstraintType.EQ, entry.getKey(), entry.getValue()));
  219.     }
  220.     return getMentions(annotationType, predicates, engine);
  221.   }

  222.  
  223.  
  224.   /* (non-Javadoc)
  225.    * @see gate.mimir.SemanticAnnotationHelper#describeMention(java.lang.String)
  226.    */
  227.   @Override
  228.   public String describeMention(String mentionUri) {
  229.     if(mentionDescriber == null) {
  230.       mentionDescriber = new DefaultMentionDescriber();
  231.     }
  232.     return mentionDescriber.describeMention(this, mentionUri,
  233.       getDescriptiveFeatures(), getDescriptiveFeatureValues(mentionUri));
  234.   }
  235.  
  236.   /**
  237.    * Calculates the textual representations for the values of features that are
  238.    * part of the description of an annotation mention. The list of features for
  239.    * which the values should be returned is {@link #descriptiveFeatures}.
  240.    *
  241.    * This implementation always returns <code>null</code> as the abstract class
  242.    * has no way of accessing the actual feature values. Subclasses should
  243.    * provide an actual implementation to support proper mention descriptions.
  244.    *
  245.    * @param mentionUri the URI for the mention that needs to be described.
  246.    *
  247.    * @return an array of strings parallel with {@link #descriptiveFeatures}, or
  248.    * null if the feature values are not known.
  249.    */
  250.   protected String[] getDescriptiveFeatureValues(String mentionUri) {
  251.     return null;
  252.   }
  253.  
  254.   /**
  255.    * Helper method to concatenate a number of arrays into one, for helpers
  256.    * that don't support all the feature types and want to combine some of
  257.    * them together.
  258.    * @return null if all the supplied arrays are either null or empty,
  259.    *        otherwise a single array containing the concatenation of
  260.    *        all the supplied arrays in order.
  261.    */
  262.   protected static String[] concatenateArrays(String[]... arrays) {
  263.     int totalLength = 0;
  264.     for(String[] arr : arrays) {
  265.       if(arr != null) totalLength += arr.length;
  266.     }
  267.     if(totalLength == 0) return null;
  268.     String[] concat = new String[totalLength];
  269.     int start = 0;
  270.     for(String[] arr : arrays) {
  271.       if(arr != null) {
  272.         System.arraycopy(arr, 0, concat, start, arr.length);
  273.         start += arr.length;
  274.       }
  275.     }
  276.     return concat;
  277.   }

  278.   private void checkInit() {
  279.     if(isInited) throw new IllegalStateException(
  280.       "This helper has already been initialised!");
  281.    
  282.     isInited = true;
  283.   }

  284.  
  285.   @Override
  286.   public void init(AtomicAnnotationIndex index) {
  287.     checkInit();
  288.     // calculate the list of descriptive features if needed
  289.     if(descriptiveFeatures == null) {
  290.       List<String> featNames = new ArrayList<String>();
  291.       if(nominalFeatureNames != null){
  292.         Collections.addAll(featNames, nominalFeatureNames);
  293.       }
  294.       if(integerFeatureNames != null) {
  295.         Collections.addAll(featNames, integerFeatureNames);
  296.       }
  297.       if(floatFeatureNames != null) {
  298.         Collections.addAll(featNames, floatFeatureNames);
  299.       }
  300.       if(textFeatureNames != null) {
  301.         Collections.addAll(featNames, textFeatureNames);
  302.       }
  303.       if(uriFeatureNames != null) {
  304.         Collections.addAll(featNames, uriFeatureNames);
  305.       }
  306.       descriptiveFeatures = featNames.toArray(new String[featNames.size()]);
  307.     }
  308.   }
  309. }