KickJava   Java API By Example, From Geeks To Geeks.

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


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

24
25 package org.xquark.xquery.normalize;
26
27 import java.util.ArrayList JavaDoc;
28
29 import org.xquark.xpath.Axis;
30 import org.xquark.xpath.NodeKind;
31 import org.xquark.xquery.parser.*;
32 import org.xquark.xquery.parser.primitivefunctions.fnfunctions.FunctionCOLLECTION;
33 import org.xquark.xquery.parser.primitivefunctions.fnfunctions.FunctionDATA;
34 import org.xquark.xquery.typing.*;
35
36 /**
37  * This class reduce a located expression.
38  * It is used by ExpressionNormalizationVisitor class.
39  * <BR>
40  */

41 public class LocatedExpressionReducer {
42
43     /****************************************************************/
44     /*************************** Constants declaration **************/
45     /****************************************************************/
46
47     /** CVS/QA stuff. */
48     private static final String JavaDoc RCSRevision = "$Revision: 1.3 $";
49
50     /** CVS/QA stuff. */
51     private static final String JavaDoc RCSName = "$Name: $";
52
53     /****************************************************************/
54     /************************** Properties declaration **************/
55     /****************************************************************/
56
57     /** main expression */
58     protected LocatedExpression rootExpr;
59
60     /** The list of the expressions on which to apply one or more steps. */
61     protected ArrayList JavaDoc expressions;
62
63     /** The list of steps to apply. */
64     protected ArrayList JavaDoc steps;
65
66     /** The current position in the list of steps to apply. */
67     protected int currentPos;
68
69     /** Flag to indicate if the current located expression were reduced. */
70     protected boolean reduced;
71
72     /** Flag to indicate if the current steps were reduced. */
73     // protected boolean stepsReduced;
74

75     /** To know if this current located expression can be reduce or not. */
76     private boolean isUnapplicable;
77
78     /** The list of reduced expressions (could be empty). */
79     protected ArrayList JavaDoc reducedExpressions;
80
81     /** The type visitor to build new XQuery expressions. */
82     protected TypeVisitor typeVisitor;
83
84     /****************************************************************/
85     /************************** Constructors ************************/
86     /****************************************************************/
87
88     /**
89      * To construct a new LocatedExpressionReducer.
90      * @param expr the XQuery expression on which apply XPath.
91      * @param steps steps of XPath to apply/reduce.
92      * @param typeVisitor an instance of the type visitor (could be null).
93      * @throws NormalizeException
94      */

95     // add 22/08/2003
96
protected LocatedExpressionReducer() {
97     }
98
99     // add 22/08/2003
100
protected void reset(LocatedExpression locExpr, TypeVisitor typeVisitor) throws NormalizeException {
101         rootExpr = locExpr;
102         XQueryExpression expr = rootExpr.getExpression();
103         this.expressions = new ArrayList JavaDoc();
104         if (expr instanceof XQueryExpressionSequence) {
105             this.expressions = ((XQueryExpressionSequence) expr).getSubExpressions();
106         } else {
107             this.expressions.add(expr);
108         }
109         this.steps = locExpr.getSteps();
110         this.currentPos = 1;
111         this.reduced = false;
112         // this.stepsReduced = false;
113
this.isUnapplicable = false;
114         if (this.reducedExpressions == null)
115             this.reducedExpressions = new ArrayList JavaDoc();
116         else
117             this.reducedExpressions.clear();
118         this.typeVisitor = typeVisitor;
119     }
120
121     /****************************************************************/
122     /************************** Private methods *********************/
123     /****************************************************************/
124
125     /****************************************************************/
126     /************************ Protected methods *********************/
127     /****************************************************************/
128
129     /**
130      * To retrieve the list of XQuery expressions that were reduce.
131      * @return the list of XQuery expressions that were reduce (could be empty).
132      */

133     protected ArrayList JavaDoc getReducedExpressions() {
134         return this.reducedExpressions;
135     }
136
137     /**
138      * To build a new expression from an ArrayList of expressions.
139      * @param expressions an ArrayList of expressions.
140      * @return a new XQueryExpression (could be null).
141      */

142     protected XQueryExpression buildExpression(ArrayList JavaDoc expressions) throws NormalizeException {
143         try {
144             if ((expressions == null) || (expressions.size() == 0)) {
145                 return null;
146             } else if (expressions.size() == 1) {
147                 return (XQueryExpression) expressions.get(0);
148             } else {
149                 return new XQueryExpressionSequence(expressions, ((XQueryExpression) expressions.get(0)).getParentModule());
150             }
151         } catch (XQueryException e) {
152             throw new NormalizeException(0, "Unexpected exception in LocatedExpressionReducer.buildExpression(...) :\n==>" + e.toString() + "<==\n", e);
153         }
154     }
155
156     /**
157      * To retrieve the XQuery expression that were reduce.
158      * @return the XQuery expression that were reduce (could be null if the reduction eliminated the expression).
159      */

160     protected XQueryExpression getReducedExpression() throws NormalizeException {
161         return this.buildExpression(this.reducedExpressions);
162     }
163
164     /**
165      * To retrieve the steps that were reduce.
166      * @return the steps that were reduce (could be an empty if all steps have been appling).
167      */

168     protected ArrayList JavaDoc getReducedSteps() {
169         return this.steps;
170     }
171
172     /**
173      * To know if a step is node test with axis self (i.e. /self::node()).
174      * @param step the step to test.
175      * @return true if the step is /self::node(), false otherwise.
176      */

177     protected boolean isStepSelfNode(Step step) throws NormalizeException {
178         if ((step != null) && (step.getPredicates() == null) && (step.getAxis() == Axis.SELF)) {
179             XQueryExpression test = step.getExpression();
180             if ((test != null) && (test instanceof NodeTest) && (((NodeTest) test).getKind() == NodeKind.NODE)) {
181                 return true;
182             }
183         }
184         return false;
185     }
186
187     /**
188      * To know if a step is a node test (with any axis).
189      * @param step the step to test.
190      * @return true if the step is /axis::node(), false otherwise.
191      */

192     protected boolean isStepNode(Step step) throws NormalizeException {
193         if ((step != null) && (step.getPredicates() == null)) {
194             XQueryExpression test = step.getExpression();
195             if ((test != null) && (test instanceof NodeTest) && (((NodeTest) test).getKind() == NodeKind.NODE)) {
196                 return true;
197             }
198         }
199         return false;
200     }
201
202     /**
203      * To know if a step is equal to /descendant-or-self::node() (i.e. //).
204      * @param step the step to test.
205      * @return true if the step is equal to /descendant-or-self::node(), false otherwise.
206      */

207     protected boolean isSlashSlash(Step step) throws NormalizeException {
208         if ((step != null) && (step.getAxis() == Axis.DESCENDANT_OR_SELF) && (step.getPredicates() == null)) {
209             XQueryExpression test = step.getExpression();
210             if ((test != null) && (test instanceof NodeTest) && (((NodeTest) test).getKind() == NodeKind.NODE)) {
211                 return true;
212             }
213         }
214         return false;
215     }
216
217     /**
218      * To retrieve the next step(s) to apply (null, one or two steps maximum). Valid steps pairs are :<BR>
219      * <UL>
220      * <LI>/descendant-or-self::node(), /self::node()</LI>
221      * <LI>/descendant-or-self::node(), /self::text()</LI>
222      * <LI>/descendant-or-self::node(), /self::nametest</LI>
223      * <LI>/descendant-or-self::node(), /child::text()</LI>
224      * <LI>/descendant-or-self::node(), /child::nametest</LI>
225      * <LI>/descendant-or-self::node(), /@nametest</LI>
226      * <LI>/child:: node(), null</LI>
227      * <LI>/self::text(), null</LI>
228      * <LI>/self::nametest, null</LI>
229      * <LI>/child::text(), null</LI>
230      * <LI>/child::nametest, null</LI>
231      * <LI>/@nametest, null</LI>
232      * </UL>
233      * @return the next step(s) to apply (if null, there is no more steps to apply).
234      */

235     protected Step[] getNextSteps() throws NormalizeException {
236         Step[] next = new Step[2];
237         if (this.currentPos >= this.steps.size()) {
238             return null;
239         } else if (this.steps.size() - this.currentPos == 1) {
240             this.currentPos++;
241             next[0] = (Step) this.steps.get(this.currentPos - 1);
242         } else {
243             Step currentStep = (Step) this.steps.get(this.currentPos);
244             if (this.isSlashSlash(currentStep)) {
245                 next[0] = currentStep;
246                 this.currentPos++;
247                 Step secondStep = (Step) this.steps.get(this.currentPos);
248                 if ((this.steps.size() - this.currentPos >= 1) && ((this.isStepSelfNode(secondStep)) || (!(this.isStepNode(secondStep))))) {
249                     //All step except /axis::node() (but self::node() is ok)
250
next[1] = secondStep;
251                     this.currentPos++;
252                 }
253             } else {
254                 next[0] = currentStep;
255                 this.currentPos++;
256             }
257         }
258         return next;
259     }
260
261     /**
262      * Test if two QName match (including when contains wildcard '*') :<BR>
263      * <PRE><CODE>
264     namespace1 localname1 namespace2 localname2 match?
265     -------------------------------------------------------
266     1 null A null A true
267     2 null A null B false
268     3 null A * * true
269     4 null A * A true
270     5 null A * B false
271     6 null A ns2 * false
272     7 null A ns2 A false
273     8 null A ns2 B false
274     -------------------------------------------------------
275     9 * * null A true (idem 3)
276     10 * * * * true
277     11 * * * A true
278     12 * * ns2 * true
279     13 * * ns2 A true
280     -------------------------------------------------------
281     14 * A null A true (idem 4)
282     15 * A null B false (idem 5)
283     16 * A * * true (idem 11)
284     17 * A * A true
285     18 * A * B false
286     19 * A ns2 * true
287     20 * A ns2 A true
288     21 * A ns2 B false
289     -------------------------------------------------------
290     22 ns1 A null A false (idem 7)
291     23 ns1 A null B false (idem 8)
292     24 ns1 A * * true (idem 13)
293     25 ns1 A * A true (idem 20)
294     26 ns1 A * B false (idem 21)
295     27 ns1 A ns2 * false
296     28 ns1 A ns2 A false
297     29 ns1 A ns2 B false
298     30 ns1 A ns1 * true
299     31 ns1 A ns1 A true
300     32 ns1 A ns1 B false
301     -------------------------------------------------------
302     33 ns1 * null A false (idem 6)
303     34 ns1 * * * true (idem 12)
304     35 ns1 * * A true (idem 19)
305     36 ns1 * ns2 * false
306     37 ns1 * ns2 A false (idem 27)
307     38 ns1 * ns1 * true
308     39 ns1 * ns1 A true (idem 30)
309     -------------------------------------------------------
310     Impossible case : namespace = null, localname = *
311      * </CODE></PRE>
312      * @param q1 a QName to test if it match with pattern.
313      * @param q2 a pattern to test a QName.
314      * @return true if first paramter match with second parameter, false otherwise.
315      */

316 // static protected boolean matchQName(QName q1, QName q2) throws NormalizeException {
317
// //outln(" Matching test between : "+q1.getPrefixName()+"("+q1.getNameSpace()+"):"+q1.getLocalName()+" and "+q2.getPrefixName()+"("+q2.getNameSpace()+"):"+q2.getLocalName());
318
// boolean resp = false; //Default value.
319
// //Test impossible case :
320
// if (((q1.getNameSpace() == null) && (q1.getLocalName().equals("*"))) || ((q2.getNameSpace() == null) && (q2.getLocalName().equals("*")))) {
321
// throw new NormalizeException(0, "Impossible case : a QName can not have namespace == null AND localname '*' !");
322
// }
323
// //Test match (big test but only one, two or maximum three conditions to answer if QNames match :
324
// if (q1.getNameSpace() == null) { //NS1 = null
325
// if (q2.getNameSpace() == null) { //NS2 = null
326
// resp = q1.getLocalName().equals(q2.getLocalName());
327
// } else if (q2.getNameSpace().equals("*")) { //NS2 = *
328
// resp = (q2.getLocalName().equals("*")) || (q1.getLocalName().equals(q2.getLocalName()));
329
// } //Default NS2 = url
330
// } else if (q1.getNameSpace().equals("*")) { //NS1 = *
331
// if (q2.getNameSpace() == null) { //NS2 = null
332
// resp = (q1.getLocalName().equals("*")) || (q1.getLocalName().equals(q2.getLocalName()));
333
// } else if (q2.getNameSpace().equals("*")) { //NS2 = *
334
// resp = (q1.getLocalName().equals("*")) || (q2.getLocalName().equals("*")) || (q1.getLocalName().equals(q2.getLocalName()));
335
// } else { //Default NS2 = url
336
// resp = (q1.getLocalName().equals("*")) || (q2.getLocalName().equals("*")) || (q1.getLocalName().equals(q2.getLocalName()));
337
// }
338
// } else { //NS1 = url
339
// if (q2.getNameSpace() == null) { //NS2 = null
340
// //Nothing to do (default = false);
341
// } else if (q2.getNameSpace().equals("*")) { //NS2 = *
342
// resp = (q1.getLocalName().equals("*")) || (q2.getLocalName().equals("*")) || (q1.getLocalName().equals(q2.getLocalName()));
343
// } else if (q1.getNameSpace().equals(q2.getNameSpace())) { //Default NS2 = url (and == NS1)
344
// resp = (q1.getLocalName().equals("*")) || (q2.getLocalName().equals("*")) || (q1.getLocalName().equals(q2.getLocalName()));
345
// } //Default : NS2 = url and <> NS1
346
// }
347
// //outln(" RESULT MATCHING = "+resp);
348
// return resp;
349
// }
350
static protected boolean matchStepExpr(XQueryExpression expr1, XQueryExpression expr2) throws NormalizeException {
351         //outln(" Matching test between : "+q1.getPrefixName()+"("+q1.getNameSpace()+"):"+q1.getLocalName()+" and "+q2.getPrefixName()+"("+q2.getNameSpace()+"):"+q2.getLocalName());
352
boolean resp = false; //Default value.
353
String JavaDoc namespace1 = null;
354         String JavaDoc localname1 = null;
355         String JavaDoc namespace2 = null;
356         String JavaDoc localname2 = null;
357         if (expr1 instanceof QName) {
358             namespace1 = ((QName)expr1).getNameSpace();
359             localname1 = ((QName)expr1).getLocalName();
360         } else if (expr1 instanceof ValueString) {
361             localname1 = ((ValueString)expr1).getValue();
362         }
363         if (expr2 instanceof QName) {
364             namespace2 = ((QName)expr2).getNameSpace();
365             localname2 = ((QName)expr2).getLocalName();
366         } else if (expr2 instanceof ValueString) {
367             localname2 = ((ValueString)expr2).getValue();
368         }
369         
370         // TODO handle this case, not done yet
371
if (localname1 == null || localname2 == null) {
372             //return false;
373
throw new NormalizeException(0, "Error in normalization, case not yet handled! (matching : " + expr1 + " with " + expr2 + ")");
374         }
375         //Test impossible case :
376
if (((namespace1 == null) && (localname1.equals("*"))) || ((namespace2 == null) && (localname2.equals("*")))) {
377             throw new NormalizeException(0, "Impossible case : namespace is null and localname is '*' !");
378         }
379         //Test match (big test but only one, two or maximum three conditions to answer if QNames match :
380
if (namespace1 == null) { //NS1 = null
381
if (namespace2 == null) { //NS2 = null
382
resp = localname1.equals(localname2);
383             } else if (namespace2.equals("*")) { //NS2 = *
384
resp = (localname2.equals("*")) || (localname1.equals(localname2));
385             } //Default NS2 = url
386
} else if (namespace1.equals("*")) { //NS1 = *
387
if (namespace2 == null) { //NS2 = null
388
resp = (localname1.equals("*")) || (localname1.equals(localname2));
389             } else if (namespace2.equals("*")) { //NS2 = *
390
resp = (localname1.equals("*")) || (localname2.equals("*")) || (localname1.equals(localname2));
391             } else { //Default NS2 = url
392
resp = (localname1.equals("*")) || (localname2.equals("*")) || (localname1.equals(localname2));
393             }
394         } else { //NS1 = url
395
if (namespace2 == null) { //NS2 = null
396
//Nothing to do (default = false);
397
} else if (namespace2.equals("*")) { //NS2 = *
398
resp = (localname1.equals("*")) || (localname2.equals("*")) || (localname1.equals(localname2));
399             } else if (namespace1.equals(namespace2)) { //Default NS2 = url (and == NS1)
400
resp = (localname1.equals("*")) || (localname2.equals("*")) || (localname1.equals(localname2));
401             } //Default : NS2 = url and <> NS1
402
}
403         //outln(" RESULT MATCHING = "+resp);
404
return resp;
405     }
406
407     /**
408      * Gets a new /descendant-or-self::node() step.
409      * @return a new step.
410      */

411     /** Contants for /descendant-or-self::node() step. */
412     //static private Step descOrSelf;
413
static protected Step getDOSNodeStep() throws NormalizeException {
414         try {
415             // if (descOrSelf == null) {
416
// descOrSelf = new Step(true, Axis.DESCENDANT_OR_SELF, new NodeType(NodeKind.NODE, null, null), null, null);
417
// return descOrSelf;
418
// } else {
419
// return (Step) descOrSelf.clone();
420
// }
421
return new Step(true, Axis.DESCENDANT_OR_SELF, new NodeTest(NodeKind.NODE, null, null), null, null);
422         } catch (XQueryException e) {
423             throw new NormalizeException(0, "Unexpected exception in LocatedExpressionReducer.getDOSNode() :\n==>" + e.toString() + "<==\n", e);
424         }
425     }
426
427     /**
428      * Gets a new /parent::node() step.
429      * @return a new step.
430      */

431     /** Contants for /parent::node() step. */
432     //static protected Step parent;
433
static protected Step getParentNodeStep() throws NormalizeException {
434         try {
435             // if (parent == null) {
436
// parent = new Step(true, Axis.PARENT, new NodeType(NodeKind.NODE, null, null), null, null);
437
// return parent;
438
// } else {
439
// return (Step) parent.clone();
440
// }
441
return new Step(true, Axis.PARENT, new NodeTest(NodeKind.NODE, null, null), null, null);
442         } catch (XQueryException e) {
443             throw new NormalizeException(0, "Unexpected exception in LocatedExpressionReducer.getParentNode() :\n==>" + e.toString() + "<==\n", e);
444         }
445     }
446
447     /**
448      * Gets a new step with the given axis and the same test that the given step (and copy predicates).
449      * @return a new step.
450      */

451     static protected Step modifyStep(boolean separator, byte axis, Step aStep) throws NormalizeException {
452         aStep.setHasSeparator(separator);
453         aStep.setAxis(axis);
454         return aStep;
455     }
456
457     // add 04/09/2003
458
// spilts a step into two steps whenever possible
459
static protected void splitStep(ArrayList JavaDoc stepList, int firstStepPosition, int caseFirstStep) throws NormalizeException {
460         Step firstStep = (Step) stepList.get(firstStepPosition);
461         if (caseFirstStep == 14)
462             stepList.set(firstStepPosition, getParentNodeStep());
463         else
464             stepList.set(firstStepPosition, getDOSNodeStep());
465         if ((caseFirstStep == 10) || (caseFirstStep == 11) || (caseFirstStep == 14)) {
466             stepList.add(firstStepPosition + 1, modifyStep(true, Axis.SELF, firstStep));
467         } else { //caseFirstStep == 7, 8 or 9 :
468
stepList.add(firstStepPosition + 1, modifyStep(true, Axis.CHILD, firstStep));
469         }
470     }
471
472     static protected Step createUnionStep(ArrayList JavaDoc list1, ArrayList JavaDoc list2) throws NormalizeException {
473         try {
474             ((Step) list1.get(0)).setHasSeparator(false);
475             ((Step) list2.get(0)).setHasSeparator(false);
476             // create LocatedExpressions
477
LocatedExpression tmpLoc1 = new LocatedExpression(list1, false, null, false);
478             LocatedExpression tmpLoc2 = new LocatedExpression(list2, false, null, false);
479             // create union
480
ListOpUNIONExpression tmpListUnion = new ListOpUNIONExpression(tmpLoc1, tmpLoc2, null);
481             tmpListUnion.setParenthesis(true);
482             // create new Step
483
return new Step(true, Axis.NONE, tmpListUnion, null, null);
484         } catch (XQueryException e) {
485             throw new NormalizeException("Could not construct Union Step " + e.getMessage());
486         }
487     }
488     /**
489      * Gets an integer code according to the type of the given step.
490      * @param oneStep a step.
491      * @return an integer witch according to the type of step. The values are in [0, 16] :
492      * <OL start="0">
493      * <LI>any union step</LI>
494      * <LI>/self::anynametest</LI>
495      * <LI>/self::text()</LI>
496      * <LI>/self::node() or /.</LI>
497      * <LI>/child::anynametest</LI>
498      * <LI>/child::text()</LI>
499      * <LI>/child::node()</LI>
500      * <LI>/descendant::anynametest</LI>
501      * <LI>/descendant::text()</LI>
502      * <LI>/descendant::node()</LI>
503      * <LI>/descendant-or-self::anynametest</LI>
504      * <LI>/descendant-or-self::text()</LI>
505      * <LI>/descendant-or-self::node()</LI>
506      * <LI>/attribute::anynametest or /@anynametest</LI>
507      * <LI>/parent::node() or /..</LI>
508      * <LI>/parent::text</LI>
509      * <LI>/parent::anynametest</LI>
510      * </OL>
511      */

512     static final int SELF_NT = 1;
513     static final int SELF_TEXT = 2;
514     static final int SELF_NODE = 3;
515     static final int CHILD_NT = 4;
516     static final int CHILD_TEXT = 5;
517     static final int CHILD_NODE = 6;
518     static final int DESC_NT = 7;
519     static final int DESC_TEXT = 8;
520     static final int DESC_NODE = 9;
521     static final int DOS_NT = 10;
522     static final int DOS_TEXT = 11;
523     static final int DOS_NODE = 12;
524     static final int ATT_NT = 13;
525     static final int PARENT_NT = 14;
526     static final int PARENT_TEXT = 15;
527     static final int PARENT_NODE = 16;
528     // special steps!!!
529
static final int LOCATED = 20;
530     static final int UNION = 21;
531
532     static protected int getType(Step oneStep, boolean hasRootStep) throws NormalizeException {
533         if (hasRootStep && !oneStep.hasSeparator()) {
534             throw new NormalizeException(0, "Separator type " + oneStep.hasSeparator() + " of step " + oneStep + " not supported !");
535         }
536         //Get the type of sub expression :
537
int innerExpr = -1; //Values : anynametest => 1, text() => 2 and node() => 3
538
XQueryExpression subExpr = oneStep.getExpression();
539         if (subExpr instanceof QName) {
540             innerExpr = 1;
541         } else if (subExpr instanceof NodeTest) {
542             NodeTest thisNode = (NodeTest) subExpr;
543             if (thisNode.getKind() == NodeKind.TEXT) {
544                 innerExpr = 2;
545             } else if (thisNode.getKind() == NodeKind.NODE) {
546                 innerExpr = 3;
547             } else {
548                 throw new NormalizeException(0, "Node type " + NodeKind.NODEKINDSTRINGS[thisNode.getKind()] + " of step " + oneStep + " not supported !");
549             }
550         } else if (subExpr instanceof LocatedExpression) {
551             return LOCATED;
552         } else if (subExpr instanceof ListOpUNIONExpression) {
553             return UNION;
554         } else {
555             throw new NormalizeException(0, "Expression " + subExpr + " of step " + oneStep + " not supported !");
556         }
557         //Switch according to axis of given step :
558
int axis = oneStep.getAxis();
559         switch (axis) {
560             case Axis.SELF :
561                 return innerExpr;
562             case Axis.CHILD :
563                 return innerExpr + 3;
564             case Axis.DESCENDANT :
565                 return innerExpr + 6;
566             case Axis.DESCENDANT_OR_SELF :
567                 return innerExpr + 9;
568             case Axis.ATTRIBUTE :
569                 if (innerExpr == 1)
570                     return innerExpr + 12;
571                 throw new NormalizeException(0, "Node test or text test on attribute of step " + oneStep + " not supported !");
572             case Axis.PARENT :
573                 if (innerExpr == 1 || innerExpr == 3)
574                     return innerExpr + 13;
575                 throw new NormalizeException(0, "Text test on parent axis of step " + oneStep + " not supported !");
576             default :
577                 if (axis < 0) {
578                     throw new NormalizeException(0, "Axis (value = " + axis + ") of step " + oneStep + " not supported !");
579                 } else {
580                     throw new NormalizeException(0, "Axis " + Axis.AXISSTRINGS[axis] + " of step " + oneStep + " not supported !");
581                 }
582         }
583     }
584
585     /**
586      * To simplify (normalize) steps two by two. We use various rules to do this (see StepNormalization_0_2.xls).
587      * Example : /descendant-or-self::A/self::B becomes /descendant-or-self::A if A = B else it can be eliminate !
588      * @return Flag to indicate if the current located expression must be eliminated.
589      * 0 elimination
590      * 1 no elimination and reduced
591      * 2 no elimination not reduced
592      */

593     static public boolean eliminateSteps(ArrayList JavaDoc stepList, boolean hasRootStep) throws NormalizeException {
594         //outln("\n\n==> OLD STEPS = "+stepList);
595
if (stepList == null)
596             return true;
597         Step firstStep = null;
598         Step secondStep = null;
599         int stepsReduced = 0;
600         // int size = stepList.size();
601
//if (size <= 0) {
602
// change 22/08/2003
603
if (stepList.size() <= (hasRootStep ? 1 : 0)) {
604             //Nothing to do ! impossible ?
605
} else if (stepList.size() >= (hasRootStep ? 2 : 1)) {
606             //General case :
607
// ArrayList newSteps = new ArrayList();
608
int caseFirstStep;
609             int caseSecondStep;
610             int firstStepPosition = (hasRootStep ? 1 : 0);
611             boolean hasPredicate = false;
612             //outln("STEP 1 = "+firstStep+" "+caseFirstStep);
613
//Loop until there is no more stepList :
614
do {
615                 firstStep = (Step) stepList.get(firstStepPosition);
616                 caseFirstStep = getType(firstStep, hasRootStep); //See getType(Step) method for step type code !
617
hasPredicate = firstStep.hasPredicates();
618                 caseSecondStep = -1;
619                 if (stepList.size() > firstStepPosition + 1) {
620                     secondStep = (Step) stepList.get(firstStepPosition + 1);
621                     caseSecondStep = getType(secondStep, true); //See getType(Step) method for step type code !
622
//outln("STEP 2 = "+secondStep+" "+caseSecondStep);
623
}
624                 firstStepPosition++;
625                 if (caseFirstStep == 0 || caseSecondStep == 0)
626                     continue;
627                 //Switch according to steps types combinaisons (two by two or one if this is the last step) :
628
if (caseSecondStep == -1) {
629                 } else {
630                     //------------------------------- There are at least two steps :
631
switch (caseFirstStep) {
632                         case SELF_NT :
633                             switch (caseSecondStep) {
634                                 case SELF_NT :
635                                     if (!matchStepExpr(firstStep.getExpression(),secondStep.getExpression())) {
636                                         //QNames are not matching : Eliminate this Located Expression :
637
return true;
638                                     }
639                                     break;
640                                 case SELF_TEXT :
641                                     //Eliminate this Located Expression :
642
return true;
643                             }
644                             break;
645                         case SELF_TEXT :
646                             switch (caseSecondStep) {
647                                 case PARENT_NT :
648                                 case PARENT_NODE :
649                                 case SELF_TEXT :
650                                 case SELF_NODE :
651                                 case DOS_NODE :
652                                     break;
653                                 default :
654                                     //Eliminate this Located Expression :
655
return true;
656                             }
657                             break;
658                         case SELF_NODE :
659                             break;
660                         case CHILD_NT :
661                             switch (caseSecondStep) {
662                                 case SELF_NT :
663                                     if (!matchStepExpr(firstStep.getExpression(),secondStep.getExpression())) {
664                                         //QNames are not matching : Eliminate this Located Expression :
665
return true;
666                                     }
667                                     break;
668                                 case SELF_TEXT :
669                                     //Eliminate this Located Expression :
670
return true;
671                             }
672                             break;
673                         case CHILD_TEXT :
674                             switch (caseSecondStep) {
675                                 case PARENT_NT :
676                                 case PARENT_NODE :
677                                 case SELF_TEXT :
678                                 case SELF_NODE :
679                                 case DOS_NODE :
680                                     break;
681                                 default :
682                                     //Eliminate this Located Expression :
683
return true;
684                             }
685                             break;
686                         case CHILD_NODE :
687                             break;
688                         case DESC_NT :
689                             switch (caseSecondStep) {
690                                 case SELF_TEXT :
691                                     //Eliminate this Located Expression :
692
return true;
693                             }
694                             break;
695                         case DESC_TEXT :
696                             switch (caseSecondStep) {
697                                 case SELF_TEXT :
698                                 case SELF_NODE :
699                                 case PARENT_NT :
700                                 case PARENT_NODE :
701                                 case DOS_NODE :
702                                     break;
703                                 default :
704                                     //Eliminate this Located Expression :
705
return true;
706                             }
707                             break;
708                         case DESC_NODE :
709                             break;
710                         case DOS_NT :
711                             switch (caseSecondStep) {
712                                 case SELF_TEXT :
713                                     //Eliminate this Located Expression :
714
return true;
715                             }
716                             break;
717                         case DOS_TEXT :
718                             switch (caseSecondStep) {
719                                 case SELF_TEXT :
720                                 case SELF_NODE :
721                                 case PARENT_NT :
722                                 case PARENT_NODE :
723                                     break;
724                                 default :
725                                     //Eliminate this Located Expression :
726
return true;
727                             }
728                             break;
729                         case DOS_NODE :
730                             break;
731                         case ATT_NT :
732                             switch (caseSecondStep) {
733                                 case SELF_NODE :
734                                 case PARENT_NT :
735                                 case PARENT_NODE :
736                                 case DOS_NODE :
737                                     break;
738                                 default :
739                                     //Eliminate this Located Expression :
740
return true;
741                             }
742                             break;
743                         case PARENT_NT :
744                             switch (caseSecondStep) {
745                                 case SELF_TEXT :
746                                     //Eliminate this Located Expression :
747
return true;
748                             }
749                             break;
750                         case PARENT_NODE :
751                             switch (caseSecondStep) {
752                                 case SELF_TEXT :
753                                     //Eliminate this Located Expression :
754
return true;
755                             }
756                             break;
757                     }
758                 }
759             } while ((stepList.size() >= firstStepPosition) && (firstStep != null) && (caseSecondStep != -1));
760             // stepList = newSteps;
761
}
762         //outln("NEW STEPS ="+stepList);
763
//Do not eliminate this Located Expression :
764
return false;
765     }
766
767     static public int simplifySteps(ArrayList JavaDoc steps, boolean inPredicate, XQueryModule parentModule) throws NormalizeException {
768
769         boolean hasRootVar = false;
770         try {
771             Step step0 = (Step) steps.get(0);
772             if (step0.getExpression() instanceof Variable)
773                 hasRootVar = true;
774             if (step0.getAxis() != -1 && step0.hasSeparator()) {
775                 ArrayList JavaDoc argVect = new ArrayList JavaDoc();
776                 argVect.add(new ValueString("*:*", parentModule));
777                 FunctionCOLLECTION funcColExpr = new FunctionCOLLECTION(argVect, parentModule);
778                 Step step = new Step(false, Axis.NONE, funcColExpr, null, parentModule);
779                 step.setParentModule(parentModule);
780                 steps.add(0, step);
781             } else if (inPredicate && !step0.hasSeparator()) {
782                 if (step0.getExpression() instanceof QName || step0.getExpression() instanceof NodeTest) {
783                     hasRootVar = true;
784                     if (step0.getAxis() == -1 && step0.getExpression() instanceof QName)
785                         step0.setAxis(Axis.CHILD);
786                 }
787             }
788         } catch (XQueryException xqe) {
789             throw new NormalizeException(xqe.getMessage(), xqe);
790         }
791         return simplifySteps(steps, ((Step) steps.get(0)).getAxis() == Axis.NONE, hasRootVar, parentModule);
792     }
793
794     static private int simplifySteps(ArrayList JavaDoc stepList, boolean hasRootStep, boolean hasRootVar, XQueryModule parentModule) throws NormalizeException {
795         //outln("\n\n==> OLD STEPS = "+stepList);
796
if (stepList == null || eliminateSteps(stepList, hasRootStep))
797             return 0;
798         Step firstStep = null;
799         Step secondStep = null;
800         int stepsReduced = 0;
801         boolean hasSeparator = ((Step) stepList.get(0)).hasSeparator();
802         // int size = stepList.size();
803
//if (size <= 0) {
804
// change 22/08/2003
805
if (stepList.size() <= (hasRootStep ? 1 : 0)) {
806             //Nothing to do ! impossible ?
807
} else if (stepList.size() >= (hasRootStep ? 2 : 1)) {
808             //General case :
809
// ArrayList newSteps = new ArrayList();
810
int caseFirstStep;
811             int caseSecondStep;
812             int firstStepPosition = (hasRootStep ? 1 : 0);
813             int minStepPosition = firstStepPosition;
814             boolean hasPredicate = false;
815             //outln("STEP 1 = "+firstStep+" "+caseFirstStep);
816
//Loop until there is no more stepList :
817
do {
818                 firstStep = (Step) stepList.get(firstStepPosition);
819                 caseFirstStep = getType(firstStep, hasRootStep); //See getType(Step) method for step type code !
820
hasPredicate = firstStep.hasPredicates();
821                 caseSecondStep = -1;
822                 if (stepList.size() > firstStepPosition + 1) {
823                     secondStep = (Step) stepList.get(firstStepPosition + 1);
824                     caseSecondStep = getType(secondStep, true); //See getType(Step) method for step type code !
825
//outln("STEP 2 = "+secondStep+" "+caseSecondStep);
826
}
827                 //Switch according to steps types combinaisons (two by two or one if this is the last step) :
828
if (caseSecondStep == -1) {
829                     switch (caseFirstStep) {
830                         case SELF_NT :
831                         case SELF_TEXT :
832                         case CHILD_NT :
833                         case CHILD_TEXT :
834                         case CHILD_NODE :
835                         case DOS_NODE :
836                         case ATT_NT :
837                         case PARENT_NODE :
838                              ((Step) stepList.get(0)).setHasSeparator(hasSeparator);
839                             return (stepsReduced != 0) ? 1 : 2;
840                         case SELF_NODE :
841                             // Expr/self::node()[p1] -> Expr[p1] if possible otherwise unchanged
842
//We eliminate this step !
843
//PB if ($x, "toto")/self::node() => $x but not "toto" (not a node)
844
if (firstStepPosition != minStepPosition) {
845                                 stepList.remove(firstStepPosition);
846                                 ((Step) stepList.get(firstStepPosition - 1)).addPredicates(firstStep.getPredicates());
847                                 stepsReduced++;
848                             } else if (!firstStep.hasPredicates() && hasRootStep == true) {
849                                 stepList.remove(firstStepPosition);
850                                 stepsReduced++;
851                             }
852                             ((Step) stepList.get(0)).setHasSeparator(hasSeparator);
853                             return (stepsReduced != 0) ? 1 : 2;
854                         case DESC_NT :
855                         case DESC_TEXT :
856                         case DESC_NODE :
857                         case DOS_NT :
858                         case DOS_TEXT :
859                         case PARENT_NT :
860                             // Expr/descendant::node()[p1] -> Expr/descendant-or-self::node()/child::node()[p1]
861
// Expr/descendant::NT[p1] -> Expr/descendant-or-self::node()/child::NT[p1]
862
// Expr/descendant::text()[p1] -> Expr/descendant-or-self::node()/child::text()[p1]
863
// Expr/descendant-or-self::NT[p1] -> Expr/descendant-or-self::node()/self::NT[p1]
864
// Expr/descendant-or-self::text()[p1] -> Expr/descendant-or-self::node()/self::text()[p1]
865
// Expr/parent::NT[p1] -> Expr/parent::node()/child::NT[p1]
866
splitStep(stepList, firstStepPosition, caseFirstStep);
867                             if (firstStepPosition > minStepPosition)
868                                 firstStepPosition--;
869                             // to ensure looping
870
caseSecondStep = 0;
871                             break;
872                     }
873                     continue;
874                 }
875                 if (caseSecondStep == LOCATED) {
876                     if ((caseFirstStep == CHILD_NT || caseFirstStep == CHILD_NODE) && !firstStep.hasPredicates()) {
877                         //---> child::NT[p0] / dos::node()[p1]/parent::node()[p2]
878
//---> self::node()[child::NT[p0]] ( self::node() | child::NT/dos::node() ) [child::node()[p1]][p2]
879

880                         LocatedExpression tmpLoc = (LocatedExpression) secondStep.getExpression();
881                         ArrayList JavaDoc tmpSteps = tmpLoc.getSteps();
882                         // create [child::node()[p1]][p2]
883
ArrayList JavaDoc predicates = new ArrayList JavaDoc(2);
884                         // creating [child::node()[p1]]
885
try {
886                             ArrayList JavaDoc tmpList = new ArrayList JavaDoc(1);
887                             tmpList.add(modifyStep(false, Axis.CHILD, (Step) tmpSteps.get(0)));
888                             ((Step) tmpList.get(0)).setHasSeparator(false);
889                             //LocatedExpression pred1 = new LocatedExpression(tmpList, true, typevisitor);
890
LocatedExpression pred1 = new LocatedExpression(tmpList, true, null);
891 // pred1.setBracket(true);
892
predicates.add(pred1);
893                         } catch (XQueryException e) {
894                             throw new NormalizeException("Could not construct predicate " + e.getMessage());
895                         }
896                         // add [p2]
897
secondStep = (Step) tmpSteps.get(1);
898                         if (secondStep.getPredicates() != null)
899                             predicates.addAll(secondStep.getPredicates());
900                         // create self::node()[child::NT[p0]]
901
try {
902                             ArrayList JavaDoc tmpList = new ArrayList JavaDoc(1);
903                             firstStep.setHasSeparator(false);
904                             tmpList.add(firstStep);
905                             //LocatedExpression pred1 = new LocatedExpression(tmpList, true, typevisitor);
906
LocatedExpression pred1 = new LocatedExpression(tmpList, true, null);
907 // pred1.setBracket(true);
908
ArrayList JavaDoc tmpPreds = new ArrayList JavaDoc(1);
909                             tmpPreds.add(pred1);
910                             stepList.set(firstStepPosition, new Step(true, Axis.SELF, new NodeTest(NodeKind.NODE, null, null), tmpPreds, null));
911                         } catch (XQueryException e) {
912                             throw new NormalizeException("Could not construct step " + e.getMessage());
913                         }
914                         //create (self::node() | child::NT/dos::node())
915
// construct tpmSteps1
916
ArrayList JavaDoc tmpSteps1 = new ArrayList JavaDoc(1);
917                         try {
918                             tmpSteps1.add(new Step(false, Axis.SELF, new NodeTest(NodeKind.NODE, null, null), null, null));
919                         } catch (XQueryException e) {
920                             throw new NormalizeException("Could not construct step " + e.getMessage());
921                         }
922                         // construct tmpSteps2
923
ArrayList JavaDoc tmpSteps2 = new ArrayList JavaDoc(2);
924                         try {
925                             firstStep = (Step) firstStep.clone();
926                         } catch (CloneNotSupportedException JavaDoc e) {
927                             throw new NormalizeException("Could not clone step " + e.getMessage());
928                         }
929                         firstStep.setPredicates(null);
930                         tmpSteps2.add(firstStep);
931                         tmpSteps2.add(getDOSNodeStep());
932
933                         firstStep = createUnionStep(tmpSteps1, tmpSteps2);
934                         firstStep.setPredicates(predicates);
935                         stepList.set(firstStepPosition + 1, firstStep);
936
937                         if (firstStepPosition > minStepPosition)
938                             firstStepPosition--;
939
940                     } else {
941                         throw new NormalizeException("Could not handle " + stepList);
942                     }
943                     continue;
944                 }
945                 if (caseSecondStep == UNION) {
946                     if (firstStep.hasPredicates()) {
947                         firstStepPosition++;
948                         continue;
949                     }
950                     // step/unionStep(list1,list2)[p2] -> unionStep(step/list1,step/list2)[p2]
951
// handle first list
952
ArrayList JavaDoc tmpSteps1 = ((LocatedExpression) ((ListOpUNIONExpression) secondStep.getExpression()).getExpression1()).getSteps();
953                     ((Step) tmpSteps1.get(0)).setHasSeparator(true);
954                     try {
955                         tmpSteps1.add(0, firstStep.clone());
956                     } catch (CloneNotSupportedException JavaDoc e) {
957                         throw new NormalizeException("Could not clone " + firstStep);
958                     }
959                     int retVal1 = simplifySteps(tmpSteps1, false, false, parentModule);
960                     // handle second list
961
ArrayList JavaDoc tmpSteps2 = ((LocatedExpression) ((ListOpUNIONExpression) secondStep.getExpression()).getExpression2()).getSteps();
962                     ((Step) tmpSteps2.get(0)).setHasSeparator(true);
963                     try {
964                         tmpSteps2.add(0, firstStep.clone());
965                     } catch (CloneNotSupportedException JavaDoc e) {
966                         throw new NormalizeException("Could not clone " + firstStep);
967                     }
968                     int retVal2 = simplifySteps(tmpSteps2, false, false, parentModule);
969                     if (retVal1 == 0 && retVal2 == 0)
970                         return 0;
971                     if (retVal1 == 0) {
972                         stepList.remove(firstStepPosition);
973                         stepList.addAll(firstStepPosition, tmpSteps2);
974                         if (firstStepPosition > minStepPosition)
975                             firstStepPosition--;
976                     } else if (retVal2 == 0) {
977                         stepList.remove(firstStepPosition);
978                         stepList.addAll(firstStepPosition, tmpSteps1);
979                         if (firstStepPosition > minStepPosition)
980                             firstStepPosition--;
981                     } else if (retVal1 == 2 && retVal2 == 2) {
982                         tmpSteps1.remove(0);
983                         tmpSteps2.remove(0);
984                         ((Step) tmpSteps1.get(0)).setHasSeparator(false);
985                         ((Step) tmpSteps2.get(0)).setHasSeparator(false);
986                         firstStepPosition++;
987                     } else {
988                         stepList.remove(firstStepPosition);
989                         ((Step) tmpSteps1.get(0)).setHasSeparator(false);
990                         ((Step) tmpSteps2.get(0)).setHasSeparator(false);
991                         if (firstStepPosition > minStepPosition)
992                             firstStepPosition--;
993                     }
994                     continue;
995                 }
996                 switch (caseFirstStep) {
997                     case UNION :
998                         // advance one step
999
firstStepPosition++;
1000                        break;
1001                    case SELF_NT :
1002                        switch (caseSecondStep) {
1003                            case SELF_NT :
1004                                // self::NT1[p1]/self::NT2[p2] -> self:NT1[p1][p2] if NT1 and NT2 are compatible otherwise ERROR
1005
if (matchStepExpr(firstStep.getExpression(), secondStep.getExpression())) {
1006                                    if (firstStep.getExpression() instanceof QName && ((QName) firstStep.getExpression()).getLocalName().equals("*")) {
1007                                        //remove step :
1008
stepList.remove(firstStepPosition);
1009                                        secondStep.addPredicates(firstStep.getPredicates());
1010                                        stepsReduced++;
1011                                    } else if (secondStep.getExpression() instanceof QName && ((QName) secondStep.getExpression()).getLocalName().equals("*")) {
1012                                        //remove step :
1013
stepList.remove(firstStepPosition + 1);
1014                                        firstStep.addPredicates(secondStep.getPredicates());
1015                                        stepsReduced++;
1016                                    } else {
1017                                        //QNames are matching !
1018
//remove step :
1019
stepList.remove(firstStepPosition);
1020                                        secondStep.addPredicates(firstStep.getPredicates());
1021                                        stepsReduced++;
1022                                    }
1023                                } else {
1024                                    //QNames are not matching : Eliminate this Located Expression :
1025
return 0;
1026                                }
1027                                break;
1028                            case SELF_TEXT :
1029                                // self::NT1[p1]/self::text() -> ERROR
1030
//Eliminate this Located Expression :
1031
return 0;
1032                            case SELF_NODE :
1033                                // self::NT1[p1]/self::node()[p2] -> self::NT1[p1][p2]
1034
//remove step :
1035
stepList.remove(firstStepPosition + 1);
1036                                firstStep.addPredicates(secondStep.getPredicates());
1037                                stepsReduced++;
1038                                break;
1039                            case PARENT_NT :
1040                            case PARENT_NODE :
1041                                // self::NT1[p1]/parent::NT2[p2] -> parent::node()/child::NT2[child::node()[p1]][p2]
1042
// self::NT1[p1]/parent::node()[p2] -> parent::node()[child::node()[p1]][p2]
1043
stepsReduced++;
1044                                //remove step :
1045
stepList.remove(firstStepPosition);
1046                                // add predicate
1047
ArrayList JavaDoc tmpSteps = new ArrayList JavaDoc(1);
1048                                tmpSteps.add(modifyStep(false, Axis.CHILD, firstStep));
1049                                try {
1050                                    //LocatedExpression tmpLoc = new LocatedExpression(tmpSteps, true, typevisitor, false);
1051
LocatedExpression tmpLoc = new LocatedExpression(tmpSteps, true, null, false);
1052// tmpLoc.setBracket(true);
1053
secondStep.addPredicate(0, tmpLoc);
1054                                } catch (XQueryException e) {
1055                                    throw new NormalizeException("Could not add predicate " + e.getMessage());
1056                                }
1057                                if (firstStepPosition > minStepPosition)
1058                                    firstStepPosition--;
1059                                break;
1060                                // case DESC_NODE :
1061
// case DESC_TEXT :
1062
// case DESC_NT :
1063
// case DOS_TEXT :
1064
// case DOS_NT :
1065
// splitStep(stepList, firstStepPosition + 1, caseSecondStep);
1066
// // Advance two steps
1067
// firstStepPosition += 2;
1068
default :
1069                                //Advance one step :
1070
firstStepPosition++;
1071                                break;
1072                        }
1073                        break;
1074                    case SELF_TEXT :
1075                        switch (caseSecondStep) {
1076                            case PARENT_NT :
1077                            case PARENT_NODE :
1078                                // self::text()[p1]/parent::NT[p2] -> parent::node()/child::NT[child::text()[p1]][p2]
1079
// self::text()[p1]/parent::node[p2] -> parent::node()[child::text()[p1]][p2]
1080
stepsReduced++;
1081                                //remove step :
1082
stepList.remove(firstStepPosition);
1083                                // add predicate
1084
ArrayList JavaDoc tmpSteps = new ArrayList JavaDoc(1);
1085                                tmpSteps.add(modifyStep(false, Axis.CHILD, firstStep));
1086                                try {
1087                                    //LocatedExpression tmpLoc = new LocatedExpression(tmpSteps, true, typevisitor, false);
1088
LocatedExpression tmpLoc = new LocatedExpression(tmpSteps, true, null, false);
1089// tmpLoc.setBracket(true);
1090
secondStep.addPredicate(0, tmpLoc);
1091                                } catch (XQueryException e) {
1092                                    throw new NormalizeException("Could not add predicate " + e.getMessage());
1093                                }
1094                                if (firstStepPosition > minStepPosition)
1095                                    firstStepPosition--;
1096                                break;
1097                            case SELF_TEXT :
1098                            case SELF_NODE :
1099                            case DOS_NODE :
1100                                // self::text()[p1]/self::text()[p2] -> self::text()[p1][p2]
1101
// self::text()[p1]/self::node()[p2] -> self::text()[p1][p2]
1102
//remove step :
1103
stepList.remove(firstStepPosition + 1);
1104                                firstStep.addPredicates(secondStep.getPredicates());
1105                                stepsReduced++;
1106                                break;
1107                            default :
1108                                //Eliminate this Located Expression :
1109
return 0;
1110                        }
1111                        break;
1112                    case SELF_NODE :
1113                        if (firstStep.hasPredicates()) {
1114                            if (firstStepPosition != minStepPosition) {
1115                                stepList.remove(firstStepPosition);
1116                                ((Step) stepList.get(firstStepPosition - 1)).addPredicates(firstStep.getPredicates());
1117                                stepsReduced++;
1118                                firstStepPosition--;
1119                            } else {
1120                                //Advance one step :
1121
firstStepPosition++;
1122                            }
1123                        } else {
1124                            stepList.remove(firstStepPosition);
1125                            stepsReduced++;
1126                            if (firstStepPosition > minStepPosition)
1127                                firstStepPosition--;
1128                        }
1129                        break;
1130                    case CHILD_NT :
1131                        switch (caseSecondStep) {
1132                            case SELF_NT :
1133                                if (matchStepExpr(firstStep.getExpression(), secondStep.getExpression())) {
1134                                    if (firstStep.getExpression() instanceof QName && ((QName) firstStep.getExpression()).getLocalName().equals("*")) {
1135                                        // remove step
1136
stepList.remove(firstStepPosition);
1137                                        secondStep.addPredicates(firstStep.getPredicates());
1138                                        // modify second step
1139
stepList.set(firstStepPosition, modifyStep(true, Axis.CHILD, secondStep));
1140                                        stepsReduced++;
1141                                        //move back one step :
1142
if (firstStepPosition > minStepPosition)
1143                                            firstStepPosition--;
1144                                    } else if (secondStep.getExpression() instanceof QName && ((QName) secondStep.getExpression()).getLocalName().equals("*")) {
1145                                        //remove step :
1146
stepList.remove(firstStepPosition + 1);
1147                                        firstStep.addPredicates(secondStep.getPredicates());
1148                                        stepsReduced++;
1149                                    } else {
1150                                        //QNames are matching !
1151
//remove step :
1152
stepList.remove(firstStepPosition + 1);
1153                                        firstStep.addPredicates(secondStep.getPredicates());
1154                                        stepsReduced++;
1155                                    }
1156                                    break;
1157                                } else {
1158                                    //QNames are not matching : Eliminate this Located Expression :
1159
return 0;
1160                                }
1161                            case SELF_TEXT :
1162                                //Eliminate this Located Expression :
1163
return 0;
1164                            case SELF_NODE :
1165                                //remove step :
1166
stepList.remove(firstStepPosition + 1);
1167                                firstStep.addPredicates(secondStep.getPredicates());
1168                                stepsReduced++;
1169                                break;
1170                            case PARENT_NT :
1171                            case PARENT_NODE :
1172                                stepsReduced++;
1173                                //remove step :
1174
stepList.remove(firstStepPosition);
1175                                secondStep = modifyStep(true, Axis.SELF, secondStep);
1176                                stepList.set(firstStepPosition, secondStep);
1177                                // add predicate
1178
ArrayList JavaDoc tmpSteps = new ArrayList JavaDoc(1);
1179                                tmpSteps.add(modifyStep(false, Axis.CHILD, firstStep));
1180                                try {
1181                                    //LocatedExpression tmpLoc = new LocatedExpression(tmpSteps, true, typevisitor, false);
1182
LocatedExpression tmpLoc = new LocatedExpression(tmpSteps, true, null, false);
1183// tmpLoc.setBracket(true);
1184
secondStep.addPredicate(0, tmpLoc);
1185                                } catch (XQueryException e) {
1186                                    throw new NormalizeException("Could not add predicate " + e.getMessage());
1187                                }
1188                                if (firstStepPosition > minStepPosition)
1189                                    firstStepPosition--;
1190                                break;
1191                            default :
1192                                //Advance one step :
1193
firstStepPosition++;
1194                                break;
1195                        }
1196                        break;
1197                    case CHILD_TEXT :
1198                        switch (caseSecondStep) {
1199                            case PARENT_NT :
1200                            case PARENT_NODE :
1201                                stepsReduced++;
1202                                //remove step :
1203
stepList.remove(firstStepPosition);
1204                                secondStep = modifyStep(true, Axis.SELF, secondStep);
1205                                stepList.set(firstStepPosition, secondStep);
1206                                // add predicate
1207
ArrayList JavaDoc tmpSteps = new ArrayList JavaDoc(1);
1208                                firstStep.setHasSeparator(false);
1209                                tmpSteps.add(firstStep);
1210                                try {
1211                                    //LocatedExpression tmpLoc = new LocatedExpression(tmpSteps, true, typevisitor, false);
1212
LocatedExpression tmpLoc = new LocatedExpression(tmpSteps, true, null, false);
1213// tmpLoc.setBracket(true);
1214
secondStep.addPredicate(0, tmpLoc);
1215                                } catch (XQueryException e) {
1216                                    throw new NormalizeException("Could not add predicate " + e.getMessage());
1217                                }
1218                                if (firstStepPosition > minStepPosition)
1219                                    firstStepPosition--;
1220                                break;
1221                            case SELF_TEXT :
1222                            case SELF_NODE :
1223                            case DOS_NODE :
1224                                //remove step :
1225
stepList.remove(firstStepPosition + 1);
1226                                firstStep.addPredicates(secondStep.getPredicates());
1227                                stepsReduced++;
1228                                break;
1229                            default :
1230                                //Eliminate this Located Expression :
1231
return 0;
1232                        }
1233                        break;
1234                    case CHILD_NODE :
1235                        switch (caseSecondStep) {
1236                            case SELF_NT :
1237                            case SELF_TEXT :
1238                                if (!firstStep.hasPredicates()) {
1239                                    stepsReduced++;
1240                                    //modify step :
1241
stepList.set(firstStepPosition, modifyStep(true, Axis.CHILD, secondStep));
1242                                    // remove step
1243
stepList.remove(firstStepPosition + 1);
1244                                    //move back one step :
1245
if (firstStepPosition > minStepPosition)
1246                                        firstStepPosition--;
1247                                } else {
1248                                    //Advance one step :
1249
firstStepPosition++;
1250                                }
1251                                break;
1252                            case SELF_NODE :
1253                                stepsReduced++;
1254                                stepList.remove(firstStepPosition + 1);
1255                                firstStep.addPredicates(secondStep.getPredicates());
1256                                break;
1257                            case DOS_NODE :
1258                                stepsReduced++;
1259                                // modify step
1260
if (!firstStep.hasPredicates()) {
1261                                    stepList.set(firstStepPosition, secondStep);
1262                                    stepList.set(firstStepPosition + 1, firstStep);
1263                                    if (firstStepPosition > minStepPosition)
1264                                        firstStepPosition--;
1265                                } else {
1266                                    //Advance one step :
1267
firstStepPosition++;
1268                                }
1269                                break;
1270                            case PARENT_NT :
1271                            case PARENT_NODE :
1272                                stepsReduced++;
1273                                //remove step :
1274
stepList.remove(firstStepPosition);
1275                                secondStep = modifyStep(true, Axis.SELF, secondStep);
1276                                stepList.set(firstStepPosition, secondStep);
1277                                // add predicate
1278
ArrayList JavaDoc tmpSteps = new ArrayList JavaDoc(1);
1279                                firstStep.setHasSeparator(false);
1280                                tmpSteps.add(firstStep);
1281                                try {
1282                                    //LocatedExpression tmpLoc = new LocatedExpression(tmpSteps, true, typevisitor, false);
1283
LocatedExpression tmpLoc = new LocatedExpression(tmpSteps, true, null, false);
1284// tmpLoc.setBracket(true);
1285
secondStep.addPredicate(0, tmpLoc);
1286                                } catch (XQueryException e) {
1287                                    throw new NormalizeException("Could not add predicate " + e.getMessage());
1288                                }
1289                                if (firstStepPosition > minStepPosition)
1290                                    firstStepPosition--;
1291                                break;
1292                            default :
1293                                //Advance one step :
1294
firstStepPosition++;
1295                                break;
1296                        }
1297                        break;
1298                    case DESC_NT :
1299                        switch (caseSecondStep) {
1300                            case SELF_TEXT :
1301                                //Eliminate this Located Expression :
1302
return 0;
1303                            default :
1304                                stepsReduced++;
1305                                stepList.set(firstStepPosition, modifyStep(true, Axis.CHILD, firstStep));
1306                                stepList.add(firstStepPosition, getDOSNodeStep());
1307                                if (firstStepPosition > minStepPosition)
1308                                    firstStepPosition--;
1309                                else
1310                                    firstStepPosition++;
1311                                break;
1312                        }
1313                        break;
1314                    case DESC_TEXT :
1315                        switch (caseSecondStep) {
1316                            case SELF_TEXT :
1317                            case SELF_NODE :
1318                            case DOS_NODE :
1319                            case PARENT_NT :
1320                            case PARENT_NODE :
1321                                stepsReduced++;
1322                                stepList.set(firstStepPosition, modifyStep(true, Axis.CHILD, firstStep));
1323                                stepList.add(firstStepPosition, getDOSNodeStep());
1324                                if (firstStepPosition > minStepPosition)
1325                                    firstStepPosition--;
1326                                else
1327                                    firstStepPosition++;
1328                                break;
1329                            default :
1330                                //Eliminate this Located Expression :
1331
return 0;
1332                        }
1333                        break;
1334                    case DESC_NODE :
1335                        stepsReduced++;
1336                        stepList.set(firstStepPosition, modifyStep(true, Axis.CHILD, firstStep));
1337                        stepList.add(firstStepPosition, getDOSNodeStep());
1338                        if (firstStepPosition > minStepPosition)
1339                            firstStepPosition--;
1340                        else
1341                            firstStepPosition++;
1342                        break;
1343                    case DOS_NT :
1344                        switch (caseSecondStep) {
1345                            case SELF_TEXT :
1346                                //Eliminate this Located Expression :
1347
return 0;
1348                            default :
1349                                stepsReduced++;
1350                                stepList.set(firstStepPosition, modifyStep(true, Axis.SELF, firstStep));
1351                                stepList.add(firstStepPosition, getDOSNodeStep());
1352                                if (firstStepPosition > minStepPosition)
1353                                    firstStepPosition--;
1354                                else
1355                                    firstStepPosition++;
1356                                break;
1357                        }
1358                        break;
1359                    case DOS_TEXT :
1360                        switch (caseSecondStep) {
1361                            case SELF_TEXT :
1362                            case SELF_NODE :
1363                            case DOS_NODE :
1364                            case PARENT_NT :
1365                            case PARENT_NODE :
1366                                stepsReduced++;
1367                                stepList.set(firstStepPosition, modifyStep(true, Axis.SELF, firstStep));
1368                                stepList.add(firstStepPosition, getDOSNodeStep());
1369                                if (firstStepPosition > minStepPosition)
1370                                    firstStepPosition--;
1371                                else
1372                                    firstStepPosition++;
1373                                break;
1374                            default :
1375                                //Eliminate this Located Expression :
1376
return 0;
1377                        }
1378                        break;
1379                    case DOS_NODE :
1380                        switch (caseSecondStep) {
1381                            case SELF_NODE :
1382                                // remove step
1383
stepList.remove(firstStepPosition + 1);
1384                                firstStep.addPredicates(secondStep.getPredicates());
1385                                stepsReduced++;
1386                                break;
1387                            case DESC_NT :
1388                            case DESC_TEXT :
1389                            case DESC_NODE :
1390                            case DOS_NT :
1391                            case DOS_TEXT :
1392                            case DOS_NODE :
1393                                if (!firstStep.hasPredicates()) {
1394                                    stepsReduced++;
1395                                    stepList.remove(firstStepPosition);
1396                                    if (firstStepPosition > minStepPosition)
1397                                        firstStepPosition--;
1398                                } else {
1399                                    firstStepPosition++;
1400                                    break;
1401                                }
1402                                break;
1403                                // case PARENT_NT :
1404
case PARENT_NODE :
1405
1406                                // dos::node()[p1]/parent::node()[p2] -> (parent::node() | dos::node())[child::node()[p1]][p2]
1407
// dos::node()[p1]/parent::NT2()[p2] -> (parent::node() | dos::node())/self::NT2[child::node()[p1]][p2]
1408
// test if not first step
1409
if (firstStepPosition == minStepPosition) {
1410                                    if (hasRootVar) {
1411                                        // advance of step
1412
firstStepPosition++;
1413                                        // add LARS
1414
//throw new NormalizeException("Could not handle " + stepList);
1415
} else {
1416                                        // change DOS into DESC
1417
modifyStep(firstStep.hasSeparator(), Axis.DESCENDANT, firstStep);
1418                                    }
1419                                    break;
1420                                }
1421                                // for now make special step
1422
// remove step
1423
stepList.remove(firstStepPosition + 1);
1424                                // create locatedExpression
1425
LocatedExpression tmpLoc = null;
1426                                ArrayList JavaDoc tmpSteps = new ArrayList JavaDoc(3);
1427                                firstStep.setHasSeparator(false);
1428                                tmpSteps.add(firstStep);
1429                                tmpSteps.add(secondStep);
1430                                try {
1431                                    tmpLoc = new LocatedExpression(tmpSteps, true, null, false);
1432                                    firstStep = new Step(true, Axis.NONE, tmpLoc, null, null);
1433                                } catch (XQueryException e) {
1434                                    throw new NormalizeException("Could not create located expression " + e.getMessage());
1435                                }
1436                                stepList.set(firstStepPosition, firstStep);
1437                                if (firstStepPosition > minStepPosition)
1438                                    firstStepPosition--;
1439
1440                                /*
1441                                // erase one step
1442                                stepList.remove(firstStepPosition + 1);
1443                                stepsReduced++;
1444                                // construct future predicates
1445                                ArrayList predicates = new ArrayList(2);
1446                                LocatedExpression tmpLoc = null;
1447                                ArrayList tmpSteps = new ArrayList(1);
1448                                try {
1449                                    tmpSteps.add(modifyStep(false, Axis.CHILD, firstStep));
1450                                    tmpLoc = new LocatedExpression(tmpSteps, true, null);
1451                                    tmpLoc.setBracket(true);
1452                                } catch (XQueryException e) {
1453                                    throw new NormalizeException("Could not construct predicate " + e.getMessage());
1454                                }
1455                                predicates.add(tmpLoc);
1456                                if (secondStep.hasPredicates())
1457                                    predicates.addAll(secondStep.getPredicates());
1458                                // construct tpmSteps1
1459                                ArrayList tmpSteps1 = new ArrayList(2);
1460                                secondStep.setHasSeparator(false);
1461                                secondStep.setPredicates(null);
1462                                tmpSteps1.add(secondStep);
1463                                // construct tmpSteps2
1464                                ArrayList tmpSteps2 = new ArrayList(2);
1465                                firstStep = getDOSNodeStep();
1466                                tmpSteps2.add(firstStep);
1467                                firstStep = createUnionStep(tmpSteps1, tmpSteps2);
1468                                firstStep.setPredicates(predicates);
1469                                stepList.set(firstStepPosition, firstStep);
1470                                
1471                                if (firstStepPosition > minStepPosition)
1472                                    firstStepPosition--;
1473                                */

1474                                // dos::node()[p1]/parent::node()[p2] -> ( self::node[P1]/parent::node() | descendant::node()/parent::node()[p1]) [p2]
1475

1476                                break;
1477
1478                            default :
1479                                //Advance one step :
1480
firstStepPosition++;
1481                                break;
1482                        }
1483                        break;
1484                    case ATT_NT :
1485                        switch (caseSecondStep) {
1486                            case SELF_NODE :
1487                            case DOS_NODE :
1488                                // remove step
1489
stepList.remove(firstStepPosition + 1);
1490                                firstStep.addPredicates(secondStep.getPredicates());
1491                                stepsReduced++;
1492                                break;
1493                            case SELF_NT :
1494                            case SELF_TEXT :
1495                            case CHILD_NT :
1496                            case CHILD_TEXT :
1497                            case CHILD_NODE :
1498                            case DESC_NT :
1499                            case DESC_TEXT :
1500                            case DESC_NODE :
1501                            case DOS_NT :
1502                            case DOS_TEXT :
1503                            case ATT_NT :
1504                                return 0;
1505                                //case PARENT_NT :
1506
case PARENT_NODE :
1507                                // TODO add parent node in special construct
1508
stepsReduced++;
1509                                //remove step :
1510
stepList.remove(firstStepPosition);
1511                                secondStep = modifyStep(true, Axis.SELF, secondStep);
1512                                stepList.set(firstStepPosition, secondStep);
1513                                // add predicate
1514
ArrayList JavaDoc tmpSteps = new ArrayList JavaDoc(1);
1515                                firstStep.setHasSeparator(false);
1516                                tmpSteps.add(firstStep);
1517                                try {
1518                                    //LocatedExpression tmpLoc = new LocatedExpression(tmpSteps, true, typevisitor, false);
1519
LocatedExpression tmpLoc = new LocatedExpression(tmpSteps, true, null, false);
1520// tmpLoc.setBracket(true);
1521
secondStep.addPredicate(0, tmpLoc);
1522                                } catch (XQueryException e) {
1523                                    throw new NormalizeException("Could not add predicate " + e.getMessage());
1524                                }
1525                                if (firstStepPosition > minStepPosition)
1526                                    firstStepPosition--;
1527                                break;
1528                            default :
1529                                //Advance one step :
1530
firstStepPosition++;
1531                                break;
1532                        }
1533                        break;
1534                    case PARENT_NT :
1535                        switch (caseSecondStep) {
1536                            case SELF_TEXT :
1537                                //Eliminate this Located Expression :
1538
return 0;
1539                            default :
1540                                stepsReduced++;
1541                                stepList.set(firstStepPosition, modifyStep(true, Axis.SELF, firstStep));
1542                                stepList.add(firstStepPosition, getParentNodeStep());
1543                                if (firstStepPosition > minStepPosition)
1544                                    firstStepPosition--;
1545                                else
1546                                    firstStepPosition++;
1547                                break;
1548                        }
1549                        break;
1550                    case PARENT_NODE :
1551                        switch (caseSecondStep) {
1552                            case SELF_TEXT :
1553                                //Eliminate this Located Expression :
1554
return 0;
1555                            case SELF_NODE :
1556                                //remove step :
1557
stepList.remove(firstStepPosition + 1);
1558                                firstStep.addPredicates(secondStep.getPredicates());
1559                                stepsReduced++;
1560                                break;
1561                            default :
1562                                //Advance one step :
1563
firstStepPosition++;
1564                                break;
1565                        }
1566                        break;
1567                }
1568            } while ((stepList.size() >= firstStepPosition) && (firstStep != null) && (caseSecondStep != -1));
1569            // stepList = newSteps;
1570
}
1571        //outln("NEW STEPS ="+stepList);
1572
//Do not eliminate this Located Expression :
1573
((Step) stepList.get(0)).setHasSeparator(hasSeparator);
1574        return (stepsReduced != 0) ? 1 : 2;
1575    }
1576
1577    /**
1578     * To apply a Step recursively (when /descendant-or-self::node() is present).
1579     * @param element an element constructor
1580     * @param oneFinalStep the step to apply recursively on element.
1581     * @return a list of sub expressions reduce whith the given step recursively.
1582     */

1583    protected ArrayList JavaDoc recursiveReduction(Element element, Step oneFinalStep, boolean noAttributes) throws NormalizeException {
1584        //outln("[recursiveReduction] "+element+"/"+oneFinalStep);
1585
try {
1586            ArrayList JavaDoc subExpr = new ArrayList JavaDoc();
1587            ArrayList JavaDoc subExprs = element.getSubExpressions();
1588            if (subExprs != null) {
1589                for (int i = 0; i < subExprs.size(); i++) {
1590                    XQueryExpression subExpri = (XQueryExpression) subExprs.get(i);
1591                    if (noAttributes && subExpri.getQType() != null && subExpri.getQType().getSubClass() == QType.ATTRIBUTE)
1592                        continue;
1593                    subExpr.addAll(this.applyFinalStep(subExpri, oneFinalStep, true, 0, element.getParentModule()));
1594                }
1595            }
1596            return subExpr;
1597        } catch (XQueryException e) {
1598            throw new NormalizeException(0, e.getMessage());
1599        }
1600    }
1601
1602    /**
1603     * Apply one of theses normalized steps :<BR>
1604     * <UL>
1605     * <LI>//self::node() (<B>*</B>)</LI>
1606     * <LI>//self::text() (<B>*</B>)</LI>
1607     * <LI>//self::nametest (<B>*</B>)</LI>
1608     * <LI>//child::text() (<B>*</B>)</LI>
1609     * <LI>//child::nametest (<B>*</B>)</LI>
1610     * <LI>//@nametest (<B>*</B>)</LI>
1611     * <LI>/self::node()</LI>
1612     * <LI>/self::text()</LI>
1613     * <LI>/self::nametest</LI>
1614     * <LI>/child::node()</LI>
1615     * <LI>/child::text()</LI>
1616     * <LI>/child::nametest</LI>
1617     * <LI>/@nametest</LI>
1618     * <LI>/parent::node()</LI>
1619     * <LI>/parent::nametest</LI>
1620     * </UL>
1621     * on an XQuery expression. The supported (explicitly) XQueryExpressions type are :
1622     * <UL>
1623     * <LI>XQueryExpressionSequence</LI>
1624     * <LI>Element</LI>
1625     * <LI>ValueText</LI>
1626     * <LI>FLWRExpression</LI>
1627     * <LI>LocatedExpression</LI>
1628     * <LI>Variable</LI>
1629     * <LI>ITEExpression</LI>
1630     * <LI>ListOpUNIONExpression</LI>
1631     * <LI>ValueString</LI>
1632     * <LI>ValueBoolean</LI>
1633     * <LI>ValueDouble</LI>
1634     * <LI>ValueFloat</LI>
1635     * <LI>ValueInteger</LI>
1636     * <LI>XQueryBooleanOperatorExpression</LI>
1637     * <LI>AttributeValuePair</LI>
1638     * <LI>UnOpMinusExpression</LI>
1639     * <LI>ListOpArithExpression</LI>
1640     * <LI>ListOpCompExpression</LI>
1641     * </UL>
1642     * Other expressions are supported (by default : can not apply XPath on them).
1643     * (Note: E//S1 : when there is //, the parameter slashSlash is true and oneFinalStep
1644     * parameter contains only the step without the //, i.e. S1).
1645     * @param expressionToNormalize an expression on which to apply a step.
1646     * @param oneFinalStep a step to apply on given expression.
1647     * @param slashSlash true if the given step if preceded by /descendant-or-self::node(), false otherwise.
1648     * @param depth the current depth from the last node on which one applies step /descendant-or-self::node().
1649     * @return an ArrayList of reduce expressions (could be null).
1650     */

1651    private ArrayList JavaDoc applyFinalStep(XQueryExpression expressionToNormalize, Step appliedStep, boolean slashSlash, int depth, XQueryModule parentModule) throws NormalizeException {
1652        //outln("[applyFinalStep] //="+slashSlash+" depth="+depth+" "+oneFinalStep+" "+this.reduced+" "+this.isUnapplicable
1653
//+" "+expressionToNormalize.getClass().getName()+" "+expressionToNormalize);
1654
try {
1655            ArrayList JavaDoc results = new ArrayList JavaDoc();
1656            if (expressionToNormalize == null) {
1657                return results;
1658            }
1659            //Special case if it is a sequence :
1660
if (expressionToNormalize instanceof XQueryExpressionSequence) {
1661                ArrayList JavaDoc subExpr = ((XQueryExpressionSequence) expressionToNormalize).getSubExpressions();
1662                for (int i = 0; i < subExpr.size(); i++) {
1663                    results.addAll(this.applyFinalStep((XQueryExpression) subExpr.get(i), appliedStep, slashSlash, depth, parentModule));
1664                }
1665            } else {
1666                if (appliedStep == null) {
1667                    results.add(expressionToNormalize);
1668                } else if (appliedStep.getPredicates() != null) {
1669                    //outln("=========> PREDICATE !!!!!"+oneFinalStep.getPredicates()+" "+oneFinalStep.getPredicates().get(0).getClass().getName());
1670
this.reduced = false;
1671                    //throw new NormalizeException("Can not apply a step with predicate ("
1672
//+oneFinalStep.getPredicates()+") in LocatedExpressionReducer !");
1673
} else {
1674                    //Here we have really a step to apply on an xqueryexpression :
1675
XQueryExpression test = null;
1676                    if (expressionToNormalize instanceof ValueText) {
1677                        //----------------------------------------------------
1678
//----------------------------- ValueText expression :
1679
//----------------------------------------------------
1680
test = appliedStep.getExpression();
1681                        if ((appliedStep.getAxis() == Axis.SELF) && (test instanceof NodeTest) && (((NodeTest) test).getKind() == NodeKind.TEXT)) {
1682                            //++++++++++++++++++++ step = /self::text()
1683
if (appliedStep.getPredicates() == null) {
1684                                this.reduced = true;
1685                                results.add((ValueText) expressionToNormalize);
1686                            }
1687                        } else if ((appliedStep.getAxis() == Axis.SELF) && (test instanceof NodeTest) && (((NodeTest) test).getKind() == NodeKind.NODE)) {
1688                            //++++++++++++++++++++ Step = /self::node()
1689
if (appliedStep.getPredicates() == null) {
1690                                this.reduced = true;
1691                                results.add(expressionToNormalize);
1692                            }
1693                        } else {
1694                            //Other case (like Step = /self::nametest) : nothing to do !
1695
//results is empty
1696
this.reduced = true;
1697                        }
1698                    } else if (expressionToNormalize instanceof Element) {
1699                        //--------------------------------------------------
1700
//----------------------------- Element expression :
1701
//--------------------------------------------------
1702
Element elt = (Element) expressionToNormalize;
1703                        //Switch according to the type of step :
1704
test = appliedStep.getExpression();
1705                        if ((appliedStep.getAxis() == Axis.ATTRIBUTE) && (test instanceof QName)) {
1706                            //++++++++++++++++++++ step = @nametest
1707
this.reduced = true;
1708                            ArrayList JavaDoc tmplist = elt.getAttributes();
1709                            if (tmplist != null) {
1710                                for (int i = 0; i < tmplist.size(); i++) {
1711                                    AttributeValuePair atti = (AttributeValuePair) tmplist.get(i);
1712                                    if (!atti.isXmlns() && matchStepExpr(atti.getAttributeName(), test)) {
1713                                        results.add(tmplist.get(i));
1714                                    }
1715                                }
1716                            }
1717                            // add LARS 17/09/2003
1718
// look also in subexpressions!!!
1719
tmplist = elt.getSubExpressions();
1720                            if (tmplist != null) {
1721                                for (int i = 0; i < tmplist.size(); i++) {
1722                                    XQueryExpression expri = (XQueryExpression) tmplist.get(i);
1723                                    if (expri.getQType() != null && expri.getQType().getSubClass() == QType.ATTRIBUTE) {
1724                                        XQueryExpression expriname = ((QTypeAttribute) expri.getQType()).getName();
1725                                        if (matchStepExpr( expriname, test)) {
1726                                            results.add(expri);
1727                                        }
1728                                    }
1729                                }
1730                            }
1731                            if (slashSlash) { //To apply step // if it is present :
1732
results.addAll(this.recursiveReduction(elt, appliedStep, false));
1733                            }
1734                        } else if (appliedStep.getAxis() == Axis.SELF) {
1735                            //++++++++++++++++++++ Axis = self :
1736
if (test instanceof QName) {
1737                                //++++++++++++++++++++ Step = /self::nametest
1738
this.reduced = true;
1739                                XQueryExpression eltName = elt.getStartTag();
1740                                if (matchStepExpr(eltName, test)) {
1741                                    if (slashSlash) { //To apply step // if it is present :
1742
results.add(elt.clone());
1743                                        results.addAll(this.recursiveReduction(elt, appliedStep, true));
1744                                    } else {
1745                                        results.add(elt);
1746                                    }
1747                                } else {
1748                                    if (slashSlash) { //To apply step // if it is present :
1749
results.addAll(this.recursiveReduction(elt, appliedStep, true));
1750                                    } //else nothing to do : result is empty !
1751

1752                                }
1753                            } else if ((test instanceof NodeTest) && (((NodeTest) test).getKind() == NodeKind.NODE)) {
1754                                //++++++++++++++++++++ Step = /self::node()
1755
this.reduced = true;
1756                                if (slashSlash) { //To apply step // if it is present :
1757
results.add(elt.clone());
1758                                    results.addAll(this.recursiveReduction(elt, appliedStep, true));
1759                                } else {
1760                                    results.add(elt);
1761                                }
1762                            } else if ((test instanceof NodeTest) && (((NodeTest) test).getKind() == NodeKind.TEXT)) {
1763                                //++++++++++++++++++++ Step = /self::text()
1764
//Nothing to do !
1765
//results is empty
1766
this.reduced = true;
1767                                if (slashSlash) { //To apply step // if it is present :
1768
results.addAll(this.recursiveReduction(elt, appliedStep, true));
1769                                }
1770                            } else {
1771                                throw new NormalizeException("Unsupported step (" + appliedStep + ") in LocatedExpressionReducer !");
1772                            }
1773                        } else if (appliedStep.getAxis() == Axis.CHILD) {
1774                            //++++++++++++++++++++ Axis = child :
1775
ArrayList JavaDoc subNodes = elt.getSubExpressions();
1776                            if ((subNodes == null) || (subNodes.size() == 0)) {
1777                                //No children : nothing to do !
1778
//results is empty
1779
this.reduced = true;
1780                            } else {
1781                                if ((test instanceof NodeTest) && (((NodeTest) test).getKind() == NodeKind.TEXT)) {
1782                                    //++++++++++++++++++++ Step = /child::text()
1783
for (int i = 0; i < subNodes.size(); i++) {
1784                                        if (subNodes.get(i) instanceof ValueText) {
1785                                            this.reduced = true;
1786                                            results.add((ValueText) subNodes.get(i));
1787                                        } else if (!(subNodes.get(i) instanceof Element)) {
1788                                            Step newStep = (Step) appliedStep.clone();
1789                                            newStep.setAxis(Axis.SELF);
1790                                            results.addAll(this.applyFinalStep((XQueryExpression) subNodes.get(i), newStep, slashSlash, depth + 1, parentModule));
1791                                        } else {
1792                                            //Child is Element !
1793
this.reduced = true;
1794                                            if (slashSlash) { //To apply step // if it is present :
1795
Step newStep = (Step) appliedStep.clone();
1796                                                newStep.setAxis(Axis.SELF);
1797                                                results.addAll(this.recursiveReduction((Element) subNodes.get(i), newStep, true));
1798                                            }
1799                                        }
1800
1801                                    }
1802                                } else if ((test instanceof NodeTest) && (((NodeTest) test).getKind() == NodeKind.NODE)) {
1803                                    //++++++++++++++++++++ Step = /child::node()
1804
for (int i = 0; i < subNodes.size(); i++) {
1805                                        XQueryExpression subExpri = (XQueryExpression) subNodes.get(i);
1806                                        if (subExpri.getQType() != null && subExpri.getQType().getSubClass() == QType.ATTRIBUTE)
1807                                            continue;
1808                                        if ((subExpri instanceof Element) || (subExpri instanceof ValueText)) {
1809                                            this.reduced = true;
1810                                            results.add(subExpri);
1811                                        } else {
1812                                            Step newStep = (Step) appliedStep.clone();
1813                                            newStep.setAxis(Axis.SELF);
1814                                            results.addAll(this.applyFinalStep(subExpri, newStep, slashSlash, depth + 1, parentModule));
1815                                        }
1816                                    }
1817                                } else if (test instanceof QName) {
1818                                    //++++++++++++++++++++ Step = /child::nametest
1819
for (int i = 0; i < subNodes.size(); i++) {
1820                                        Step newStep = (Step) appliedStep.clone();
1821                                        newStep.setAxis(Axis.SELF);
1822                                        results.addAll(this.applyFinalStep((XQueryExpression) subNodes.get(i), newStep, slashSlash, depth + 1, parentModule));
1823                                    }
1824                                } else {
1825                                    throw new NormalizeException("Unsupported step test (" + appliedStep + ") in LocatedExpressionReducer !");
1826                                }
1827                            }
1828                        } else {
1829                            //Other Axis : nothing to do !
1830
//results is empty
1831
}
1832                    } else if (expressionToNormalize instanceof FLWRExpression) {
1833                        //----------------------------------------------
1834
//----------------------------- FLWRExpression :
1835
//----------------------------------------------
1836
//Modified this FLWRExpression
1837
FLWRExpression flwr = (FLWRExpression) expressionToNormalize;
1838                        XQueryExpression returnClause = flwr.getReturnClause();
1839                        ArrayList JavaDoc newReturnClause = this.applyFinalStep(returnClause, appliedStep, slashSlash, depth, parentModule);
1840                        XQueryExpression newReturnExpression = this.buildExpression(newReturnClause);
1841                        if (newReturnExpression != null) {
1842                            flwr.setReturnClause(newReturnExpression);
1843                            results.add(flwr);
1844                        }
1845                    } else if (expressionToNormalize instanceof LocatedExpression) {
1846                        //-------------------------------------------------
1847
//----------------------------- LocatedExpression :
1848
//-------------------------------------------------
1849
// add LARS do not redo locatedexpression with attribute QType
1850
if (appliedStep.getAxis() == Axis.ATTRIBUTE && expressionToNormalize.getQType() != null && expressionToNormalize.getQType().getSubClass() == QType.ATTRIBUTE) {
1851                            // do nothing
1852
} else {
1853                            LocatedExpression tmploc = (LocatedExpression) expressionToNormalize;
1854                            //Update this located epxression :
1855
if (slashSlash) {
1856                                tmploc.addStep(getDOSNodeStep());
1857                            }
1858                            tmploc.addStep(appliedStep);
1859                            if (!this.isUnapplicable) {
1860                                this.reduced = true;
1861                            }
1862                            if (simplifySteps(tmploc.getSteps(), true, (tmploc.getStepNum(0).getExpression() instanceof Variable), tmploc.getStepNum(0).getExpression().getParentModule()) != 0) {
1863                                boolean correctType = true;
1864                                try {
1865                                    if (this.typeVisitor != null) {
1866                                        expressionToNormalize.accept(this.typeVisitor);
1867                                    }
1868                                } catch (TypeException te) {
1869                                    //Nothing to do : eliminate this located by default.
1870
correctType = false;
1871                                }
1872                                if (correctType)
1873                                    results.add(expressionToNormalize);
1874                            }
1875                        }
1876                    } else if (expressionToNormalize instanceof Variable) {
1877                        //---------------------------------------------------
1878
//----------------------------- Variable expression :
1879
//---------------------------------------------------
1880
//Modified this Variable :
1881
this.reduced = true;
1882                        if (this.isStepSelfNode(appliedStep)) {
1883                            results.add(expressionToNormalize);
1884                        } else {
1885                            ArrayList JavaDoc newSteps = new ArrayList JavaDoc();
1886                            newSteps.add(new Step(false, Axis.NONE, expressionToNormalize, null, null));
1887                            if (slashSlash) {
1888                                newSteps.add(getDOSNodeStep());
1889                            }
1890                            newSteps.add(appliedStep);
1891                            try {
1892                                results.add(new LocatedExpression(newSteps, parentModule));
1893                            } catch (TypeException te) {
1894                                //Nothing to do : eliminate this located by default.
1895
}
1896                        }
1897                    } else if (expressionToNormalize instanceof ITEExpression) {
1898                        //-------------------------------------------------
1899
//----------------------------- ITEExpression :
1900
//-------------------------------------------------
1901
//Modified this ITEExpression :
1902
ITEExpression ite = (ITEExpression) expressionToNormalize;
1903                        XQueryExpression thenClause = ite.getThenExpression();
1904                        XQueryExpression elseClause = ite.getElseExpression();
1905                        ArrayList JavaDoc newThenClause = this.applyFinalStep(thenClause, appliedStep, slashSlash, depth, parentModule);
1906                        ArrayList JavaDoc newElseClause = this.applyFinalStep(elseClause, appliedStep, slashSlash, depth, parentModule);
1907                        ite.setThenExpression(this.buildExpression(newThenClause));
1908                        ite.setElseExpression(this.buildExpression(newElseClause));
1909                        results.add(ite);
1910                    } else if (expressionToNormalize instanceof ListOpUNIONExpression) {
1911                        //-------------------------------------------------
1912
//----------------------------- ListOpUNIONExpression :
1913
//-------------------------------------------------
1914
//Modified this ListOpUNIONExpression :
1915
ListOpUNIONExpression loue = (ListOpUNIONExpression) expressionToNormalize;
1916                        XQueryExpression left = loue.getExpression1();
1917                        XQueryExpression rigth = loue.getExpression2();
1918                        ArrayList JavaDoc newLeft = this.applyFinalStep(left, appliedStep, slashSlash, depth, parentModule);
1919                        ArrayList JavaDoc newRigth = this.applyFinalStep(rigth, appliedStep, slashSlash, depth, parentModule);
1920                        loue.setExpression1(this.buildExpression(newLeft));
1921                        loue.setExpression2(this.buildExpression(newRigth));
1922                        results.add(loue);
1923                    } else if (expressionToNormalize instanceof FunctionDATA) {
1924                        test = appliedStep.getExpression();
1925                        if (appliedStep.getAxis() == Axis.SELF && test instanceof NodeTest && ((NodeTest) test).getKind() == NodeKind.TEXT) {
1926                            results.add(expressionToNormalize);
1927                        } else {
1928                            // do nothing, eliminate!
1929
}
1930                        /*
1931                        } else if (expressionToNormalize instanceof ValueString) {
1932                        } else if (expressionToNormalize instanceof ValueBoolean) {
1933                        } else if (expressionToNormalize instanceof ValueDouble) {
1934                        } else if (expressionToNormalize instanceof ValueFloat) {
1935                        } else if (expressionToNormalize instanceof ValueInteger) {
1936                        */

1937                    } else if (expressionToNormalize instanceof Value) {
1938                        //Other supported cases : nothing to do (eliminate this by default)
1939
//results is empty
1940
this.reduced = true;
1941                    } else if (expressionToNormalize instanceof AggregateFunctionCall) {
1942                        test = appliedStep.getExpression();
1943                        if (appliedStep.getAxis() == Axis.SELF) {
1944                            if ((test instanceof NodeTest) && (((NodeTest) test).getKind() == NodeKind.TEXT)) {
1945                                results.add(expressionToNormalize);
1946                            }
1947                        }
1948                    } else if ((expressionToNormalize instanceof PrimitiveFunctionCall) && !(expressionToNormalize instanceof InputFunctionCall)) {
1949                    } else if (expressionToNormalize instanceof XQueryBooleanOperatorExpression) {
1950                    } else if (expressionToNormalize instanceof AttributeValuePair) {
1951                    } else if (expressionToNormalize instanceof UnOpMinusExpression) {
1952                    } else if (expressionToNormalize instanceof ListOpArithExpression) {
1953                    } else if (expressionToNormalize instanceof ListOpCompExpression) {
1954                        //Other supported cases : nothing to do (eliminate this by default)
1955
//results is empty
1956
this.reduced = true;
1957                    } else {
1958                        //Other types of expressions (ex : FunctionCOLLECTION):
1959
//We should not modify them!
1960
this.isUnapplicable = true;
1961                        ArrayList JavaDoc newSteps = new ArrayList JavaDoc();
1962                        newSteps.add(new Step(false, Axis.NONE, expressionToNormalize, null, null));
1963                        if (slashSlash) {
1964                            newSteps.add(getDOSNodeStep());
1965                        }
1966                        newSteps.add(appliedStep);
1967                        try {
1968                            results.add(new LocatedExpression(newSteps, parentModule));
1969                        } catch (TypeException te) {
1970                            //Nothing to do : eliminate this located by default.
1971
}
1972                    }
1973                }
1974            }
1975            //outln("RESULT = "+results);
1976
return results;
1977        } catch (CloneNotSupportedException JavaDoc e) {
1978            throw new NormalizeException(0, e.getMessage(), e);
1979        } catch (XQueryException e) {
1980            throw new NormalizeException(0, e.getMessage());
1981        }
1982    }
1983
1984    /**
1985     * To reduce (this) located expression (if it is possible).
1986     * @return true if expression was reduce, false otherwise.
1987     */

1988
1989    protected boolean reduceLocatedExpression(XQueryModule parentModule) throws NormalizeException {
1990        try {
1991            this.reduced = false;
1992            // this.stepsReduced = false;
1993
boolean stepsReduced = false;
1994            //Normalize steps two by two :
1995
int simplified = simplifySteps(steps, true, (rootExpr.getExpression() instanceof Variable), parentModule);
1996            if (simplified == 0) {
1997                //We must eliminate the current Located Expression !
1998
this.reduced = true;
1999            } else {
2000                stepsReduced = (simplified == 1);
2001                Step[] next = null;
2002                boolean firstTime = true;
2003                //Apply each step on the first step expression :
2004
do {
2005                    next = this.getNextSteps();
2006                    //Format next one or two steps :
2007
if (next != null) {
2008                        //boolean slashSlash = false;
2009
boolean slashSlash = this.isSlashSlash(next[0]);
2010                        boolean special = false;
2011                        if (slashSlash) {
2012                            if (next[1] != null) {
2013                                next[0] = next[1];
2014                            } else {
2015                                //Create "this" step, i.e. : /self::node()
2016
next[0] = new Step(true, Axis.SELF, new NodeTest(NodeKind.NODE, null, parentModule), null, parentModule);
2017                                special = true;
2018                            }
2019                            next[1] = null;
2020                        }
2021                        //Reduce expressions and/or Steps :
2022
if (firstTime && (this.expressions.size() == 1)) {
2023                            //Eliminate all cases that can not be reduce, i.e. :
2024
//1- E/axis::anyTest if E is Variable
2025
//1- E/axis::anyTest if E is FunctionCall
2026
if (this.expressions.get(0) instanceof Variable || this.expressions.get(0) instanceof InputFunctionCall) {
2027                                // //For steps normalization (two by two) :
2028
// if (stepsReduced && (this.steps.size() >= 1)) {
2029
// Step firstExpr = new Step(false, Axis.NONE, (XQueryExpression) this.expressions.get(0), null, this.typeVisitor);
2030
// this.steps.add(0, firstExpr);
2031
// this.reducedExpressions.add(new LocatedExpression(this.steps, this.typeVisitor));
2032
// } else {
2033
// this.reducedExpressions.add(this.expressions.get(0));
2034
// }
2035
if (steps.size() == 1 && ((Step) steps.get(0)).getAxis() == Axis.NONE)
2036                                    this.reducedExpressions.add(rootExpr.getExpression());
2037                                else
2038                                    this.reducedExpressions.add(rootExpr);
2039                                return this.reduced || stepsReduced;
2040                            }
2041                        }
2042                        firstTime = false;
2043                        for (int i = 0; i < this.expressions.size(); i++) {
2044                            ArrayList JavaDoc partialExprs = this.applyFinalStep((XQueryExpression) this.expressions.get(i), next[0], slashSlash, 0, parentModule);
2045                            if (partialExprs != null && !partialExprs.isEmpty()) {
2046                                XQueryExpression tmpExpr = (XQueryExpression) partialExprs.get(partialExprs.size() - 1);
2047                                // if (special && tmpExpr instanceof LocatedExpression) {
2048
// LocatedExpression tmpLoc = (LocatedExpression) tmpExpr;
2049
// tmpLoc.getSteps().remove(tmpLoc.getSteps().size() - 1);
2050
// }
2051
this.reducedExpressions.addAll(partialExprs);
2052                            }
2053                        }
2054                        this.expressions.clear();
2055                        this.expressions.addAll(this.reducedExpressions);
2056                        this.reducedExpressions.clear();
2057                    } else {
2058                        this.reducedExpressions.addAll(this.expressions);
2059                    }
2060                } while (next != null);
2061            }
2062            return this.reduced || stepsReduced;
2063        } catch (XQueryException e) {
2064            throw new NormalizeException(0, e.getMessage());
2065        }
2066    }
2067
2068    /****************************************************************/
2069    /*************** Package visibility methods *********************/
2070    /****************************************************************/
2071
2072    /****************************************************************/
2073    /************************** Public methods **********************/
2074    /****************************************************************/
2075}
2076
Popular Tags