public void annotateGroup(int group, Map<String, String> attributes) {
   int groupStart = start(group);
   if (groupStart >= 0) {
     int groupEnd = end(group);
     ChunkAnnotationUtils.annotateChunks(elements, groupStart, groupEnd, attributes);
   }
 }
 public SequenceMatchResult<T> apply(SequenceMatchResult<T> matchResult, int... groups) {
   for (int group : groups) {
     int groupStart = matchResult.start(group);
     if (groupStart >= 0) {
       int groupEnd = matchResult.end(group);
       ChunkAnnotationUtils.annotateChunks(
           matchResult.elements(), groupStart, groupEnd, attributes);
     }
   }
   return matchResult;
 }
 private List<CoreMap> toCoreMaps(
     CoreMap annotation, List<TimeExpression> timeExpressions, SUTime.TimeIndex timeIndex) {
   if (timeExpressions == null) return null;
   List<CoreMap> coreMaps = new ArrayList<CoreMap>(timeExpressions.size());
   for (TimeExpression te : timeExpressions) {
     CoreMap cm = te.getAnnotation();
     SUTime.Temporal temporal = te.getTemporal();
     if (temporal != null) {
       String origText = annotation.get(CoreAnnotations.TextAnnotation.class);
       String text = cm.get(CoreAnnotations.TextAnnotation.class);
       if (origText != null) {
         // Make sure the text is from original (and not from concatenated tokens)
         ChunkAnnotationUtils.annotateChunkText(cm, annotation);
         text = cm.get(CoreAnnotations.TextAnnotation.class);
       }
       Map<String, String> timexAttributes;
       try {
         timexAttributes = temporal.getTimexAttributes(timeIndex);
         if (options.includeRange) {
           SUTime.Temporal rangeTemporal = temporal.getRange();
           if (rangeTemporal != null) {
             timexAttributes.put("range", rangeTemporal.toString());
           }
         }
       } catch (Exception e) {
         logger.log(
             Level.WARNING,
             "Failed to get attributes from " + text + ", timeIndex " + timeIndex,
             e);
         continue;
       }
       Timex timex;
       try {
         timex = Timex.fromMap(text, timexAttributes);
       } catch (Exception e) {
         logger.log(
             Level.WARNING,
             "Failed to process " + text + " with attributes " + timexAttributes,
             e);
         continue;
       }
       cm.set(TimexAnnotation.class, timex);
       if (timex != null) {
         coreMaps.add(cm);
       } else {
         logger.warning("No timex expression for: " + text);
       }
     }
   }
   return coreMaps;
 }
 private CoreMap createMergedChunk(int groupStart, int groupEnd) {
   CoreMap merged = null;
   /*  if (annotation != null) {
     // Take start and end
     merged = ChunkAnnotationUtils.getMergedChunk(elements, annotation.get(CoreAnnotations.TextAnnotation.class), groupStart, groupEnd);
   }  */
   if (merged == null) {
     // Okay, have to go through these one by one and merge them
     merged =
         ChunkAnnotationUtils.getMergedChunk(
             elements, groupStart, groupEnd, CoreMapAttributeAggregator.getDefaultAggregators());
   }
   return merged;
 }
/**
 * CoreMap Sequence Matcher for regular expressions for sequences over coremaps
 *
 * @author Angel Chang
 */
public class CoreMapSequenceMatcher<T extends CoreMap> extends SequenceMatcher<T> {
  protected static final Function<List<? extends CoreMap>, String>
      COREMAP_LIST_TO_STRING_CONVERTER =
          in ->
              (in != null)
                  ? ChunkAnnotationUtils.getTokenText(in, CoreAnnotations.TextAnnotation.class)
                  : null;

  public CoreMapSequenceMatcher(SequencePattern<T> pattern, List<? extends T> tokens) {
    super(pattern, tokens);
    //    this.nodesToStringConverter = COREMAP_LIST_TO_STRING_CONVERTER;
  }

  public static class BasicCoreMapSequenceMatcher extends CoreMapSequenceMatcher<CoreMap> {
    CoreMap annotation;

    public BasicCoreMapSequenceMatcher(SequencePattern<CoreMap> pattern, CoreMap annotation) {
      super(pattern, annotation.get(CoreAnnotations.TokensAnnotation.class));
      this.annotation = annotation;
      this.nodesToStringConverter = COREMAP_LIST_TO_STRING_CONVERTER;
    }
  }

  public void annotateGroup(Map<String, String> attributes) {
    annotateGroup(0, attributes);
  }

  public void annotateGroup(int group, Map<String, String> attributes) {
    int groupStart = start(group);
    if (groupStart >= 0) {
      int groupEnd = end(group);
      ChunkAnnotationUtils.annotateChunks(elements, groupStart, groupEnd, attributes);
    }
  }

  public List<CoreMap> getMergedList() {
    return getMergedList(0);
  }

  public List<CoreMap> getMergedList(int... groups) {
    List<CoreMap> res = new ArrayList<CoreMap>();
    int last = 0;
    List<Integer> orderedGroups = CollectionUtils.asList(groups);
    Collections.sort(orderedGroups);
    for (int group : orderedGroups) {
      int groupStart = start(group);
      if (groupStart >= last) {
        res.addAll(elements.subList(last, groupStart));
        int groupEnd = end(group);
        if (groupEnd - groupStart >= 1) {
          CoreMap merged = createMergedChunk(groupStart, groupEnd);
          res.add(merged);
          last = groupEnd;
        }
      }
    }
    res.addAll(elements.subList(last, elements.size()));
    return res;
  }

  public CoreMap mergeGroup() {
    return mergeGroup(0);
  }

  private CoreMap createMergedChunk(int groupStart, int groupEnd) {
    CoreMap merged = null;
    /*  if (annotation != null) {
      // Take start and end
      merged = ChunkAnnotationUtils.getMergedChunk(elements, annotation.get(CoreAnnotations.TextAnnotation.class), groupStart, groupEnd);
    }  */
    if (merged == null) {
      // Okay, have to go through these one by one and merge them
      merged =
          ChunkAnnotationUtils.getMergedChunk(
              elements, groupStart, groupEnd, CoreMapAttributeAggregator.getDefaultAggregators());
    }
    return merged;
  }

  public CoreMap mergeGroup(int group) {
    int groupStart = start(group);
    if (groupStart >= 0) {
      int groupEnd = end(group);
      if (groupEnd - groupStart >= 1) {
        return createMergedChunk(groupStart, groupEnd);
      }
    }
    return null;
  }
}