1 cananian 1.1     // Tuple.java, created Sat Oct 10 01:37:39 1998 by cananian
 2 cananian 1.2     // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu>
 3 cananian 1.2     // Licensed under the terms of the GNU GPL; see COPYING for details.
 4 cananian 1.1     package harpoon.Util;
 5 cananian 1.1     
 6 cananian 1.2.2.3 import java.util.Arrays;
 7 cananian 1.2.2.3 import java.util.Collections;
 8 cananian 1.2.2.6 import java.util.Comparator;
 9 cananian 1.2.2.3 import java.util.List;
10 cananian 1.4     
11 cananian 1.4     import net.cscott.jutil.Default;
12 cananian 1.1     /**
13 cananian 1.1      * A <code>Tuple</code> is an ordered list of objects that works
14 cananian 1.2.2.3  * properly in Hashtables & etc.  Tuples may have <code>null</code> elements.
15 cananian 1.2.2.6  * <code>Tuple</code>s are <code>Comparable</code> iff the objects in
16 cananian 1.2.2.6  * the elements array are <code>Comparable</code>.
17 cananian 1.1      * 
18 cananian 1.1      * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
19 cananian 1.4      * @version $Id: Tuple.java,v 1.4 2004/02/08 01:56:15 cananian Exp $
20 cananian 1.1      */
21 cananian 1.2.2.9 public class Tuple implements Comparable, java.io.Serializable {
22 cananian 1.2.2.6     final Comparator objcmp;
23 cananian 1.2.2.6     final Object elements[];
24 cananian 1.1         /** Creates a <code>Tuple</code>. */
25 cananian 1.1         public Tuple(Object[] elements) {
26 cananian 1.1             this.elements = elements;
27 cananian 1.2.2.6         this.objcmp = Default.comparator;
28 cananian 1.1         }
29 cananian 1.2.2.6     /** Creates a <code>Comparable</code> <code>Tuple</code> which will use
30 cananian 1.2.2.6      *  the specified <code>Comparator</code> to do object comparisons. */
31 cananian 1.2.2.6     public Tuple(Object[] elements, Comparator objcmp) {
32 cananian 1.2.2.6         this.elements = elements;
33 cananian 1.2.2.6         this.objcmp = objcmp;
34 cananian 1.1         }
35 cananian 1.2.2.1     /** Projects an element of the <code>Tuple</code>. */
36 cananian 1.2.2.1     public Object proj(int i) { return elements[i]; }
37 cananian 1.2.2.7     /** Returns an unmodifiable list view of the <code>Tuple</code>. */
38 cananian 1.2.2.3     public List asList() {
39 cananian 1.2.2.3         return Collections.unmodifiableList(Arrays.asList(elements));
40 cananian 1.2.2.3     }
41 cananian 1.2.2.8     /** Returns a human-readable description of this <code>Tuple</code>. */
42 cananian 1.2.2.8     public String toString() { return Util.print(asList()); }
43 cananian 1.2.2.1     /** Synthesizes a hashcode from the hashcodes of the elements. */
44 cananian 1.1         public int hashCode() {
45 cananian 1.1             int hc = elements.length;
46 cananian 1.1             for (int i=0; i<elements.length; i++)
47 cananian 1.2.2.3             if (elements[i]!=null)
48 cananian 1.2.2.3                 hc ^= elements[i].hashCode();
49 cananian 1.1             return hc;
50 cananian 1.1         }
51 cananian 1.2.2.1     /** Does an element-by-element comparison of two <code>Tuple</code>s. */
52 cananian 1.1         public boolean equals(Object obj) {
53 cananian 1.2.2.4         Tuple t;
54 cananian 1.2.2.5         if (this==obj) return true;
55 cananian 1.2.2.5         if (null==obj) return false;
56 cananian 1.2.2.4         try { t = (Tuple) obj; } catch (ClassCastException e) { return false; }
57 cananian 1.1             if (this.elements.length != t.elements.length) return false;
58 cananian 1.1             for (int i=0; i<elements.length; i++)
59 cananian 1.2.2.3             if (this.elements[i]==null) {
60 cananian 1.2.2.3                 if (t.elements[i]!=null) return false;
61 cananian 1.2.2.3             } else {
62 cananian 1.2.2.3                 if (!this.elements[i].equals(t.elements[i])) return false;
63 cananian 1.2.2.3             }
64 cananian 1.1             return true;
65 cananian 1.2.2.6     }
66 cananian 1.2.2.6     /** Does an element-by-element comparison of two <code>Tuple</code>s.
67 cananian 1.2.2.6      *  Inconsistent with <code>equals()</code> only if the underlying
68 cananian 1.2.2.6      *  comparator is.  Shorter tuples are compared as less than longer
69 cananian 1.2.2.6      *  tuples. */
70 cananian 1.2.2.6     public int compareTo(Object o) { // dict order: smaller first.
71 cananian 1.2.2.6         Object[] el2 = ((Tuple)o).elements;
72 cananian 1.2.2.6         if (elements.length!=el2.length) return elements.length-el2.length;
73 cananian 1.2.2.6         for (int i=0; i<elements.length; i++) {
74 cananian 1.2.2.6             int c = objcmp.compare(elements[i], el2[i]);
75 cananian 1.2.2.6             if (c!=0) return c;
76 cananian 1.2.2.6         }
77 cananian 1.2.2.6         return 0;
78 cananian 1.1         }
79 cananian 1.1     }