getOperand().typeCheck(visitor, contextInfo); untyped = untyped | !visitor.getStaticContext().getPackageData().isSchemaAware(); computeSingleValued(th); resetLocalStaticProperties(); ItemType operandType = getOperandItemType(); if (th.isSubType(operandType, BuiltInAtomicType.ANY_ATOMIC)) { return getBaseExpression(); String thing = operandType instanceof MapType ? "map" : "function item"; err = new XPathException( expandMessage("Cannot atomize a " + thing), "FOTY0013"); } else { err = new XPathException( expandMessage("Cannot atomize an element that is defined in the schema to have element-only content"), "FOTY0012"); err.setLocation(getLocation()); throw err; getBaseExpression().setFlattened(true); return this;
/** * Copy an expression. This makes a deep copy. * * @return the copy of the original expression */ public Expression copy() { return new Atomizer(getBaseExpression().copy(), config); }
/** * Determine the data type of the items returned by the expression, if possible * * @return a value such as Type.STRING, Type.BOOLEAN, Type.NUMBER. For this class, the * result is always an atomic type, but it might be more specific. */ /*@NotNull*/ public ItemType getItemType() { operandItemType = getBaseExpression().getItemType(); TypeHierarchy th = getConfiguration().getTypeHierarchy(); return getAtomizedItemType(getBaseExpression(), untyped, th); }
/** * Iterate over the sequence of values */ /*@NotNull*/ public SequenceIterator<?> iterate(XPathContext context) throws XPathException { SequenceIterator base = getBaseExpression().iterate(context); return getAtomizingIterator(base, untyped && operandItemType instanceof NodeTest); }
untyped = !getPackageData().isSchemaAware(); computeSingleValued(getConfiguration().getTypeHierarchy()); Expression operand = getBaseExpression().simplify(); if (operand instanceof Literal) { GroundedValue val = ((Literal) operand).getValue(); } else if (((Function)i).isMap()) { XPathException err = new XPathException( expandMessage("Cannot atomize a map (" + i.toShortString() + ")"), "FOTY0013"); err.setIsTypeError(true); err.setLocation(getLocation()); throw err; } else { XPathException err = new XPathException( expandMessage("Cannot atomize a function item"), "FOTY0013"); err.setIsTypeError(true); err.setLocation(getLocation()); throw err; setBaseExpression(operand); return this;
public ItemType getOperandItemType() { if (operandItemType == null) { operandItemType = getBaseExpression().getItemType(); } return operandItemType; }
/** * Iterate over the sequence of values */ public SequenceIterator iterate(XPathContext context) throws XPathException { SequenceIterator base = operand.iterate(context); return getAtomizingIterator(base); }
/** * Make an atomizer with a given operand * * @param sequence the operand * @return an Atomizer that atomizes the given operand, or another expression that returns the same result */ public static Expression makeAtomizer(Expression sequence) { if (sequence instanceof Literal && ((Literal) sequence).getValue() instanceof AtomicSequence) { return sequence; } else { return new Atomizer(sequence); } }
/** * Determine the data type of the items returned by the expression, if possible * @return a value such as Type.STRING, Type.BOOLEAN, Type.NUMBER. For this class, the * result is always an atomic type, but it might be more specific. * @param th the type hierarchy cache */ public ItemType getItemType(TypeHierarchy th) { return getAtomizedItemType(operand, untyped, th); }
/** * Determine the static cardinality of the expression */ public int computeCardinality() { ItemType in = getOperandItemType(); Expression operand = getBaseExpression(); if (singleValued) { return operand.getCardinality(); } else if (untyped && in instanceof NodeTest) { return operand.getCardinality(); } else if (Cardinality.allowsMany(operand.getCardinality())) { return StaticProperty.ALLOWS_ZERO_OR_MORE; } else if (in.isPlainType()) { return operand.getCardinality(); } else if (in instanceof NodeTest) { SchemaType schemaType = ((NodeTest) in).getContentType(); if (schemaType.isAtomicType()) { // can return at most one atomic value per node return operand.getCardinality(); } } return StaticProperty.ALLOWS_ZERO_OR_MORE; }
/** * The typeCheck() method is called in XQuery, where node constructors * are implemented as Expressions. In this case the required type for the * select expression is a single string. * @param visitor an expression visitor * @return the rewritten expression * @throws XPathException if any static errors are found in this expression * or any of its children */ public Expression typeCheck(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException { localTypeCheck(visitor, contextItemType); if (select != null) { final TypeHierarchy th = visitor.getConfiguration().getTypeHierarchy(); select = visitor.typeCheck(select, contextItemType); if (!select.getItemType(th).isAtomicType()) { select = new Atomizer(select, visitor.getConfiguration()).simplify(visitor); } if (!th.isSubType(select.getItemType(th), BuiltInAtomicType.STRING)) { select = new AtomicSequenceConverter(select, BuiltInAtomicType.STRING); } adoptChildExpression(select); } return this; }
/** * Iterate over the sequence of values */ /*@NotNull*/ public SequenceIterator<?> iterate(XPathContext context) throws XPathException { try { SequenceIterator base = getBaseExpression().iterate(context); return getAtomizingIterator(base, untyped && operandItemType instanceof NodeTest); } catch (XPathException e) { if (roleDiagnostic == null) { throw e; } else { String message = e.getMessage() + ". Failed while atomizing the " + roleDiagnostic.getMessage(); XPathException e2 = new XPathException(message, e.getErrorCodeLocalPart(), e.getLocator()); e2.setXPathContext(context); e2.maybeSetLocation(getLocation()); throw e2; } } }
PathMap.PathMapNodeSet result = getBaseExpression().addToPathMap(pathMap, pathMapNodeSet); if (result != null) { TypeHierarchy th = getConfiguration().getTypeHierarchy(); ItemType operandItemType = getBaseExpression().getItemType(); if (th.relationship(NodeKindTest.ELEMENT, operandItemType) != TypeHierarchy.DISJOINT || th.relationship(NodeKindTest.DOCUMENT, operandItemType) != TypeHierarchy.DISJOINT) {
/** * Constructor * @param sequence the sequence to be atomized * @param config the Configuration. Used only for optimization, may be null. Atomization is faster if * it is known in advance that all nodes will be untyped. */ public Atomizer(Expression sequence, Configuration config) { super(sequence); this.config = config; if (config != null) { untyped = (config.areAllNodesUntyped()); computeSingleValued(config.getTypeHierarchy()); } sequence.setFlattened(true); }
untyped = !getPackageData().isSchemaAware(); computeSingleValued(getConfiguration().getTypeHierarchy()); Expression operand = getBaseExpression().simplify(); if (operand instanceof Literal) { GroundedValue val = ((Literal) operand).getValue(); XPathException err = new XPathException("Cannot atomize a map", "FOTY0013"); err.setIsTypeError(true); err.setLocation(getLocation()); throw err; } else { XPathException err = new XPathException("Cannot atomize a function item", "FOTY0013"); err.setIsTypeError(true); err.setLocation(getLocation()); throw err; setBaseExpression(operand); return this;
/** * The toString() method for an expression attempts to give a representation of the expression * in an XPath-like form, but there is no guarantee that the syntax will actually be true XPath. * In the case of XSLT instructions, the toString() method gives an abstracted view of the syntax */ @Override public String toString() { return "data(" + getBaseExpression().toString() + ")"; }
/** * Iterate over the sequence of values */ public SequenceIterator iterate(XPathContext context) throws XPathException { SequenceIterator base = operand.iterate(context); return getAtomizingIterator(base); }
/** * Make an atomizer with a given operand * * @param sequence the operand * @param role (may be null) additional information for diagnostics * @return an Atomizer that atomizes the given operand, or another expression that returns the same result */ public static Expression makeAtomizer(Expression sequence, RoleDiagnostic role) { if (sequence instanceof Literal && ((Literal) sequence).getValue() instanceof AtomicSequence) { return sequence; } else { return new Atomizer(sequence, role); } }
/** * Determine the data type of the items returned by the expression, if possible * @return a value such as Type.STRING, Type.BOOLEAN, Type.NUMBER. For this class, the * result is always an atomic type, but it might be more specific. * @param th the type hierarchy cache */ public ItemType getItemType(TypeHierarchy th) { return getAtomizedItemType(operand, untyped, th); }
/** * Determine the static cardinality of the expression */ public int computeCardinality() { ItemType in = getOperandItemType(); Expression operand = getBaseExpression(); if (singleValued) { return operand.getCardinality(); } else if (untyped && in instanceof NodeTest) { return operand.getCardinality(); } else if (Cardinality.allowsMany(operand.getCardinality())) { return StaticProperty.ALLOWS_ZERO_OR_MORE; } else if (in.isPlainType()) { return operand.getCardinality(); } else if (in instanceof NodeTest) { SchemaType schemaType = ((NodeTest) in).getContentType(); if (schemaType.isAtomicType()) { // can return at most one atomic value per node return operand.getCardinality(); } } return StaticProperty.ALLOWS_ZERO_OR_MORE; }