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 15 16 public class PromotionOffer { 17 18 25 26 public static final int FOCUS_INDEPENDENT = 10; 27 28 37 38 public static final int RANGE_INDEPENDENT = 11; 39 40 47 48 public static final int INLINE_VARIABLE_REFERENCES = 12; 49 50 55 60 61 public static final int UNORDERED = 13; 62 63 67 68 public static final int REPLACE_CURRENT = 14; 69 70 73 74 private Optimizer optimizer; 75 76 80 81 public int action; 82 83 91 92 public boolean promoteDocumentDependent = false; 93 94 99 100 public boolean promoteXSLTFunctions = true; 101 102 109 110 public boolean mustEliminateDuplicates = true; 111 112 116 117 public Binding[] bindingList; 118 119 124 125 public Expression containingExpression; 126 127 130 131 public boolean accepted = false; 132 133 136 137 public PromotionOffer(Optimizer optimizer) { 138 this.optimizer = optimizer; 139 } 140 141 144 145 public Optimizer getOptimizer() { 146 return optimizer; 147 } 148 149 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 ("Unknown promotion action " + action); 210 } 211 return null; 212 } 213 214 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 | Popular Tags |