Package org.apache.uima.ruta.rule

Source Code of org.apache.uima.ruta.rule.WildCardRuleElement

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.uima.ruta.rule;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.apache.uima.cas.CAS;
import org.apache.uima.cas.CASException;
import org.apache.uima.cas.ConstraintFactory;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.cas.FSTypeConstraint;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.jcas.JCas;
import org.apache.uima.ruta.RutaBlock;
import org.apache.uima.ruta.RutaStream;
import org.apache.uima.ruta.action.AbstractRutaAction;
import org.apache.uima.ruta.condition.AbstractRutaCondition;
import org.apache.uima.ruta.expression.string.StringExpression;
import org.apache.uima.ruta.type.RutaBasic;
import org.apache.uima.ruta.type.RutaFrame;
import org.apache.uima.ruta.visitor.InferenceCrowd;

public class WildCardRuleElement extends AbstractRuleElement {

  public WildCardRuleElement(List<AbstractRutaCondition> conditions,
          List<AbstractRutaAction> actions, RuleElementContainer container,
          RutaBlock parent) {
    super(null, conditions, actions, container, parent);
  }

  public void startMatch(RuleMatch ruleMatch, RuleApply ruleApply,
          ComposedRuleElementMatch containerMatch, RuleElement entryPoint, RutaStream stream,
          InferenceCrowd crowd) {
    continueMatch(true, null, ruleMatch, ruleApply, containerMatch, null, entryPoint, stream, crowd);
  }

  public void continueMatch(boolean after, AnnotationFS annotation, RuleMatch ruleMatch,
          RuleApply ruleApply, ComposedRuleElementMatch containerMatch,
          RutaRuleElement sideStepOrigin, RuleElement entryPoint, RutaStream stream,
          InferenceCrowd crowd) {
    RuleElement nextElement = getContainer().getNextElement(after, this);

    tryWithNextRuleElement(nextElement, after, annotation, ruleMatch, ruleApply, containerMatch,
            sideStepOrigin, entryPoint, stream, crowd);

  }

  private void tryWithNextRuleElement(RuleElement nextElement, boolean after,
          AnnotationFS annotation, RuleMatch ruleMatch, RuleApply ruleApply,
          ComposedRuleElementMatch containerMatch, RutaRuleElement sideStepOrigin,
          RuleElement entryPoint, RutaStream stream, InferenceCrowd crowd) {
    // what is the next stuff that should match?
    if (nextElement == null) {
      AnnotationFS afs = getCoveredByWildCard(after, annotation, null, stream);
      doMatch(afs, ruleMatch, containerMatch, annotation == null, stream, crowd);
      ComposedRuleElement composed = (ComposedRuleElement) getContainer();
      composed.fallbackContinue(after, ruleMatch.matched(), afs, ruleMatch, ruleApply,
              containerMatch, sideStepOrigin, entryPoint, stream, crowd);
    } else if (nextElement instanceof RutaRuleElement) {
      RutaRuleElement re = (RutaRuleElement) nextElement;
      RutaMatcher matcher = re.getMatcher();
      if (matcher instanceof RutaTypeMatcher) {
        tryWithNextType(after, annotation, nextElement, null, ruleMatch, ruleApply, containerMatch,
                sideStepOrigin, stream, crowd);
      } else if (matcher instanceof RutaLiteralMatcher) {
        tryWithNextLiteral(after, annotation, re, ruleMatch, ruleApply, containerMatch,
                sideStepOrigin, stream, crowd);
      } else if (matcher instanceof RutaDisjunctiveMatcher) {
        tryWithNextType(after, annotation, re, null, ruleMatch, ruleApply, containerMatch,
                sideStepOrigin, stream, crowd);
      }

    } else if (nextElement instanceof ComposedRuleElement) {

      ComposedRuleElement cre = ((ComposedRuleElement) nextElement);
      tryWithNextComposed(after, annotation, cre, ruleMatch, ruleApply, containerMatch,
              sideStepOrigin, stream, crowd);
      RuleElement nextInnerRuleElement = null;
      if (after) {
        nextInnerRuleElement = cre.getFirstElement();
      } else {
        nextInnerRuleElement = cre.getLastElement();
      }
      // TODO won't work ...!!!
      ComposedRuleElementMatch composedMatch = new ComposedRuleElementMatch(cre, containerMatch);
      if (containerMatch == null) {
        ruleMatch.setRootMatch(composedMatch);
      } else {
        containerMatch.addInnerMatch(this, composedMatch, false);
      }
      tryWithNextRuleElement(nextInnerRuleElement, after, annotation, ruleMatch, ruleApply,
              composedMatch, sideStepOrigin, entryPoint, stream, crowd);
    } else if (nextElement instanceof WildCardRuleElement) {
      // another wildcard? seriously? then just assume its an "Annotation" type
      CAS cas = stream.getCas();
      tryWithNextType(after, annotation, nextElement, cas.getAnnotationType(), ruleMatch,
              ruleApply, containerMatch, sideStepOrigin, stream, crowd);
    }
  }

