19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/* 29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one 39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * or more contributor license agreements. See the NOTICE file 49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed with this work for additional information 59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * regarding copyright ownership. The ASF licenses this file 69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to you under the Apache License, Version 2.0 (the "License"); 79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * you may not use this file except in compliance with the License. 89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * You may obtain a copy of the License at 99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unless required by applicable law or agreed to in writing, software 139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * See the License for the specific language governing permissions and 169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * limitations under the License. 179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/* 199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * $Id: RedundentExprEliminator.java 468643 2006-10-28 06:56:03Z minchau $ 209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpackage org.apache.xalan.templates; 229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.util.Vector; 249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xalan.res.XSLMessages; 269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xalan.res.XSLTErrorResources; 279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.QName; 289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.WrappedRuntimeException; 299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.Expression; 309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.ExpressionNode; 319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.ExpressionOwner; 329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.XPath; 339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.axes.AxesWalker; 349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.axes.FilterExprIteratorSimple; 359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.axes.FilterExprWalker; 369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.axes.LocPathIterator; 379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.axes.SelfIteratorNoPredicate; 389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.axes.WalkerFactory; 399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.axes.WalkingIterator; 409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.operations.Variable; 419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.operations.VariableSafeAbsRef; 429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/** 449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This class eleminates redundent XPaths from a given subtree, 459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * and also collects all absolute paths within the subtree. First 469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * it must be called as a visitor to the subtree, and then 479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * eleminateRedundent must be called. 489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpublic class RedundentExprEliminator extends XSLTVisitor 509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson{ 519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Vector m_paths; 529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Vector m_absPaths; 539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean m_isSameContext; 549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson AbsPathChecker m_absPathChecker = new AbsPathChecker(); 559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private static int m_uniquePseudoVarID = 1; 579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson static final String PSUEDOVARNAMESPACE = Constants.S_VENDORURL+"/xalan/psuedovar"; 589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public static final boolean DEBUG = false; 609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public static final boolean DIAGNOSE_NUM_PATHS_REDUCED = false; 619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public static final boolean DIAGNOSE_MULTISTEPLIST = false; 629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * So we can reuse it over and over again. 659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson VarNameCollector m_varNameCollector = new VarNameCollector(); 679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Construct a RedundentExprEliminator. 709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public RedundentExprEliminator() 729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_isSameContext = true; 749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_absPaths = new Vector(); 759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_paths = null; 769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Method to be called after the all expressions within an 819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * node context have been visited. It eliminates redundent 829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * expressions by creating a variable in the psuedoVarRecipient 839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * for each redundent expression, and then rewriting the redundent 849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * expression to be a variable reference. 859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param psuedoVarRecipient The recipient of the psuedo vars. The 879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * variables will be inserted as first children of the element, before 889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * any existing variables. 899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public void eleminateRedundentLocals(ElemTemplateElement psuedoVarRecipient) 919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson eleminateRedundent(psuedoVarRecipient, m_paths); 939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Method to be called after the all global expressions within a stylesheet 979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * have been collected. It eliminates redundent 989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * expressions by creating a variable in the psuedoVarRecipient 999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * for each redundent expression, and then rewriting the redundent 1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * expression to be a variable reference. 1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public void eleminateRedundentGlobals(StylesheetRoot stylesheet) 1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson eleminateRedundent(stylesheet, m_absPaths); 1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Method to be called after the all expressions within an 1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * node context have been visited. It eliminates redundent 1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * expressions by creating a variable in the psuedoVarRecipient 1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * for each redundent expression, and then rewriting the redundent 1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * expression to be a variable reference. 1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param psuedoVarRecipient The owner of the subtree from where the 1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * paths were collected. 1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param paths A vector of paths that hold ExpressionOwner objects, 1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * which must yield LocationPathIterators. 1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected void eleminateRedundent(ElemTemplateElement psuedoVarRecipient, Vector paths) 1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int n = paths.size(); 1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int numPathsEliminated = 0; 1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int numUniquePathsEliminated = 0; 1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (int i = 0; i < n; i++) 1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ExpressionOwner owner = (ExpressionOwner) paths.elementAt(i); 1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (null != owner) 1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int found = findAndEliminateRedundant(i + 1, i, owner, psuedoVarRecipient, paths); 1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (found > 0) 1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson numUniquePathsEliminated++; 1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson numPathsEliminated += found; 1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson eleminateSharedPartialPaths(psuedoVarRecipient, paths); 1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(DIAGNOSE_NUM_PATHS_REDUCED) 1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson diagnoseNumPaths(paths, numPathsEliminated, numUniquePathsEliminated); 1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Eliminate the shared partial paths in the expression list. 1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param psuedoVarRecipient The recipient of the psuedo vars. 1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param paths A vector of paths that hold ExpressionOwner objects, 1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * which must yield LocationPathIterators. 1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 1529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected void eleminateSharedPartialPaths(ElemTemplateElement psuedoVarRecipient, Vector paths) 1539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder list = createMultistepExprList(paths); 1559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null != list) 1569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(DIAGNOSE_MULTISTEPLIST) 1589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson list.diagnose(); 1599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean isGlobal = (paths == m_absPaths); 1619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Iterate over the list, starting with the most number of paths, 1639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // trying to find the longest matches first. 1649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int longestStepsCount = list.m_stepCount; 1659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (int i = longestStepsCount-1; i >= 1; i--) 1669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder next = list; 1689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != next) 1699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(next.m_stepCount < i) 1719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson break; 1729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson list = matchAndEliminatePartialPaths(next, list, isGlobal, i, psuedoVarRecipient); 1739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson next = next.m_next; 1749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 1809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * For a given path, see if there are any partitial matches in the list, 1819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * and, if there are, replace those partial paths with psuedo variable refs, 1829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * and create the psuedo variable decl. 1839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return The head of the list, which may have changed. 1859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 1869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected MultistepExprHolder matchAndEliminatePartialPaths(MultistepExprHolder testee, 1879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder head, 1889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean isGlobal, 1899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int lengthToTest, 1909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement varScope) 1919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null == testee.m_exprOwner) 1939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return head; 1949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Start with the longest possible match, and move down. 1969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson WalkingIterator iter1 = (WalkingIterator) testee.m_exprOwner.getExpression(); 1979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(partialIsVariable(testee, lengthToTest)) 1989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return head; 1999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder matchedPaths = null; 2009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder matchedPathsTail = null; 2019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder meh = head; 2029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while( null != meh) 2039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if ((meh != testee) && (null != meh.m_exprOwner)) 2059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson WalkingIterator iter2 = (WalkingIterator) meh.m_exprOwner.getExpression(); 2079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (stepsEqual(iter1, iter2, lengthToTest)) 2089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (null == matchedPaths) 2109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson try 2129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson matchedPaths = (MultistepExprHolder)testee.clone(); 2149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson testee.m_exprOwner = null; // So it won't be processed again. 2159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson catch(CloneNotSupportedException cnse){} 2179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson matchedPathsTail = matchedPaths; 2189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson matchedPathsTail.m_next = null; 2199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson try 2229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson matchedPathsTail.m_next = (MultistepExprHolder)meh.clone(); 2249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson meh.m_exprOwner = null; // So it won't be processed again. 2259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson catch(CloneNotSupportedException cnse){} 2279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson matchedPathsTail = matchedPathsTail.m_next; 2289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson matchedPathsTail.m_next = null; 2299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson meh = meh.m_next; 2329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int matchCount = 0; 2359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null != matchedPaths) 2369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement root = isGlobal ? varScope : findCommonAncestor(matchedPaths); 2389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson WalkingIterator sharedIter = (WalkingIterator)matchedPaths.m_exprOwner.getExpression(); 2399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson WalkingIterator newIter = createIteratorFromSteps(sharedIter, lengthToTest); 2409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemVariable var = createPseudoVarDecl(root, newIter, isGlobal); 2419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(DIAGNOSE_MULTISTEPLIST) 2429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.println("Created var: "+var.getName()+(isGlobal ? "(Global)" : "")); 2439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != matchedPaths) 2449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ExpressionOwner owner = matchedPaths.m_exprOwner; 2469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson WalkingIterator iter = (WalkingIterator)owner.getExpression(); 2479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(DIAGNOSE_MULTISTEPLIST) 2499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson diagnoseLineNumber(iter); 2509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson LocPathIterator newIter2 = 2529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson changePartToRef(var.getName(), iter, lengthToTest, isGlobal); 2539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson owner.setExpression(newIter2); 2549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson matchedPaths = matchedPaths.m_next; 2569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(DIAGNOSE_MULTISTEPLIST) 2609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson diagnoseMultistepList(matchCount, lengthToTest, isGlobal); 2619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return head; 2629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 2659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Check if results of partial reduction will just be a variable, in 2669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * which case, skip it. 2679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 2689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean partialIsVariable(MultistepExprHolder testee, int lengthToTest) 2699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(1 == lengthToTest) 2719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson WalkingIterator wi = (WalkingIterator)testee.m_exprOwner.getExpression(); 2739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(wi.getFirstWalker() instanceof FilterExprWalker) 2749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return true; 2759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 2779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 2809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Tell what line number belongs to a given expression. 2819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 2829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected void diagnoseLineNumber(Expression expr) 2839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement e = getElemFromExpression(expr); 2859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.println(" " + e.getSystemId() + " Line " + e.getLineNumber()); 2869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 2899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Given a linked list of expressions, find the common ancestor that is 2909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * suitable for holding a psuedo variable for shared access. 2919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 2929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected ElemTemplateElement findCommonAncestor(MultistepExprHolder head) 2939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Not sure this algorithm is the best, but will do for the moment. 2959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int numExprs = head.getLength(); 2969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // The following could be made cheaper by pre-allocating large arrays, 2979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // but then we would have to assume a max number of reductions, 2989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // which I am not inclined to do right now. 2999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement[] elems = new ElemTemplateElement[numExprs]; 3009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int[] ancestorCounts = new int[numExprs]; 3019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Loop through, getting the parent elements, and counting the 3039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // ancestors. 3049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder next = head; 3059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int shortestAncestorCount = 10000; 3069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(int i = 0; i < numExprs; i++) 3079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement elem = 3099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson getElemFromExpression(next.m_exprOwner.getExpression()); 3109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson elems[i] = elem; 3119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int numAncestors = countAncestors(elem); 3129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ancestorCounts[i] = numAncestors; 3139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(numAncestors < shortestAncestorCount) 3149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson shortestAncestorCount = numAncestors; 3169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson next = next.m_next; 3189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Now loop through and "correct" the elements that have more ancestors. 3219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(int i = 0; i < numExprs; i++) 3229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(ancestorCounts[i] > shortestAncestorCount) 3249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int numStepCorrection = ancestorCounts[i] - shortestAncestorCount; 3269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(int j = 0; j < numStepCorrection; j++) 3279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson elems[i] = elems[i].getParentElem(); 3299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Now everyone has an equal number of ancestors. Walk up from here 3349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // equally until all are equal. 3359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement first = null; 3369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(shortestAncestorCount-- >= 0) 3379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean areEqual = true; 3399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson first = elems[0]; 3409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(int i = 1; i < numExprs; i++) 3419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(first != elems[i]) 3439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson areEqual = false; 3459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson break; 3469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // This second check is to make sure we have a common ancestor that is not the same 3499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // as the expression owner... i.e. the var decl has to go above the expression owner. 3509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(areEqual && isNotSameAsOwner(head, first) && first.canAcceptVariables()) 3519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(DIAGNOSE_MULTISTEPLIST) 3539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.print(first.getClass().getName()); 3559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.println(" at " + first.getSystemId() + " Line " + first.getLineNumber()); 3569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return first; 3589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(int i = 0; i < numExprs; i++) 3619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson elems[i] = elems[i].getParentElem(); 3639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson assertion(false, "Could not find common ancestor!!!"); 3679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return null; 3689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 3719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Find out if the given ElemTemplateElement is not the same as one of 3729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * the ElemTemplateElement owners of the expressions. 3739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 3749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param head Head of linked list of expression owners. 3759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param ete The ElemTemplateElement that is a candidate for a psuedo 3769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * variable parent. 3779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return true if the given ElemTemplateElement is not the same as one of 3789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * the ElemTemplateElement owners of the expressions. This is to make sure 3799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * we find an ElemTemplateElement that is in a viable position to hold 3809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * psuedo variables that are visible to the references. 3819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 3829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected boolean isNotSameAsOwner(MultistepExprHolder head, ElemTemplateElement ete) 3839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder next = head; 3859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != next) 3869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement elemOwner = getElemFromExpression(next.m_exprOwner.getExpression()); 3889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(elemOwner == ete) 3899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 3909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson next = next.m_next; 3919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return true; 3939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 3969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Count the number of ancestors that a ElemTemplateElement has. 3979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 3989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param elem An representation of an element in an XSLT stylesheet. 3999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return The number of ancestors of elem (including the element itself). 4009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 4019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected int countAncestors(ElemTemplateElement elem) 4029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int count = 0; 4049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != elem) 4059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson count++; 4079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson elem = elem.getParentElem(); 4089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return count; 4109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 4139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Print out diagnostics about partial multistep evaluation. 4149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 4159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected void diagnoseMultistepList( 4169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int matchCount, 4179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int lengthToTest, 4189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean isGlobal) 4199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (matchCount > 0) 4219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.print( 4239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson "Found multistep matches: " + matchCount + ", " + lengthToTest + " length"); 4249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (isGlobal) 4259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.println(" (global)"); 4269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 4279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.println(); 4289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 4329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Change a given number of steps to a single variable reference. 4339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 4349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param uniquePseudoVarName The name of the variable reference. 4359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param wi The walking iterator that is to be changed. 4369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param numSteps The number of steps to be changed. 4379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param isGlobal true if this will be a global reference. 4389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 4399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected LocPathIterator changePartToRef(final QName uniquePseudoVarName, WalkingIterator wi, 4409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final int numSteps, final boolean isGlobal) 4419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Variable var = new Variable(); 4439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson var.setQName(uniquePseudoVarName); 4449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson var.setIsGlobal(isGlobal); 4459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(isGlobal) 4469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { ElemTemplateElement elem = getElemFromExpression(wi); 4479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson StylesheetRoot root = elem.getStylesheetRoot(); 4489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Vector vars = root.getVariablesAndParamsComposed(); 4499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson var.setIndex(vars.size()-1); 4509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Walk to the first walker after the one's we are replacing. 4539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson AxesWalker walker = wi.getFirstWalker(); 4549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(int i = 0; i < numSteps; i++) 4559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson assertion(null != walker, "Walker should not be null!"); 4579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson walker = walker.getNextWalker(); 4589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null != walker) 4619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson FilterExprWalker few = new FilterExprWalker(wi); 4649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson few.setInnerExpression(var); 4659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson few.exprSetParent(wi); 4669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson few.setNextWalker(walker); 4679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson walker.setPrevWalker(few); 4689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson wi.setFirstWalker(few); 4699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return wi; 4709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 4729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson FilterExprIteratorSimple feis = new FilterExprIteratorSimple(var); 4749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson feis.exprSetParent(wi.exprGetParent()); 4759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return feis; 4769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 4809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Create a new WalkingIterator from the steps in another WalkingIterator. 4819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 4829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param wi The iterator from where the steps will be taken. 4839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param numSteps The number of steps from the first to copy into the new 4849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * iterator. 4859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return The new iterator. 4869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 4879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected WalkingIterator createIteratorFromSteps(final WalkingIterator wi, int numSteps) 4889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson WalkingIterator newIter = new WalkingIterator(wi.getPrefixResolver()); 4909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson try 4919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson AxesWalker walker = (AxesWalker)wi.getFirstWalker().clone(); 4939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson newIter.setFirstWalker(walker); 4949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson walker.setLocPathIterator(newIter); 4959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(int i = 1; i < numSteps; i++) 4969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson AxesWalker next = (AxesWalker)walker.getNextWalker().clone(); 4989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson walker.setNextWalker(next); 4999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson next.setLocPathIterator(newIter); 5009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson walker = next; 5019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 5029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson walker.setNextWalker(null); 5039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 5049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson catch(CloneNotSupportedException cnse) 5059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 5069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throw new WrappedRuntimeException(cnse); 5079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 5089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return newIter; 5099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 5109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 5119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 5129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Compare a given number of steps between two iterators, to see if they are equal. 5139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 5149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param iter1 The first iterator to compare. 5159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param iter2 The second iterator to compare. 5169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param numSteps The number of steps to compare. 5179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return true If the given number of steps are equal. 5189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 5199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 5209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected boolean stepsEqual(WalkingIterator iter1, WalkingIterator iter2, 5219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int numSteps) 5229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 5239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson AxesWalker aw1 = iter1.getFirstWalker(); 5249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson AxesWalker aw2 = iter2.getFirstWalker(); 5259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 5269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(int i = 0; (i < numSteps); i++) 5279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 5289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if((null == aw1) || (null == aw2)) 5299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 5309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 5319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(!aw1.deepEquals(aw2)) 5329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 5339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 5349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson aw1 = aw1.getNextWalker(); 5359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson aw2 = aw2.getNextWalker(); 5369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 5379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 5389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson assertion((null != aw1) || (null != aw2), "Total match is incorrect!"); 5399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 5409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return true; 5419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 5429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 5439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 5449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * For the reduction of location path parts, create a list of all 5459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * the multistep paths with more than one step, sorted by the 5469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * number of steps, with the most steps occuring earlier in the list. 5479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * If the list is only one member, don't bother returning it. 5489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 5499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param paths Vector of ExpressionOwner objects, which may contain null entries. 5509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The ExpressionOwner objects must own LocPathIterator objects. 5519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return null if no multipart paths are found or the list is only of length 1, 5529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * otherwise the first MultistepExprHolder in a linked list of these objects. 5539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 5549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected MultistepExprHolder createMultistepExprList(Vector paths) 5559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 5569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder first = null; 5579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int n = paths.size(); 5589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(int i = 0; i < n; i++) 5599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 5609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ExpressionOwner eo = (ExpressionOwner)paths.elementAt(i); 5619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null == eo) 5629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson continue; 5639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 5649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Assuming location path iterators should be OK. 5659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson LocPathIterator lpi = (LocPathIterator)eo.getExpression(); 5669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int numPaths = countSteps(lpi); 5679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(numPaths > 1) 5689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 5699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null == first) 5709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson first = new MultistepExprHolder(eo, numPaths, null); 5719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 5729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson first = first.addInSortedOrder(eo, numPaths); 5739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 5749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 5759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 5769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if((null == first) || (first.getLength() <= 1)) 5779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return null; 5789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 5799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return first; 5809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 5819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 5829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 5839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Look through the vector from start point, looking for redundant occurances. 5849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * When one or more are found, create a psuedo variable declaration, insert 5859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * it into the stylesheet, and replace the occurance with a reference to 5869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * the psuedo variable. When a redundent variable is found, it's slot in 5879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * the vector will be replaced by null. 5889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 5899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param start The position to start looking in the vector. 5909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param firstOccuranceIndex The position of firstOccuranceOwner. 5919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param firstOccuranceOwner The owner of the expression we are looking for. 5929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param psuedoVarRecipient Where to put the psuedo variables. 5939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 5949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return The number of expression occurances that were modified. 5959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 5969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected int findAndEliminateRedundant(int start, int firstOccuranceIndex, 5979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ExpressionOwner firstOccuranceOwner, 5989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement psuedoVarRecipient, 5999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Vector paths) 6009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throws org.w3c.dom.DOMException 6019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 6029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder head = null; 6039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder tail = null; 6049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int numPathsFound = 0; 6059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int n = paths.size(); 6069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 6079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Expression expr1 = firstOccuranceOwner.getExpression(); 6089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(DEBUG) 6099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson assertIsLocPathIterator(expr1, firstOccuranceOwner); 6109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean isGlobal = (paths == m_absPaths); 6119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson LocPathIterator lpi = (LocPathIterator)expr1; 6129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int stepCount = countSteps(lpi); 6139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(int j = start; j < n; j++) 6149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 6159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ExpressionOwner owner2 = (ExpressionOwner)paths.elementAt(j); 6169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null != owner2) 6179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 6189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Expression expr2 = owner2.getExpression(); 6199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean isEqual = expr2.deepEquals(lpi); 6209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(isEqual) 6219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 6229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson LocPathIterator lpi2 = (LocPathIterator)expr2; 6239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null == head) 6249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 6259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson head = new MultistepExprHolder(firstOccuranceOwner, stepCount, null); 6269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson tail = head; 6279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson numPathsFound++; 6289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 6299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson tail.m_next = new MultistepExprHolder(owner2, stepCount, null); 6309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson tail = tail.m_next; 6319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 6329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Null out the occurance, so we don't have to test it again. 6339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson paths.setElementAt(null, j); 6349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 6359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // foundFirst = true; 6369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson numPathsFound++; 6379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 6389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 6399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 6409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 6419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Change all globals in xsl:templates, etc, to global vars no matter what. 6429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if((0 == numPathsFound) && isGlobal) 6439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 6449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson head = new MultistepExprHolder(firstOccuranceOwner, stepCount, null); 6459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson numPathsFound++; 6469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 6479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 6489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null != head) 6499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 6509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement root = isGlobal ? psuedoVarRecipient : findCommonAncestor(head); 6519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson LocPathIterator sharedIter = (LocPathIterator)head.m_exprOwner.getExpression(); 6529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemVariable var = createPseudoVarDecl(root, sharedIter, isGlobal); 6539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(DIAGNOSE_MULTISTEPLIST) 6549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.println("Created var: "+var.getName()+(isGlobal ? "(Global)" : "")); 6559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson QName uniquePseudoVarName = var.getName(); 6569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != head) 6579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 6589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ExpressionOwner owner = head.m_exprOwner; 6599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(DIAGNOSE_MULTISTEPLIST) 6609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson diagnoseLineNumber(owner.getExpression()); 6619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson changeToVarRef(uniquePseudoVarName, owner, paths, root); 6629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson head = head.m_next; 6639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 6649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Replace the first occurance with the variable's XPath, so 6659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // that further reduction may take place if needed. 6669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson paths.setElementAt(var.getSelect(), firstOccuranceIndex); 6679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 6689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 6699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return numPathsFound; 6709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 6719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 6729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 6739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * To be removed. 6749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 6759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected int oldFindAndEliminateRedundant(int start, int firstOccuranceIndex, 6769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ExpressionOwner firstOccuranceOwner, 6779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement psuedoVarRecipient, 6789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Vector paths) 6799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throws org.w3c.dom.DOMException 6809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 6819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson QName uniquePseudoVarName = null; 6829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean foundFirst = false; 6839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int numPathsFound = 0; 6849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int n = paths.size(); 6859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Expression expr1 = firstOccuranceOwner.getExpression(); 6869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(DEBUG) 6879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson assertIsLocPathIterator(expr1, firstOccuranceOwner); 6889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean isGlobal = (paths == m_absPaths); 6899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson LocPathIterator lpi = (LocPathIterator)expr1; 6909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(int j = start; j < n; j++) 6919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 6929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ExpressionOwner owner2 = (ExpressionOwner)paths.elementAt(j); 6939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null != owner2) 6949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 6959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Expression expr2 = owner2.getExpression(); 6969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean isEqual = expr2.deepEquals(lpi); 6979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(isEqual) 6989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 6999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson LocPathIterator lpi2 = (LocPathIterator)expr2; 7009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(!foundFirst) 7019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 7029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson foundFirst = true; 7039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Insert variable decl into psuedoVarRecipient 7049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // We want to insert this into the first legitimate 7059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // position for a variable. 7069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemVariable var = createPseudoVarDecl(psuedoVarRecipient, lpi, isGlobal); 7079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null == var) 7089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return 0; 7099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson uniquePseudoVarName = var.getName(); 7109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 7119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson changeToVarRef(uniquePseudoVarName, firstOccuranceOwner, 7129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson paths, psuedoVarRecipient); 7139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 7149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Replace the first occurance with the variable's XPath, so 7159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // that further reduction may take place if needed. 7169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson paths.setElementAt(var.getSelect(), firstOccuranceIndex); 7179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson numPathsFound++; 7189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 7199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 7209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson changeToVarRef(uniquePseudoVarName, owner2, paths, psuedoVarRecipient); 7219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 7229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Null out the occurance, so we don't have to test it again. 7239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson paths.setElementAt(null, j); 7249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 7259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // foundFirst = true; 7269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson numPathsFound++; 7279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 7289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 7299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 7309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 7319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Change all globals in xsl:templates, etc, to global vars no matter what. 7329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if((0 == numPathsFound) && (paths == m_absPaths)) 7339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 7349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemVariable var = createPseudoVarDecl(psuedoVarRecipient, lpi, true); 7359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null == var) 7369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return 0; 7379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson uniquePseudoVarName = var.getName(); 7389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson changeToVarRef(uniquePseudoVarName, firstOccuranceOwner, paths, psuedoVarRecipient); 7399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson paths.setElementAt(var.getSelect(), firstOccuranceIndex); 7409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson numPathsFound++; 7419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 7429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return numPathsFound; 7439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 7449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 7459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 7469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Count the steps in a given location path. 7479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 7489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param lpi The location path iterator that owns the steps. 7499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return The number of steps in the given location path. 7509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 7519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected int countSteps(LocPathIterator lpi) 7529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 7539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(lpi instanceof WalkingIterator) 7549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 7559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson WalkingIterator wi = (WalkingIterator)lpi; 7569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson AxesWalker aw = wi.getFirstWalker(); 7579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int count = 0; 7589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != aw) 7599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 7609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson count++; 7619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson aw = aw.getNextWalker(); 7629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 7639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return count; 7649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 7659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 7669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return 1; 7679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 7689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 7699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 7709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Change the expression owned by the owner argument to a variable reference 7719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * of the given name. 7729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 7739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Warning: For global vars, this function relies on the variable declaration 7749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to which it refers having been added just prior to this function being called, 7759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * so that the reference index can be determined from the size of the global variables 7769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * list minus one. 7779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 7789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param varName The name of the variable which will be referenced. 7799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param owner The owner of the expression which will be replaced by a variable ref. 7809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param paths The paths list that the iterator came from, mainly to determine 7819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * if this is a local or global reduction. 7829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param psuedoVarRecipient The element within whose scope the variable is 7839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * being inserted, possibly a StylesheetRoot. 7849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 7859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected void changeToVarRef(QName varName, ExpressionOwner owner, 7869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Vector paths, ElemTemplateElement psuedoVarRecipient) 7879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 7889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Variable varRef = (paths == m_absPaths) ? new VariableSafeAbsRef() : new Variable(); 7899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson varRef.setQName(varName); 7909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(paths == m_absPaths) 7919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 7929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson StylesheetRoot root = (StylesheetRoot)psuedoVarRecipient; 7939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Vector globalVars = root.getVariablesAndParamsComposed(); 7949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Assume this operation is occuring just after the decl has 7959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // been added. 7969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson varRef.setIndex(globalVars.size()-1); 7979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson varRef.setIsGlobal(true); 7989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 7999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson owner.setExpression(varRef); 8009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 8019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private synchronized static int getPseudoVarID(){ 8039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return m_uniquePseudoVarID++; 8049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 8059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 8079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Create a psuedo variable reference that will represent the 8089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * shared redundent XPath, and add it to the stylesheet. 8099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 8109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param psuedoVarRecipient The broadest scope of where the variable 8119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * should be inserted, usually an xsl:template or xsl:for-each. 8129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param lpi The LocationPathIterator that the variable should represent. 8139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param isGlobal true if the paths are global. 8149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return The new psuedo var element. 8159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 8169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected ElemVariable createPseudoVarDecl( 8179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement psuedoVarRecipient, 8189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson LocPathIterator lpi, boolean isGlobal) 8199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throws org.w3c.dom.DOMException 8209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 8219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson QName uniquePseudoVarName = new QName (PSUEDOVARNAMESPACE, "#"+getPseudoVarID()); 8229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(isGlobal) 8249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 8259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return createGlobalPseudoVarDecl(uniquePseudoVarName, 8269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson (StylesheetRoot)psuedoVarRecipient, lpi); 8279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 8289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 8299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return createLocalPseudoVarDecl(uniquePseudoVarName, psuedoVarRecipient, lpi); 8309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 8319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 8339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Create a psuedo variable reference that will represent the 8349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * shared redundent XPath, for a local reduction. 8359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 8369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param uniquePseudoVarName The name of the new variable. 8379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param stylesheetRoot The broadest scope of where the variable 8389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * should be inserted, which must be a StylesheetRoot element in this case. 8399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param lpi The LocationPathIterator that the variable should represent. 8409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return null if the decl was not created, otherwise the new Pseudo var 8419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * element. 8429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 8439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected ElemVariable createGlobalPseudoVarDecl(QName uniquePseudoVarName, 8449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson StylesheetRoot stylesheetRoot, 8459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson LocPathIterator lpi) 8469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throws org.w3c.dom.DOMException 8479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 8489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemVariable psuedoVar = new ElemVariable(); 8499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson psuedoVar.setIsTopLevel(true); 8509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson XPath xpath = new XPath(lpi); 8519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson psuedoVar.setSelect(xpath); 8529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson psuedoVar.setName(uniquePseudoVarName); 8539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Vector globalVars = stylesheetRoot.getVariablesAndParamsComposed(); 8559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson psuedoVar.setIndex(globalVars.size()); 8569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson globalVars.addElement(psuedoVar); 8579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return psuedoVar; 8589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 8599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 8649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Create a psuedo variable reference that will represent the 8659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * shared redundent XPath, for a local reduction. 8669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 8679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param uniquePseudoVarName The name of the new variable. 8689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param psuedoVarRecipient The broadest scope of where the variable 8699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * should be inserted, usually an xsl:template or xsl:for-each. 8709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param lpi The LocationPathIterator that the variable should represent. 8719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return null if the decl was not created, otherwise the new Pseudo var 8729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * element. 8739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 8749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected ElemVariable createLocalPseudoVarDecl(QName uniquePseudoVarName, 8759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement psuedoVarRecipient, 8769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson LocPathIterator lpi) 8779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throws org.w3c.dom.DOMException 8789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 8799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemVariable psuedoVar = new ElemVariablePsuedo(); 8809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson XPath xpath = new XPath(lpi); 8829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson psuedoVar.setSelect(xpath); 8839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson psuedoVar.setName(uniquePseudoVarName); 8849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemVariable var = addVarDeclToElem(psuedoVarRecipient, lpi, psuedoVar); 8869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson lpi.exprSetParent(var); 8889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return var; 8909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 8919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 8929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 8939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Add the given variable to the psuedoVarRecipient. 8949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 8959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected ElemVariable addVarDeclToElem( 8969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement psuedoVarRecipient, 8979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson LocPathIterator lpi, 8989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemVariable psuedoVar) 8999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throws org.w3c.dom.DOMException 9009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Create psuedo variable element 9029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement ete = psuedoVarRecipient.getFirstChildElem(); 9039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 9049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson lpi.callVisitors(null, m_varNameCollector); 9059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 9069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // If the location path contains variables, we have to insert the 9079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // psuedo variable after the reference. (Otherwise, we want to 9089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // insert it as close as possible to the top, so we'll be sure 9099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // it is in scope for any other vars. 9109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (m_varNameCollector.getVarCount() > 0) 9119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement baseElem = getElemFromExpression(lpi); 9139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemVariable varElem = getPrevVariableElem(baseElem); 9149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while (null != varElem) 9159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (m_varNameCollector.doesOccur(varElem.getName())) 9179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson psuedoVarRecipient = varElem.getParentElem(); 9199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ete = varElem.getNextSiblingElem(); 9209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson break; 9219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson varElem = getPrevVariableElem(varElem); 9239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 9269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if ((null != ete) && (Constants.ELEMNAME_PARAMVARIABLE == ete.getXSLToken())) 9279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Can't stick something in front of a param, so abandon! (see variable13.xsl) 9299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(isParam(lpi)) 9309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return null; 9319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 9329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while (null != ete) 9339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ete = ete.getNextSiblingElem(); 9359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if ((null != ete) && Constants.ELEMNAME_PARAMVARIABLE != ete.getXSLToken()) 9369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson break; 9379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson psuedoVarRecipient.insertBefore(psuedoVar, ete); 9409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_varNameCollector.reset(); 9419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return psuedoVar; 9429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 9449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 9459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Tell if the expr param is contained within an xsl:param. 9469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 9479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected boolean isParam(ExpressionNode expr) 9489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != expr) 9509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(expr instanceof ElemTemplateElement) 9529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson break; 9539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson expr = expr.exprGetParent(); 9549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null != expr) 9569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement ete = (ElemTemplateElement)expr; 9589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != ete) 9599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int type = ete.getXSLToken(); 9619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson switch(type) 9629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson case Constants.ELEMNAME_PARAMVARIABLE: 9649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return true; 9659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson case Constants.ELEMNAME_TEMPLATE: 9669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson case Constants.ELEMNAME_STYLESHEET: 9679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 9689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ete = ete.getParentElem(); 9709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 9739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 9749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 9769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 9779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Find the previous occurance of a xsl:variable. Stop 9789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * the search when a xsl:for-each, xsl:template, or xsl:stylesheet is 9799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * encountered. 9809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 9819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param elem Should be non-null template element. 9829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return The first previous occurance of an xsl:variable or xsl:param, 9839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * or null if none is found. 9849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 9859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected ElemVariable getPrevVariableElem(ElemTemplateElement elem) 9869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // This could be somewhat optimized. since getPreviousSiblingElem is a 9889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // fairly expensive operation. 9899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != (elem = getPrevElementWithinContext(elem))) 9909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int type = elem.getXSLToken(); 9929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 9939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if((Constants.ELEMNAME_VARIABLE == type) || 9949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson (Constants.ELEMNAME_PARAMVARIABLE == type)) 9959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 9969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return (ElemVariable)elem; 9979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 9999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return null; 10009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 10019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 10029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 10039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Get the previous sibling or parent of the given template, stopping at 10049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * xsl:for-each, xsl:template, or xsl:stylesheet. 10059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 10069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param elem Should be non-null template element. 10079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return previous sibling or parent, or null if previous is xsl:for-each, 10089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * xsl:template, or xsl:stylesheet. 10099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 10109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected ElemTemplateElement getPrevElementWithinContext(ElemTemplateElement elem) 10119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 10129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemTemplateElement prev = elem.getPreviousSiblingElem(); 10139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null == prev) 10149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson prev = elem.getParentElem(); 10159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null != prev) 10169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 10179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int type = prev.getXSLToken(); 10189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if((Constants.ELEMNAME_FOREACH == type) || 10199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson (Constants.ELEMNAME_TEMPLATE == type) || 10209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson (Constants.ELEMNAME_STYLESHEET == type)) 10219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 10229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson prev = null; 10239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 10249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 10259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return prev; 10269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 10279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 10289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 10299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * From an XPath expression component, get the ElemTemplateElement 10309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * owner. 10319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 10329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param expr Should be static expression with proper parentage. 10339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return Valid ElemTemplateElement, or throw a runtime exception 10349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * if it is not found. 10359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 10369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected ElemTemplateElement getElemFromExpression(Expression expr) 10379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 10389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ExpressionNode parent = expr.exprGetParent(); 10399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != parent) 10409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 10419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(parent instanceof ElemTemplateElement) 10429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return (ElemTemplateElement)parent; 10439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson parent = parent.exprGetParent(); 10449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 10459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throw new RuntimeException(XSLMessages.createMessage(XSLTErrorResources.ER_ASSERT_NO_TEMPLATE_PARENT, null)); 10469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // "Programmer's error! expr has no ElemTemplateElement parent!"); 10479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 10489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 10499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 10509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Tell if the given LocPathIterator is relative to an absolute path, i.e. 10519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * in not dependent on the context. 10529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 10539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return true if the LocPathIterator is not dependent on the context node. 10549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 10559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public boolean isAbsolute(LocPathIterator path) 10569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 10579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int analysis = path.getAnalysisBits(); 10589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean isAbs = (WalkerFactory.isSet(analysis, WalkerFactory.BIT_ROOT) || 10599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson WalkerFactory.isSet(analysis, WalkerFactory.BIT_ANY_DESCENDANT_FROM_ROOT)); 10609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(isAbs) 10619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 10629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson isAbs = m_absPathChecker.checkAbsolute(path); 10639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 10649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return isAbs; 10659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 10669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 10679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 10689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 10699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Visit a LocationPath. 10709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param owner The owner of the expression, to which the expression can 10719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * be reset if rewriting takes place. 10729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param path The LocationPath object. 10739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return true if the sub expressions should be traversed. 10749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 10759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public boolean visitLocationPath(ExpressionOwner owner, LocPathIterator path) 10769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 10779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Don't optimize "." or single step variable paths. 10789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Both of these cases could use some further optimization by themselves. 10799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(path instanceof SelfIteratorNoPredicate) 10809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 10819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return true; 10829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 10839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else if(path instanceof WalkingIterator) 10849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 10859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson WalkingIterator wi = (WalkingIterator)path; 10869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson AxesWalker aw = wi.getFirstWalker(); 10879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if((aw instanceof FilterExprWalker) && (null == aw.getNextWalker())) 10889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 10899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson FilterExprWalker few = (FilterExprWalker)aw; 10909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Expression exp = few.getInnerExpression(); 10919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(exp instanceof Variable) 10929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return true; 10939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 10949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 10959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 10969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (isAbsolute(path) && (null != m_absPaths)) 10979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 10989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(DEBUG) 10999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson validateNewAddition(m_absPaths, owner, path); 11009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_absPaths.addElement(owner); 11019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 11029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else if (m_isSameContext && (null != m_paths)) 11039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 11049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(DEBUG) 11059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson validateNewAddition(m_paths, owner, path); 11069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_paths.addElement(owner); 11079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 11089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return true; 11109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 11119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 11139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Visit a predicate within a location path. Note that there isn't a 11149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * proper unique component for predicates, and that the expression will 11159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * be called also for whatever type Expression is. 11169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 11179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param owner The owner of the expression, to which the expression can 11189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * be reset if rewriting takes place. 11199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param pred The predicate object. 11209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return true if the sub expressions should be traversed. 11219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 11229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public boolean visitPredicate(ExpressionOwner owner, Expression pred) 11239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 11249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean savedIsSame = m_isSameContext; 11259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_isSameContext = false; 11269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Any further down, just collect the absolute paths. 11289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pred.callVisitors(owner, this); 11299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_isSameContext = savedIsSame; 11319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // We've already gone down the subtree, so don't go have the caller 11339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // go any further. 11349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 11359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 11369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 11389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Visit an XSLT top-level instruction. 11399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 11409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param elem The xsl instruction element object. 11419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return true if the sub expressions should be traversed. 11429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 11439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public boolean visitTopLevelInstruction(ElemTemplateElement elem) 11449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 11459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int type = elem.getXSLToken(); 11469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson switch(type) 11479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 11489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson case Constants.ELEMNAME_TEMPLATE : 11499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return visitInstruction(elem); 11509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson default: 11519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return true; 11529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 11539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 11549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 11579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Visit an XSLT instruction. Any element that isn't called by one 11589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * of the other visit methods, will be called by this method. 11599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 11609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param elem The xsl instruction element object. 11619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return true if the sub expressions should be traversed. 11629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 11639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public boolean visitInstruction(ElemTemplateElement elem) 11649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 11659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int type = elem.getXSLToken(); 11669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson switch (type) 11679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 11689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson case Constants.ELEMNAME_CALLTEMPLATE : 11699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson case Constants.ELEMNAME_TEMPLATE : 11709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson case Constants.ELEMNAME_FOREACH : 11719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 11729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Just get the select value. 11749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(type == Constants.ELEMNAME_FOREACH) 11759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 11769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ElemForEach efe = (ElemForEach) elem; 11779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Expression select = efe.getSelect(); 11799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson select.callVisitors(efe, this); 11809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 11819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Vector savedPaths = m_paths; 11839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_paths = new Vector(); 11849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Visit children. Call the superclass callChildVisitors, because 11869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // we don't want to visit the xsl:for-each select attribute, or, for 11879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // that matter, the xsl:template's match attribute. 11889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson elem.callChildVisitors(this, false); 11899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson eleminateRedundentLocals(elem); 11909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_paths = savedPaths; 11929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 11939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // select.callVisitors(efe, this); 11949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 11959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 11969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson case Constants.ELEMNAME_NUMBER : 11979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson case Constants.ELEMNAME_SORT : 11989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Just collect absolute paths until and unless we can fully 11999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // analyze these cases. 12009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean savedIsSame = m_isSameContext; 12019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_isSameContext = false; 12029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson elem.callChildVisitors(this); 12039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_isSameContext = savedIsSame; 12049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 12059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 12069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson default : 12079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return true; 12089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 12119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // ==== DIAGNOSTIC AND DEBUG FUNCTIONS ==== 12129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 12139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 12149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Print out to std err the number of paths reduced. 12159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 12169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected void diagnoseNumPaths(Vector paths, int numPathsEliminated, 12179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int numUniquePathsEliminated) 12189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 12199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (numPathsEliminated > 0) 12209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 12219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(paths == m_paths) 12229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 12239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.println("Eliminated " + numPathsEliminated + " total paths!"); 12249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.println( 12259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson "Consolodated " + numUniquePathsEliminated + " redundent paths!"); 12269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 12289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 12299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.println("Eliminated " + numPathsEliminated + " total global paths!"); 12309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.println( 12319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson "Consolodated " + numUniquePathsEliminated + " redundent global paths!"); 12329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 12369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 12379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 12389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Assert that the expression is a LocPathIterator, and, if 12399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * not, try to give some diagnostic info. 12409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 12419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private final void assertIsLocPathIterator(Expression expr1, ExpressionOwner eo) 12429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throws RuntimeException 12439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 12449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(!(expr1 instanceof LocPathIterator)) 12459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 12469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson String errMsg; 12479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(expr1 instanceof Variable) 12489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 12499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson errMsg = "Programmer's assertion: expr1 not an iterator: "+ 12509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ((Variable)expr1).getQName(); 12519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 12539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 12549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson errMsg = "Programmer's assertion: expr1 not an iterator: "+ 12559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson expr1.getClass().getName(); 12569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throw new RuntimeException(errMsg + ", "+ 12589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson eo.getClass().getName()+" "+ 12599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson expr1.exprGetParent()); 12609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 12639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 12649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 12659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Validate some assumptions about the new LocPathIterator and it's 12669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * owner and the state of the list. 12679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 12689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private static void validateNewAddition(Vector paths, ExpressionOwner owner, 12699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson LocPathIterator path) 12709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throws RuntimeException 12719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 12729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson assertion(owner.getExpression() == path, "owner.getExpression() != path!!!"); 12739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int n = paths.size(); 12749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // There should never be any duplicates in the list! 12759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(int i = 0; i < n; i++) 12769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 12779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ExpressionOwner ew = (ExpressionOwner)paths.elementAt(i); 12789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson assertion(ew != owner, "duplicate owner on the list!!!"); 12799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson assertion(ew.getExpression() != path, "duplicate expression on the list!!!"); 12809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 12839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 12849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Simple assertion. 12859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 12869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected static void assertion(boolean b, String msg) 12879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 12889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(!b) 12899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 12909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throw new RuntimeException(XSLMessages.createMessage(XSLTErrorResources.ER_ASSERT_REDUNDENT_EXPR_ELIMINATOR, new Object[]{msg})); 12919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // "Programmer's assertion in RundundentExprEliminator: "+msg); 12929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 12949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 12959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 12969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Since we want to sort multistep expressions by length, use 12979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * a linked list with elements of type MultistepExprHolder. 12989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 12999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson class MultistepExprHolder implements Cloneable 13009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 13019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ExpressionOwner m_exprOwner; // Will change to null once we have processed this item. 13029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final int m_stepCount; 13039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder m_next; 13049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 13059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 13069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Clone this object. 13079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 13089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public Object clone() 13099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throws CloneNotSupportedException 13109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 13119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return super.clone(); 13129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 13139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 13149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 13159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Create a MultistepExprHolder. 13169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 13179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param exprOwner the owner of the expression we are holding. 13189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * It must hold a LocationPathIterator. 13199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param stepCount The number of steps in the location path. 13209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 13219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder(ExpressionOwner exprOwner, int stepCount, MultistepExprHolder next) 13229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 13239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_exprOwner = exprOwner; 13249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson assertion(null != m_exprOwner, "exprOwner can not be null!"); 13259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_stepCount = stepCount; 13269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_next = next; 13279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 13289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 13299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 13309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Add a new MultistepExprHolder in sorted order in the list. 13319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 13329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param exprOwner the owner of the expression we are holding. 13339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * It must hold a LocationPathIterator. 13349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param stepCount The number of steps in the location path. 13359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return The new head of the linked list. 13369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 13379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder addInSortedOrder(ExpressionOwner exprOwner, int stepCount) 13389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 13399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder first = this; 13409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder next = this; 13419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder prev = null; 13429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != next) 13439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 13449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(stepCount >= next.m_stepCount) 13459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 13469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder newholder = new MultistepExprHolder(exprOwner, stepCount, next); 13479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null == prev) 13489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson first = newholder; 13499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 13509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson prev.m_next = newholder; 13519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 13529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return first; 13539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 13549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson prev = next; 13559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson next = next.m_next; 13569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 13579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 13589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson prev.m_next = new MultistepExprHolder(exprOwner, stepCount, null); 13599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return first; 13609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 13619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 13629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 13639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Remove the given element from the list. 'this' should 13649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * be the head of the list. If the item to be removed is not 13659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * found, an assertion will be made. 13669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 13679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param itemToRemove The item to remove from the list. 13689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return The head of the list, which may have changed if itemToRemove 13699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * is the same as this element. Null if the item to remove is the 13709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * only item in the list. 13719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 13729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder unlink(MultistepExprHolder itemToRemove) 13739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 13749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder first = this; 13759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder next = this; 13769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder prev = null; 13779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != next) 13789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 13799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(next == itemToRemove) 13809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 13819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if(null == prev) 13829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson first = next.m_next; 13839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 13849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson prev.m_next = next.m_next; 13859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 13869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson next.m_next = null; 13879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 13889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return first; 13899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 13909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson prev = next; 13919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson next = next.m_next; 13929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 13939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 13949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson assertion(false, "unlink failed!!!"); 13959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return null; 13969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 13979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 13989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 13999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Get the number of linked list items. 14009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 14019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int getLength() 14029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 14039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int count = 0; 14049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder next = this; 14059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while(null != next) 14069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 14079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson count++; 14089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson next = next.m_next; 14099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 14109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return count; 14119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 14129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 14139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 14149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Print diagnostics out for the multistep list. 14159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 14169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected void diagnose() 14179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 14189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.print("Found multistep iterators: " + this.getLength() + " "); 14199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MultistepExprHolder next = this; 14209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while (null != next) 14219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 14229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.print("" + next.m_stepCount); 14239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson next = next.m_next; 14249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (null != next) 14259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.print(", "); 14269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 14279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.err.println(); 14289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 14299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 14309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 14319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 14329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 1433