/*
 * 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;

import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeMap;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.uima.cas.BooleanArrayFS;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.CASException;
import org.apache.uima.cas.ConstraintFactory;
import org.apache.uima.cas.DoubleArrayFS;
import org.apache.uima.cas.FSIndex;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.cas.FSMatchConstraint;
import org.apache.uima.cas.Feature;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.FloatArrayFS;
import org.apache.uima.cas.IntArrayFS;
import org.apache.uima.cas.StringArrayFS;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.cas.impl.FSIteratorImplBase;
import org.apache.uima.cas.impl.TypeImpl;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.cas.text.AnnotationIndex;
import org.apache.uima.fit.util.CasUtil;
import org.apache.uima.fit.util.FSCollectionFactory;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.tcas.Annotation;
import org.apache.uima.ruta.block.RutaBlock;
import org.apache.uima.ruta.engine.RutaEngine;
import org.apache.uima.ruta.expression.AnnotationTypeExpression;
import org.apache.uima.ruta.expression.IRutaExpression;
import org.apache.uima.ruta.expression.annotation.IAnnotationExpression;
import org.apache.uima.ruta.expression.annotation.IAnnotationListExpression;
import org.apache.uima.ruta.expression.bool.IBooleanExpression;
import org.apache.uima.ruta.expression.bool.IBooleanListExpression;
import org.apache.uima.ruta.expression.feature.CoveredTextFeature;
import org.apache.uima.ruta.expression.feature.FeatureExpression;
import org.apache.uima.ruta.expression.feature.FeatureMatchExpression;
import org.apache.uima.ruta.expression.feature.GenericFeatureExpression;
import org.apache.uima.ruta.expression.feature.LazyFeature;
import org.apache.uima.ruta.expression.feature.SimpleFeatureExpression;
import org.apache.uima.ruta.expression.feature.TypeFeature;
import org.apache.uima.ruta.expression.number.INumberExpression;
import org.apache.uima.ruta.expression.number.INumberListExpression;
import org.apache.uima.ruta.expression.string.IStringExpression;
import org.apache.uima.ruta.expression.string.IStringListExpression;
import org.apache.uima.ruta.expression.type.ITypeExpression;
import org.apache.uima.ruta.expression.type.ITypeListExpression;
import org.apache.uima.ruta.rule.AbstractRule;
import org.apache.uima.ruta.rule.AbstractRuleMatch;
import org.apache.uima.ruta.rule.MatchContext;
import org.apache.uima.ruta.type.RutaAnnotation;
import org.apache.uima.ruta.type.RutaBasic;
import org.apache.uima.ruta.type.RutaOptional;
import org.apache.uima.ruta.utils.RutaListUtils;
import org.apache.uima.ruta.utils.UIMAUtils;
import org.apache.uima.ruta.visitor.InferenceCrowd;

public class RutaStream extends FSIteratorImplBase<AnnotationFS> {

  private final CAS cas;

  private FSIterator<AnnotationFS> basicIt;

  private FSIterator<AnnotationFS> currentIt;

  private AnnotationFS documentAnnotation;

  private Type documentAnnotationType;

  private Type basicType;

  private NavigableMap<Integer, RutaBasic> beginAnchors = new TreeMap<>();

  private NavigableMap<Integer, RutaBasic> endAnchors = new TreeMap<>();

  private FilterManager filter;

  private boolean dynamicAnchoring;

  private double indexPenalty = 0;

  private double anchoringFactor;

  private boolean lowMemoryProfile;

  private boolean simpleGreedyForComposed;

  private InferenceCrowd crowd;

  private TypeUsageInformation typeUsage;

  private Boolean greedyRuleElement;

  private Boolean greedyRule;

  private boolean onlyOnce = false;

  private Annotation documentBeginAnchor;

  private Annotation documentEndAnchor;

  private boolean emptyIsInvisible;

  private long maxRuleMatches;

  private long maxRuleElementMatches;

  public RutaStream(CAS cas, Type basicType, FilterManager filter, boolean lowMemoryProfile,
          boolean simpleGreedyForComposed, boolean emptyIsInvisible, TypeUsageInformation typeUsage,
          InferenceCrowd crowd) {
    super();
    this.cas = cas;
    this.filter = filter;
    this.basicType = basicType;
    this.lowMemoryProfile = lowMemoryProfile;
    this.simpleGreedyForComposed = simpleGreedyForComposed;
    this.emptyIsInvisible = emptyIsInvisible;
    this.typeUsage = typeUsage;
    this.crowd = crowd;
    AnnotationFS additionalWindow = filter.getWindowAnnotation();
    updateIterators(cas, basicType, filter, additionalWindow);
    // really an if? sub it of basic should fix this
    if (additionalWindow == null) {
      documentAnnotation = cas.getDocumentAnnotation();
      documentAnnotationType = getCas().getDocumentAnnotation().getType();
      basicIt.moveToFirst();
      documentBeginAnchor = new RutaOptional(getJCas(), 0, 0);
      documentEndAnchor = new RutaOptional(getJCas(), documentAnnotation.getEnd(),
              documentAnnotation.getEnd());
    } else {
      documentAnnotation = additionalWindow;
      documentAnnotationType = filter.getWindowType();
    }
  }

  protected RutaStream(CAS cas, Type basicType, NavigableMap<Integer, RutaBasic> beginAnchors,
          NavigableMap<Integer, RutaBasic> endAnchors, FilterManager filter,
          boolean lowMemoryProfile, boolean simpleGreedyForComposed, boolean emptyIsInvisible,
          TypeUsageInformation typeUsage, InferenceCrowd crowd) {
    super();
    this.cas = cas;
    this.beginAnchors = beginAnchors;
    this.endAnchors = endAnchors;
    this.filter = filter;
    this.basicType = basicType;
    this.lowMemoryProfile = lowMemoryProfile;
    this.simpleGreedyForComposed = simpleGreedyForComposed;
    this.emptyIsInvisible = emptyIsInvisible;
    this.typeUsage = typeUsage;
    this.crowd = crowd;
    AnnotationFS additionalWindow = filter.getWindowAnnotation();
    updateIterators(cas, basicType, filter, additionalWindow);
    // really an if? sub it of basic should fix this
    if (additionalWindow == null) {
      documentAnnotation = cas.getDocumentAnnotation();
      documentAnnotationType = getCas().getDocumentAnnotation().getType();
      basicIt.moveToFirst();
    } else {
      documentAnnotation = additionalWindow;
      documentAnnotationType = filter.getWindowType();
    }
  }

  private void updateIterators(AnnotationFS additionalWindow) {
    updateIterators(cas, basicType, filter, additionalWindow);
  }

  private void updateIterators(CAS cas, Type basicType, FilterManager filter,
          AnnotationFS additionalWindow) {
    if (additionalWindow != null) {
      basicIt = cas.getAnnotationIndex(basicType).subiterator(additionalWindow);
    } else {
      basicIt = cas.getAnnotationIndex(basicType).iterator();
    }
    currentIt = filter.createFilteredIterator(cas, basicType);
  }

  @Deprecated
  public void initalizeBasics(String[] reindexOnly, boolean reindexOnlyMentionedTypes) {
    RutaIndexingConfiguration config = new RutaIndexingConfiguration();
    config.setReindexOnly(reindexOnly);
    config.setReindexOnlyMentionedTypes(reindexOnlyMentionedTypes);
    config.setReindexUpdateMode(ReindexUpdateMode.ADDITIVE);
    initalizeBasics(config);
  }

  public void initalizeBasics(RutaIndexingConfiguration config) {

    AnnotationIndex<AnnotationFS> basicIndex = cas.getAnnotationIndex(basicType);
    boolean basicsAvailable = basicIndex.size() != 0;

    if (config.getReindexUpdateMode() == ReindexUpdateMode.NONE && basicsAvailable) {

      // there are already some ruta basics and we do not want to update anything, since we know we
      // do not need to. Only set internal maps
      initializeInternalAnchorMaps(basicIndex);
      return;
    }

    if (!basicsAvailable) {
      // indexing
      createBasics(config);
    } else {
      // reindexing
      updateBasics(basicIndex, config);
    }
  }

  private void createBasics(RutaIndexingConfiguration config) {
    TypeSystem typeSystem = cas.getTypeSystem();
    Collection<Type> indexTypes;
    if (config.isIndexOnlyMentionedTypes()) {
      indexTypes = convertNamesToTypes(typeUsage.getUsedTypes().toArray(new String[0]), typeSystem);
    } else {
      indexTypes = convertNamesToTypes(config.getIndexOnly(), typeSystem);
    }
    Collection<Type> indexSkipTypes = convertNamesToTypes(config.getIndexSkipTypes(), typeSystem);
    Collection<Type> indexParentTypes = removeSubsumedTypes(indexTypes, typeSystem);
    Collection<Type> allIndexTypes = expandToAllSubtypes(indexTypes, indexSkipTypes, typeSystem);

    List<FSIndex<AnnotationFS>> relevantIndexes = getRelevantIndexes(typeSystem, indexParentTypes,
            indexSkipTypes);
    createBasics(relevantIndexes, allIndexTypes);
  }

  private void updateBasics(AnnotationIndex<AnnotationFS> basicIndex,
          RutaIndexingConfiguration config) {
    TypeSystem typeSystem = cas.getTypeSystem();
    Collection<Type> reindexTypes;
    if (config.isReindexOnlyMentionedTypes()) {
      reindexTypes = convertNamesToTypes(typeUsage.getUsedTypes().toArray(new String[0]),
              typeSystem);
    } else {
      reindexTypes = convertNamesToTypes(config.getReindexOnly(), typeSystem);
    }
    Collection<Type> reindexSkipTypes = convertNamesToTypes(config.getReindexSkipTypes(),
            typeSystem);
    Collection<Type> reindexParentTypes = removeSubsumedTypes(reindexTypes, typeSystem);
    Collection<Type> allReindexTypes = expandToAllSubtypes(reindexTypes, reindexSkipTypes,
            typeSystem);
    List<FSIndex<AnnotationFS>> relevantIndexes = getRelevantIndexes(typeSystem, reindexParentTypes,
            reindexSkipTypes);
    updateBasics(basicIndex, relevantIndexes, allReindexTypes, config.getReindexUpdateMode());

  }

  private List<FSIndex<AnnotationFS>> getRelevantIndexes(TypeSystem typeSystem,
          Collection<Type> rootReindexTypeList, Collection<Type> skipTypeList) {
    List<FSIndex<AnnotationFS>> relevantIndexes = new ArrayList<>();

    for (Type type : rootReindexTypeList) {

      if (skipTypeForIndexing(type, skipTypeList, typeSystem)) {
        continue;
      }

      if (StringUtils.equals(type.getName(), CAS.TYPE_NAME_ANNOTATION)) {
        relevantIndexes.add(cas.getAnnotationIndex().withSnapshotIterators());
      } else {
        relevantIndexes.add(cas.getAnnotationIndex(type).withSnapshotIterators());
      }
    }
    return relevantIndexes;
  }

  private boolean skipTypeForIndexing(Type type, Collection<Type> skipTypeList,
          TypeSystem typeSystem) {
    // collect no ruta basics
    if (typeSystem.subsumes(basicType, type)) {
      return true;
    }
    if (skipTypeList != null) {
      if (skipTypeList.contains(type)) {
        return true;
      } else {
        for (Type skipType : skipTypeList) {
          if (typeSystem.subsumes(skipType, type)) {
            return true;
          }
        }
      }
    }
    return false;
  }

  private void createBasics(List<FSIndex<AnnotationFS>> relevantIndexes,
          Collection<Type> allIndexTypes) {

    List<Integer> anchors = getSortedUniqueAnchors(relevantIndexes);
    createBasicsForAnchors(anchors);

    // add all annotations
    for (FSIndex<AnnotationFS> index : relevantIndexes) {
      for (AnnotationFS a : index) {
        // consider skipped types
        if (allIndexTypes == null || allIndexTypes.contains(a.getType())) {
          addAnnotation(a, false, false, null);
        }
      }
    }

    updateIterators(documentAnnotation);
  }

  private void createBasicsForAnchors(List<Integer> anchors) {
    if (anchors.size() == 0) {
      // empty document
      createRutaBasic(0, 0);
    } else if (anchors.size() == 1) {
      Integer first = anchors.get(0);
      createRutaBasic(first, first);
    } else {
      for (int i = 0; i < anchors.size() - 1; i++) {
        Integer first = anchors.get(i);
        Integer second = anchors.get(i + 1);
        if (first < second) { // not really needed
          createRutaBasic(first, second);
        }
      }
    }
  }

  private List<Integer> getSortedUniqueAnchors(List<FSIndex<AnnotationFS>> relevantIndexes) {
    Set<Integer> anchorSet = new HashSet<>();
    for (FSIndex<AnnotationFS> annotationIndex : relevantIndexes) {
      for (AnnotationFS a : annotationIndex) {
        anchorSet.add(a.getBegin());
        anchorSet.add(a.getEnd());
      }
    }
    List<Integer> anchors = new ArrayList<>(anchorSet);
    Collections.sort(anchors);
    return anchors;
  }

  private void updateBasics(AnnotationIndex<AnnotationFS> basicIndex,
          List<FSIndex<AnnotationFS>> relevantIndexes, Collection<Type> allReindexTypes,
          ReindexUpdateMode indexUpdateMode) {

    initializeInternalAnchorMaps(basicIndex);

    updateRutaBasicMemoryProfile(basicIndex);

    switch (indexUpdateMode) {
      case COMPLETE:
        updateBasicsComplete(basicIndex, relevantIndexes, allReindexTypes);
        break;
      case ADDITIVE:
        updateBasicsAdditive(basicIndex, relevantIndexes);
        break;
      case SAFE_ADDITIVE:
        updateBasicsSafeAdditive(basicIndex, relevantIndexes, allReindexTypes);
        break;
      case NONE:
        // do nothing
        break;

      default:
        throw new IllegalArgumentException(
                "The given IndexUpdateMode is not supported: " + indexUpdateMode);
    }

  }

  private void updateBasicsComplete(AnnotationIndex<AnnotationFS> basicIndex,
          List<FSIndex<AnnotationFS>> relevantIndexes, Collection<Type> completeReindexTypeList) {

    // cleanup index info for given types
    for (AnnotationFS each : basicIndex) {
      RutaBasic rutaBasic = (RutaBasic) each;
      for (Type type : completeReindexTypeList) {
        int code = ((TypeImpl) type).getCode();
        rutaBasic.getPartOf()[code] = 0;
        rutaBasic.getBeginMap()[code] = null;
        rutaBasic.getEndMap()[code] = null;
      }
    }

    // add all annotations
    for (FSIndex<AnnotationFS> index : relevantIndexes) {
      for (AnnotationFS a : index) {
        // consider skipped types
        if (completeReindexTypeList.contains(a.getType())) {
          addAnnotation(a, false, false, null);
        }
      }
    }
  }

  private void updateBasicsAdditive(AnnotationIndex<AnnotationFS> basicIndex,
          List<FSIndex<AnnotationFS>> relevantIndexes) {

    // adds annotation only if not already known and included
    for (FSIndex<AnnotationFS> annotationIndex : relevantIndexes) {
      for (AnnotationFS a : annotationIndex) {
        Type type = a.getType();
        RutaBasic beginAnchor = getBeginAnchor(a.getBegin());
        RutaBasic endAnchor = getEndAnchor(a.getEnd());
        boolean shouldBeAdded = false;
        if (beginAnchor == null || endAnchor == null) {
          shouldBeAdded = true;
        } else {
          Collection<AnnotationFS> set = beginAnchor.getBeginAnchors(type);
          if (!set.contains(a)) {
            shouldBeAdded = true;
          }
        }
        if (shouldBeAdded) {
          addAnnotation(a, false, false, null);
        }
      }
    }
  }

  private void updateBasicsSafeAdditive(AnnotationIndex<AnnotationFS> basicIndex,
          List<FSIndex<AnnotationFS>> relevantIndexes, Collection<Type> completeReindexTypeList) {

    // search for removed annotations, and remove them
    for (AnnotationFS each : basicIndex) {
      RutaBasic rutaBasic = (RutaBasic) each;
      for (Type type : completeReindexTypeList) {
        // it's sufficient to check begin anchors, end should be consistent
        Collection<AnnotationFS> beginAnchors = rutaBasic.getBeginAnchors(type);
        Collection<AnnotationFS> toRemove = new ArrayList<>();
        for (AnnotationFS annotationAtAnchor : beginAnchors) {
          if (!annotationAtAnchor.getCAS().getAnnotationIndex().contains(annotationAtAnchor)) {
            // not in index? -> was removed
            toRemove.add(annotationAtAnchor);
          }
        }
        toRemove.forEach(a -> removeAnnotation(a));
      }
    }

    updateBasicsAdditive(basicIndex, relevantIndexes);
  }

  private void initializeInternalAnchorMaps(AnnotationIndex<AnnotationFS> basicIndex) {
    for (AnnotationFS e : basicIndex) {
      beginAnchors.put(e.getBegin(), (RutaBasic) e);
      endAnchors.put(e.getEnd(), (RutaBasic) e);
    }
  }

  private void updateRutaBasicMemoryProfile(AnnotationIndex<AnnotationFS> basicIndex) {
    RutaBasic firstBasic = (RutaBasic) basicIndex.iterator().get();
    if (firstBasic.isLowMemoryProfile() != lowMemoryProfile) {
      for (AnnotationFS each : basicIndex) {
        RutaBasic eachBasic = (RutaBasic) each;
        eachBasic.setLowMemoryProfile(lowMemoryProfile);
      }
    }
  }

  private RutaBasic createRutaBasic(int begin, int end) {
    RutaBasic newTMB = new RutaBasic(getJCas(), begin, end);
    newTMB.setLowMemoryProfile(lowMemoryProfile);
    beginAnchors.put(begin, newTMB);
    endAnchors.put(end, newTMB);
    cas.addFsToIndexes(newTMB);
    return newTMB;
  }

  public void addAnnotation(AnnotationFS annotation, boolean addToIndex,
          AbstractRuleMatch<? extends AbstractRule> creator) {
    addAnnotation(annotation, addToIndex, true, creator);
  }

  public void addAnnotation(AnnotationFS annotation,
          AbstractRuleMatch<? extends AbstractRule> creator) {
    addAnnotation(annotation, false, true, creator);
  }

  public void addAnnotation(AnnotationFS annotation, boolean addToIndex, boolean updateInternal,
          AbstractRuleMatch<? extends AbstractRule> creator) {
    Type type = annotation.getType();
    // no internal indexing for basics themselves or for zero-length annotations, exception for
    // DocumentAnnotation
    if (type.equals(basicType) || (annotation.getBegin() >= annotation.getEnd()
            && !annotation.equals(cas.getDocumentAnnotation()))) {
      return;
    }
    if (indexType(annotation.getType())) {
      boolean modified = checkSpan(annotation);
      if (modified && updateInternal) {
        updateIterators(filter.getWindowAnnotation());
      }
      RutaBasic beginAnchor = getBeginAnchor(annotation.getBegin());
      RutaBasic endAnchor = getEndAnchor(annotation.getEnd());
      if (beginAnchor != null) {
        beginAnchor.addBegin(annotation, type);
      }
      if (endAnchor != null) {
        endAnchor.addEnd(annotation, type);
      }
      Collection<RutaBasic> basicAnnotationsInWindow = getAllBasicsInWindow(annotation);
      for (RutaBasic basic : basicAnnotationsInWindow) {
        basic.addPartOf(type);
      }
    }
    if (addToIndex) {
      cas.addFsToIndexes(annotation);
    }
    crowd.annotationAdded(annotation, creator);
  }

  private boolean indexType(Type type) {
    if (typeUsage != null) {
      boolean contains = typeUsage.getUsedTypesWithSubTypes().contains(type.getName());
      return contains;
    }
    return true;
  }

  private boolean checkSpan(AnnotationFS annotation) {
    boolean result = false;
    int begin = annotation.getBegin();
    int end = annotation.getEnd();
    RutaBasic beginAnchor = getBeginAnchor(begin);
    RutaBasic endAnchor = getEndAnchor(end);
    if (beginAnchor != null && endAnchor != null) {
      result = false;
    } else {
      if (beginAnchor == null) {
        result |= checkAnchor(begin);
      }
      if (endAnchor == null) {
        result |= checkAnchor(end);
      }
    }
    return result;
  }

  private boolean checkAnchor(int anchor) {
    Entry<Integer, RutaBasic> floorEntry = endAnchors.floorEntry(anchor);
    if (floorEntry == null) {
      floorEntry = beginAnchors.floorEntry(anchor);
    }
    Entry<Integer, RutaBasic> ceilingEntry = endAnchors.ceilingEntry(anchor);
    if (floorEntry != null && ceilingEntry != null) {
      RutaBasic floor = floorEntry.getValue();
      RutaBasic ceiling = ceilingEntry.getValue();
      RutaBasic toSplit = null;
      if (floor.getEnd() > anchor) {
        toSplit = floor;
      } else {
        toSplit = ceiling;
      }
      int newEnd = toSplit.getEnd();
      if (newEnd == anchor) {
        return false;
      }
      cas.removeFsFromIndexes(toSplit);
      toSplit.setEnd(anchor);
      RutaBasic newRB = new RutaBasic(getJCas(), anchor, newEnd);
      newRB.setLowMemoryProfile(lowMemoryProfile);
      newRB.setEndMap(toSplit.getEndMap().clone());
      newRB.setPartOf(toSplit.getPartOf().clone());
      toSplit.clearEndMap();
      cas.addFsToIndexes(toSplit);
      cas.addFsToIndexes(newRB);
      beginAnchors.put(floor.getBegin(), floor);
      beginAnchors.put(newRB.getBegin(), newRB);
      beginAnchors.put(ceiling.getBegin(), ceiling);
      endAnchors.put(floor.getEnd(), floor);
      endAnchors.put(newRB.getEnd(), newRB);
      endAnchors.put(ceiling.getEnd(), ceiling);
      return true;
    } else {
      // TODO this should never happen! test it!
    }
    return false;
  }

  public void removeAnnotation(AnnotationFS annotationFS) {
    removeAnnotation(annotationFS, annotationFS.getType());
  }

  public void removeAnnotation(AnnotationFS annotation, Type type) {
    if (type.getName().equals(CAS.TYPE_NAME_DOCUMENT_ANNOTATION)) {
      // do not remove DocumentAnnotation
      return;
    }
    Collection<RutaBasic> basicAnnotationsInWindow = getAllBasicsInWindow(annotation);
    for (RutaBasic basic : basicAnnotationsInWindow) {
      basic.removePartOf(type);
    }
    Type parent = type;
    RutaBasic beginAnchor = getBeginAnchor(annotation.getBegin());
    RutaBasic endAnchor = getEndAnchor(annotation.getEnd());
    if (beginAnchor != null) {
      beginAnchor.removeBegin(annotation, parent);
    }
    if (endAnchor != null) {
      endAnchor.removeEnd(annotation, parent);
    }
    if (!(annotation instanceof RutaBasic)) {
      cas.removeFsFromIndexes(annotation);
    }

  }

  public FSIterator<AnnotationFS> getFilteredBasicIterator(FSMatchConstraint constraint) {
    ConstraintFactory cf = cas.getConstraintFactory();
    FSMatchConstraint matchConstraint = cf.and(constraint, filter.getDefaultConstraint());
    return cas.createFilteredIterator(basicIt, matchConstraint);
  }

  public RutaStream getWindowStream(AnnotationFS windowAnnotation, Type windowType) {
    if (windowAnnotation.getBegin() == documentAnnotation.getBegin()
            && windowAnnotation.getEnd() == documentAnnotation.getEnd()) {
      return this;
    }

    FilterManager filterManager = new FilterManager(filter.getDefaultFilterTypes(),
            filter.getCurrentFilterTypes(), filter.getCurrentRetainTypes(), windowAnnotation,
            windowType, emptyIsInvisible, cas);

    // NavigableMap<Integer, RutaBasic> newBeginAnchors = beginAnchors.subMap(
    // windowAnnotation.getBegin(), true, windowAnnotation.getEnd(), false);
    // NavigableMap<Integer, RutaBasic> newEndAnchors =
    // endAnchors.subMap(windowAnnotation.getBegin(),
    // false, windowAnnotation.getEnd(), true);

    RutaStream stream = new RutaStream(cas, basicType, beginAnchors, endAnchors, filterManager,
            lowMemoryProfile, simpleGreedyForComposed, emptyIsInvisible, typeUsage, crowd);
    stream.setDynamicAnchoring(dynamicAnchoring);
    stream.setGreedyRuleElement(greedyRuleElement);
    stream.setGreedyRule(greedyRule);
    stream.setMaxRuleMatches(maxRuleMatches);
    stream.setMaxRuleElementMatches(maxRuleElementMatches);
    return stream;
  }

  @Override
  public FSIterator<AnnotationFS> copy() {
    RutaStream stream = new RutaStream(cas, basicType, beginAnchors, endAnchors, filter,
            lowMemoryProfile, simpleGreedyForComposed, emptyIsInvisible, typeUsage, crowd);
    stream.setDynamicAnchoring(dynamicAnchoring);
    stream.setGreedyRuleElement(greedyRuleElement);
    stream.setGreedyRule(greedyRule);
    stream.setMaxRuleMatches(maxRuleMatches);
    stream.setMaxRuleElementMatches(maxRuleElementMatches);
    return stream;
  }

  @Override
  public AnnotationFS get() throws NoSuchElementException {
    return currentIt.get();
  }

  @Override
  public boolean isValid() {
    return currentIt.isValid();
  }

  @Override
  public void moveTo(FeatureStructure fs) {
    try {
      currentIt.moveTo(fs);
    } catch (Exception e) {
      // e.printStackTrace();
    }
  }

  @Override
  public void moveToFirst() {
    currentIt.moveToFirst();
  }

  @Override
  public void moveToLast() {
    currentIt.moveToLast();
  }

  @Override
  public void moveToNext() {
    currentIt.moveToNext();
  }

  @Override
  public void moveToPrevious() {
    currentIt.moveToPrevious();
  }

  public List<AnnotationFS> getOverappingAnnotations(AnnotationFS window, Type type) {
    List<AnnotationFS> result = new ArrayList<>();
    AnnotationFS newWindow = cas.createAnnotation(type, window.getBegin(), window.getEnd() - 1);
    FSIterator<AnnotationFS> iterator = cas.getAnnotationIndex(type).iterator(newWindow);
    if (!iterator.isValid()) {
      iterator.moveToLast();
    }
    while (iterator.isValid()) {
      FeatureStructure fs = iterator.get();
      if (fs instanceof AnnotationFS) {
        AnnotationFS a = (AnnotationFS) fs;
        if (a.getEnd() >= window.getEnd() && a.getBegin() <= window.getBegin()) {
          result.add(a);
        }
      }
      iterator.moveToPrevious();
    }
    return result;
  }

  public List<Annotation> getAnnotationsFollowing(Annotation annotation) {
    List<Annotation> result = new ArrayList<>();
    moveTo(annotation);
    while (currentIt.isValid()) {
      currentIt.moveToNext();
      if (currentIt.isValid()) {
        Annotation nextAnnotation = (Annotation) currentIt.get();
        if (nextAnnotation.getBegin() == annotation.getEnd()) {
          result.add(nextAnnotation);
        } else if (nextAnnotation.getBegin() >= annotation.getEnd()) {
          break;
        }
      }
    }
    return result;
  }

  public CAS getCas() {
    return cas;
  }

  public JCas getJCas() {
    try {
      return cas.getJCas();
    } catch (CASException e) {
      // e.printStackTrace();
    }
    return null;
  }

  public List<AnnotationFS> getAllofType(Type type) {
    List<AnnotationFS> result = new ArrayList<>();
    FSIterator<AnnotationFS> iterator = cas.getAnnotationIndex(type).iterator();
    while (iterator.isValid()) {
      FeatureStructure featureStructure = iterator.get();
      result.add((AnnotationFS) featureStructure);
      iterator.moveToNext();
    }
    return result;
  }

  public List<AnnotationFS> getAnnotationsInWindow(AnnotationFS windowAnnotation, Type type) {

    if (windowAnnotation == null || type == null) {
      return Collections.emptyList();
    }
    TypeSystem typeSystem = getCas().getTypeSystem();
    List<AnnotationFS> result = new ArrayList<>();
    if (typeSystem.subsumes(type, windowAnnotation.getType())) {
      result.add(windowAnnotation);
    }
    result.addAll(CasUtil.selectCovered(cas, type, windowAnnotation));
    return result;
  }

  public Collection<RutaBasic> getAllBasicsInWindow(AnnotationFS windowAnnotation) {
    if (windowAnnotation.getBegin() >= windowAnnotation.getEnd()) {
      return emptySet();
    }

    RutaBasic beginAnchor = getBeginAnchor(windowAnnotation.getBegin());
    if (beginAnchor != null && beginAnchor.getEnd() == windowAnnotation.getEnd()) {
      return asList(beginAnchor);
    }

    if (windowAnnotation.getEnd() == cas.getDocumentAnnotation().getEnd()
            && windowAnnotation.getBegin() == 0) {
      return beginAnchors.values();
    }

    return beginAnchors.subMap(windowAnnotation.getBegin(), true, windowAnnotation.getEnd(), false)
            .values();
  }

  public RutaBasic getBasicNextTo(boolean before, AnnotationFS annotation) {

    if (annotation == null) {
      return null;
    }

    if (before) {

      RutaBasic pointer = endAnchors.get(annotation.getBegin());
      while (pointer != null && pointer.getBegin() >= documentAnnotation.getBegin()) {

        if (isVisible(pointer)) {
          return pointer;
        }

        Entry<Integer, RutaBasic> lowerEntry = endAnchors.lowerEntry(pointer.getEnd());
        if (lowerEntry != null) {
          pointer = lowerEntry.getValue();
        } else {
          pointer = null;
        }
      }

    } else {

      RutaBasic pointer = beginAnchors.get(annotation.getEnd());
      while (pointer != null && pointer.getEnd() <= documentAnnotation.getEnd()) {

        if (isVisible(pointer)) {
          return pointer;
        }

        Entry<Integer, RutaBasic> higherEntry = beginAnchors.higherEntry(pointer.getBegin());
        if (higherEntry != null) {
          pointer = higherEntry.getValue();
        } else {
          pointer = null;
        }
      }
    }
    return null;
  }

  public List<RutaBasic> getBasicsInWindow(AnnotationFS windowAnnotation) {
    List<RutaBasic> result = new ArrayList<>();
    if (windowAnnotation instanceof RutaBasic) {
      result.add((RutaBasic) windowAnnotation);
      return result;
    }
    FSMatchConstraint defaultConstraint = filter.getDefaultConstraint();
    FSIterator<AnnotationFS> iterator = cas.createFilteredIterator(
            cas.getAnnotationIndex(basicType).subiterator(windowAnnotation), defaultConstraint);

    while (iterator.isValid()) {
      result.add((RutaBasic) iterator.get());
      iterator.moveToNext();
    }
    return result;
  }

  public RutaBasic getFirstBasicInWindow(AnnotationFS windowAnnotation) {
    return getFirstBasicInWindow(windowAnnotation, currentIt);
  }

  public RutaBasic getFirstBasicInWindow(AnnotationFS windowAnnotation,
          FSIterator<AnnotationFS> it) {
    if (windowAnnotation instanceof RutaBasic) {
      return (RutaBasic) windowAnnotation;
    }
    it.moveTo(windowAnnotation);
    if (it.isValid()) {
      return (RutaBasic) it.get();
    }
    return null;
  }

  public List<RutaBasic> getAnnotationsOverlappingWindow(AnnotationFS annotation) {
    if (annotation != null) {
      return getBasicsInWindow(annotation);
    } else {
      return new ArrayList<>();
    }
  }

  public FSIterator<AnnotationFS> getUnfilteredBasicIterator() {
    return basicIt;
  }

  public AnnotationFS getDocumentAnnotation() {
    return documentAnnotation;
  }

  public void retainTypes(List<Type> list) {
    filter.retainTypes(list);
    currentIt = filter.createFilteredIterator(cas, basicType);
  }

  public void filterTypes(List<Type> list) {
    filter.filterTypes(list);
    currentIt = filter.createFilteredIterator(cas, basicType);
  }

  public void addFilterTypes(List<Type> types) {
    filter.addFilterTypes(types);
    currentIt = filter.createFilteredIterator(cas, basicType);
  }

  public void addRetainTypes(List<Type> types) {
    filter.addRetainTypes(types);
    currentIt = filter.createFilteredIterator(cas, basicType);
  }

  public void removeFilterTypes(List<Type> types) {
    filter.removeFilterTypes(types);
    currentIt = filter.createFilteredIterator(cas, basicType);
  }

  public void removeRetainTypes(List<Type> types) {
    filter.removeRetainTypes(types);
    currentIt = filter.createFilteredIterator(cas, basicType);
  }

  public FilterManager getFilter() {
    return filter;
  }

  public RutaBasic getFirstBasicOfAll() {
    if (beginAnchors.isEmpty()) {
      return null;
    }
    return beginAnchors.firstEntry().getValue();
  }

  public RutaBasic getLastBasicOfAll() {
    if (endAnchors.isEmpty()) {
      return null;
    }
    return endAnchors.lastEntry().getValue();
  }

  public Type getDocumentAnnotationType() {
    return documentAnnotationType;
  }

  public RutaBasic getNextBasic2(AnnotationFS previous) {
    AnnotationFS pointer = cas.createAnnotation(basicType, previous.getEnd() - 1,
            previous.getEnd());
    currentIt.moveTo(pointer);
    if (currentIt.isValid()) {
      RutaBasic basic = (RutaBasic) currentIt.get();
      return basic;
    }
    return null;
  }

  public long getHistogram(Type type) {
    return cas.getAnnotationIndex(type).size();
  }

  public double getIndexPenalty() {
    return indexPenalty;
  }

  public RutaBasic getEndAnchor(int end) {
    return endAnchors.get(end);
  }

  public RutaBasic getBeginAnchor(int begin) {
    return beginAnchors.get(begin);
  }

  public boolean isDynamicAnchoring() {
    return dynamicAnchoring;
  }

  public void setDynamicAnchoring(boolean dynamicAnchoring) {
    this.dynamicAnchoring = dynamicAnchoring;
  }

  public boolean isGreedyRuleElement() {
    return greedyRuleElement;
  }

  public void setGreedyRuleElement(Boolean greedyAnchoring) {
    greedyRuleElement = greedyAnchoring;
  }

  public boolean isGreedyRule() {
    return greedyRule;
  }

  public void setGreedyRule(Boolean greedyAnchoring) {
    greedyRule = greedyAnchoring;
  }

  public void setIndexPenalty(double indexPenalty) {
    this.indexPenalty = indexPenalty;
  }

  public double getAnchoringFactor() {
    return anchoringFactor;
  }

  public void setAnchoringFactor(double anchoringFactor) {
    this.anchoringFactor = anchoringFactor;
  }

  public boolean isSimpleGreedyForComposed() {
    return simpleGreedyForComposed;
  }

  public void setSimpleGreedyForComposed(boolean simpleGreedyForComposed) {
    this.simpleGreedyForComposed = simpleGreedyForComposed;
  }

  public boolean isGreedyAnchoring() {
    return greedyRule || greedyRuleElement;
  }

  public boolean isOnlyOnce() {
    return onlyOnce;
  }

  public void setOnlyOnce(Boolean onlyOnce) {
    this.onlyOnce = onlyOnce;
  }

  public boolean isVisible(AnnotationFS annotationFS) {
    return isVisible(annotationFS, false);
  }

  public boolean isVisible(AnnotationFS annotationFS, boolean ignoreWindow) {
    if (annotationFS == null) {
      return false;
    }
    if (annotationFS.getBegin() >= annotationFS.getEnd()) {
      return false;
    }

    AnnotationFS windowAnnotation = filter.getWindowAnnotation();
    if (!ignoreWindow && windowAnnotation != null
            && (annotationFS.getBegin() < windowAnnotation.getBegin()
                    || annotationFS.getEnd() > windowAnnotation.getEnd())) {
      return false;
    }
    int begin = annotationFS.getBegin();
    int end = annotationFS.getEnd();
    Set<Type> currentHiddenTypes = filter.getCurrentHiddenTypes();
    RutaBasic beginAnchor = getBeginAnchor(begin);
    if (beginAnchor != null) {
      for (Type type : currentHiddenTypes) {
        boolean partOf = beginAnchor.isPartOf(type);
        if (partOf) {
          return false;
        }
      }
    }
    RutaBasic endAnchor = getEndAnchor(end);
    if (endAnchor != null) {
      for (Type type : currentHiddenTypes) {
        boolean partOf = endAnchor.isPartOf(type);
        if (partOf) {
          return false;
        }
      }
    }
    if (beginAnchor == null && endAnchor == null) {
      // missing segmentation in RutaBasics maybe because of temp annotation?
      Entry<Integer, RutaBasic> floorEntry = beginAnchors.floorEntry(Integer.valueOf(begin));
      Entry<Integer, RutaBasic> ceilingEntry = endAnchors.ceilingEntry(Integer.valueOf(end));
      if (floorEntry != null && ceilingEntry != null) {
        for (Type type : currentHiddenTypes) {
          if (floorEntry.getValue().isPartOf(type) || ceilingEntry.getValue().isPartOf(type)) {
            return false;
          }
        }
      }
    }

    return true;
  }

  public RutaBasic getAnchor(boolean direction, int pointer) {
    if (direction) {
      return getBeginAnchor(pointer);
    } else {
      return getEndAnchor(pointer);
    }
  }

  public RutaBasic getAnchor(boolean direction, AnnotationFS annotation) {
    if (direction) {
      return getEndAnchor(annotation.getEnd());
    } else {
      return getBeginAnchor(annotation.getBegin());
    }
  }

  public Collection<AnnotationFS> getAnnotations(Type type) {

    return getAnnotations(type, filter.getWindowAnnotation());
  }

  public Collection<AnnotationFS> getAnnotations(Type type, AnnotationFS windowAnnotation) {
    Collection<AnnotationFS> result = new LinkedList<>();
    if (windowAnnotation != null
            && (windowAnnotation.getBegin() != cas.getDocumentAnnotation().getBegin()
                    || windowAnnotation.getEnd() != cas.getDocumentAnnotation().getEnd())) {
      AnnotationFS frame = cas.createAnnotation(cas.getTypeSystem().getType(RutaEngine.FRAME_TYPE),
              windowAnnotation.getBegin(), windowAnnotation.getEnd());
      FSIterator<AnnotationFS> subiterator = cas.getAnnotationIndex(type).subiterator(frame);
      while (subiterator.hasNext()) {
        AnnotationFS each = subiterator.next();
        if (isVisible(each)) {
          result.add(each);
        }
      }
    } else {
      AnnotationIndex<AnnotationFS> annotationIndex = cas.getAnnotationIndex(type);
      for (AnnotationFS each : annotationIndex) {
        if (isVisible(each)) {
          result.add(each);
        }
      }
    }
    return result;
  }

  public String getVisibleCoveredText(AnnotationFS annotationFS) {
    StringBuilder result = new StringBuilder();
    List<RutaBasic> basicsInWindow = getBasicsInWindow(annotationFS);
    for (RutaBasic each : basicsInWindow) {
      if (isVisible(each)) {
        result.append(each.getCoveredText());
      }
    }
    return result.toString();
  }

  public void assignFeatureValues(FeatureStructure annotation,
          Map<IStringExpression, IRutaExpression> map, MatchContext context) {
    Type type = annotation.getType();
    Set<Entry<IStringExpression, IRutaExpression>> entrySet = map.entrySet();
    for (Entry<IStringExpression, IRutaExpression> entry : entrySet) {
      IStringExpression key = entry.getKey();
      IRutaExpression value = entry.getValue();
      String featureName = key.getStringValue(context, this);
      Feature feature = type.getFeatureByBaseName(featureName);
      if (feature == null) {
        throw new IllegalArgumentException("Not able to assign feature value for feature '"
                + featureName + "'. Feature is not defined for type '" + type.getName() + "'"
                + " in script " + context.getParent().getName());
      }
      assignFeatureValue(annotation, feature, value, context);
    }
  }

  public void assignFeatureValue(FeatureStructure annotation, Feature feature,
          IRutaExpression value, MatchContext context) {
    if (feature == null || feature instanceof CoveredTextFeature
            || feature instanceof TypeFeature) {
      throw new IllegalArgumentException(
              "Not able to assign feature value (e.g., coveredText, type) in script "
                      + context.getParent().getName());
    }
    if (feature instanceof LazyFeature) {
      LazyFeature lazyFeature = (LazyFeature) feature;
      feature = lazyFeature.initialize(annotation);
    }

    CAS cas = annotation.getCAS();
    TypeSystem typeSystem = cas.getTypeSystem();
    Type range = feature.getRange();
    String rangeName = range.getName();

    if (typeSystem.subsumes(typeSystem.getType(CAS.TYPE_NAME_STRING), range)) {
      if (value instanceof IStringExpression) {
        IStringExpression stringExpr = (IStringExpression) value;
        String string = stringExpr.getStringValue(context, this);
        annotation.setStringValue(feature, string);
      }
    } else if (rangeName.equals(CAS.TYPE_NAME_STRING_ARRAY)) {
      if (value instanceof IStringListExpression) {
        IStringListExpression stringListExpr = (IStringListExpression) value;
        List<String> stringList = stringListExpr.getStringList(context, this);
        StringArrayFS stringArray = FSCollectionFactory.createStringArray(cas, stringList);
        annotation.setFeatureValue(feature, stringArray);
      } else if (value instanceof IStringExpression) {
        IStringExpression stringExpr = (IStringExpression) value;
        String string = stringExpr.getStringValue(context, this);
        StringArrayFS array = FSCollectionFactory.createStringArray(cas, new String[] { string });
        annotation.setFeatureValue(feature, array);
      }
    } else if (rangeName.equals(CAS.TYPE_NAME_INTEGER) || rangeName.equals(CAS.TYPE_NAME_LONG)
            || rangeName.equals(CAS.TYPE_NAME_SHORT) || rangeName.equals(CAS.TYPE_NAME_BYTE)) {
      if (value instanceof INumberExpression) {
        INumberExpression numberExpr = (INumberExpression) value;
        int v = numberExpr.getIntegerValue(context, this);
        if (annotation instanceof AnnotationFS
                && StringUtils.equals(feature.getShortName(), CAS.FEATURE_BASE_NAME_BEGIN)) {
          changeBegin((AnnotationFS) annotation, v, context.getRuleMatch());
        } else if (annotation instanceof AnnotationFS
                && StringUtils.equals(feature.getShortName(), CAS.FEATURE_BASE_NAME_END)) {
          changeEnd((AnnotationFS) annotation, v, context.getRuleMatch());
        } else {
          annotation.setIntValue(feature, v);
        }
      }
    } else if (rangeName.equals(CAS.TYPE_NAME_INTEGER_ARRAY)) {
      if (value instanceof INumberExpression) {
        INumberExpression numberExpr = (INumberExpression) value;
        int v = numberExpr.getIntegerValue(context, this);
        IntArrayFS array = FSCollectionFactory.createIntArray(cas, new int[] { v });
        annotation.setFeatureValue(feature, array);
      } else if (value instanceof INumberListExpression) {
        INumberListExpression expr = (INumberListExpression) value;
        List<Number> list = expr.getNumberList(context, this);
        IntArrayFS array = FSCollectionFactory.createIntArray(cas, RutaListUtils.toIntArray(list));
        annotation.setFeatureValue(feature, array);
      }
    } else if (rangeName.equals(CAS.TYPE_NAME_DOUBLE)) {
      if (value instanceof INumberExpression) {
        INumberExpression numberExpr = (INumberExpression) value;
        double v = numberExpr.getDoubleValue(context, this);
        annotation.setDoubleValue(feature, v);
      }
    } else if (rangeName.equals(CAS.TYPE_NAME_DOUBLE_ARRAY)) {
      if (value instanceof INumberExpression) {
        INumberExpression numberExpr = (INumberExpression) value;
        double v = numberExpr.getDoubleValue(context, this);
        DoubleArrayFS array = FSCollectionFactory.createDoubleArray(cas, new double[] { v });
        annotation.setFeatureValue(feature, array);
      } else if (value instanceof INumberListExpression) {
        INumberListExpression expr = (INumberListExpression) value;
        List<Number> list = expr.getNumberList(context, this);
        DoubleArrayFS array = FSCollectionFactory.createDoubleArray(cas,
                RutaListUtils.toDoubleArray(list));
        annotation.setFeatureValue(feature, array);
      }
    } else if (rangeName.equals(CAS.TYPE_NAME_FLOAT)) {
      if (value instanceof INumberExpression) {
        INumberExpression numberExpr = (INumberExpression) value;
        float v = numberExpr.getFloatValue(context, this);
        annotation.setFloatValue(feature, v);
      }
    } else if (rangeName.equals(CAS.TYPE_NAME_FLOAT_ARRAY)) {
      if (value instanceof INumberExpression) {
        INumberExpression numberExpr = (INumberExpression) value;
        float v = numberExpr.getFloatValue(context, this);
        FloatArrayFS array = FSCollectionFactory.createFloatArray(cas, new float[] { v });
        annotation.setFeatureValue(feature, array);
      } else if (value instanceof INumberListExpression) {
        INumberListExpression expr = (INumberListExpression) value;
        List<Number> list = expr.getNumberList(context, this);
        FloatArrayFS array = FSCollectionFactory.createFloatArray(cas,
                RutaListUtils.toFloatArray(list));
        annotation.setFeatureValue(feature, array);
      }
    } else if (rangeName.equals(CAS.TYPE_NAME_BOOLEAN)) {
      if (value instanceof IBooleanExpression) {
        IBooleanExpression expr = (IBooleanExpression) value;
        Boolean v = expr.getBooleanValue(context, this);
        annotation.setBooleanValue(feature, v);
      }
    } else if (rangeName.equals(CAS.TYPE_NAME_BOOLEAN_ARRAY)) {
      if (value instanceof IBooleanListExpression) {
        IBooleanListExpression expr = (IBooleanListExpression) value;
        List<Boolean> list = expr.getBooleanList(context, this);
        BooleanArrayFS array = FSCollectionFactory.createBooleanArray(cas, list);
        annotation.setFeatureValue(feature, array);
      } else if (value instanceof IBooleanExpression) {
        IBooleanExpression expr = (IBooleanExpression) value;
        Boolean v = expr.getBooleanValue(context, this);
        BooleanArrayFS array = FSCollectionFactory.createBooleanArray(cas, new boolean[] { v });
        annotation.setFeatureValue(feature, array);
      }
    } else if (value instanceof AnnotationTypeExpression && !range.isPrimitive()) {
      AnnotationTypeExpression ate = (AnnotationTypeExpression) value;
      if (range.isArray()) {
        List<AnnotationFS> annotations = ate.getAnnotationList(context, this);
        annotation.setFeatureValue(feature, UIMAUtils.toFSArray(getJCas(), annotations));
      } else {
        AnnotationFS a = ate.getAnnotation(context, this);
        annotation.setFeatureValue(feature, a);
      }
    } else if (value instanceof IAnnotationExpression && !range.isPrimitive()) {
      IAnnotationExpression ae = (IAnnotationExpression) value;
      boolean rangeSubsumesAnnotation = cas.getTypeSystem().subsumes(cas.getAnnotationType(),
              range);

      FeatureStructure a = null;
      if (rangeSubsumesAnnotation) {
        a = ae.getAnnotation(context, this);
      } else {
        a = ae.getFeatureStructure(context, this);
      }
      if (range.isArray()) {
        List<FeatureStructure> c = new ArrayList<>();
        c.add(a);
        annotation.setFeatureValue(feature, UIMAUtils.toFSArray(getJCas(), c));
      } else {
        annotation.setFeatureValue(feature, a);
      }
    } else if (value instanceof IAnnotationListExpression && !range.isPrimitive()) {
      IAnnotationListExpression ale = (IAnnotationListExpression) value;
      List<AnnotationFS> annotations = ale.getAnnotationList(context, this);
      if (annotations != null) {
        if (range.isArray()) {
          annotation.setFeatureValue(feature, UIMAUtils.toFSArray(getJCas(), annotations));
        } else {
          if (annotations.isEmpty()) {
            annotation.setFeatureValue(feature, null);
          } else {
            annotation.setFeatureValue(feature, annotations.get(0));
          }
        }
      } else {
        annotation.setFeatureValue(feature, null);
      }
    } else if (value instanceof ITypeExpression && !range.isPrimitive()) {
      ITypeExpression typeExpr = (ITypeExpression) value;
      Type t = typeExpr.getType(context, this);
      assignAnnotationByTypeInWindow(annotation, feature, context, t);
    } else if (value instanceof GenericFeatureExpression && !range.isPrimitive()) {
      FeatureExpression fe = ((GenericFeatureExpression) value).getFeatureExpression();
      Type t = fe.getInitialType(context, this);
      List<AnnotationFS> inWindow = getAnnotationsInWindow(context.getAnnotation(), t);
      if (fe instanceof SimpleFeatureExpression) {
        SimpleFeatureExpression sfe = (SimpleFeatureExpression) fe;
        List<? extends FeatureStructure> featureAnnotations = null;
        if (fe.getFeatures(context, this) != null) {
          featureAnnotations = new ArrayList<>(
                  sfe.getFeatureStructures(inWindow, false, context, this));
        } else {
          featureAnnotations = inWindow;
        }
        if (range.isArray()) {
          annotation.setFeatureValue(feature, UIMAUtils.toFSArray(getJCas(), featureAnnotations));
        } else if (!featureAnnotations.isEmpty()) {
          FeatureStructure a = featureAnnotations.get(0);
          annotation.setFeatureValue(feature, a);
        }
      } else {
        if (range.isArray()) {
          annotation.setFeatureValue(feature, UIMAUtils.toFSArray(getJCas(), inWindow));
        } else {
          AnnotationFS a = inWindow.get(0);
          annotation.setFeatureValue(feature, a);
        }
      }
    }
  }

  private void assignAnnotationByTypeInWindow(FeatureStructure annotation, Feature feature,
          MatchContext context, Type type) {

    List<AnnotationFS> inWindow = getAnnotationsInWindow(context.getAnnotation(), type);
    if (feature.getRange().isArray()) {
      annotation.setFeatureValue(feature, UIMAUtils.toFSArray(getJCas(), inWindow));
    } else {
      if (inWindow != null && !inWindow.isEmpty()) {
        AnnotationFS a = inWindow.get(0);
        annotation.setFeatureValue(feature, a);
      } else {
        annotation.setFeatureValue(feature, null);
      }
    }
  }

  public void assignVariable(String var, IRutaExpression expression, MatchContext context) {
    RutaBlock parent = context.getParent();
    RutaEnvironment environment = parent.getEnvironment();
    Class<?> clazz = environment.getVariableType(var);
    if (clazz.equals(Double.class) && expression instanceof INumberExpression) {
      double v = ((INumberExpression) expression).getDoubleValue(context, this);
      environment.setVariableValue(var, v);
    } else if (clazz.equals(Float.class) && expression instanceof INumberExpression) {
      float v = (float) ((INumberExpression) expression).getDoubleValue(context, this);
      environment.setVariableValue(var, v);
    } else if (clazz.equals(Integer.class) && expression instanceof INumberExpression) {
      int v = ((INumberExpression) expression).getIntegerValue(context, this);
      environment.setVariableValue(var, v);
    } else if (clazz.equals(Type.class) && expression instanceof ITypeExpression) {
      Type v = ((ITypeExpression) expression).getType(context, this);
      environment.setVariableValue(var, v);
    } else if (clazz.equals(Boolean.class) && expression instanceof IBooleanExpression) {
      boolean v = ((IBooleanExpression) expression).getBooleanValue(context, this);
      environment.setVariableValue(var, v);
    } else if (clazz.equals(String.class) && expression instanceof IStringExpression) {
      String v = ((IStringExpression) expression).getStringValue(context, this);
      environment.setVariableValue(var, v);
    } else if (clazz.equals(AnnotationFS.class) && expression instanceof IAnnotationExpression) {
      AnnotationFS v = ((IAnnotationExpression) expression).getAnnotation(context, this);
      environment.setVariableValue(var, v);
    } else if (clazz.equals(List.class)) {
      Class<?> variableGenericType = environment.getVariableGenericType(var);
      if (variableGenericType.equals(AnnotationFS.class)
              && expression instanceof IAnnotationListExpression) {
        List<AnnotationFS> v = ((IAnnotationListExpression) expression).getAnnotationList(context,
                this);
        environment.setVariableValue(var, v);
      } else if (variableGenericType.equals(Boolean.class)
              && expression instanceof IBooleanListExpression) {
        List<Boolean> v = ((IBooleanListExpression) expression).getBooleanList(context, this);
        environment.setVariableValue(var, v);
      } else if (Number.class.isAssignableFrom(variableGenericType)
              && expression instanceof INumberListExpression) {
        List<Number> v = ((INumberListExpression) expression).getNumberList(context, this);
        environment.setVariableValue(var, v);
      } else if (variableGenericType.equals(String.class)
              && expression instanceof IStringListExpression) {
        List<String> v = ((IStringListExpression) expression).getStringList(context, this);
        environment.setVariableValue(var, v);
      } else if (variableGenericType.equals(Type.class)
              && expression instanceof ITypeListExpression) {
        List<Type> v = ((ITypeListExpression) expression).getTypeList(context, this);
        environment.setVariableValue(var, v);
      }
    } else if (clazz.equals(Boolean.class) && expression instanceof AnnotationTypeExpression) {
      // special not yet supported use case: b = a1==a2
      // TODO: this should be solved by having a boolean expression and an atomic feature
      // expression?
      AnnotationTypeExpression ate = (AnnotationTypeExpression) expression;
      AnnotationFS annotation = ate.getAnnotation(context, this);
      FeatureExpression featureExpression = ate.getFeatureExpression();
      if (featureExpression instanceof FeatureMatchExpression) {
        FeatureMatchExpression fme = (FeatureMatchExpression) featureExpression;
        IRutaExpression arg = fme.getArg();
        if (arg instanceof IAnnotationExpression) {
          AnnotationFS argAnnotation = ((IAnnotationExpression) arg).getAnnotation(context, this);
          if (StringUtils.equals(fme.getOp(), "==")) {
            environment.setVariableValue(var, annotation == argAnnotation);
          } else if (StringUtils.equals(fme.getOp(), "!=")) {
            environment.setVariableValue(var, annotation != argAnnotation);
          }
        }
      }
    }
  }

  @SuppressWarnings("unchecked")
  public <T extends Object> T getExpressionValue(Class<T> clazz, IRutaExpression expression,
          MatchContext context) {
    if (clazz.equals(Double.class) && expression instanceof INumberExpression) {
      double v = ((INumberExpression) expression).getDoubleValue(context, this);
      return (T) Double.valueOf(v);
    } else if (clazz.equals(Float.class) && expression instanceof INumberExpression) {
      float v = (float) ((INumberExpression) expression).getDoubleValue(context, this);
      return (T) Float.valueOf(v);
    } else if (clazz.equals(Integer.class) && expression instanceof INumberExpression) {
      int v = ((INumberExpression) expression).getIntegerValue(context, this);
      return (T) Integer.valueOf(v);
    } else if (clazz.equals(Type.class) && expression instanceof ITypeExpression) {
      Type v = ((ITypeExpression) expression).getType(context, this);
      return (T) v;
    } else if (clazz.equals(Boolean.class) && expression instanceof IBooleanExpression) {
      boolean v = ((IBooleanExpression) expression).getBooleanValue(context, this);
      return (T) Boolean.valueOf(v);
    } else if (clazz.equals(String.class) && expression instanceof IStringExpression) {
      String v = ((IStringExpression) expression).getStringValue(context, this);
      return (T) v;
    } else if (clazz.equals(AnnotationFS.class) && expression instanceof IAnnotationExpression) {
      AnnotationFS v = ((IAnnotationExpression) expression).getAnnotation(context, this);
      return (T) v;
    }
    return null;
  }

  public AnnotationFS getSingleAnnotationByTypeInContext(Type type, MatchContext context) {
    List<AnnotationFS> inWindow = getAnnotationsInWindow(context.getAnnotation(), type);
    if (inWindow != null && !inWindow.isEmpty()) {
      return inWindow.get(0);
    }
    return null;
  }

  public List<AnnotationFS> getAnnotationsByTypeInContext(Type type, MatchContext context) {
    List<AnnotationFS> inWindow = getAnnotationsInWindow(context.getAnnotation(), type);
    return inWindow;
  }

  public List<AnnotationFS> getBestGuessedAnnotationsAt(AnnotationFS window, Type type) {
    List<AnnotationFS> result = new ArrayList<>();
    if (window == null || type == null) {
      return result;
    }
    TypeSystem typeSystem = getCas().getTypeSystem();
    if (typeSystem.subsumes(type, window.getType())) {
      result.add(window);
    } else {
      Collection<AnnotationFS> beginAnchors = getBeginAnchor(window.getBegin())
              .getBeginAnchors(type);
      Collection<AnnotationFS> endAnchors = getEndAnchor(window.getEnd()).getEndAnchors(type);
      @SuppressWarnings("unchecked")
      Collection<AnnotationFS> intersection = CollectionUtils.intersection(beginAnchors,
              endAnchors);
      result.addAll(intersection);
    }
    return result;
  }

  public void changeOffsets(AnnotationFS annotation, int begin, int end,
          AbstractRuleMatch<? extends AbstractRule> modifikator) {
    if (!(annotation instanceof Annotation)) {
      return;
    }
    Annotation a = (Annotation) annotation;
    if (annotation.getBegin() == begin && annotation.getEnd() == end) {
      return;
    }
    // TODO implement incremental reindexing
    removeAnnotation(a);
    a.setBegin(begin);
    a.setEnd(end);
    addAnnotation(a, true, modifikator);
  }

  public void changeBegin(AnnotationFS annotation, int begin,
          AbstractRuleMatch<? extends AbstractRule> modifikator) {
    changeOffsets(annotation, begin, annotation.getEnd(), modifikator);
  }

  public void changeEnd(AnnotationFS annotation, int end,
          AbstractRuleMatch<? extends AbstractRule> modifikator) {
    changeOffsets(annotation, annotation.getBegin(), end, modifikator);
  }

  public AnnotationFS getVeryFirstBeforeWindow(boolean direction) {
    if (direction) {
      RutaBasic firstBasicOfAll = getFirstBasicOfAll();
      int begin = firstBasicOfAll.getBegin();
      if (begin == 0) {
        return documentBeginAnchor;
      } else {
        return getEndAnchor(begin);
      }
    } else {
      RutaBasic lastBasicOfAll = getLastBasicOfAll();
      int end = lastBasicOfAll.getEnd();
      if (end == cas.getDocumentAnnotation().getEnd()) {
        return documentEndAnchor;
      } else {
        return getBeginAnchor(end);
      }
    }
  }

  public Type getSharedParentType(List<Type> types) {
    if (types == null || types.isEmpty()) {
      return cas.getAnnotationType();
    }
    if (types.size() == 1) {
      return types.get(0);
    }
    TypeSystem typeSystem = cas.getTypeSystem();
    Type parentType = types.get(0);
    for (Type type : types) {
      parentType = getSharedParentType(parentType, type, typeSystem);
    }
    return parentType;
  }

  private Type getSharedParentType(Type type1, Type type2, TypeSystem typeSystem) {
    if (cas.getAnnotationType().equals(type1) || cas.getAnnotationType().equals(type2)) {
      return cas.getAnnotationType();
    }
    if (type1.equals(type2)) {
      return type1;
    }
    if (typeSystem.subsumes(type1, type2)) {
      return type1;
    }
    if (typeSystem.subsumes(type2, type1)) {
      return type2;
    }
    Type parentType = typeSystem.getParent(type1);
    while (parentType != null && !cas.getAnnotationType().equals(parentType)) {
      if (typeSystem.subsumes(parentType, type2)) {
        return parentType;
      }
    }

    return cas.getAnnotationType();
  }

  public RutaAnnotation getRutaAnnotationFor(AnnotationFS annotation, boolean create,
          RutaStream stream) {
    Type heuristicType = cas.getTypeSystem().getType(RutaAnnotation.class.getName());
    List<AnnotationFS> ras = CasUtil.selectAt(cas, heuristicType, annotation.getBegin(),
            annotation.getEnd());
    for (AnnotationFS each : ras) {
      if (((RutaAnnotation) each).getAnnotation() == annotation) {
        return (RutaAnnotation) each;
      }
    }
    if (create) {
      JCas jCas = stream.getJCas();
      RutaAnnotation result = new RutaAnnotation(jCas, annotation.getBegin(), annotation.getEnd());
      result.setAnnotation((Annotation) annotation);
      result.addToIndexes();
      return result;
    }
    return null;
  }

  private Collection<Type> removeSubsumedTypes(Collection<Type> types, TypeSystem typeSystem) {
    List<Type> rootTypes = new ArrayList<>(types);
    for (Type type1 : types) {
      for (Type type2 : types) {
        if (type1 != type2 && typeSystem.subsumes(type1, type2)) {
          rootTypes.remove(type2);
        }
      }
    }
    return rootTypes;
  }

  private Collection<Type> expandToAllSubtypes(Collection<Type> reindexTypeList,
          Collection<Type> reindexSkipTypes, TypeSystem typeSystem) {
    if (reindexTypeList.isEmpty()) {
      return Collections.emptyList();
    }

    Collection<Type> result = new LinkedHashSet<>();
    for (Type type : reindexTypeList) {

      if (skipTypeForIndexing(type, reindexSkipTypes, typeSystem)) {
        continue;
      }

      result.add(type);
      List<Type> properlySubsumedTypes = typeSystem.getProperlySubsumedTypes(type);
      for (Type subType : properlySubsumedTypes) {
        if (skipTypeForIndexing(subType, reindexSkipTypes, typeSystem)) {
          continue;
        }
        result.add(subType);
      }

      // if we started with uima.tcas.Annotation, we already collected all
      if (type.getName().equals(CAS.TYPE_NAME_ANNOTATION)) {
        return result;
      }
    }

    return result;
  }

  private Collection<Type> convertNamesToTypes(String[] typeNames, TypeSystem typeSystem) {
    if (typeNames == null) {
      return Collections.emptyList();
    }

    Collection<Type> result = new ArrayList<>(typeNames.length);
    for (String each : typeNames) {
      Type type = typeSystem.getType(each);
      if (type != null) {
        result.add(type);
      }
    }
    return result;
  }

  public void setMaxRuleMatches(long maxRuleMatches) {
    this.maxRuleMatches = maxRuleMatches;
  }

  public void setMaxRuleElementMatches(long maxRuleElementMatches) {
    this.maxRuleElementMatches = maxRuleElementMatches;
  }

  public long getMaxRuleMatches() {
    return maxRuleMatches;
  }

  public long getMaxRuleElementMatches() {
    return maxRuleElementMatches;
  }

}
