1   /*
2    *  ComplexPatternElement.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: ComplexPatternElement.java,v 1.11 2005/01/11 13:51:36 ian Exp $
14   */
15  
16  
17  package gate.jape;
18  
19  import java.util.Iterator;
20  
21  import gate.AnnotationSet;
22  import gate.Document;
23  import gate.util.Strings;
24  
25  
26  /**
27    * A pattern element enclosed in round brackets. Has a
28    * ConstraintGroups, Kleene operator and binding name.
29    */
30  public class ComplexPatternElement extends PatternElement
31  implements JapeConstants, java.io.Serializable
32  {
33    /** Debug flag */
34    private static final boolean DEBUG = false;
35  
36    /** Kleene operator (defaults to none). Other values: KLEENE_STAR (*);
37      * KLEENE_PLUS (+); KLEENE_QUERY (?) */
38    private int kleeneOp = NO_KLEENE_OP;
39  
40    /** Binding name (may be null). */
41    private String bindingName = null;
42  
43    /** Get binding name. */
44    public String getBindingName() { return bindingName; }
45  
46    /** Get a list of CPEs that we contain. */
47    protected Iterator getCPEs() {
48      return constraintGroup.getCPEs();
49    } // getCPEs
50  
51    /** The recursive definition of what pattern elements make up this one. */
52    private ConstraintGroup constraintGroup;
53  
54    /** Construction from ConstraintGroup, Kleene operator type and binding
55      * name. Kleene types are defined in JapeConstants.
56      */
57    public ComplexPatternElement(
58      ConstraintGroup constraintGroup,
59      int kleeneOp,
60      String bindingName
61    ) {
62      this.constraintGroup = constraintGroup;
63      this.kleeneOp = kleeneOp;
64      this.bindingName = bindingName;
65    }
66  
67    /** Need cloning for processing of macro references. See comments on
68      * <CODE>PatternElement.clone()</CODE>
69      */
70    public Object clone() {
71      ComplexPatternElement newPE = (ComplexPatternElement) super.clone();
72      newPE.constraintGroup = (ConstraintGroup) constraintGroup.clone();
73      return newPE;
74    } // clone
75  
76    /** Finish: replace dynamic data structures with Java arrays; called
77      * after parsing.
78      */
79    public void finish() {
80      constraintGroup.finish();
81    } // finish
82  
83    /** Access to the annotations that have been matched. */
84    public AnnotationSet getMatchedAnnots() {
85      return constraintGroup.getMatchedAnnots();
86    }
87  
88    /** Reset: clear caches of annotations matched. */
89    public void reset() {
90      constraintGroup.reset();
91      super.reset();
92    } // reset
93  
94    /** Multilevel rollback of annotation caches. */
95    public void rollback(int arity) {
96      /*Debug.pr(
97        this, "CPE rollback(" + arity + "), mH.size = " +
98        matchHistory.size() + Debug.getNl()
99      );*/
100 
101     // for arity times, pop the arity history stack and
102     // ask the CG to rollback how ever many times it succeeded then
103     for(int i=0; i<arity; i++) {
104       int matchArity = ((Integer) matchHistory.pop()).intValue();
105       constraintGroup.rollback(matchArity);
106     }
107   } // rollback
108 
109   /** Does this element match the document at this position? */
110   public boolean matches(
111     Document doc, int position, MutableInteger newPosition
112   ) {
113     /*Debug.pr(
114       this, "CPE.matches: trying at position " + position + Debug.getNl()
115     );*/
116     int matchArity = 0; // number of successful applications in this match
117     boolean firstTry = constraintGroup.matches(doc, position, newPosition);
118     if(firstTry) {
119       matchArity++;
120       /*Debug.pr(this,
121         "CPE.matches: first try succeeded, newPosition = " + newPosition.value
122         + Debug.getNl()
123       );*/
124     }
125     int theEndOfTheDocument = doc.getContent().size().intValue();
126 
127     if(kleeneOp == NO_KLEENE_OP) {
128       if(firstTry) matchHistory.push(new Integer(matchArity));
129       return firstTry;
130     }
131     else if(kleeneOp == KLEENE_QUERY) {
132       if(firstTry) matchHistory.push(new Integer(matchArity));
133       /* Debug.pr(this, "CPE.matches: true, QUERY rule"); */
134       return true;
135     }
136     else if(kleeneOp == KLEENE_PLUS) {
137       if(! firstTry)
138         return false; // no cache purge: maybe we're under another * etc.
139     }
140     else if(kleeneOp == KLEENE_STAR && !firstTry) {
141       /*Debug.pr(this,
142         "CPE.matches: true, STAR rule, newPos("+newPosition.value+")");*/
143       matchHistory.push(new Integer(matchArity));
144       return true;
145     }
146 
147     // we get here if we have either Kleene *, or Kleene +, and a
148     // successful first move. now we try it again as many times as it
149     // succeeds, store the final match arity and then return true
150     while(constraintGroup.matches(doc, newPosition.value, newPosition)) {
151       /*Debug.pr(this,
152         "CPE.matches: trying while loop, matchArity = " + matchArity);*/
153       matchArity++;
154 
155       // if we've negated failing constraints, we may match for ever
156       if(newPosition.value >= theEndOfTheDocument) // stop at the end!
157         break;
158     } // while
159     matchHistory.push(new Integer(matchArity));
160     //Debug.pr(this,
161     //         "CPE.matches: true, matchArity(" + matchArity + ") pushed");
162     return true;
163   } // matches
164 
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     String newline = Strings.getNl();
172 
173     StringBuffer buf = new StringBuffer(
174       pad + "CPE: bindingName(" + bindingName + "); kleeneOp("
175     );
176 
177     switch(kleeneOp) {
178       case NO_KLEENE_OP: buf.append("NO_KLEENE_OP"); break;
179       case KLEENE_STAR:  buf.append("KLEENE_STAR");  break;
180       case KLEENE_QUERY: buf.append("KLEENE_QUERY"); break;
181       case KLEENE_PLUS:  buf.append("KLEENE_PLUS");  break;
182       default: break;
183     }
184 
185     buf.append(
186       "); constraintGroup(" + newline +
187       constraintGroup.toString(Strings.addPadding(pad, INDENT_PADDING)) +
188       newline + pad + ") CPE." + newline
189     );
190 
191     return buf.toString();
192   } // toString
193   //needed by FSM
194 
195   public int getKleeneOp(){ return kleeneOp; };
196 
197   public ConstraintGroup getConstraintGroup(){ return constraintGroup; };
198 
199 } // class ComplexPatternElement
200 
201 
202 // $Log: ComplexPatternElement.java,v $
203 // Revision 1.11  2005/01/11 13:51:36  ian
204 // Updating copyrights to 1998-2005 in preparation for v3.0
205 //
206 // Revision 1.10  2004/07/21 17:10:07  akshay
207 // Changed copyright from 1998-2001 to 1998-2004
208 //
209 // Revision 1.9  2004/03/25 13:01:15  valyt
210 // Imports optimisation throughout the Java sources
211 // (to get rid of annoying warnings in Eclipse)
212 //
213 // Revision 1.8  2001/09/13 12:09:49  kalina
214 // Removed completely the use of jgl.objectspace.Array and such.
215 // Instead all sources now use the new Collections, typically ArrayList.
216 // I ran the tests and I ran some documents and compared with keys.
217 // JAPE seems to work well (that's where it all was). If there are problems
218 // maybe look at those new structures first.
219 //
220 // Revision 1.7  2001/09/12 11:59:33  kalina
221 // Changed the old JAPE stuff to use the new Collections API,
222 // instead of com.objectspace stuff. Will eliminate that library
223 // completely very soon! Just one class left to re-implement,
224 //
225 // ParseCPSL.jj changed accordingly. All tested and no smoke.
226 //
227 // Revision 1.6  2000/11/08 16:35:02  hamish
228 // formatting
229 //
230 // Revision 1.5  2000/10/26 10:45:30  oana
231 // Modified in the code style
232 //
233 // Revision 1.4  2000/10/16 16:44:33  oana
234 // Changed the comment of DEBUG variable
235 //
236 // Revision 1.3  2000/10/10 15:36:35  oana
237 // Changed System.out in Out and System.err in Err;
238 // Added the DEBUG variable seted on false;
239 // Added in the header the licence;
240 //
241 // Revision 1.2  2000/04/14 18:02:46  valyt
242 // Added some gate.fsm classes
243 // added some accessor function in old jape classes
244 //
245 // Revision 1.1  2000/02/23 13:46:05  hamish
246 // added
247 //
248 // Revision 1.1.1.1  1999/02/03 16:23:01  hamish
249 // added gate2
250 //
251 // Revision 1.14  1998/11/13 13:17:16  hamish
252 // merged in the doc length bug fix
253 //
254 // Revision 1.13  1998/11/12 17:47:27  kalina
255 // A bug fixed, wasn't restoring the document length
256 //
257 // Revision 1.12  1998/11/05 13:36:29  kalina
258 // moved to use array of JdmAttributes for selectNextAnnotation instead
259 // of a sequence
260 //
261 // Revision 1.11  1998/11/01 21:21:35  hamish
262 // use Java arrays in transduction where possible
263 //
264 // Revision 1.10  1998/10/06 16:16:09  hamish
265 // negation percolation during constrain add; position advance when none at end
266 //
267 // Revision 1.9  1998/10/01 16:06:29  hamish
268 // new appelt transduction style, replacing buggy version
269 //
270 // Revision 1.8  1998/09/26 09:19:14  hamish
271 // added cloning of PE macros
272 //
273 // Revision 1.7  1998/09/17 16:48:29  hamish
274 // added macro defs and macro refs on LHS
275 //
276 // Revision 1.6  1998/08/12 15:39:32  hamish
277 // added padding toString methods
278 //
279 // Revision 1.5  1998/08/05 21:58:04  hamish
280 // backend works on simple test
281 //
282 // Revision 1.4  1998/08/03 19:51:19  hamish
283 // rollback added
284 //
285 // Revision 1.3  1998/07/30 11:05:14  hamish
286 // more jape
287 //
288 // Revision 1.2  1998/07/29 11:06:54  hamish
289 // first compiling version
290 //
291 // Revision 1.1.1.1  1998/07/28 16:37:46  hamish
292 // gate2 lives
293