  private void tryWithNextComposed(boolean after, AnnotationFS annotation, ComposedRuleElement cre,
          RuleMatch ruleMatch, RuleApply ruleApply, ComposedRuleElementMatch containerMatch,
          RutaRuleElement sideStepOrigin, RutaStream stream, InferenceCrowd crowd) {
    AnnotationFS nextOne = annotation;
    boolean doneHere = false;
    while (!doneHere
            && (nextOne = getNextPositionForComposed(cre, after, nextOne, stream)) != null) {
      RutaBasic endAnchor = stream.getEndAnchor(nextOne.getBegin());
      ComposedRuleElementMatch extendedContainerMatch = containerMatch.copy();
      RuleMatch extendedMatch = ruleMatch.copy(extendedContainerMatch);
      AnnotationFS coveredByWildCard = getCoveredByWildCard(after, annotation, nextOne, stream);

      doMatch(coveredByWildCard, extendedMatch, extendedContainerMatch, annotation == null, stream,
              crowd);
      if (extendedMatch.matched()) {
        cre.continueMatch(after, endAnchor, extendedMatch, ruleApply,
                extendedContainerMatch, sideStepOrigin, cre, stream, crowd);
        List<RuleElementMatch> nextList = extendedContainerMatch.getInnerMatches().get(cre);
        boolean matched = hasMatched(nextList);
        if (!matched) {
          nextOne = stream.getAnchor(after, getNextPointer(!after, nextOne));
        } else {
          doneHere = true;
        }
      } else {
        // conditions of wildcard element did not match, try the next possible anchor for the
        // next rule element
        nextOne = annotation;
      }
    }
    if (!doneHere) {
      cre.continueMatch(after, annotation, ruleMatch, ruleApply, containerMatch, sideStepOrigin,
              null, stream, crowd);
    }
  }

  private boolean hasMatched(List<RuleElementMatch> nextList) {
    if(nextList == null || nextList.isEmpty()) {
      return false;
    }
    boolean result = true;
    for (RuleElementMatch each : nextList) {
      result &= each.matched();
    }
    return result;
  }

  private AnnotationFS getNextPositionForComposed(ComposedRuleElement cre, boolean after,
          AnnotationFS annotation, RutaStream stream) {
    RuleElement element = getNextAtomicRuleElement(cre, after);
    AnnotationFS result = null;
    if (element instanceof WildCardRuleElement) {
      if (after) {
        return stream.getAnchor(after, annotation.getEnd());
      } else {
        return stream.getAnchor(after, annotation.getBegin());
      }
    } else {
      RutaRuleElement re = (RutaRuleElement) element;
      RutaMatcher matcher = re.getMatcher();
      if (matcher instanceof RutaTypeMatcher) {
        FSIterator<AnnotationFS> iterator = getIterator(after, annotation, re, null, stream);
//        moveOn(after, iterator);
        if (iterator.isValid()) {
          result = iterator.get();
        }
      } else if (matcher instanceof RutaLiteralMatcher) {
        RutaLiteralMatcher lm = (RutaLiteralMatcher) matcher;
        StringExpression expression = lm.getExpression();
        String stringValue = expression.getStringValue(parent);
        AnnotationFS documentAnnotation = stream.getDocumentAnnotation();
        int delta = documentAnnotation.getBegin();
        String document = documentAnnotation.getCoveredText();
        int pointer = annotation.getEnd() - delta;
        int indexOf = document.indexOf(stringValue, pointer);
        if (indexOf < 0) {
          return null;
        } else {
          return stream.getAnchor(after, indexOf);
        }
      }
    }

    return result;
  }

