/** * Copy an expression. This makes a deep copy. * * @return the copy of the original expression * @param rebindings variables that need to be re-bound */ /*@NotNull*/ public Expression copy(RebindingMap rebindings) { AtomicSequenceConverter atomicConverter = new AtomicSequenceConverter(getBaseExpression().copy(rebindings), requiredItemType); ExpressionTool.copyLocationInfo(this, atomicConverter); atomicConverter.setConverter(converter); atomicConverter.setRoleDiagnostic(getRoleDiagnostic()); return atomicConverter; }
/** * Simplify an expression * */ /*@NotNull*/ public Expression simplify() throws XPathException { Expression operand = getBaseExpression().simplify(); setBaseExpression(operand); if (operand instanceof Literal && requiredItemType instanceof AtomicType) { if (Literal.isEmptySequence(operand)) { return operand; } Configuration config = getConfiguration(); allocateConverterStatically(config, true); if (converter != null) { GroundedValue<?> val = iterate(new EarlyEvaluationContext(config)).materialize(); return Literal.makeLiteral(val, operand); } } return this; }
public Converter allocateConverter(Configuration config, boolean allowNull) { return allocateConverter(config, allowNull, getBaseExpression().getItemType()); }
/** * Copy an expression. This makes a deep copy. * * @return the copy of the original expression */ public Expression copy() { return new AtomicSequenceConverter(getBaseExpression().copy(), requiredItemType); }
/** * Make a string-join expression that concatenates the string-values of items in * a sequence with intervening spaces. This may be simplified later as a result * of type-checking. * * @param exp the base expression, evaluating to a sequence * @param env the static context * @return a call on string-join to create a string containing the * representations of the items in the sequence separated by spaces. */ /*@Nullable*/ public static Expression makeStringJoin(Expression exp, /*@NotNull*/ StaticContext env) { exp = Atomizer.makeAtomizer(exp, null); ItemType t = exp.getItemType(); if (!t.equals(BuiltInAtomicType.STRING) && !t.equals(BuiltInAtomicType.UNTYPED_ATOMIC)) { exp = new AtomicSequenceConverter(exp, BuiltInAtomicType.STRING); ((AtomicSequenceConverter) exp).allocateConverterStatically(env.getConfiguration(), false); } if (exp.getCardinality() == StaticProperty.EXACTLY_ONE) { return exp; } else { RetainedStaticContext rsc = new RetainedStaticContext(env); Expression fn = SystemFunction.makeCall("string-join", rsc, exp, new StringLiteral(StringValue.SINGLE_SPACE)); ExpressionTool.copyLocationInfo(exp, fn); return fn; } }
return e; if (getBaseExpression() instanceof UntypedSequenceConverter) { UntypedSequenceConverter asc = (UntypedSequenceConverter) getBaseExpression(); ItemType ascType = asc.getItemType(); if (ascType == requiredItemType) { return getBaseExpression(); } else if ((requiredItemType == BuiltInAtomicType.STRING || requiredItemType == BuiltInAtomicType.UNTYPED_ATOMIC) && (ascType == BuiltInAtomicType.STRING || ascType == BuiltInAtomicType.UNTYPED_ATOMIC)) { UntypedSequenceConverter old = (UntypedSequenceConverter) getBaseExpression(); UntypedSequenceConverter asc2 = new UntypedSequenceConverter( old.getBaseExpression(), } else if (getBaseExpression() instanceof AtomicSequenceConverter) { AtomicSequenceConverter asc = (AtomicSequenceConverter) getBaseExpression(); ItemType ascType = asc.getItemType(); if (ascType == requiredItemType) { return getBaseExpression(); } else if ((requiredItemType == BuiltInAtomicType.STRING || requiredItemType == BuiltInAtomicType.UNTYPED_ATOMIC) && (ascType == BuiltInAtomicType.STRING || ascType == BuiltInAtomicType.UNTYPED_ATOMIC)) { AtomicSequenceConverter old = (AtomicSequenceConverter) getBaseExpression(); AtomicSequenceConverter asc2 = new AtomicSequenceConverter( old.getBaseExpression(), requiredItemType ); return asc2.typeCheck(visitor, contextInfo) .optimize(visitor, contextInfo);
/** * Register a key definition. Note that multiple key definitions with the same name are * allowed * @param keyName Structured QName representing the name of the key * @param keydef The details of the key's definition * @param config The configuration * @throws XPathException if this key definition is inconsistent with existing key definitions having the same name */ public void addKeyDefinition(StructuredQName keyName, KeyDefinition keydef, Configuration config) throws XPathException { KeyDefinitionSet keySet = (KeyDefinitionSet)keyMap.get(keyName); if (keySet==null) { keySet = new KeyDefinitionSet(keyName, keyMap.size()); keyMap.put(keyName, keySet); } keySet.addKeyDefinition(keydef); boolean backwardsCompatible = keySet.isBackwardsCompatible(); if (backwardsCompatible) { // In backwards compatibility mode, convert all the use-expression results to sequences of strings List v = keySet.getKeyDefinitions(); for (int i=0; i<v.size(); i++) { KeyDefinition kd = (KeyDefinition)v.get(i); kd.setBackwardsCompatible(true); if (!kd.getBody().getItemType(config.getTypeHierarchy()).equals(BuiltInAtomicType.STRING)) { Expression exp = new AtomicSequenceConverter(kd.getBody(), BuiltInAtomicType.STRING); kd.setBody(exp); } } } }
} else if (operand.getItemType() == BuiltInAtomicType.STRING) { AtomicSequenceConverter old = (AtomicSequenceConverter) operand; AtomicSequenceConverter asc = new AtomicSequenceConverter( old.getBaseExpression(), BuiltInAtomicType.UNTYPED_ATOMIC ); return asc.typeCheck(visitor, contextInfo) .optimize(visitor, contextInfo); ItemType it = operand.getItemType(); if (th.isSubType(it, BuiltInAtomicType.STRING) || th.isSubType(it, BuiltInAtomicType.UNTYPED_ATOMIC)) { Expression e = ((AtomicSequenceConverter) operand).getBaseExpression(); ItemType et = e.getItemType(); if (et instanceof AtomicType &&
/** * Evaluate as an Item. This should only be called if the AtomicSequenceConverter has cardinality zero-or-one */ public AtomicValue evaluateItem(XPathContext context) throws XPathException { Converter conv = getConverterDynamically(context); AtomicValue item = (AtomicValue) getBaseExpression().evaluateItem(context); if (item == null) { return null; } ConversionResult result = conv.convert(item); if (roleDiagnostic != null && result instanceof ValidationFailure) { // TODO: use more of the information in the roleDiagnostic to form the error message ((ValidationFailure)result).setErrorCode(roleDiagnostic.getErrorCode()); } return result.asAtomic(); }
/** * Type-check the expression */ /*@NotNull*/ public Expression typeCheck(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException { typeCheckChildren(visitor, contextInfo); Configuration config = visitor.getConfiguration(); final TypeHierarchy th = config.getTypeHierarchy(); Expression operand = getBaseExpression(); if (th.isSubType(operand.getItemType(), requiredItemType)) { return operand; } else { if (converter == null) { allocateConverterStatically(config, true); } return this; } }
/** * Diagnostic print of expression structure. The abstract expression tree * is written to the supplied output destination. */ public void export(ExpressionPresenter destination) throws XPathException { destination.startElement("convert", this); destination.emitAttribute("from", getBaseExpression().getItemType().toExportString()); destination.emitAttribute("to", requiredItemType.toExportString()); if (converter instanceof Converter.PromoterToDouble || converter instanceof Converter.PromoterToFloat) { destination.emitAttribute("flags", "p"); } if (getRoleDiagnostic() != null) { destination.emitAttribute("diag", getRoleDiagnostic().save()); } getBaseExpression().export(destination); destination.endElement(); }
/** * Determine the static cardinality of the expression */ public int computeCardinality() { return getBaseExpression().getCardinality(); }
private static Expression makePromoter(Expression exp, Converter converter, BuiltInAtomicType type) { ConversionRules rules = exp.getConfiguration().getConversionRules(); converter.setConversionRules(rules); if (exp instanceof Literal && ((Literal) exp).getValue() instanceof AtomicValue) { ConversionResult result = converter.convert((AtomicValue) ((Literal) exp).getValue()); if (result instanceof AtomicValue) { Literal converted = Literal.makeLiteral((AtomicValue) result, exp); ExpressionTool.copyLocationInfo(exp, converted); return converted; } } AtomicSequenceConverter asc = new AtomicSequenceConverter(exp, type); asc.setConverter(converter); ExpressionTool.copyLocationInfo(exp, asc); return asc; }
if (xPath10ModeIsEnabled()) { if (!useType.equals(BuiltInAtomicType.STRING) && !useType.equals(BuiltInAtomicType.UNTYPED_ATOMIC)) { use = new AtomicSequenceConverter(use, BuiltInAtomicType.STRING); ((AtomicSequenceConverter) use).allocateConverter(config, false); useType = BuiltInAtomicType.STRING;
/** * Simplify an expression * @param visitor an expression visitor */ public Expression simplify(ExpressionVisitor visitor) throws XPathException { operand = visitor.simplify(operand); if (operand instanceof Literal) { return Literal.makeLiteral( new SequenceExtent(iterate(visitor.getStaticContext().makeEarlyEvaluationContext()))); } return this; }
/** * Determine the special properties of this expression * * @return {@link net.sf.saxon.expr.StaticProperty#NO_NODES_NEWLY_CREATED}. */ public int computeSpecialProperties() { int p = super.computeSpecialProperties(); return p | StaticProperty.NO_NODES_NEWLY_CREATED | StaticProperty.NOT_UNTYPED_ATOMIC; }
protected Converter getConverterDynamically(XPathContext context) { if (converter != null) { return converter; } return allocateConverter(context.getConfiguration(), false); }
/** * get HashCode for comparing two expressions. */ @Override public int computeHashCode() { return super.computeHashCode(); }
/** * Make a string-join expression that concatenates the string-values of items in * a sequence with intervening spaces. This may be simplified later as a result * of type-checking. * * @param exp the base expression, evaluating to a sequence * @param env the static context * @return a call on string-join to create a string containing the * representations of the items in the sequence separated by spaces. */ /*@Nullable*/ public static Expression makeStringJoin(Expression exp, /*@NotNull*/ StaticContext env) { exp = Atomizer.makeAtomizer(exp); ItemType t = exp.getItemType(); if (!t.equals(BuiltInAtomicType.STRING) && !t.equals(BuiltInAtomicType.UNTYPED_ATOMIC)) { exp = new AtomicSequenceConverter(exp, BuiltInAtomicType.STRING); ((AtomicSequenceConverter) exp).allocateConverterStatically(env.getConfiguration(), false); } if (exp.getCardinality() == StaticProperty.EXACTLY_ONE) { return exp; } else { RetainedStaticContext rsc = new RetainedStaticContext(env); Expression fn = SystemFunction.makeCall("string-join", rsc, exp, new StringLiteral(StringValue.SINGLE_SPACE)); ExpressionTool.copyLocationInfo(exp, fn); return fn; } }
return e; if (getBaseExpression() instanceof UntypedSequenceConverter) { UntypedSequenceConverter asc = (UntypedSequenceConverter) getBaseExpression(); ItemType ascType = asc.getItemType(); if (ascType == requiredItemType) { return getBaseExpression(); } else if ((requiredItemType == BuiltInAtomicType.STRING || requiredItemType == BuiltInAtomicType.UNTYPED_ATOMIC) && (ascType == BuiltInAtomicType.STRING || ascType == BuiltInAtomicType.UNTYPED_ATOMIC)) { UntypedSequenceConverter old = (UntypedSequenceConverter) getBaseExpression(); UntypedSequenceConverter asc2 = new UntypedSequenceConverter( old.getBaseExpression(), } else if (getBaseExpression() instanceof AtomicSequenceConverter) { AtomicSequenceConverter asc = (AtomicSequenceConverter) getBaseExpression(); ItemType ascType = asc.getItemType(); if (ascType == requiredItemType) { return getBaseExpression(); } else if ((requiredItemType == BuiltInAtomicType.STRING || requiredItemType == BuiltInAtomicType.UNTYPED_ATOMIC) && (ascType == BuiltInAtomicType.STRING || ascType == BuiltInAtomicType.UNTYPED_ATOMIC)) { AtomicSequenceConverter old = (AtomicSequenceConverter) getBaseExpression(); AtomicSequenceConverter asc2 = new AtomicSequenceConverter( old.getBaseExpression(), requiredItemType ); return asc2.typeCheck(visitor, contextInfo) .optimize(visitor, contextInfo);