redundentexpreliminator.java
来自「java jdk 1.4的源码」· Java 代码 · 共 1,474 行 · 第 1/4 页
JAVA
1,474 行
Expression expr2 = owner2.getExpression(); boolean isEqual = expr2.deepEquals(lpi); if(isEqual) { LocPathIterator lpi2 = (LocPathIterator)expr2; if(!foundFirst) { foundFirst = true; // Insert variable decl into psuedoVarRecipient // We want to insert this into the first legitimate // position for a variable. ElemVariable var = createPsuedoVarDecl(psuedoVarRecipient, lpi, isGlobal); if(null == var) return 0; uniquePsuedoVarName = var.getName(); changeToVarRef(uniquePsuedoVarName, firstOccuranceOwner, paths, psuedoVarRecipient); // Replace the first occurance with the variable's XPath, so // that further reduction may take place if needed. paths.setElementAt(var.getSelect(), firstOccuranceIndex); numPathsFound++; } changeToVarRef(uniquePsuedoVarName, owner2, paths, psuedoVarRecipient); // Null out the occurance, so we don't have to test it again. paths.setElementAt(null, j); // foundFirst = true; numPathsFound++; } } } // Change all globals in xsl:templates, etc, to global vars no matter what. if((0 == numPathsFound) && (paths == m_absPaths)) { ElemVariable var = createPsuedoVarDecl(psuedoVarRecipient, lpi, true); if(null == var) return 0; uniquePsuedoVarName = var.getName(); changeToVarRef(uniquePsuedoVarName, firstOccuranceOwner, paths, psuedoVarRecipient); paths.setElementAt(var.getSelect(), firstOccuranceIndex); numPathsFound++; } return numPathsFound; } /** * Count the steps in a given location path. * * @param lpi The location path iterator that owns the steps. * @return The number of steps in the given location path. */ protected int countSteps(LocPathIterator lpi) { if(lpi instanceof WalkingIterator) { WalkingIterator wi = (WalkingIterator)lpi; AxesWalker aw = wi.getFirstWalker(); int count = 0; while(null != aw) { count++; aw = aw.getNextWalker(); } return count; } else return 1; } /** * Change the expression owned by the owner argument to a variable reference * of the given name. * * Warning: For global vars, this function relies on the variable declaration * to which it refers having been added just prior to this function being called, * so that the reference index can be determined from the size of the global variables * list minus one. * * @param varName The name of the variable which will be referenced. * @param owner The owner of the expression which will be replaced by a variable ref. * @param paths The paths list that the iterator came from, mainly to determine * if this is a local or global reduction. * @param psuedoVarRecipient The element within whose scope the variable is * being inserted, possibly a StylesheetRoot. */ protected void changeToVarRef(QName varName, ExpressionOwner owner, Vector paths, ElemTemplateElement psuedoVarRecipient) { Variable varRef = (paths == m_absPaths) ? new VariableSafeAbsRef() : new Variable(); varRef.setQName(varName); if(paths == m_absPaths) { StylesheetRoot root = (StylesheetRoot)psuedoVarRecipient; Vector globalVars = root.getVariablesAndParamsComposed(); // Assume this operation is occuring just after the decl has // been added. varRef.setIndex(globalVars.size()-1); varRef.setIsGlobal(true); } owner.setExpression(varRef); } /** * Create a psuedo variable reference that will represent the * shared redundent XPath, and add it to the stylesheet. * * @param psuedoVarRecipient The broadest scope of where the variable * should be inserted, usually an xsl:template or xsl:for-each. * @param lpi The LocationPathIterator that the variable should represent. * @param isGlobal true if the paths are global. * @return The new psuedo var element. */ protected ElemVariable createPsuedoVarDecl( ElemTemplateElement psuedoVarRecipient, LocPathIterator lpi, boolean isGlobal) throws org.w3c.dom.DOMException { QName uniquePsuedoVarName = new QName (PSUEDOVARNAMESPACE, "#"+m_uniquePsuedoVarID); m_uniquePsuedoVarID++; if(isGlobal) { return createGlobalPsuedoVarDecl(uniquePsuedoVarName, (StylesheetRoot)psuedoVarRecipient, lpi); } else return createLocalPsuedoVarDecl(uniquePsuedoVarName, psuedoVarRecipient, lpi); } /** * Create a psuedo variable reference that will represent the * shared redundent XPath, for a local reduction. * * @param uniquePsuedoVarName The name of the new variable. * @param stylesheetRoot The broadest scope of where the variable * should be inserted, which must be a StylesheetRoot element in this case. * @param lpi The LocationPathIterator that the variable should represent. * @return null if the decl was not created, otherwise the new Psuedo var * element. */ protected ElemVariable createGlobalPsuedoVarDecl(QName uniquePsuedoVarName, StylesheetRoot stylesheetRoot, LocPathIterator lpi) throws org.w3c.dom.DOMException { ElemVariable psuedoVar = new ElemVariable(); psuedoVar.setIsTopLevel(true); XPath xpath = new XPath(lpi); psuedoVar.setSelect(xpath); psuedoVar.setName(uniquePsuedoVarName); Vector globalVars = stylesheetRoot.getVariablesAndParamsComposed(); psuedoVar.setIndex(globalVars.size()); globalVars.addElement(psuedoVar); return psuedoVar; } /** * Create a psuedo variable reference that will represent the * shared redundent XPath, for a local reduction. * * @param uniquePsuedoVarName The name of the new variable. * @param psuedoVarRecipient The broadest scope of where the variable * should be inserted, usually an xsl:template or xsl:for-each. * @param lpi The LocationPathIterator that the variable should represent. * @param addToContext true if the decl should be added to psuedoVarRecipient. * @return null if the decl was not created, otherwise the new Psuedo var * element. */ protected ElemVariable createLocalPsuedoVarDecl(QName uniquePsuedoVarName, ElemTemplateElement psuedoVarRecipient, LocPathIterator lpi) throws org.w3c.dom.DOMException { ElemVariable psuedoVar = new ElemVariablePsuedo(); XPath xpath = new XPath(lpi); psuedoVar.setSelect(xpath); psuedoVar.setName(uniquePsuedoVarName); ElemVariable var = addVarDeclToElem(psuedoVarRecipient, lpi, psuedoVar); lpi.exprSetParent(var); return var; } /** * Add the given variable to the psuedoVarRecipient. */ protected ElemVariable addVarDeclToElem( ElemTemplateElement psuedoVarRecipient, LocPathIterator lpi, ElemVariable psuedoVar) throws org.w3c.dom.DOMException { // Create psuedo variable element ElemTemplateElement ete = psuedoVarRecipient.getFirstChildElem(); lpi.callVisitors(null, m_varNameCollector); // If the location path contains variables, we have to insert the // psuedo variable after the reference. (Otherwise, we want to // insert it as close as possible to the top, so we'll be sure // it is in scope for any other vars. if (m_varNameCollector.getVarCount() > 0) { ElemTemplateElement baseElem = getElemFromExpression(lpi); ElemVariable varElem = getPrevVariableElem(baseElem); while (null != varElem) { if (m_varNameCollector.doesOccur(varElem.getName())) { psuedoVarRecipient = varElem.getParentElem(); ete = varElem.getNextSiblingElem(); break; } varElem = getPrevVariableElem(varElem); } } if ((null != ete) && (Constants.ELEMNAME_PARAMVARIABLE == ete.getXSLToken())) { // Can't stick something in front of a param, so abandon! (see variable13.xsl) if(isParam(lpi)) return null; while (null != ete) { ete = ete.getNextSiblingElem(); if ((null != ete) && Constants.ELEMNAME_PARAMVARIABLE != ete.getXSLToken()) break; } } psuedoVarRecipient.insertBefore(psuedoVar, ete); m_varNameCollector.reset(); return psuedoVar; } /** * Tell if the expr param is contained within an xsl:param. */ protected boolean isParam(ExpressionNode expr) { while(null != expr) { if(expr instanceof ElemTemplateElement) break; expr = expr.exprGetParent(); } if(null != expr) { ElemTemplateElement ete = (ElemTemplateElement)expr; while(null != ete) { int type = ete.getXSLToken(); switch(type) { case Constants.ELEMNAME_PARAMVARIABLE: return true; case Constants.ELEMNAME_TEMPLATE: case Constants.ELEMNAME_STYLESHEET: return false; } ete = ete.getParentElem(); } } return false; } /** * Find the previous occurance of a xsl:variable. Stop * the search when a xsl:for-each, xsl:template, or xsl:stylesheet is * encountered. * * @param elem Should be non-null template element. * @return The first previous occurance of an xsl:variable or xsl:param, * or null if none is found. */ protected ElemVariable getPrevVariableElem(ElemTemplateElement elem) { // This could be somewhat optimized. since getPreviousSiblingElem is a // fairly expensive operation. while(null != (elem = getPrevElementWithinContext(elem))) { int type = elem.getXSLToken(); if((Constants.ELEMNAME_VARIABLE == type) || (Constants.ELEMNAME_PARAMVARIABLE == type)) { return (ElemVariable)elem; } } return null; } /** * Get the previous sibling or parent of the given template, stopping at * xsl:for-each, xsl:template, or xsl:stylesheet. * * @param elem Should be non-null template element. * @return previous sibling or parent, or null if previous is xsl:for-each, * xsl:template, or xsl:stylesheet. */ protected ElemTemplateElement getPrevElementWithinContext(ElemTemplateElement elem) { ElemTemplateElement prev = elem.getPreviousSiblingElem(); if(null == prev) prev = elem.getParentElem(); if(null != prev) { int type = prev.getXSLToken(); if((Constants.ELEMNAME_FOREACH == type) || (Constants.ELEMNAME_TEMPLATE == type) || (Constants.ELEMNAME_STYLESHEET == type)) { prev = null; } } return prev; } /** * From an XPath expression component, get the ElemTemplateElement * owner. * * @param expr Should be static expression with proper parentage. * @return Valid ElemTemplateElement, or throw a runtime exception * if it is not found. */ protected ElemTemplateElement getElemFromExpression(Expression expr) { ExpressionNode parent = expr.exprGetParent(); while(null != parent) { if(parent instanceof ElemTemplateElement) return (ElemTemplateElement)parent; parent = parent.exprGetParent(); } throw new RuntimeException(XSLMessages.createMessage(XSLTErrorResources.ER_ASSERT_NO_TEMPLATE_PARENT, null)); // "Programmer's error! expr has no ElemTemplateElement parent!"); } /** * Tell if the given LocPathIterator is relative to an absolute path, i.e. * in not dependent on the context. * * @return true if the LocPathIterator is not dependent on the context node. */ public boolean isAbsolute(LocPathIterator path) { int analysis = path.getAnalysisBits(); boolean isAbs = (WalkerFactory.isSet(analysis, WalkerFactory.BIT_ROOT) || WalkerFactory.isSet(analysis, WalkerFactory.BIT_ANY_DESCENDANT_FROM_ROOT)); if(isAbs) { isAbs = m_absPathChecker.checkAbsolute(path); } return isAbs; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?