
public class TemporalTransTable {

  private int[][] table;
  public static int NOINFO = 0;
  public static int EQUALS = 1;
  public static int BEFORE = 2;
  public static int AFTER = 4;
  public static int DURING = 8;
  public static int CONTAINS = 16;
  public static int OVERLAPS = 32;
  public static int OVERLAPPEDBY = 64;
  public static int MEETS = 128;
  public static int METBY = 256;
  public static int STARTS = 512;
  public static int STARTEDBY = 1024;
  public static int FINISHES = 2048;
  public static int FINISHEDBY = 4096;
  public static int NOCONSTRAINTS = 8191;
  
  public TemporalTransTable(){	
    this.table = new int[13][13];
    setTable();
  }
  
  protected int getIndex(int relation){
    return((int)(Math.log((double)relation) / Math.log((double)2)));
  }
  
  public int getTemporalTransitiveRelation(int relationA, int relationB){
    return(this.table[getIndex(relationA)][getIndex(relationB)]);
  }
  
  public int intersection(int relationA, int relationB){
    return(relationA & relationB);
  }
  
  public int union(int relationA, int relationB){
    return(relationA | relationB);
  }
  
  public String toString(int relation){
    String s = "";
    if((relation & EQUALS) == EQUALS)
      s = s + "equals ";
    if((relation & BEFORE) == BEFORE)
      s = s + "before ";
    if((relation & AFTER) == AFTER)
      s = s + "after ";
    if((relation & DURING) == DURING)
      s = s + "during ";
    if((relation & CONTAINS) == CONTAINS)
      s = s + "contains ";
    if((relation & OVERLAPS) == OVERLAPS)
      s = s + "overlaps ";
    if((relation & OVERLAPPEDBY) == OVERLAPPEDBY) 
      s = s + "overlappedBy ";
    if((relation & MEETS) == MEETS)
      s = s + "meets ";
    if((relation & METBY) == METBY)
      s = s + "metBy ";
    if((relation & STARTS) == STARTS)
      s = s + "starts ";
    if((relation & STARTEDBY) == STARTEDBY)
      s = s + "startedBy ";
    if((relation & FINISHES) == FINISHES)
      s = s + "finishes ";
    if((relation & FINISHEDBY) == FINISHEDBY)
      s = s + "finishedBy ";
    if(s == null)  
      s = s + "noInfo ";

    return(s);
  }
  private void setTable(){
    this.table[getIndex(EQUALS)][getIndex(EQUALS)] = EQUALS;
    this.table[getIndex(EQUALS)][getIndex(BEFORE)] = BEFORE;
	this.table[getIndex(EQUALS)][getIndex(AFTER)] = AFTER;
	this.table[getIndex(EQUALS)][getIndex(DURING)] = DURING;
	this.table[getIndex(EQUALS)][getIndex(CONTAINS)] = CONTAINS;
	this.table[getIndex(EQUALS)][getIndex(OVERLAPS)] = OVERLAPS;
	this.table[getIndex(EQUALS)][getIndex(OVERLAPPEDBY)] = OVERLAPPEDBY;
	this.table[getIndex(EQUALS)][getIndex(MEETS)] = MEETS;
	this.table[getIndex(EQUALS)][getIndex(METBY)] = METBY;
	this.table[getIndex(EQUALS)][getIndex(STARTS)] = STARTS;
	this.table[getIndex(EQUALS)][getIndex(STARTEDBY)] = STARTEDBY;
	this.table[getIndex(EQUALS)][getIndex(FINISHES)] = FINISHES;
	this.table[getIndex(EQUALS)][getIndex(FINISHEDBY)] = FINISHEDBY;
	this.table[getIndex(BEFORE)][getIndex(EQUALS)] = BEFORE;
	this.table[getIndex(BEFORE)][getIndex(BEFORE)] = BEFORE;
	this.table[getIndex(BEFORE)][getIndex(AFTER)] = NOCONSTRAINTS;
	this.table[getIndex(BEFORE)][getIndex(DURING)] = (
							  BEFORE | 
							  OVERLAPS | 
							  MEETS | 
							  DURING | 
							  STARTS);
	this.table[getIndex(BEFORE)][getIndex(CONTAINS)] = BEFORE;
	this.table[getIndex(BEFORE)][getIndex(OVERLAPS)] = BEFORE;
	this.table[getIndex(BEFORE)][getIndex(OVERLAPPEDBY)] = (
								BEFORE |
								OVERLAPS |
								MEETS |
								DURING |
								STARTS);
	this.table[getIndex(BEFORE)][getIndex(MEETS)] = BEFORE;
	this.table[getIndex(BEFORE)][getIndex(METBY)] = (
							 BEFORE |
							 OVERLAPS |
							 MEETS |
							 DURING |
							 STARTS);
	this.table[getIndex(BEFORE)][getIndex(STARTS)] = BEFORE;
	this.table[getIndex(BEFORE)][getIndex(STARTEDBY)] = BEFORE;
	this.table[getIndex(BEFORE)][getIndex(FINISHES)] = (
							    BEFORE |
							    OVERLAPS |
							    MEETS |
							    DURING |
							    STARTS);
	this.table[getIndex(BEFORE)][getIndex(FINISHEDBY)] = BEFORE;
	
	this.table[getIndex(AFTER)][getIndex(EQUALS)] = AFTER;
	this.table[getIndex(AFTER)][getIndex(BEFORE)] = NOCONSTRAINTS;
	this.table[getIndex(AFTER)][getIndex(AFTER)] = AFTER;
	this.table[getIndex(AFTER)][getIndex(DURING)] = (
							 AFTER |
							 OVERLAPPEDBY |
							 METBY |
							 DURING |
							 FINISHES);
	this.table[getIndex(AFTER)][getIndex(CONTAINS)] = AFTER;
	this.table[getIndex(AFTER)][getIndex(OVERLAPS)] = (
							   AFTER |
							   OVERLAPPEDBY |
							   METBY |
							   DURING |
							   FINISHES);
	this.table[getIndex(AFTER)][getIndex(OVERLAPPEDBY)] = AFTER;
	this.table[getIndex(AFTER)][getIndex(MEETS)] = (
							AFTER |
							OVERLAPPEDBY |
							METBY |
							DURING |
							FINISHES);
	this.table[getIndex(AFTER)][getIndex(METBY)] = AFTER;
	this.table[getIndex(AFTER)][getIndex(STARTS)] = (
							 AFTER | 
							 OVERLAPPEDBY |
							 METBY |
							 DURING |
							 FINISHES);
	this.table[getIndex(AFTER)][getIndex(STARTEDBY)] = AFTER;
	this.table[getIndex(AFTER)][getIndex(FINISHES)] = AFTER;
	this.table[getIndex(AFTER)][getIndex(FINISHEDBY)] = AFTER;
	this.table[getIndex(DURING)][getIndex(EQUALS)] = DURING;
	this.table[getIndex(DURING)][getIndex(BEFORE)] = BEFORE;
	this.table[getIndex(DURING)][getIndex(AFTER)] = AFTER;
	this.table[getIndex(DURING)][getIndex(DURING)] = DURING;
	this.table[getIndex(DURING)][getIndex(CONTAINS)] = NOCONSTRAINTS;
	this.table[getIndex(DURING)][getIndex(OVERLAPS)] = (
							    BEFORE |
							    OVERLAPS |
							    MEETS |
							    DURING |
							    STARTS);
	this.table[getIndex(DURING)][getIndex(OVERLAPPEDBY)] = (
								AFTER |
								OVERLAPPEDBY |
								METBY |
								DURING |
								FINISHES);
	this.table[getIndex(DURING)][getIndex(MEETS)] = BEFORE;
	this.table[getIndex(DURING)][getIndex(METBY)] = AFTER;
	this.table[getIndex(DURING)][getIndex(STARTS)] = DURING;
	this.table[getIndex(DURING)][getIndex(STARTEDBY)] = ( 
							     AFTER | 
							     OVERLAPPEDBY |
							     METBY |
							     DURING |
							     FINISHES);
	this.table[getIndex(DURING)][getIndex(FINISHES)] = DURING;
	this.table[getIndex(DURING)][getIndex(FINISHEDBY)] = (
							      BEFORE |
							      OVERLAPS |
							      MEETS |
							      DURING |
							      STARTS);
	this.table[getIndex(CONTAINS)][getIndex(EQUALS)] = CONTAINS;
	this.table[getIndex(CONTAINS)][getIndex(BEFORE)] = (
							    BEFORE |
							    OVERLAPS |
							    MEETS |
							    CONTAINS |
							    FINISHEDBY);
	this.table[getIndex(CONTAINS)][getIndex(AFTER)] = (
							   AFTER |
							   OVERLAPPEDBY |
							   CONTAINS |
							   METBY |
							   STARTEDBY);
	this.table[getIndex(CONTAINS)][getIndex(DURING)] = (
							    OVERLAPS |
							    OVERLAPPEDBY |
							    DURING |
							    CONTAINS |
							    EQUALS |
						            STARTS |
						      	    STARTEDBY |
					 		    FINISHES |
							    FINISHEDBY);
	this.table[getIndex(CONTAINS)][getIndex(CONTAINS)] = CONTAINS;
	this.table[getIndex(CONTAINS)][getIndex(OVERLAPS)] = (
							      OVERLAPS |
							      CONTAINS |
							      FINISHEDBY);
	this.table[getIndex(CONTAINS)][getIndex(OVERLAPPEDBY)] = (
								  OVERLAPPEDBY |
								  CONTAINS |
								  STARTEDBY);
	this.table[getIndex(CONTAINS)][getIndex(MEETS)] = ( 
							   OVERLAPS |
							   CONTAINS |
							   FINISHEDBY);
	this.table[getIndex(CONTAINS)][getIndex(METBY)] = (
							   OVERLAPPEDBY |
							   CONTAINS |
							   STARTEDBY);
	this.table[getIndex(CONTAINS)][getIndex(STARTS)] = (
							    CONTAINS |
							    FINISHEDBY |
							    OVERLAPS);
	this.table[getIndex(CONTAINS)][getIndex(STARTEDBY)] = CONTAINS;
	this.table[getIndex(CONTAINS)][getIndex(FINISHES)] = (
							      CONTAINS |
							      STARTEDBY |
							      OVERLAPPEDBY);
	this.table[getIndex(CONTAINS)][getIndex(FINISHEDBY)] = CONTAINS;
	this.table[getIndex(OVERLAPS)][getIndex(EQUALS)] = OVERLAPS;
	this.table[getIndex(OVERLAPS)][getIndex(BEFORE)] = BEFORE;
	this.table[getIndex(OVERLAPS)][getIndex(AFTER)] = (
							   AFTER |
							   CONTAINS |
							   OVERLAPPEDBY |
							   METBY |
							   STARTEDBY);
	this.table[getIndex(OVERLAPS)][getIndex(DURING)] = ( 
							    OVERLAPS |
							    DURING |
							    STARTS);
	this.table[getIndex(OVERLAPS)][getIndex(CONTAINS)] = (
							      BEFORE |
							      OVERLAPS |
							      MEETS |
							      CONTAINS |
							      FINISHEDBY);
	this.table[getIndex(OVERLAPS)][getIndex(OVERLAPS)] = (
							      OVERLAPS |
							      BEFORE |
							      MEETS);
	this.table[getIndex(OVERLAPS)][getIndex(OVERLAPPEDBY)] = (
								  OVERLAPS |
								  OVERLAPPEDBY |
								  DURING |
								  CONTAINS |
								  EQUALS 
|
								  STARTS 
|

STARTEDBY |

FINISHES |

FINISHEDBY);
	this.table[getIndex(OVERLAPS)][getIndex(MEETS)] = BEFORE;
	this.table[getIndex(OVERLAPS)][getIndex(METBY)] = (
							   OVERLAPPEDBY |
							   CONTAINS |
							   STARTEDBY);
	this.table[getIndex(OVERLAPS)][getIndex(STARTS)] = OVERLAPS;
	this.table[getIndex(OVERLAPS)][getIndex(STARTEDBY)] = (
							       CONTAINS |
							       FINISHEDBY |
							       OVERLAPS);
	this.table[getIndex(OVERLAPS)][getIndex(FINISHES)] = (
							      DURING |
							      STARTS |
							      OVERLAPS);
	this.table[getIndex(OVERLAPS)][getIndex(FINISHEDBY)] = (
								BEFORE |
								OVERLAPS |
								MEETS);
	this.table[getIndex(OVERLAPPEDBY)][getIndex(EQUALS)] = OVERLAPPEDBY;
	this.table[getIndex(OVERLAPPEDBY)][getIndex(BEFORE)] = (
								BEFORE |
								OVERLAPS |
								MEETS |
								CONTAINS |
								FINISHEDBY);
	this.table[getIndex(OVERLAPPEDBY)][getIndex(AFTER)] = AFTER;
	this.table[getIndex(OVERLAPPEDBY)][getIndex(DURING)] = (
								OVERLAPPEDBY |
								DURING |
								FINISHES);
	this.table[getIndex(OVERLAPPEDBY)][getIndex(CONTAINS)] = (
								  OVERLAPPEDBY |
								  AFTER |
								  METBY |
								  CONTAINS |
								  STARTEDBY);
	this.table[getIndex(OVERLAPPEDBY)][getIndex(OVERLAPS)] = (
								  OVERLAPS |
								  DURING |
								  CONTAINS |
								  EQUALS |

OVERLAPPEDBY |
								  STARTS 
|

STARTEDBY |

FINISHEDBY |

FINISHES);
	this.table[getIndex(OVERLAPPEDBY)][getIndex(OVERLAPPEDBY)] = (
								      OVERLAPPEDBY |
								      METBY |
								      AFTER);
	this.table[getIndex(OVERLAPPEDBY)][getIndex(MEETS)] = (
							       OVERLAPS |
							       CONTAINS |
							       FINISHEDBY);
	this.table[getIndex(OVERLAPPEDBY)][getIndex(METBY)] = AFTER;
	this.table[getIndex(OVERLAPPEDBY)][getIndex(STARTS)] = (
								OVERLAPPEDBY |
								DURING |
								FINISHES);
	this.table[getIndex(OVERLAPPEDBY)][getIndex(STARTEDBY)] = (
								   OVERLAPPEDBY |
								   AFTER |
								   METBY);
	this.table[getIndex(OVERLAPPEDBY)][getIndex(FINISHES)] = OVERLAPPEDBY;
	this.table[getIndex(OVERLAPPEDBY)][getIndex(FINISHEDBY)] = (
								    OVERLAPPEDBY |
								    CONTAINS |
								    STARTEDBY);
	this.table[getIndex(MEETS)][getIndex(EQUALS)] = MEETS;
	this.table[getIndex(MEETS)][getIndex(BEFORE)] = BEFORE;
	this.table[getIndex(MEETS)][getIndex(AFTER)] = (
							AFTER |
							OVERLAPPEDBY |
							METBY |
							CONTAINS |
							STARTEDBY);
	this.table[getIndex(MEETS)][getIndex(DURING)] = (
							 OVERLAPS |
							 DURING |
							 STARTS);
	this.table[getIndex(MEETS)][getIndex(CONTAINS)] = BEFORE;
	this.table[getIndex(MEETS)][getIndex(OVERLAPS)] = BEFORE;
	this.table[getIndex(MEETS)][getIndex(OVERLAPPEDBY)] = (
							       OVERLAPS |
							       DURING |
							       STARTS);
	this.table[getIndex(MEETS)][getIndex(MEETS)] = BEFORE;
	this.table[getIndex(MEETS)][getIndex(METBY)] = (
							FINISHES |
							FINISHEDBY |
							EQUALS);
	this.table[getIndex(MEETS)][getIndex(STARTS)] = MEETS;
	this.table[getIndex(MEETS)][getIndex(STARTEDBY)] = MEETS;
	this.table[getIndex(MEETS)][getIndex(FINISHES)] = (
							   DURING |
							   STARTS |
							   OVERLAPS);
	this.table[getIndex(MEETS)][getIndex(FINISHEDBY)] = BEFORE;
	this.table[getIndex(METBY)][getIndex(EQUALS)] = METBY;
	this.table[getIndex(METBY)][getIndex(BEFORE)] = (
							 BEFORE |
							 OVERLAPS |
							 CONTAINS |
							 MEETS |
							 FINISHEDBY);
	this.table[getIndex(METBY)][getIndex(AFTER)] = AFTER;
	this.table[getIndex(METBY)][getIndex(DURING)] = (
							 OVERLAPPEDBY |
							 DURING |
							 FINISHES);
	this.table[getIndex(METBY)][getIndex(CONTAINS)] = AFTER;
	this.table[getIndex(METBY)][getIndex(OVERLAPS)] = (
							   OVERLAPPEDBY |
							   DURING |
							   FINISHES);
	this.table[getIndex(METBY)][getIndex(OVERLAPPEDBY)] = AFTER;
	this.table[getIndex(METBY)][getIndex(MEETS)] = (
							STARTS |
							STARTEDBY |
							EQUALS);
	this.table[getIndex(METBY)][getIndex(METBY)] = AFTER;
	this.table[getIndex(METBY)][getIndex(STARTS)] = (
							 DURING |
							 FINISHES |
							 OVERLAPPEDBY);
	this.table[getIndex(METBY)][getIndex(STARTEDBY)] = AFTER;
	this.table[getIndex(METBY)][getIndex(FINISHES)] = METBY;
	this.table[getIndex(METBY)][getIndex(FINISHEDBY)] = METBY;
	this.table[getIndex(STARTS)][getIndex(EQUALS)] = STARTS;
	this.table[getIndex(STARTS)][getIndex(BEFORE)] = BEFORE;
	this.table[getIndex(STARTS)][getIndex(AFTER)] = AFTER;
	this.table[getIndex(STARTS)][getIndex(DURING)] = DURING;
	this.table[getIndex(STARTS)][getIndex(CONTAINS)] = (
							    BEFORE |
							    OVERLAPS |
							    MEETS |
							    CONTAINS |
							    FINISHEDBY);
	this.table[getIndex(STARTS)][getIndex(OVERLAPS)] = (
							    BEFORE |
							    OVERLAPS |
							    MEETS);
	this.table[getIndex(STARTS)][getIndex(OVERLAPPEDBY)] = (
								OVERLAPPEDBY |
								DURING |
								FINISHES);
	this.table[getIndex(STARTS)][getIndex(MEETS)] = BEFORE;
	this.table[getIndex(STARTS)][getIndex(METBY)] = METBY;
	this.table[getIndex(STARTS)][getIndex(STARTS)] = STARTS;
	this.table[getIndex(STARTS)][getIndex(STARTEDBY)] = (
							     STARTS |
							     STARTEDBY |
							     EQUALS);
	this.table[getIndex(STARTS)][getIndex(FINISHES)] = DURING;
	this.table[getIndex(STARTS)][getIndex(FINISHEDBY)] = (
							      BEFORE |
							      MEETS |
							      OVERLAPS);
	this.table[getIndex(STARTEDBY)][getIndex(EQUALS)] = STARTEDBY; 
	this.table[getIndex(STARTEDBY)][getIndex(BEFORE)] = (
							     BEFORE |
							     OVERLAPS |
							     MEETS |
							     CONTAINS |
							     FINISHEDBY); 
	this.table[getIndex(STARTEDBY)][getIndex(AFTER)] = AFTER; 
	this.table[getIndex(STARTEDBY)][getIndex(DURING)] = (
							     OVERLAPPEDBY |
							     DURING |
							     FINISHES); 
	this.table[getIndex(STARTEDBY)][getIndex(CONTAINS)] = CONTAINS; 
	this.table[getIndex(STARTEDBY)][getIndex(OVERLAPS)] = (
							       OVERLAPS |
							       CONTAINS |
							       FINISHEDBY); 
	this.table[getIndex(STARTEDBY)][getIndex(OVERLAPPEDBY)] = OVERLAPPEDBY; 
	this.table[getIndex(STARTEDBY)][getIndex(MEETS)] = (
							    OVERLAPS |
							    CONTAINS |
							    FINISHEDBY); 
	this.table[getIndex(STARTEDBY)][getIndex(METBY)] = METBY; 
	this.table[getIndex(STARTEDBY)][getIndex(STARTS)] = (
							     STARTS |
							     STARTEDBY |
							     EQUALS); 
	this.table[getIndex(STARTEDBY)][getIndex(STARTEDBY)] = STARTEDBY; 
	this.table[getIndex(STARTEDBY)][getIndex(FINISHES)] = OVERLAPPEDBY; 
	this.table[getIndex(STARTEDBY)][getIndex(FINISHEDBY)] = CONTAINS; 
	this.table[getIndex(FINISHES)][getIndex(EQUALS)] = FINISHES; 
	this.table[getIndex(FINISHES)][getIndex(BEFORE)] = BEFORE; 
	this.table[getIndex(FINISHES)][getIndex(AFTER)] = AFTER; 
	this.table[getIndex(FINISHES)][getIndex(DURING)] = DURING; 
	this.table[getIndex(FINISHES)][getIndex(CONTAINS)] = (
							      AFTER |
							      OVERLAPPEDBY |
							      METBY |
							      CONTAINS |
							      STARTEDBY); 
	this.table[getIndex(FINISHES)][getIndex(OVERLAPS)] = (
							      OVERLAPS |
							      DURING |
							      STARTS);
	this.table[getIndex(FINISHES)][getIndex(OVERLAPPEDBY)] = (
								  AFTER |
								  OVERLAPPEDBY |
								  METBY); 
	this.table[getIndex(FINISHES)][getIndex(MEETS)] = MEETS;
	this.table[getIndex(FINISHES)][getIndex(METBY)] = AFTER; 
	this.table[getIndex(FINISHES)][getIndex(STARTS)] = DURING; 
	this.table[getIndex(FINISHES)][getIndex(STARTEDBY)] = (
							       AFTER |
							       OVERLAPPEDBY |
							       METBY); 
	this.table[getIndex(FINISHES)][getIndex(FINISHES)] = FINISHES; 
	this.table[getIndex(FINISHES)][getIndex(FINISHEDBY)] = (
								FINISHES |
								FINISHEDBY |
								EQUALS); 
	this.table[getIndex(FINISHEDBY)][getIndex(EQUALS)] = FINISHEDBY; 
	this.table[getIndex(FINISHEDBY)][getIndex(BEFORE)] = BEFORE; 
	this.table[getIndex(FINISHEDBY)][getIndex(AFTER)] = (
							     AFTER |
							     OVERLAPPEDBY |
							     METBY |
							     CONTAINS |
							     STARTEDBY); 
	this.table[getIndex(FINISHEDBY)][getIndex(DURING)] = (
							      OVERLAPS |
							      DURING |
							      STARTS);
	this.table[getIndex(FINISHEDBY)][getIndex(CONTAINS)] = CONTAINS; 
	this.table[getIndex(FINISHEDBY)][getIndex(OVERLAPS)] = OVERLAPS; 
	this.table[getIndex(FINISHEDBY)][getIndex(OVERLAPPEDBY)] = (
								    OVERLAPPEDBY |
								    CONTAINS |
								    STARTEDBY);
	this.table[getIndex(FINISHEDBY)][getIndex(MEETS)] = MEETS; 
	this.table[getIndex(FINISHEDBY)][getIndex(METBY)] = (
							     STARTEDBY |
							     OVERLAPPEDBY |
							     CONTAINS); 
	this.table[getIndex(FINISHEDBY)][getIndex(STARTS)] = OVERLAPS; 
	this.table[getIndex(FINISHEDBY)][getIndex(STARTEDBY)] = CONTAINS; 
	this.table[getIndex(FINISHEDBY)][getIndex(FINISHES)] = (
								FINISHEDBY |
								FINISHES |
								EQUALS); 
	this.table[getIndex(FINISHEDBY)][getIndex(FINISHEDBY)] = FINISHEDBY; 
    }    
}
		
	

