Hi Roberto,

here's an alternative to your solution.  It's a bit
shorter, and I find it easier to understand ;-)
It's untested, but you get the idea.

--Thilo

  /**
   * Find a covering parent annotation of a certain type, e.g., the sentence 
containing a given
   * annotation.
   *
   * @param cas
   *          The CAS.
   * @param childAnnotation
   *          The annotation that we want to find a parent for (e.g., a token).
   * @param parentType
   *          The type of covering annotation we're looking for.
   * @return A parent annotation, if it exists; <code>null</code> else.
   */
  public static FeatureStructure findParentAnnotation(CAS cas, AnnotationFS 
childAnnotation,
      Type parentType) {
    final int start = childAnnotation.getBegin();
    final int end = childAnnotation.getEnd();
    // Find a parent FS by searching in the annotation index. Start by creating 
a temp parent FS
    // which is only used to position an iterator. If this is done many times, 
the search FS should
    // be cached and only the start/end position modified as necessary 
(creating a FS allocates
    // space in the CAS that is not garbage collected).
    FeatureStructure searchFS = cas.createAnnotation(parentType, start, end);
    FSIterator parentIterator = cas.getAnnotationIndex(parentType).iterator();
    // Position the iterator.
    parentIterator.moveTo(searchFS);
    // Return parent at position if it is indeed a covering annotation.
    if (parentIterator.isValid()) {
      AnnotationFS candidateParent = (AnnotationFS) parentIterator.get();
      if ((candidateParent.getBegin() <= start) && (candidateParent.getEnd() >= 
end)) {
        return candidateParent;
      }
    }
    // If no parent annotation could be found.
    return null;
  }


Roberto Franchini wrote:
On Wed, Jan 7, 2009 at 11:55 AM, Roberto Franchini
<[email protected]> wrote:
Hi,
I need to get a parent annotation of a given one.
Example: given a Token annotation, I want to know the parent Sentence.
I need to extract it from a cas. Maybe filters or constraint?
I mean a sort of "parentIterator", as the subiterator, but "reversed" :)
Regards,
Roberto

Here's the answer with filtered iterator:

public static FSIterator getAnnotationParent(JCas jcas, Annotation
son, Type parent) {
                ConstraintFactory cf = jcas.getConstraintFactory();
                
                FSIntConstraint beginCons = cf.createIntConstraint();
                beginCons.leq(son.getBegin());
                
                FSIntConstraint endCons = cf.createIntConstraint();
                endCons.geq(son.getEnd());
                
                FSTypeConstraint typeCons = cf.createTypeConstraint();
                
                Type type = jcas.getTypeSystem().getType(parent.getName());
                typeCons.add(type);
                
                Feature beginFeature = type.getFeatureByBaseName("begin");
                FeaturePath beginPath = jcas.createFeaturePath();
                beginPath.addFeature(beginFeature);

                Feature endFeature = type.getFeatureByBaseName("end");
                FeaturePath endPath = jcas.createFeaturePath();
                endPath.addFeature(endFeature);

                FSMatchConstraint begin = cf.embedConstraint(beginPath, 
beginCons);
                
                FSMatchConstraint end  = cf.embedConstraint(endPath, endCons);
                
                FSMatchConstraint beginAndEnd  = cf.and(begin, end);
                
                FSMatchConstraint beginAndEndAndType  = cf.and(beginAndEnd, 
typeCons);
                FSIterator filteredIterator =
jcas.createFilteredIterator(jcas.getAnnotationIndex(parent).iterator(),
beginAndEndAndType);
                
                return filteredIterator;

        }


Here's a test (junit).

        @Test
        public void getParent() throws Exception {

                AnalysisEngine tokenizer = AnnotatorFactory.createTokenizer();
//this is my own factory for tests!!!
                JCas jcas = tokenizer.newJCas();
                jcas.setDocumentText("My name is .");
                Sentence sentence = new Sentence(jcas, 0, 
jcas.getDocumentText().length());
                sentence.addToIndexes();
                tokenizer.process(jcas);
                FSIterator iterator = 
jcas.getAnnotationIndex(Token.type).iterator();
                iterator.moveToNext();
                Token token = (Token) iterator.get();

                FSIterator parentIt = CasUtil.getAnnotationParent(jcas, token,
sentence.getType());
                assertNotNull(parentIt);

                parentIt.moveToFirst();
                Sentence sentence2 = (Sentence) parentIt.get();
                assertNotNull(sentence2);
                assertEquals(sentence.getCoveredText(), 
sentence2.getCoveredText());

        }

It works :)
Roberto

Reply via email to