  private RuleElement getNextAtomicRuleElement(ComposedRuleElement cre, boolean after) {
    if (after) {
      RuleElement firstElement = cre.getFirstElement();
      if (firstElement instanceof ComposedRuleElement) {
        return getNextAtomicRuleElement((ComposedRuleElement) firstElement, after);
      } else {
        return firstElement;
      }
    } else {
      RuleElement lastElement = cre.getLastElement();
      if (lastElement instanceof ComposedRuleElement) {
        return getNextAtomicRuleElement((ComposedRuleElement) lastElement, after);
      } else {
        return lastElement;
      }
    }
  }

  private void tryWithNextType(boolean after, AnnotationFS annotation, RuleElement nextElement,
          Type defaultType, RuleMatch ruleMatch, RuleApply ruleApply,
          ComposedRuleElementMatch containerMatch, RutaRuleElement sideStepOrigin,
          RutaStream stream, InferenceCrowd crowd) {
    FSIterator<AnnotationFS> iterator = getIterator(after, annotation, nextElement, defaultType,
            stream);
    boolean doneHere = false;
    while (!doneHere && iterator.isValid() && stream.isVisible(iterator.get())) {
      AnnotationFS nextOne = iterator.get();
      RutaBasic endAnchor = stream.getEndAnchor(nextOne.getBegin());
      ComposedRuleElementMatch extendedContainerMatch = containerMatch.copy();
      RuleMatch extendedMatch = ruleMatch.copy(extendedContainerMatch);

      AnnotationFS coveredByWildCard = getCoveredByWildCard(after, annotation, nextOne, stream);

      doMatch(coveredByWildCard, extendedMatch, extendedContainerMatch, annotation == null, stream,
              crowd);
      if (extendedMatch.matched()) {
        nextElement.continueMatch(after, endAnchor, extendedMatch, ruleApply,
                extendedContainerMatch, sideStepOrigin, nextElement, stream, crowd);
        List<RuleElementMatch> nextList = extendedContainerMatch.getInnerMatches().get(nextElement);
        if (nextList == null || nextList.isEmpty()) {
          moveOn(after, iterator);
        } else {
          doneHere = true;
        }
      } else {
        // conditions of wildcard element did not match, try the next possible anchor for the
        // next rule element
        moveOn(after, iterator);
      }
    }
  }

  private FSIterator<AnnotationFS> getIterator(boolean after, AnnotationFS annotation,
          RuleElement nextElement, Type defaultType, RutaStream stream) {
    CAS cas = stream.getCas();
    FSIterator<AnnotationFS> iterator = null;
    if (defaultType == null) {
      RutaRuleElement re = (RutaRuleElement) nextElement;
      RutaMatcher matcher = re.getMatcher();
      if (matcher instanceof RutaTypeMatcher) {
        RutaTypeMatcher typeMatcher = (RutaTypeMatcher) re.getMatcher();
        List<Type> types = typeMatcher.getTypes(parent, stream);
        Type type = types.get(0);
        iterator = getIteratorOfType(type, annotation, stream);
      } else if (matcher instanceof RutaDisjunctiveMatcher) {
        List<Type> types = matcher.getTypes(parent, stream);
        iterator = getIteratorForDisjunctive(cas, types, after, annotation, stream);
      } else {
        // should not happen
      }
    } else {
      iterator = getIteratorOfType(defaultType, annotation, stream);
    }
    return iterator;
  }

