Search in sources :

Example 16 with Annotation

use of gate.Annotation in project gate-core by GateNLP.

the class AnnotationSetImpl method edit.

// addToStartOffsetIndex(a)
/**
 * Propagate document content changes to this AnnotationSet.
 *
 * This method is called for all annotation sets of a document from
 * DocumentImpl.edit to adapt the annotations to the text changes made through
 * the edit. The behaviour of this method is influenced by the configuration
 * setting {@link gate.GateConstants#DOCEDIT_INSERT_PREPEND GateConstants.DOCEDIT_INSERT_PREPEND }:
 * annotations immediately
 * ending before or starting after the point of insertion will either become
 * part of the inserted text or not. Currently it works like this:
 * <ul>
 * <li>PREPEND=true: annotation before will become part, annotation after not
 * <li>PREPEND=false: annotation before will not become part, annotation after
 * will become part
 * </UL>
 * NOTE 1 (JP): There is another setting
 * {@link gate.GateConstants#DOCEDIT_INSERT_APPEND GateConstants.DOCEDIT_INSERT_APPEND }
 * but
 * this setting does currently not influence the behaviour of this method.
 * The behaviour of this method may change in the future so that
 * DOCEDIT_INSERT_APPEND is considered separately and in addition to
 * DOCEDIT_INSERT_PREPEND so that it can be controlled independently if
 * the annotation before and/or after an insertion point gets expanded or not.
 * <p>
 * NOTE 2: This method has, unfortunately, to be
 * public, to allow DocumentImpls to get at it. Oh for a "friend" declaration.
 * Doesn't throw InvalidOffsetException as DocumentImpl is the only client,
 * and that checks the offsets before calling this method.
 */
