KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > xquery > normalize > VisitorContext


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 Universite de Versailles Saint-Quentin.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
18  * You can also get it at http://www.gnu.org/licenses/lgpl.html
19  *
20  * For more information on this software, see http://www.xquark.org.
21  */

22
23 package org.xquark.xquery.normalize;
24
25 /**
26  * This class is used to store and retrieve a context informations inside the expression normalize visitor.<BR>
27  * Context information are stored in a hashmap: the key is the question (or the order), the value is an object that
28  * is the (possibly) answer of the question (or the data to use for the order).<BR>
29  * IMPORTANT: the question is a string like &lt;depth&gt;'.'&lt;node name&gt;["."&lt;question&gt;] where:<BR><UL>
30  * <LI>&lt;depth&gt; is the absolute depth where is the node that must answer the question. The wildcard '*' can be used to
31  * mean that the depth is indifferent.</LI>
32  * <LI>&lt;node name&gt; is the corresponding Class name that must answer the question (if its depth equals &lt;depth&gt;).</LI>
33  * <LI>&lt;question&gt; a possible question. If there is no question, the implicite question is "is there a &lt;node name&gt;
34  * at the given &lt;depth&gt;?".</LI>
35  * </UL>Examples of questions:<BR><UL>
36  * <LI>"5.FLWRExpression": is there a FLWRExpresion node in the absolute depth 5? Can return true or false (for example).</LI>
37  * <LI>"*.FLWRExpression": is there a FLWRExpresion node in any depth? Can return true or false (for example).</LI>
38  * <LI>"3.XQueryExpressionSequence.containsOnlyOneChild": is there a XQueryExpressionSequence in the absolute depth 3 and
39  * have it only one child expression? Can return true or false (for example).</LI>
40  * <LI>"10.Variable.getExpression": If there is a Variable node in the absolute depth 10, get me the associeted expression.
41  * Can return null or an expression.</LI>
42  * </UL><BR>
43  */