  private FSIterator<AnnotationFS> getIteratorOfType(Type type, AnnotationFS annotation,
          RutaStream stream) {
    CAS cas = stream.getCas();
    FSIterator<AnnotationFS> result = null;
    if(stream.getDocumentAnnotation().equals(cas.getDocumentAnnotation())) {
      // no windowing needed
      if(annotation == null) {
        result = cas.getAnnotationIndex(type).iterator();
      } else {
        result = cas.getAnnotationIndex(type).iterator(annotation);
      }
    } else {
      JCas jcas = null;
      try {
        jcas = cas.getJCas();
      } catch (CASException e) {
        e.printStackTrace();
      }
      RutaFrame window = new RutaFrame(jcas, stream.getDocumentAnnotation().getBegin(), stream.getDocumentAnnotation().getEnd());
      if(annotation == null) {
        result = cas.getAnnotationIndex(type).subiterator(window);
      } else {
        result = cas.getAnnotationIndex(type).subiterator(window);
        result.moveTo(annotation);
      }
    }
   
    return result;
  }

  private void tryWithNextLiteral(boolean after, AnnotationFS annotation,
          RutaRuleElement nextElement, RuleMatch ruleMatch, RuleApply ruleApply,
          ComposedRuleElementMatch containerMatch, RutaRuleElement sideStepOrigin,
          RutaStream stream, InferenceCrowd crowd) {
    RutaLiteralMatcher matcher = (RutaLiteralMatcher) nextElement.getMatcher();
    StringExpression expression = matcher.getExpression();
    String stringValue = expression.getStringValue(parent);
    AnnotationFS documentAnnotation = stream.getDocumentAnnotation();
    int delta = documentAnnotation.getBegin();
    String document = documentAnnotation.getCoveredText();
    int pointer = 0;
    if(annotation != null) {
      pointer = annotation.getEnd() - delta;
    }
    int indexOf = 0;
    boolean doneHere = false;
    // TODO matching direction not included in document.indexOf(). Need another method here
    while (!doneHere && (indexOf = document.indexOf(stringValue, pointer)) < document.length()) {
      if (indexOf < 0) {
        // can't match, the next next element will see it.
        nextElement.continueMatch(after, annotation, ruleMatch, ruleApply, containerMatch,
                sideStepOrigin, null, stream, crowd);
        doneHere = true;
        break;
      }
      RutaBasic anchor = stream.getAnchor(after, indexOf+delta);
      RutaBasic endAnchor = stream.getAnchor(!after, indexOf+delta);
      ComposedRuleElementMatch extendedContainerMatch = containerMatch.copy();
      RuleMatch extendedMatch = ruleMatch.copy(extendedContainerMatch);
      AnnotationFS coveredByWildCard = getCoveredByWildCard(after, annotation, anchor, stream);
      doMatch(coveredByWildCard, extendedMatch, extendedContainerMatch, annotation == null, stream,
              crowd);
      if (extendedMatch.matched()) {
        nextElement.continueMatch(after, endAnchor, extendedMatch, ruleApply,
                extendedContainerMatch, sideStepOrigin, nextElement, stream, crowd);
        List<RuleElementMatch> nextList = extendedContainerMatch.getInnerMatches().get(nextElement);
        if (nextList == null || nextList.isEmpty()) {
          pointer = getNextPointer(after, anchor);
        } else {
          doneHere = true;
        }
      } else {
        pointer = getNextPointer(after, anchor);
      }
    }
  }

  private int getNextPointer(boolean after, AnnotationFS anchor) {
    if (after) {
      return anchor.getEnd();
    } else {
      return anchor.getBegin();
    }
  }