public void edit(Long start, Long end, DocumentContent replacement) {
    // make sure we have the indices computed
    indexByStartOffset();
    if (end.compareTo(start) > 0) {
        // get the nodes that need to be processed (the nodes internal to
        // the
        // removed section plus the marginal ones
        List<Node> affectedNodes = new ArrayList<Node>(nodesByOffset.subMap(start, end.longValue() + 1).values());
        // if we have more than 1 node we need to delete all apart from
        // the first
        // and move the annotations so that they refer to the one we keep
        // (the
        // first)
        NodeImpl firstNode = null;
        if (!affectedNodes.isEmpty()) {
            firstNode = (NodeImpl) affectedNodes.get(0);
            List<Annotation> startingAnnotations = new ArrayList<Annotation>();
            List<Annotation> endingAnnotations = new ArrayList<Annotation>();
            // now we need to find all the annotations
            // ending in the zone
            List<Node> beforeNodes = new ArrayList<Node>(nodesByOffset.subMap(0L, end.longValue() + 1).values());
            Iterator<Node> beforeNodesIter = beforeNodes.iterator();
            while (beforeNodesIter.hasNext()) {
                Node currentNode = beforeNodesIter.next();
                Collection<Annotation> annotations = getAnnotsByStartNode(currentNode.getId());
                if (annotations == null)
                    continue;
                // iterates on the annotations in this set
                Iterator<Annotation> localIterator = annotations.iterator();
                while (localIterator.hasNext()) {
                    Annotation annotation = localIterator.next();
                    long offsetEndAnnotation = annotation.getEndNode().getOffset().longValue();
                    // inside the zone
                    if (offsetEndAnnotation >= start.longValue() && offsetEndAnnotation <= end.longValue())
                        endingAnnotations.add(annotation);
                }
            }
            for (int i = 1; i < affectedNodes.size(); i++) {
                Node aNode = affectedNodes.get(i);
                Collection<Annotation> annSet = getAnnotsByStartNode(aNode.getId());
                if (annSet != null) {
                    startingAnnotations.addAll(annSet);
                }
            // remove the node
            // nodesByOffset.remove(aNode.getOffset());
            // annotsByStartNode.remove(aNode);
            }
            // modify the annotations so they point to the saved node
            Iterator<Annotation> annIter = startingAnnotations.iterator();
            while (annIter.hasNext()) {
                AnnotationImpl anAnnot = (AnnotationImpl) annIter.next();
                anAnnot.start = firstNode;
                // zero-length
                if (anAnnot.start == anAnnot.end) {
                    remove(anAnnot);
                } else {
                    addToStartOffsetIndex(anAnnot);
                }
            }
            annIter = endingAnnotations.iterator();
            while (annIter.hasNext()) {
                AnnotationImpl anAnnot = (AnnotationImpl) annIter.next();
                anAnnot.end = firstNode;
                // zero-length
                if (anAnnot.start == anAnnot.end) {
                    remove(anAnnot);
                }
            }
            // remove the unused nodes inside the area
            for (int i = 1; i < affectedNodes.size(); i++) {
                Node aNode = affectedNodes.get(i);
                nodesByOffset.remove(aNode.getOffset());
                annotsByStartNode.remove(aNode.getId());
            }
            // repair the first node
            // remove from offset index
            nodesByOffset.remove(firstNode.getOffset());
            // change the offset for the saved node
            firstNode.setOffset(start);
            // add back to the offset index
            nodesByOffset.put(firstNode.getOffset(), firstNode);
        }
    }
    // now handle the insert and/or update the rest of the nodes'
    // position
    // get the user selected behaviour (defaults to append)
    boolean shouldPrepend = Gate.getUserConfig().getBoolean(GateConstants.DOCEDIT_INSERT_PREPEND).booleanValue();
    long s = start.longValue(), e = end.longValue();
    // length of the replacement value
    long rlen = ((replacement == null) ? 0 : replacement.size().longValue());
    // update the offsets and the index by offset for the rest of the
    // nodes
    List<Node> nodesAfterReplacement = new ArrayList<Node>(nodesByOffset.tailMap(start).values());
    // remove from the index by offset
    Iterator<Node> nodesAfterReplacementIter = nodesAfterReplacement.iterator();
    while (nodesAfterReplacementIter.hasNext()) {
        NodeImpl n = (NodeImpl) nodesAfterReplacementIter.next();
        nodesByOffset.remove(n.getOffset());
    }
    // change the offsets
    nodesAfterReplacementIter = nodesAfterReplacement.iterator();
    while (nodesAfterReplacementIter.hasNext()) {
        NodeImpl n = (NodeImpl) nodesAfterReplacementIter.next();
        long oldOffset = n.getOffset().longValue();
        // by default we move all nodes back
        long newOffset = oldOffset - (e - s) + rlen;
        // for the first node we need behave differently
        if (oldOffset == s) {
            // the first offset never moves back
            if (newOffset < s)
                newOffset = s;
            // if we're prepending we don't move forward
            if (shouldPrepend)
                newOffset = s;
        }
        n.setOffset(newOffset);
    }
    // add back to the index by offset with the new offsets
    nodesAfterReplacementIter = nodesAfterReplacement.iterator();
    while (nodesAfterReplacementIter.hasNext()) {
        NodeImpl n = (NodeImpl) nodesAfterReplacementIter.next();
        nodesByOffset.put(n.getOffset(), n);
    }
// //rebuild the indices with the new offsets
// nodesByOffset = null;
// annotsByStartNode = null;
// annotsByEndNode = null;
// indexByStartOffset();
// indexByEndOffset();
}
Also used : Node(gate.Node) ArrayList(java.util.ArrayList) Annotation(gate.Annotation)

Example 17 with Annotation

use of gate.Annotation in project gate-core by GateNLP.

the class AnnotationSetImpl method get.

// get(type, featureNames)
/**
 * Select annotations by offset. This returns the set of annotations whose
 * start node is the least such that it is less than or equal to offset. If a
 * positional index doesn't exist it is created. If there are no nodes at or
 * beyond the offset param then it will return an empty annotationset.
 */