44 public class VisitorContext {
45
46     /** CVS/QA stuff. éèàùâêîôûäëïöüç*/
47
48
49 /*************************** Package visibility constants *******************************/
50
51     /** Constants for specific keys. */
52
53     static final int _XQUERYEXPRESSIONSEQUENCE_EXISTS = 1;
54     //static final int _XQUERYEXPRESSIONSEQUENCE_ELEMENT_CHILDREN = 2;
55

56     static final int _VARIABLE_DECLARATION = 3;
57     static final int _VARIABLE_SUBSTITUTION4QUANTIFIED = 4;
58     static final int _VARIABLE_SUBSTITUTION4FLWR = 5;
59     static final int _VARIABLE_SUBSTITUTION4LETFLWR = 6;
60     static final int _VARIABLE_WASSUBSTITUTELETFLWR = 7;
61     static final int _VARIABLE_CHANGEEXPRESSION4FLWR = 8;
62
63     static final int _FLWREXPRESSION_GETFLWR = 9;
64     static final int _FLWREXPRESSION_INNERFLWR = 10;
65 // static final int _FLWREXPRESSION_GETVARCLAUSE = 10;
66
// static final int _FLWREXPRESSION_GETWHERECLAUSE = 11;
67
// static final int _FLWREXPRESSION_GETORDERBYCLAUSE = 12;
68
// static final int _FLWREXPRESSION_GETRETURNCLAUSE = 13;
69
static final int _QUANTIFIED_INNERFLWR = 14;
70 // static final int _FLWREXPRESSION_GETVARCLAUSE4QUANTIFIED = 14;
71
// static final int _FLWREXPRESSION_GETWHERECLAUSE4QUANTIFIED = 15;
72
// static final int _FLWREXPRESSION_GETRETURNCLAUSE4QUANTIFIED = 16;
73

74     static final int _FLWREXPRESSION_GETANDREPLACEFLWRINWHERE = 17;
75
76     static final int _ELEMENT_EXISTS = 18;
77     //static final int _ELEMENT_CHILDREN = 19;
78

79     //static final int _LOCATEDEXPRESSION_DONOTNORMALIZE = 18;
80
static final int _LOCATEDEXPRESSION_INPREDICATE = 20;
81
82     static final int _LISTOPUNIONEXPRESSION_GETEXPRESSIONS = 21;
83
84     static final int _INCLUDEINPARENTHESIS = 22;
85
86     static final int _STEP_ISPARENTAXISSTEP = 23;
87     static final int _STEP_GETPREDICATE = 24;
88
89     static final int _INAGGREGATEFUNCTION = 25;
90
91     static final int _INTERNALFUNCTIONCALL_NAMEDUNORDERED_PARAMETERS = 26;
92
93     static final int _MULTIVALUED_NEEDEXISTSFUNCTION = 27;
94
95     static final int _FLWR_RETURNS_TAG = 28;
96     // add LARS 16/04/04
97
static final int _STEP_GETPREDICATE_VAR = 29;
98     
99     /**
100      * The maximum number of differents questions.
101      * MUST BE greater (strictly) than the followings number of constants.
102      */

103     static final int MAX_QUESTIONS = 32;
104
105
106     /** To specify any depth in structure. */
107     static final int _ANY_DEPTH = 0;
108
109 /*************************** Protected properties *******************************/
110
111     /** A hashmap to store couple of (constants string, value), the key is a question, the value its response. */
112     protected java.util.HashMap JavaDoc memoMap = null;
113
114 /*************************** Constructors *******************************/
115
116     /**
117      * To construct a new empty visitor context.
118      * @throws NormalizeException
119      */

120     public VisitorContext() throws NormalizeException {
121         //trace("<o>Constructor VisitorContext 1.",0);
122
this.memoMap = new java.util.HashMap JavaDoc();
123     }
124
125     /**
126      * To construct a new visitor context with the given memo.
127      * @param depth the destination depth in the structure (0 for any depth).
128      * @param question the key (a question) of a memo couple (see class header).
129      * @param response the value (the response) or a memo couple.
130      * @throws NormalizeException
131      */

132     public VisitorContext(int depth, int question, java.lang.Object JavaDoc response) throws NormalizeException {
133         //trace("<o>Constructor VisitorContext 1.",0);
134
this.memoMap = new java.util.HashMap JavaDoc();
135         this.setMemo(depth, question, response, true);
136     }
137
138 /*************************** Public methods *******************************/
139
140     /**
141      * To get a memo value.
142      * @param depth the destination depth in the structure (0 for any depth).
143      * @param question the key (a question) of a memo couple (see class header).
144      * @return the value (an object) of the specified memo couple. Caution: return 'null' when
145      * the key does not exist or if the value is 'null'. Use existsMemo(...) to know if a key exists.
146      */

147     public java.lang.Object JavaDoc getMemo(int depth, int question) throws NormalizeException {
148         Integer JavaDoc key = new Integer JavaDoc(depth * VisitorContext.MAX_QUESTIONS + question);
149         if (this.memoMap.containsKey(key)) {
150             return this.memoMap.get(key);
151         } else {
152             return null;
153         }
154     }
155
156     /**
157      * To know if a memo couple exits in the current context.
158      * @param depth the destination depth in the structure (0 for any depth).
159      * @param question the key (a question) of a memo couple (see class header).
160      * @return true if the memo couple exists, false otherwise.
161      */

162     public boolean existsMemo(int depth, int question) throws NormalizeException {
163         Integer JavaDoc key = new Integer JavaDoc(depth * VisitorContext.MAX_QUESTIONS + question);
164         return this.memoMap.containsKey(key);
165     }
166
167     /**
168      * To remove a memo couple of the current context.
169      * @param depth the destination depth in the structure (0 for any depth).
170      * @param question the key (a question) of a memo couple (see class header).
171      * @return true if the memo couple is deleting, false otherwise.
172      */

173     public boolean removeMemo(int depth, int question) throws NormalizeException {
174         Integer JavaDoc key = new Integer JavaDoc(depth * VisitorContext.MAX_QUESTIONS + question);
175         if (this.memoMap.containsKey(key)) {
176             this.memoMap.remove(key);
177             return true;
178         } else {
179             return false;
180         }
181     }
182
183     /**
184      * To set a memo in this context.
185      * @param depth the destination depth in the structure (0 for any depth).
186      * @param question the key (a question) of a memo couple (see class header).
187      * @param response the value (the response) of the specified memo couple (can be 'null').
188      * @param overwrite if true, overwrite the previous value if exist. If false, this method throws an
189      * NormalizeException if the memo already exist, else create a new memo.
190      */

191     public void setMemo(int depth, int question, java.lang.Object JavaDoc response, boolean overwrite) throws NormalizeException {
192         Integer JavaDoc key = new Integer JavaDoc(depth * VisitorContext.MAX_QUESTIONS + question);
193         if ((!overwrite) && (this.memoMap.containsKey(key))) {
194             throw new NormalizeException("The memo couple \""+depth+"."+question+"\" already exist!");
195         } else {
196             this.memoMap.put(key, response);
197         }
198     }
199
200     /**
201      * To set a memo in this context.
202      * @param key a number that is formed with depth and question integers.
203      * @param response the value (the response) of the specified memo couple (can be 'null').
204      * @param overwrite if true, overwrite the previous value if exist. If false, this method throws an
205      * NormalizeException if the memo already exist, else create a new memo.
206      */

207     private void setMemo(Integer JavaDoc key, java.lang.Object JavaDoc response, boolean overwrite) throws NormalizeException {
208         if ((!overwrite) && (this.memoMap.containsKey(key))) {
209             int aKey = key.intValue();
210             int depth = (int)(aKey / VisitorContext.MAX_QUESTIONS);
211             int question = (int)(aKey % VisitorContext.MAX_QUESTIONS);
212             throw new NormalizeException("The memo couple \""+depth+"."+question+"\" already exist!");
213         } else {
214             this.memoMap.put(key, response);
215         }
216     }
217
218     /**
219      * Add all given context memo couples in the current context memo.
220      * @param ctx a context to merge with the current context.
221      * @param keepPrevious if a memo couple already exist and has a different value of a given memo couple, and if
222      * keepPrevious is true, we keep the value of the current memo couple. Otherwise, we put the given memo
223      * couple value (create or replace).
224      */

225     public void merge(VisitorContext ctx, boolean keepPrevious) throws NormalizeException {
226         Object JavaDoc[] keys = ctx.memoMap.keySet().toArray();
227         for (int i = 0; i < keys.length; i++) {
228             Integer JavaDoc aKey = (Integer JavaDoc)keys[i];
229             if ((!this.memoMap.containsKey(aKey)) || (!keepPrevious)) {
230                 this.memoMap.put(aKey, ctx.memoMap.get(aKey));
231             }
232         }
233     }
234
235     /**
236      * Update the values of all context memo couples of the current context with the given context
237      * (but do not create new memo couple in current context).
238      * @param ctx a context to use to update the current context values.
239      */

240     public void update(VisitorContext ctx) throws NormalizeException {
241         Object JavaDoc[] keys = this.memoMap.keySet().toArray();
242         for (int i = 0; i < keys.length; i++) {
243             Integer JavaDoc aKey = (Integer JavaDoc)keys[i];
244             if (ctx.memoMap.containsKey(aKey)) {
245                 if (aKey.intValue() == VisitorContext._FLWREXPRESSION_GETANDREPLACEFLWRINWHERE) {
246                     //Merge two ArrayList :
247
java.util.ArrayList JavaDoc content1 = (java.util.ArrayList JavaDoc)this.memoMap.get(aKey);
248                     java.util.ArrayList JavaDoc content2 = (java.util.ArrayList JavaDoc)ctx.memoMap.get(aKey);
249                     if ((content1 != null) && (content2 != null)) {
250                         for (int j = 0; j < content2.size(); j++) {
251                             if (!content1.contains(content2.get(j))) {
252                                 content1.add(content2.get(j));
253                             }
254                         }
255                     }
256                     this.memoMap.put(aKey, content1);
257                 } else {
258                     this.memoMap.put(aKey, ctx.memoMap.get(aKey));
259                 }
260             }
261         }
262     }
263
264     /**
265      * To filter the current context i.e. to remove all the memo couples of which the depth (in the key) is
266      * stricly smaller than the given depth (the depth 0 for 'any depth' is considered greater than all depth).<BR><BR>
267      * The questions must have the following prototype: &lt;depth&gt;'.'&lt;node name&gt;["."&lt;question&gt;](see class header).<BR><BR>
268      * It is use to optimize the context.
269      * @param currentDepth the current depth of the visitor.
270      */

271     public void filter(int currentDepth) throws NormalizeException {
272        Object JavaDoc[] keys = this.memoMap.keySet().toArray();
273         for (int i = 0; i < keys.length; i++) {
274             Integer JavaDoc aKey = (Integer JavaDoc)keys[i];
275             int depth = (int)(aKey.intValue() / VisitorContext.MAX_QUESTIONS);
276             if ((depth != 0) && (depth < currentDepth)) {
277                 this.memoMap.remove(aKey);
278             }
279         }
280     }
281
282     /**
283      * Removes all memo couple of the current context. Cleans the current Context.
284      */

285     public void clear() {
286         this.memoMap.clear();
287     }
288
289     /**
290      * To get the current memoMap to string.
291      * @return a string that represents the current memoMap.
292      */

293     public java.lang.String JavaDoc toString() {
294         java.lang.String JavaDoc ret = "";
295         Object JavaDoc[] keys = this.memoMap.keySet().toArray();
296         for (int i = 0; i < keys.length; i++) {
297             Integer JavaDoc aKey = (Integer JavaDoc)keys[i];
298             int aKeyAsInt = aKey.intValue();
299             int depth = (int)(aKeyAsInt / VisitorContext.MAX_QUESTIONS);
300             int question = (int)(aKeyAsInt % VisitorContext.MAX_QUESTIONS);
301             ret += depth+"."+question+" - "+this.memoMap.get(aKey)+"\n";
302         }
303         if (ret.equals("")) {
304             return "EMPTY CONTEXT";
305         }
306         return ret;
307     }
308
309     /**
310      * Clones the current context.
311      * @return a clone of the current context.
312      */

313     public VisitorContext cloneContext() throws NormalizeException {
314         VisitorContext clone = new VisitorContext();
315         Object JavaDoc[] keys = this.memoMap.keySet().toArray();
316         for (int i = 0; i < keys.length; i++) {
317             Integer JavaDoc aKey = (Integer JavaDoc)keys[i];
318             int aKeyAsInt = aKey.intValue();
319             int depth = (int)(aKeyAsInt / VisitorContext.MAX_QUESTIONS);
320             int question = (int)(aKeyAsInt % VisitorContext.MAX_QUESTIONS);
321             clone.setMemo(depth, question,this.memoMap.get(aKey), false);
322         }
323         return clone;
324     }
325 }
326
Popular Tags