1   /*
2    *  Constraint.java - transducer class
3    *
4    *  Copyright (c) 1998-2005, The University of Sheffield.
5    *
6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
7    *  software, licenced under the GNU Library General Public License,
8    *  Version 2, June 1991 (in the distribution as file licence.html,
9    *  and also available at http://gate.ac.uk/gate/licence.html).
10   *
11   *  Hamish Cunningham, 24/07/98
12   *
13   *  $Id: Constraint.java,v 1.14 2006/01/06 22:37:24 kwilliams Exp $
14   */
15  
16  
17  package gate.jape;
18  
19  import java.util.ArrayList;
20  import java.util.Arrays;
21  import java.util.Iterator;
22  
23  import gate.FeatureMap;
24  import gate.util.SimpleFeatureMapImpl;
25  
26  
27  /**
28    * An individual annotation/attribute/value expression. It doesn't extend
29    * PatternElement, even though it has to "match", because a set of
30    * Constraint must be applied together in order to avoid doing separate
31    * selectAnnotations calls for each one.
32    */
33  public class Constraint
34  implements JapeConstants, java.io.Serializable, Cloneable
35  {
36    /** Debug flag */
37    private static final boolean DEBUG = false;
38  
39    /** Construction from annot type string */
40    public Constraint(String annotType) {
41      this(annotType, new SimpleFeatureMapImpl());
42    } // Construction from annot type
43  
44    /** Construction from annot type and attribute sequence */
45    public Constraint(String annotType, FeatureMap attrs) {
46      this.annotType = annotType;
47      this.attrs1 = attrs;
48    } // Construction from annot type and attribute sequence
49  
50    /** Construction from annot type and array of attributes */
51    public Constraint(String annotType, ArrayList attrsArray) {
52      this(annotType, new SimpleFeatureMapImpl());
53      for ( Iterator i = attrsArray.iterator(); i.hasNext(); )
54        attrs1.put(((JdmAttribute) i.next()).getName(),
55                                            ((JdmAttribute) i.next()).getValue());
56    } // Construction from annot type and array of attributes
57  
58    /** The type of annnotation we're looking for. */
59    private String annotType;
60  
61    /** Are we negated? */
62    private boolean negated = false;
63  
64    /** Set negation. */
65    public void negate() { negated = true; }
66  
67    /** Access to negation flag. */
68    public boolean isNegated() { return negated; }
69  
70    /** Get the type of annnotation we're looking for. */
71    public String getAnnotType() { return annotType; }
72  
73    /** The attributes that must be present on the matched annotation. */
74    private FeatureMap attrs1;
75  
76    /** The attributes array that must be present on the matched annotation. */
77    private JdmAttribute[] attrs2;
78  
79    /** Get the attributes that must be present on the matched annotation. */
80    public FeatureMap getAttributeSeq() { return attrs1; }
81  
82    /** Get the attributes that must be present on the matched annotation. */
83    public JdmAttribute[] getAttributeArray() { return attrs2; }
84  
85    /** Add an attribute. */
86    public void addAttribute(JdmAttribute attr) {
87      attrs1.put(attr.getName(), attr.getValue());
88    } // addAttribute
89  
90    /** Create and add an attribute. */
91    public void addAttribute(String name, Object value) {
92      attrs1.put(name, value);
93    } // addAttribute
94  
95    /** Need cloning for processing of macro references. See comments on
96      * <CODE>PatternElement.clone()</CODE>
97      */
98    public Object clone() {
99      Constraint newC = null;
100     try {
101       newC = (Constraint) super.clone();
102     } catch(CloneNotSupportedException e) {
103       throw(new InternalError(e.toString()));
104     }
105     newC.annotType = annotType;
106     newC.attrs1 = (FeatureMap) ((SimpleFeatureMapImpl) attrs1).clone();
107 
108     /* Enumeration e = attrs1.getElements();
109        while(e.hasMoreElements())
110          newC.attrs1.addAll(new JdmAttribute((JdmAttribute) e.nextElement()));
111        newC.negated = negated;
112     */
113     return newC;
114   } // clone
115 
116   /** Returns a boolean value indicating whether this Constraint is
117     * equivalent to the given Constraint.  If the given object is not
118     * a Constraint, compares the two objects using
119     * <CODE>Object.equals()</CODE>.
120     */
121   public boolean equals(Object other) {
122     if (!(other instanceof Constraint)) return super.equals(other);
123     Constraint o = (Constraint) other;
124     
125     return (o.negated == negated &&
126       o.annotType.equals(annotType) &&
127       o.attrs1.toString().equals(attrs1.toString()));
128   }
129 
130   /** Returns an integer hash code for this object.
131     */
132   public int hashCode() {
133     int hashCode = negated ? 0 : 37 * 17;
134     hashCode = 37 * hashCode + annotType.hashCode();
135     hashCode = 37 * hashCode + attrs1.hashCode();
136     return hashCode;
137   }
138 
139  /** Finish: replace dynamic data structures with Java arrays; called
140     * after parsing.
141     */
142   public void finish() {
143     /*
144     if(attrs1 == null || attrs1.size() == 0) {
145       attrs2 = new JdmAttribute[0];
146       attrs1 = null;
147       return;
148     }
149     int attrsLen = attrs1.size();
150     attrs2 = new JdmAttribute[attrsLen];
151 
152     int i = 0;
153     //for(Enumeration e = attrs1.getElements(); e.hasMoreElements(); i++) {
154     //  attrs2[i] = (JdmAttribute) e.nextElement();
155     //}
156     Iterator iter = attrs1.keySet().iterator();
157     while(iter.hasNext()) {
158       String name = (String) iter.next();
159       Object value = attrs1.get(name);
160       attrs2[i++] = new JdmAttribute(name, value);
161     }
162     attrs1 = null;
163     */
164   } // finish
165 
166   /** Create a string representation of the object. */
167   public String toString() { return toString(""); }
168 
169   /** Create a string representation of the object. */
170   public String toString(String pad) {
171     StringBuffer buf = new StringBuffer
172   (pad + "Constraint: " + annotType + (negated ? "!=" : "="));
173     buf.append(attrs1 == null ? 
174          Arrays.asList(attrs2).toString() : 
175          attrs1.toString());
176     return buf.toString();
177   } // toString
178 
179   public String shortDesc() {
180     String res = annotType + "(";
181     if(attrs1 == null) {
182       for(int i=0; i<attrs2.length; i++)
183         res +=" " + attrs2[i];
184     } else {
185       res += attrs1.toString();
186     }
187     res += ")";
188     return res;
189   } // shortDesc
190 
191 } // class Constraint
192 
193 
194 // $Log: Constraint.java,v $
195 // Revision 1.14  2006/01/06 22:37:24  kwilliams
196 // Implement equals(Object) and hashCode() so we can usefully be put into Sets, HashMaps, etc.
197 //
198 // Revision 1.13  2006/01/06 22:03:04  kwilliams
199 // Define other constructors in terms of Constraint(String,FeatureMap)
200 //
201 // Revision 1.12  2005/07/15 15:37:32  valyt
202 // New toString() method from Ken Williams
203 //
204 // Revision 1.11  2005/01/11 13:51:36  ian
205 // Updating copyrights to 1998-2005 in preparation for v3.0
206 //
207 // Revision 1.10  2004/07/21 17:10:07  akshay
208 // Changed copyright from 1998-2001 to 1998-2004
209 //
210 // Revision 1.9  2004/03/25 13:01:14  valyt
211 // Imports optimisation throughout the Java sources
212 // (to get rid of annoying warnings in Eclipse)
213 //
214 // Revision 1.8  2001/09/13 12:09:49  kalina
215 // Removed completely the use of jgl.objectspace.Array and such.
216 // Instead all sources now use the new Collections, typically ArrayList.
217 // I ran the tests and I ran some documents and compared with keys.
218 // JAPE seems to work well (that's where it all was). If there are problems
219 // maybe look at those new structures first.
220 //
221 // Revision 1.7  2000/11/08 16:35:02  hamish
222 // formatting
223 //
224 // Revision 1.6  2000/10/26 10:45:30  oana
225 // Modified in the code style
226 //
227 // Revision 1.5  2000/10/16 16:44:33  oana
228 // Changed the comment of DEBUG variable
229 //
230 // Revision 1.4  2000/10/10 15:36:35  oana
231 // Changed System.out in Out and System.err in Err;
232 // Added the DEBUG variable seted on false;
233 // Added in the header the licence;
234 //
235 // Revision 1.3  2000/05/25 16:10:41  valyt
236 // JapeGUI is working
237 //
238 // Revision 1.2  2000/04/20 13:26:41  valyt
239 // Added the graph_drawing library.
240 // Creating of the NFSM and DFSM now works.
241 //
242 // Revision 1.1  2000/02/23 13:46:05  hamish
243 // added
244 //
245 // Revision 1.1.1.1  1999/02/03 16:23:01  hamish
246 // added gate2
247 //
248 // Revision 1.8  1998/11/05 13:36:30  kalina
249 // moved to use array of JdmAttributes for selectNextAnnotation instead of a sequence
250 //
251 // Revision 1.7  1998/11/01 22:35:56  kalina
252 // attribute seq hashtable mod
253 //
254 // Revision 1.6  1998/09/23 12:48:02  hamish
255 // negation added; noncontiguous BPEs disallowed
256 //
257 // Revision 1.5  1998/08/12 15:39:34  hamish
258 // added padding toString methods
259 //
260 // Revision 1.4  1998/07/31 13:12:14  mks
261 // done RHS stuff, not tested
262 //
263 // Revision 1.3  1998/07/30 11:05:15  mks
264 // more jape
265 //
266 // Revision 1.2  1998/07/29 11:06:55  hamish
267 // first compiling version
268 //
269 // Revision 1.1.1.1  1998/07/28 16:37:46  hamish
270 // gate2 lives
271