@Override
public AnnotationSet get(Long offset) {
    if (annotsByStartNode == null)
        indexByStartOffset();
    // find the next node at or after offset; get the annots starting
    // there
    Node nextNode = nodesByOffset.getNextOf(offset);
    if (// no nodes at or beyond this offset
    nextNode == null)
        return emptyAS();
    Collection<Annotation> annotationsToAdd = getAnnotsByStartNode(nextNode.getId());
    // skip all the nodes that have no starting annotations
    while (annotationsToAdd == null) {
        nextNode = nodesByOffset.getNextOf(nextNode.getOffset().longValue() + 1);
        if (nextNode == null)
            return emptyAS();
        annotationsToAdd = getAnnotsByStartNode(nextNode.getId());
    }
    return new ImmutableAnnotationSetImpl(doc, annotationsToAdd);
}
Also used : Node(gate.Node) Annotation(gate.Annotation)

Example 18 with Annotation

use of gate.Annotation in project gate-core by GateNLP.

the class AnnotationSetImpl method getCovering.

// get(type, startOfset, endOffset)
/**
 * Select annotations of the given type that completely span the range.
 * Formally, for any annotation a, a will be included in the return
 * set if:
 * <ul>
 * <li>a.getStartNode().getOffset() <= startOffset</li>
 * <li>and</li>
 * <li>a.getEndNode().getOffset() >= endOffset</li>
 *
 * @param neededType Type of annotation to return. If empty, all
 *          annotation types will be returned.
 * @return annotations of the given type that completely span the range.
 */
@Override
public AnnotationSet getCovering(String neededType, Long startOffset, Long endOffset) {
    // check the range
    if (endOffset < startOffset)
        return emptyAS();
    // ensure index
    if (annotsByStartNode == null)
        indexByStartOffset();
    // so we return an empty set.
    if (endOffset - startOffset > longestAnnot)
        return emptyAS();
    List<Annotation> annotationsToAdd = new ArrayList<Annotation>();
    Iterator<Node> nodesIter;
    Iterator<Annotation> annotsIter;
    Node currentNode;
    Annotation currentAnnot;
    boolean checkType = StringUtils.isNotBlank(neededType);
    // find all the annots with startNode <= startOffset.  Need the + 1 because
    // headMap returns strictly less than.
    // the length of the longest annot from the endOffset since we know that nothing
    // that starts earlier will be long enough to cover the entire span.
    Long searchStart = ((endOffset - 1) - longestAnnot);
    if (searchStart < 0)
        searchStart = 0l;
    // nodesIter = nodesByOffset.headMap(startOffset + 1).values().iterator();
    nodesIter = nodesByOffset.subMap(searchStart, startOffset + 1).values().iterator();
    while (nodesIter.hasNext()) {
        currentNode = nodesIter.next();
        Collection<Annotation> objFromPoint = getAnnotsByStartNode(currentNode.getId());
        if (objFromPoint == null)
            continue;
        annotsIter = objFromPoint.iterator();
        while (annotsIter.hasNext()) {
            currentAnnot = annotsIter.next();
            // if neededType is set, make sure this is the right type
            if (checkType && !currentAnnot.getType().equals(neededType))
                continue;
            // check that the annot ends at or after the endOffset
            if (currentAnnot.getEndNode().getOffset().compareTo(endOffset) >= 0)
                annotationsToAdd.add(currentAnnot);
        }
    // while
    }
    return new ImmutableAnnotationSetImpl(doc, annotationsToAdd);
}
Also used : Node(gate.Node) ArrayList(java.util.ArrayList) Annotation(gate.Annotation)

Example 19 with Annotation

use of gate.Annotation in project gate-core by GateNLP.

the class AnnotationSetImpl method remove.

/**
 * Remove an element from this set.
 */
@Override
public boolean remove(Object o) throws ClassCastException {
    Annotation a = (Annotation) o;
    boolean wasPresent = removeFromIdIndex(a);
    if (wasPresent) {
        removeFromTypeIndex(a);
        removeFromOffsetIndex(a);
    }
    // fire the event
    fireAnnotationRemoved(new AnnotationSetEvent(AnnotationSetImpl.this, AnnotationSetEvent.ANNOTATION_REMOVED, getDocument(), a));
    return wasPresent;
}
Also used : AnnotationSetEvent(gate.event.AnnotationSetEvent) Annotation(gate.Annotation)