  private FSIterator<AnnotationFS> getIteratorForDisjunctive(CAS cas, List<Type> types,
          boolean after, AnnotationFS annotation, RutaStream stream) {
    ConstraintFactory cf = cas.getConstraintFactory();
    FSTypeConstraint typeConstraint = cf.createTypeConstraint();
    for (Type each : types) {
      typeConstraint.add(each);
    }
    FSIterator<AnnotationFS> windowIt = cas.getAnnotationIndex().subiterator(
            stream.getDocumentAnnotation());
    FSIterator<AnnotationFS> iterator = cas.createFilteredIterator(windowIt, typeConstraint);
    if (annotation != null) {
      iterator.moveTo(annotation);
      if (!after) {
        iterator.moveToPrevious();
      }
    } else {
      if (after) {
        iterator.moveToFirst();
      } else {
        iterator.moveToLast();
      }
    }

    return iterator;
  }

  private void moveOn(boolean after, FSIterator<AnnotationFS> iterator) {
    if (after) {
      iterator.moveToNext();
    } else {
      iterator.moveToPrevious();
    }
  }

  private AnnotationFS getCoveredByWildCard(boolean after, AnnotationFS last,
          AnnotationFS next, RutaStream stream) {
    CAS cas = stream.getCas();
    Type type = cas.getAnnotationType();
    AnnotationFS documentAnnotation = stream.getDocumentAnnotation();

    // order like in the index
    AnnotationFS before = last;
    AnnotationFS later = next;
    if(!after) {
      before = next;
      later = last;
    }
   
    // without any information, match on everything
    int begin = documentAnnotation.getBegin();
    int end = documentAnnotation.getEnd();
   
    // limit offsets
    if(before != null) {
      begin = before.getEnd();
    }
    if(later != null) {
      end = later.getBegin();
    }
   
    AnnotationFS afs = cas.createAnnotation(type, begin, end);
   
    return afs;
  }

  private void doMatch(AnnotationFS annotation, RuleMatch ruleMatch,
          ComposedRuleElementMatch containerMatch, boolean ruleAnchor, RutaStream stream,
          InferenceCrowd crowd) {
    RuleElementMatch result = new RuleElementMatch(this, containerMatch);
    result.setRuleAnchor(ruleAnchor);
    List<EvaluatedCondition> evaluatedConditions = new ArrayList<EvaluatedCondition>(
            conditions.size());
    boolean base = true;
    List<AnnotationFS> textsMatched = new ArrayList<AnnotationFS>(1);
    if (base) {
      for (AbstractRutaCondition condition : conditions) {
        crowd.beginVisit(condition, null);
        EvaluatedCondition eval = condition.eval(annotation, this, stream, crowd);
        crowd.endVisit(condition, null);
        evaluatedConditions.add(eval);
      }
    }
    if (annotation != null) {
      textsMatched.add(annotation);
    }
    result.setMatchInfo(base, textsMatched, evaluatedConditions);
    ruleMatch.setMatched(ruleMatch.matched() && result.matched());
    List<RuleElementMatch> rems = new ArrayList<RuleElementMatch>();
    rems.add(result);
    ruleMatch.processMatchInfo(this, rems, stream);
  }

  public void continueOwnMatch(boolean after, AnnotationFS annotation, RuleMatch ruleMatch,
          RuleApply ruleApply, ComposedRuleElementMatch containerMatch,
          RutaRuleElement sideStepOrigin, RuleElement entryPoint, RutaStream stream,
          InferenceCrowd crowd) {
    // won't happen
  }

  public Collection<AnnotationFS> getAnchors(RutaStream symbolStream) {
    // shouldn't happen
    // really? what about anchoring at start?
    return Collections.emptyList();
  }

  public int estimateAnchors(RutaStream stream) {
    return Integer.MAX_VALUE;
  }

  public String toString() {
    return "#" + (conditions.isEmpty() ? "" : "(" + conditions.toString() + ")" + "\\n")
            + (actions.isEmpty() ? "" : "{" + actions.toString() + "}");
  }

}
TOP

Related Classes of org.apache.uima.ruta.rule.WildCardRuleElement

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.