code: package caevo;
  
  import java.io.Serializable;
  
  /**
   * Represents a set of TextEvents pairs with certain fixed values for some
   * attributes (e.g. tense, aspect, and class). For example, one possible pattern
   * is (((Tense=PAST, Aspect=PROGRESSIVE),(Tense=FUTURE, Aspect=NONE)),
   * SAME_SENTENCE) representing all pairs of TextEvents in which the first is in
   * the past progressive, the second is in the future, and they are both in the
   * same sentence.
   * 
   * This is useful in constructing rules about text events based on their
   * attributes.
   * 
   * @author Bill
   *
   */
  public class TextEventPairPattern implements Serializable {
    private static final long serialVersionUID = 7345682438526525636L;
  
    public enum SentenceRelation {
      SAME_SENTENCE, DIFFERENT_SENTENCE
    }
  
    private TextEventPattern p1 = null;
    private TextEventPattern p2 = null;
    private SentenceRelation sentenceRelation = null;
  
    public TextEventPairPattern() {
      this.p1 = new TextEventPattern();
      this.p2 = new TextEventPattern();
    }
  
    public TextEventPairPattern(TextEvent canonicalEvent1,
        TextEvent canonicalEvent2, boolean keepClass, boolean keepTense,
        boolean keepAspect, boolean keepSentenceRelation) {
      this.p1 = new TextEventPattern();
      this.p2 = new TextEventPattern();
      setFromCanonicalEvent(canonicalEvent1, canonicalEvent2, keepClass,
          keepTense, keepAspect, keepSentenceRelation);
    }
  
    public void setFromCanonicalEvent(TextEvent canonicalEvent1,
        TextEvent canonicalEvent2, boolean keepClass, boolean keepTense,
        boolean keepAspect, boolean keepSentenceRelation) {
      this.p1.setFromCanonicalEvent(canonicalEvent1, keepClass, keepTense,
          keepAspect);
      this.p2.setFromCanonicalEvent(canonicalEvent2, keepClass, keepTense,
          keepAspect);
  
      if (!keepSentenceRelation)
        this.sentenceRelation = null;
      if (canonicalEvent1.getSid() == canonicalEvent2.getSid())
        this.sentenceRelation = SentenceRelation.SAME_SENTENCE;
      else
        this.sentenceRelation = SentenceRelation.DIFFERENT_SENTENCE;
    }
  
    public void setFirstPattern(TextEventPattern p1) {
      this.p1 = p1;
    }
  
    public void setSecondPattern(TextEventPattern p2) {
      this.p2 = p2;
    }
  
    public void setSentenceRelation(SentenceRelation sentenceRelation) {
      this.sentenceRelation = sentenceRelation;
    }
  
    public TextEventPattern getFirstPattern() {
      return this.p1;
    }
  
    public TextEventPattern getSecondPattern() {
      return this.p2;
    }
  
    public SentenceRelation getSentenceRelation() {
      return this.sentenceRelation;
    }
  
    public boolean matches(TextEvent event1, TextEvent event2) {
      return this.p1.matches(event1) && this.p2.matches(event2)
          && (this.sentenceRelation == null
              || (this.sentenceRelation == SentenceRelation.SAME_SENTENCE
                  && event1.getSid() == event2.getSid())
              || (this.sentenceRelation == SentenceRelation.DIFFERENT_SENTENCE
                  && event1.getSid() != event2.getSid()));
    }
  
    public int hashCode() {
      return this.p1.hashCode() ^ this.p2.hashCode()
          ^ ((this.sentenceRelation == null) ? 0
              : this.sentenceRelation.toString().hashCode());
    }
  
    public boolean equals(Object o) {
      TextEventPairPattern p = (TextEventPairPattern) o;
      return p.p1.equals(this.p1) && p.p2.equals(this.p2)
          && this.sentenceRelation == p.sentenceRelation;
    }
  
    public String toString() {
      StringBuilder str = new StringBuilder();
      str.append(this.p1.toString());
      if (this.sentenceRelation != null)
        str.append("\t").append(this.sentenceRelation).append("\t");
      str.append(this.p2.toString());
  
      return str.toString();
    }
  }
  