Example 20 with Annotation

use of gate.Annotation in project gate-core by GateNLP.

the class AnnotationSetImpl method get.

// getStrict(startOfset, endOffset)
/**
 * Select annotations by offset. This returns the set of annotations of the
 * given type that overlap totaly or partially with the interval defined by
 * the two provided offsets.The result will include all the annotations that
 * either:
 * <ul>
 * <li>start before the start offset and end strictly after it</li>
 * <li>OR</li>
 * <li>start at a position between the start and the end offsets</li>
 */
@Override
public AnnotationSet get(String neededType, Long startOffset, Long endOffset) {
    if (annotsByStartNode == null)
        indexByStartOffset();
    List<Annotation> annotationsToAdd = new ArrayList<Annotation>();
    Iterator<Node> nodesIter;
    Iterator<Annotation> annotsIter;
    Node currentNode;
    Annotation currentAnnot;
    boolean checkType = StringUtils.isNotBlank(neededType);
    // find all the annots that start strictly before the start offset
    // and end
    // strictly after it
    Long searchStart = (startOffset - longestAnnot);
    if (searchStart < 0)
        searchStart = 0l;
    // nodesIter = nodesByOffset.headMap(startOffset).values().iterator();
    nodesIter = nodesByOffset.subMap(searchStart, startOffset).values().iterator();
    while (nodesIter.hasNext()) {
        currentNode = nodesIter.next();
        Collection<Annotation> objFromPoint = getAnnotsByStartNode(currentNode.getId());
        if (objFromPoint == null)
            continue;
        annotsIter = objFromPoint.iterator();
        while (annotsIter.hasNext()) {
            currentAnnot = annotsIter.next();
            // if neededType is set, make sure this is the right type
            if (checkType && !currentAnnot.getType().equals(neededType))
                continue;
            if (currentAnnot.getEndNode().getOffset().compareTo(startOffset) > 0) {
                annotationsToAdd.add(currentAnnot);
            }
        // if
        }
    // while
    }
    // find all the annots that start at or after the start offset but
    // before the end offset
    nodesIter = nodesByOffset.subMap(startOffset, endOffset).values().iterator();
    while (nodesIter.hasNext()) {
        currentNode = nodesIter.next();
        Collection<Annotation> objFromPoint = getAnnotsByStartNode(currentNode.getId());
        if (objFromPoint == null)
            continue;
        // if no specific type requested, add all of the annots
        if (!checkType)
            annotationsToAdd.addAll(objFromPoint);
        else {
            // check the type of each annot
            annotsIter = objFromPoint.iterator();
            while (annotsIter.hasNext()) {
                currentAnnot = annotsIter.next();
                if (currentAnnot.getType().equals(neededType))
                    annotationsToAdd.add(currentAnnot);
            }
        // while
        }
    }
    return new ImmutableAnnotationSetImpl(doc, annotationsToAdd);
}
Also used : Node(gate.Node) ArrayList(java.util.ArrayList) Annotation(gate.Annotation)

Aggregations

Annotation (gate.Annotation)69 AnnotationSet (gate.AnnotationSet)28 ArrayList (java.util.ArrayList)24 HashMap (java.util.HashMap)15 Node (gate.Node)10 HashSet (java.util.HashSet)10 List (java.util.List)10 FeatureMap (gate.FeatureMap)8 Map (java.util.Map)8 TreeSet (java.util.TreeSet)8 Document (gate.Document)7 InvalidOffsetException (gate.util.InvalidOffsetException)7 Point (java.awt.Point)6 LinkedList (java.util.LinkedList)5 Set (java.util.Set)5 StatusListener (gate.event.StatusListener)4 GateRuntimeException (gate.util.GateRuntimeException)3 Color (java.awt.Color)3 Stack (java.util.Stack)3 TreeMap (java.util.TreeMap)3