BasicPatternElement.java
001 /*
002  *  BasicPatternElement.java - transducer class
003  *
004  *  Copyright (c) 1995-2010, The University of Sheffield. See the file
005  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
006  *
007  *  This file is part of GATE (see http://gate.ac.uk/), and is free
008  *  software, licenced under the GNU Library General Public License,
009  *  Version 2, June 1991 (in the distribution as file licence.html,
010  *  and also available at http://gate.ac.uk/gate/licence.html).
011  *
012  *  Hamish Cunningham, 24/07/98
013  *
014  *  $Id: BasicPatternElement.java 12006 2009-12-01 17:24:28Z thomas_heitz $
015  */
016 
017 
018 package gate.jape;
019 
020 import java.util.*;
021 
022 import gate.*;
023 import gate.annotation.AnnotationSetImpl;
024 import gate.util.*;
025 
026 
027 /**
028   * A pattern element within curly braces. Has a set of Constraint,
029   * which all must be satisfied at whatever position the element is being
030   * matched at.
031   */
032 public class BasicPatternElement
033 extends PatternElement implements JapeConstants, java.io.Serializable
034 {
035   /** Debug flag */
036   private static final boolean DEBUG = false;
037 
038   /** A set of Constraint. Used during parsing. */
039   private ArrayList<Constraint> constraints1;
040 
041   /** A set of Constraint. Used during matching. */
042   private Constraint[] constraints2;
043 
044   /** A map of constraint annot type to constraint. Used during parsing. */
045   private HashMap<Object, Constraint> constraintsMap;
046 
047   /** Cache of the last position we failed at (-1 when none). */
048   private int lastFailurePoint = -1;
049 
050   /** The position of the next available annotation of the type required
051     * by the first constraint.
052     */
053   //private MutableInteger nextAvailable = new MutableInteger();
054 
055   /** The set of annotations we have matched. */
056   private AnnotationSet matchedAnnots;
057 
058   /** Construction. */
059   public BasicPatternElement() {
060     constraintsMap = new HashMap<Object, Constraint>();
061     constraints1 = new ArrayList<Constraint>();
062     lastFailurePoint = -1;
063     //nextAvailable = new MutableInteger();
064     matchedAnnots = new AnnotationSetImpl((Documentnull);
065   // construction
066 
067   /** Need cloning for processing of macro references. See comments on
068     <CODE>PatternElement.clone()</CODE>
069     */
070   public Object clone() {
071     BasicPatternElement newPE = (BasicPatternElementsuper.clone();
072     newPE.constraintsMap = (HashMap<Object, Constraint>constraintsMap.clone();
073     newPE.constraints1 = new ArrayList<Constraint>();
074     int consLen = constraints1.size();
075     for(int i = 0; i < consLen; i++)
076       newPE.constraints1.add(
077         (Constraint)constraints1.get(i).clone()
078       );
079 //    newPE.matchedAnnots = new AnnotationSetImpl((Document) null);
080 //    newPE.matchedAnnots.addAll(matchedAnnots);
081     return newPE;
082   // clone
083 
084   /** Add a constraint. Ensures that only one constraint of any given
085     * annotation type and negation state exists.
086     */
087   public void addConstraint(Constraint newConstraint) {
088     /* if a constraint with the same negation state as this constraint is
089      * already mapped, put it's attributes on the existing constraint, else
090      * add it
091      */
092     String annotType = newConstraint.getAnnotType();
093     Pair typeNegKey = new Pair(annotType, newConstraint.isNegated());
094 
095     Constraint existingConstraint = constraintsMap.get(typeNegKey);
096     if(existingConstraint == null) {
097       constraintsMap.put(typeNegKey, newConstraint);
098       constraints1.add(newConstraint);
099     }
100     else {
101       existingConstraint.addAttributes(newConstraint.getAttributeSeq());
102     }
103   // addConstraint
104 
105 
106   /**
107    * Indicates whether this constraint deals with only one type of annotation or
108    * multiple types.
109    */
110   public boolean isMultiType() {
111       return constraints2 != null ? constraints2.length > :
112              constraints1 != null ? constraints1.size() :
113              false;
114   }
115 
116   /** Finish: replace dynamic data structures with Java arrays; called
117     * after parsing.
118     */
119   public void finish() {
120     int j=0;
121     constraints2 = new Constraint[constraints1.size()];
122     for(Constraint c : constraints1 ) {
123       constraints2[j= c;
124       constraints2[j++].finish();
125     }
126     constraints1 = null;
127   // finish
128 
129 
130 
131   /** Create a string representation of the object. */
132   public String toString() {
133     StringBuffer result = new StringBuffer("{");
134     Constraint[] constraints = getConstraints();
135     for(int i = 0; i<constraints.length; i++){
136       result.append(constraints[i].shortDesc() ",");
137     }
138     result.setCharAt(result.length() -1'}');
139     return result.toString();
140   }
141 
142   /** Create a string representation of the object. */
143   public String toString(String pad) {
144     String newline = Strings.getNl();
145     String newPad = Strings.addPadding(pad, INDENT_PADDING);
146 
147     StringBuffer buf = new StringBuffer(pad +
148       "BPE: lastFailurePoint(" + lastFailurePoint + "); constraints("
149     );
150 
151     // constraints
152     if(constraints1 != null) {
153       for(int len = constraints1.size(), i = 0; i < len; i++)
154         buf.append(
155           newline + constraints1.get(i).getDisplayString(newPad)
156         );
157     else {
158       for(int len = constraints2.length, i = 0; i < len; i++)
159         buf.append(newline + constraints2[i].getDisplayString(newPad));
160     }
161 
162     // matched annots
163 //    buf.append(
164 //      newline + pad + "matchedAnnots: " + matchedAnnots +
165 //      newline + pad + ") BPE."
166 //    );
167 
168     return buf.toString();
169   // toString
170 
171   /**
172     * Returns a short description.
173     */
174   public String shortDesc() {
175     String res = "";
176     if(constraints1 != null) {
177       for(int len = constraints1.size(), i = 0; i < len; i++)
178         res += constraints1.get(i).toString();
179     else {
180       for(int len = constraints2.length, i = 0; i < len; i++)
181         res += constraints2[i].shortDesc();
182     }
183     return res;
184   }
185 
186   /**
187    * Get the current list of unfinished Constraint objects. This
188    * can only be used before the finish() method is used.
189    @return the array list of constraint objects. Will be null after
190    * the finish() method has been used.
191    */
192   public ArrayList<Constraint> getUnfinishedConstraints() {
193     return constraints1;
194   }
195 
196   /**
197    * Get the finished Constraint objects. Can only be used after the
198    * finish() method has been used.
199    @return an array of constraint objects. Will be null before the
200    * finish() method has been used.
201    */
202   public Constraint[] getConstraints(){
203     return constraints2;
204   }
205 // class BasicPatternElement