@@ -0,0 +1,3126 @@
+package com.bbn.bue.common.evaluation;%0A%0Aimport com.google.common.base.Function;%0Aimport com.google.common.collect.FluentIterable;%0Aimport com.google.common.collect.ImmutableMap;%0Aimport com.google.common.collect.ImmutableSet;%0A%0Aimport java.util.Map;%0A%0A/**%0A * Utility methods for dealing with %7B@link Alignment%7Ds.%0A */%0Apublic final class Alignments %7B%0A%0A  private Alignments() %7B%0A    throw new UnsupportedOperationException();%0A  %7D%0A%0A  /**%0A   * Splits an alignment into many alignments based on a function mapping aligned items to some set%0A   * of keys.  Returns a map where the keys are all observed outputs of the key function on items in%0A   * the alignment and the values are new alignments containing only elements which yield that%0A   * output when the key function is applied.  For example, if you had an alignment of%0A   * EventMentions, you could use an %22event type%22 key function to produce one alignment per event%0A   * type.%0A   */%0A  @SuppressWarnings(%22unchecked%22)%0A  public static %3CT, V%3E ImmutableMap%3CV, Alignment%3CT, T%3E%3E splitAlignmentByKeyFunction(%0A      Alignment%3C? extends T, ? extends T%3E alignment,%0A      Function%3C? super T, ? extends V%3E keyFunction) %7B%0A    // we first determine all keys we could ever encounter to ensure we can construct our map%0A    // deterministically%0A    // Java will complain about this cast but it is safe because ImmutableSet if covariant in its%0A    // type parameter%0A    final ImmutableSet%3C? extends V%3E allKeys =%0A        FluentIterable.from((ImmutableSet%3CT%3E) alignment.allLeftItems())%0A            .append(alignment.allRightItems())%0A            .transform(keyFunction).toSet();%0A%0A    final ImmutableMap.Builder%3CV, MultimapAlignment.Builder%3CT, T%3E%3E keysToAlignmentsB =%0A        ImmutableMap.builder();%0A    for (final V key : allKeys) %7B%0A      keysToAlignmentsB.put(key, MultimapAlignment.%3CT, T%3Ebuilder());%0A    %7D%0A%0A    final ImmutableMap%3CV, MultimapAlignment.Builder%3CT, T%3E%3E keysToAlignments =%0A        keysToAlignmentsB.build();%0A%0A    for (final T leftItem : alignment.allLeftItems()) %7B%0A      final V keyVal = keyFunction.apply(leftItem);%0A      final MultimapAlignment.Builder%3CT, T%3E alignmentForKey = keysToAlignments.get(keyVal);%0A      alignmentForKey.addLeftItem(leftItem);%0A      for (T rightItem : alignment.alignedToLeftItem(leftItem)) %7B%0A        if (keyFunction.apply(rightItem).equals(keyVal)) %7B%0A          alignmentForKey.align(leftItem, rightItem);%0A        %7D%0A      %7D%0A    %7D%0A    for (final T rightItem : alignment.allRightItems()) %7B%0A      final V keyVal = keyFunction.apply(rightItem);%0A      final MultimapAlignment.Builder%3CT, T%3E alignmentForKey = keysToAlignments.get(keyVal);%0A      alignmentForKey.addRightItem(rightItem);%0A      for (final T leftItem : alignment.alignedToRightItem(rightItem)) %7B%0A        if (keyVal.equals(keyFunction.apply(leftItem))) %7B%0A          alignmentForKey.align(leftItem, rightItem);%0A        %7D%0A      %7D%0A    %7D%0A%0A    final ImmutableMap.Builder%3CV, Alignment%3CT, T%3E%3E ret = ImmutableMap.builder();%0A    for (final Map.Entry%3CV, MultimapAlignment.Builder%3CT, T%3E%3E entry : keysToAlignments.entrySet()) %7B%0A      ret.put(entry.getKey(), entry.getValue().build());%0A    %7D%0A%0A    return ret.build();%0A  %7D%0A%7D%0A

Split an Alignment into multiple alignments based on a key function