KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > expr > PromotionOffer


1 package net.sf.saxon.expr;
2 import net.sf.saxon.sort.DocumentSorter;
3 import net.sf.saxon.sort.Reverser;
4 import net.sf.saxon.trans.XPathException;
5 import net.sf.saxon.value.SequenceType;
6 import net.sf.saxon.functions.Current;
7
8 /**
9 * PromotionOffer is an object used transiently during compilation of an expression. It contains
10 * information passed by a containing expression to its subexpressions, when looking for subexpressions
11 * that can be promoted to a higher level because they are not dependent on the context established
12 * by the containing expression. The object is also used to pass back return information when the
13 * promotion actually takes place.
14 */

15
16 public class PromotionOffer {
17
18     /**
19     * FOCUS_INDEPENDENT requests promotion of all non-trivial subexpressions that don't depend on the
20     * focus. This is typically used to extract subexpressions from a filter predicate. The offer is
21     * optional - each subexpression can decide whether it's worth the trouble of promoting itself.
22     * The offer is normally passed on to subexpressions, except subexpressions that are evaluated
23     * with a different focus
24     */

25
26     public static final int FOCUS_INDEPENDENT = 10;
27
28     /**
29     * RANGE_INDEPENDENT requests promotion of all non-trivial subexpressions that don't depend on a
30     * specified range variable. This is typically used to extract subexpressions from the action of
31     * a for expression or the condition of a some/every quantified expression. The offer is
32     * optional - each subexpression can decide whether it's worth the trouble of promoting itself.
33     * The offer is normally passed on to subexpressions, except subexpressions that are evaluated
34     * with a different focus or a different range variable, because these may have other dependencies
35     * that prevent their promotion.
36     */

37
38     public static final int RANGE_INDEPENDENT = 11;
39
40     /**
41      * Inline variable references causes all references to a variable V to be replaced by the
42      * expression E. The variable is supplied in the "binding" property; the replacement expression
43      * in the containingExpression property. A special case is where the replacement expression is
44      * a ContextItemExpression; in this case the offer is not passed on to subexpressions where
45      * the context is different.
46     */

47
48     public static final int INLINE_VARIABLE_REFERENCES = 12;
49
50     // Note: After inlining variable references, it is possible for an expression to appear at more
51
// than one place in the expression tree. This seems dangerous, since a rewrite applied to one
52
// branch might be inappropriate in another branch. We get away with it because the only expressions
53
// that we are inline are very simple ones: (a) a ContextItemExpression, and (b) another VariableReference.
54

55     /**
56      * UNORDERED indicates that the containing expression does not require the results
57      * to be delivered in any particular order. The boolean mustEliminateDuplicates
58      * is set if duplicate items in the result are not allowed.
59      */

60
61     public static final int UNORDERED = 13;
62
63     /**
64      * REPLACE_CURRENT causes calls to the XSLT current() function to be replaced by
65      * reference to a variable. The variable binding is the single member of the array bindingList
66      */

67
68     public static final int REPLACE_CURRENT = 14;
69
70     /**
71      * The optimizer in use
72      */

73
74     private Optimizer optimizer;
75
76     /**
77     * action is one of the possible promotion actions, FOCUS_INDEPENDENT, RANGE_INDEPENDENT,
78     * INLINE_VARIABLE_REFERENCES, ANY_ORDER, ANY_ORDER_UNIQUE
79     */

80
81     public int action;
82
83     /**
84     * In the case of FOCUS_INDEPENDENT, "promoteDocumentDependent" is a boolean that, when set to
85     * true, indicates that it is safe to promote a subexpression that depends on the context document
86     * but not on other aspects of the focus. This is the case, for example, in a filter expression when
87     * it is known that all the nodes selected by the expression will be in the same document - as happens
88     * when the filter is applied to a path expression. This allows subexpressions such as key() to be
89     * promoted
90     */

91
92     public boolean promoteDocumentDependent = false;
93
94     /**
95      * In the case of FOCUS_INDEPENDENT, "promoteXSLTFunctions" is a boolean that, when set to true, indicates
96      * that it is safe to promote XSLT functions such as current(). This flag is set when rewriting XPath expressions
97      * and is unset when rewriting XSLT templates.
98      */

99
100     public boolean promoteXSLTFunctions = true;
101
102     /**
103      * In the case of UNORDERED, "mustEliminateDuplicates" is a boolean that is set to
104      * true if the nodes can be delivered in any order so long as there are no duplicates
105      * (for example, as required by the count() function). If this boolean is false, the
106      * nodes can be delivered in any order and duplicates are allowed (for example, as
107      * required by the boolean() function).
108      */

109
110     public boolean mustEliminateDuplicates = true;
111
112     /**
113     * In the case of RANGE_INDEPENDENT and WHERE_CLAUSE, "binding" identifies the range variables whose dependencies
114     * we are looking for. For INLINE_VARIABLE_REFERENCES it is a single Binding that we are aiming to inline
115     */

116
117     public Binding[] bindingList;
118
119     /**
120     * When a promotion offer is made, containingExpression identifies the level to which the promotion
121     * should occur. When a subexpression is promoted, an expression of the form let $VAR := SUB return ORIG
122     * is created, and this replaces the original containingExpression within the PromotionOffer.
123     */

124
125     public Expression containingExpression;
126
127     /**
128      * Flag that is set if the offer has been accepted, that is, if the expression has changed
129      */

130
131     public boolean accepted = false;
132
133     /**
134      * Create a PromotionOffer for use with a particular Optimizer
135      */

136
137     public PromotionOffer(Optimizer optimizer) {
138         this.optimizer = optimizer;
139     }
140
141     /**
142      * Get the optimizer in use
143      */

144
145     public Optimizer getOptimizer() {
146         return optimizer;
147     }
148
149     /**
150     * Method to test whether a subexpression qualifies for promotion, and if so, to
151     * accept the promotion.
152     * @return if promotion was done, returns the expression that should be used in place
153     * of the child expression. If no promotion was done, returns null.
154     */

155
156     public Expression accept(Expression child) throws XPathException {
157         switch (action) {
158             case RANGE_INDEPENDENT: {
159                 int properties = child.getSpecialProperties();
160                 if (((properties & StaticProperty.NON_CREATIVE) != 0) && !ExpressionTool.dependsOnVariable(child, bindingList)) {
161                     return promote(child);
162                 }
163                 break;
164             }
165
166             case FOCUS_INDEPENDENT: {
167                 int dependencies = child.getDependencies();
168                 int properties = child.getSpecialProperties();
169                 if (!promoteXSLTFunctions && ((dependencies & StaticProperty.DEPENDS_ON_XSLT_CONTEXT) != 0)) {
170                     break;
171                 }
172                 if ((dependencies & StaticProperty.DEPENDS_ON_FOCUS) == 0 &&
173                         (properties & StaticProperty.NON_CREATIVE) != 0) {
174                     return promote(child);
175                 } else if (promoteDocumentDependent &&
176                         (dependencies & StaticProperty.DEPENDS_ON_NON_DOCUMENT_FOCUS) == 0 &&
177                         (properties & StaticProperty.NON_CREATIVE) != 0) {
178                     return promote(child);
179                 }
180                 break;
181             }
182
183             case REPLACE_CURRENT: {
184                 if (child instanceof Current) {
185                     VariableReference var = new VariableReference(
186                             ((Assignation)containingExpression).getVariableDeclaration());
187                     var.setParentExpression(child.getParentExpression());
188                     return var;
189                 }
190                 break;
191             }
192
193             case INLINE_VARIABLE_REFERENCES: {
194                 if (child instanceof VariableReference &&
195                     ((VariableReference)child).getBinding() == bindingList[0]) {
196                     return containingExpression;
197                 }
198                 break;
199             }
200             case UNORDERED: {
201                 if (child instanceof Reverser) {
202                     return ((Reverser)child).getBaseExpression();
203                 } else if (child instanceof DocumentSorter && !mustEliminateDuplicates) {
204                     return ((DocumentSorter)child).getBaseExpression();
205                 }
206                 break;
207             }
208             default:
209                 throw new UnsupportedOperationException JavaDoc("Unknown promotion action " + action);
210         }
211         return null;
212     }
213
214     /**
215     * Method to do the promotion.
216     */

217
218     private Expression promote(Expression child) {
219         RangeVariableDeclaration decl = new RangeVariableDeclaration();
220         decl.setVariableName("zz:" + decl.hashCode());
221         SequenceType type = SequenceType.makeSequenceType(child.getItemType(), child.getCardinality());
222         decl.setRequiredType(type);
223
224         VariableReference var = new VariableReference(decl);
225         ExpressionTool.copyLocationInfo(containingExpression, var);
226         var.setParentExpression(child.getParentExpression());
227
228         Container container = containingExpression.getParentExpression();
229         LetExpression let = new LetExpression();
230         let.setVariableDeclaration(decl);
231         let.setSequence(LazyExpression.makeLazyExpression(child));
232         let.setAction(containingExpression);
233         let.setParentExpression(container);
234         let.adoptChildExpression(containingExpression);
235         containingExpression = let;
236         accepted = true;
237
238         return var;
239     }
240
241
242 }
243
244 //
245
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
246
// you may not use this file except in compliance with the License. You may obtain a copy of the
247
// License at http://www.mozilla.org/MPL/
248
//
249
// Software distributed under the License is distributed on an "AS IS" basis,
250
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
251
// See the License for the specific language governing rights and limitations under the License.
252
//
253
// The Original Code is: all this file.
254
//
255
// The Initial Developer of the Original Code is Michael H. Kay
256
//
257
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
258
//
259
// Contributor(s): none.
260
//
261
Popular Tags