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((Document) null);
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 = (BasicPatternElement) super.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 > 1 :
112 constraints1 != null ? constraints1.size() > 1 :
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
|