All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.style.SourceBinding Maven / Gradle / Ivy

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2013 Saxonica Limited.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package net.sf.saxon.style;

import net.sf.saxon.expr.*;
import net.sf.saxon.expr.instruct.DocumentInstr;
import net.sf.saxon.expr.instruct.Executable;
import net.sf.saxon.expr.instruct.GeneralVariable;
import net.sf.saxon.expr.instruct.SlotManager;
import net.sf.saxon.expr.parser.RoleLocator;
import net.sf.saxon.expr.parser.TypeChecker;
import net.sf.saxon.lib.NamespaceConstant;
import net.sf.saxon.om.*;
import net.sf.saxon.pattern.NodeKindTest;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.tree.iter.AxisIterator;
import net.sf.saxon.type.ItemType;
import net.sf.saxon.type.Type;
import net.sf.saxon.type.TypeHierarchy;
import net.sf.saxon.value.*;
import net.sf.saxon.value.StringValue;

import java.util.ArrayList;
import java.util.List;


/**
* Helper class for xsl:variable and xsl:param elements. 
*/ public class SourceBinding { private StyleElement sourceElement; private StructuredQName name; private Expression select = null; private SequenceType declaredType = null; private SequenceType inferredType = null; protected String constantText = null; protected SlotManager slotManager = null; // used only for global variable declarations protected GeneralVariable compiledVariable = null; private boolean textonly; private int properties; public static final int PRIVATE = 1; public static final int GLOBAL = 2; public static final int PARAM = 4; public static final int TUNNEL = 8; public static final int REQUIRED = 16; public static final int IMPLICITLY_REQUIRED = 32; public static final int ASSIGNABLE = 64; public static final int SELECT = 128; public static final int AS = 256; public static final int DISALLOWS_CONTENT = 512; public static final int GROUP = 1024; public static final int STATIC = 2048; // List of VariableReference objects that reference this XSLVariableDeclaration private List references = new ArrayList(10); public SourceBinding(StyleElement sourceElement) { this.sourceElement = sourceElement; } public void prepareAttributes(int permittedAttributes) throws XPathException { AttributeCollection atts = sourceElement.getAttributeList(); String selectAtt = null; String asAtt = null; String requiredAtt = null; String tunnelAtt = null; String assignableAtt = null; String staticAtt = null; for (int a=0; a getReferences() { return references; } /** * Get the SlotManager associated with this stylesheet construct. The SlotManager contains the * information needed to manage the local stack frames used by run-time instances of the code. * @return the associated SlotManager object */ public SlotManager getSlotManager() { return slotManager; } /** * If the element contains a sequence constructor, convert this to an expression and assign it to the * select attribute * @param exec the executable * @param decl the declaration being compiled * @throws XPathException if a static error is found, for example a type error */ public void handleSequenceConstructor(Executable exec, Declaration decl) throws XPathException { // handle the "temporary tree" case by creating a Document sub-instruction // to construct and return a document node. if (sourceElement.hasChildNodes()) { if (declaredType==null) { DocumentInstr doc = new DocumentInstr(textonly, constantText, sourceElement.getBaseURI()); Expression b = sourceElement.compileSequenceConstructor( exec, decl, sourceElement.iterateAxis(AxisInfo.CHILD), true); if (b == null) { b = Literal.makeEmptySequence(); } doc.setContentExpression(b); select = doc; } else { select = sourceElement.compileSequenceConstructor( exec, decl, sourceElement.iterateAxis(AxisInfo.CHILD), true); if (select == null) { select = Literal.makeEmptySequence(); } try { assert select != null; select.setContainer(sourceElement); RoleLocator role = new RoleLocator(RoleLocator.VARIABLE, name.getDisplayName(), 0); role.setErrorCode("XTTE0570"); //role.setSourceLocator(new ExpressionLocation(this)); select = sourceElement.makeExpressionVisitor().simplify(select); select = TypeChecker.staticTypeCheck(select, declaredType, false, role, sourceElement.makeExpressionVisitor()); } catch (XPathException err) { err.setLocator(sourceElement); sourceElement.compileError(err); select = new ErrorExpression(err); } } } } /** * Get the type actually declared for the attribute * @return the type appearing in the "as" attribute, or null if the attribute was absent */ public SequenceType getDeclaredType() { if (declaredType == null) { // may be handling a forwards reference - see hof-038 String asAtt = sourceElement.getAttributeValue("", "as"); if (asAtt == null) { return null; } else { try { declaredType = sourceElement.makeSequenceType(asAtt); } catch (XPathException err) { // the error will be reported when we get round to processing the function declaration } } } return declaredType; } /** * Get the select expression actually appearing in the variable declaration * @return the select expression as it appears, or null if it is absent */ public Expression getSelectExpression() { return select; } /** * Get the best available static type of the variable. * @param useContentRules set to true if the standard rules for xsl:variable and similar elements apply, * whereby the element's contained sequence constructor substitutes for the select attribute * @return the static type declared for the variable, or inferred from its initialization */ public SequenceType getInferredType(boolean useContentRules) { if (inferredType != null) { return inferredType; } if (hasProperty(PARAM) || hasProperty(ASSIGNABLE)) { return (inferredType = (declaredType == null ? SequenceType.ANY_SEQUENCE : declaredType)); } if (select != null) { TypeHierarchy th = sourceElement.getConfiguration().getTypeHierarchy(); if (Literal.isEmptySequence(select)) { // returning Type.EMPTY gives problems with static type checking return (inferredType = (declaredType == null ? SequenceType.ANY_SEQUENCE : declaredType)); } ItemType actual = select.getItemType(th); int card = select.getCardinality(); if (declaredType != null) { if (!th.isSubType(actual, declaredType.getPrimaryType())) { actual = declaredType.getPrimaryType(); } if (!Cardinality.subsumes(declaredType.getCardinality(), card)) { card = declaredType.getCardinality(); } } inferredType = SequenceType.makeSequenceType(actual, card); return inferredType; } if (useContentRules) { if (sourceElement.hasChildNodes()) { if (declaredType == null) { return SequenceType.makeSequenceType(NodeKindTest.DOCUMENT, StaticProperty.EXACTLY_ONE); } else { return declaredType; } } else { if (declaredType == null) { // no select attribute or content: value is an empty string return SequenceType.SINGLE_STRING; } else { return declaredType; } } } return declaredType; } /** * Method called by VariableReference to register the variable reference for * subsequent fixup * @param ref the variable reference being registered */ public void registerReference(BindingReference ref) { references.add(ref); } /** * Notify all references to this variable of the data type */ public void fixupReferences() throws XPathException { final SequenceType type = getInferredType(true); final TypeHierarchy th = sourceElement.getConfiguration().getTypeHierarchy(); GroundedValue constantValue = null; int properties = 0; if (!hasProperty(ASSIGNABLE) && !hasProperty(PARAM)) { if (select instanceof Literal) { // we can't rely on the constant value because it hasn't yet been type-checked, // which could change it (eg by numeric promotion). Rather than attempt all the type-checking // now, we do a quick check. See test bug64 int relation = th.relationship(select.getItemType(th), type.getPrimaryType()); if (relation == TypeHierarchy.SAME_TYPE || relation == TypeHierarchy.SUBSUMED_BY) { constantValue = ((Literal) select).getValue(); } } if (select != null) { properties = select.getSpecialProperties(); } } for (BindingReference reference : references) { reference.setStaticType(type, constantValue, properties); } } /** * Notify all variable references of the Binding instruction * @param binding the Binding that represents this variable declaration in the executable code tree */ protected void fixupBinding(Binding binding) { for (BindingReference reference : references) { (reference).fixup(binding); } } /** * Set the number of references to this variable. This code is invoked only for a global variable, * and only if there is at least one reference. * @param var the variable */ protected void setReferenceCount(GeneralVariable var) { var.setReferenceCount(10); // TODO: temporary } /** * Get the compiled variable * @return the compiled variable if it has been compiled, or null otherwise */ /*@Nullable*/ public GeneralVariable getCompiledVariable() { return compiledVariable; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy