/** * Copy an expression. This makes a deep copy. * * @return the copy of the original expression * @param rebindings */ /*@NotNull*/ public Expression copy(RebindingMap rebindings) { AdjacentTextNodeMerger a2 = new AdjacentTextNodeMerger(getBaseExpression().copy(rebindings)); ExpressionTool.copyLocationInfo(this, a2); return a2; }
@Override public Expression typeCheck(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException { getOperand().typeCheck(visitor, contextInfo); if (th.relationship(getBaseExpression().getItemType(), NodeKindTest.TEXT) == TypeHierarchy.DISJOINT) { Expression base = getBaseExpression(); base.setParentExpression(getParentExpression()); return base; if (!Cardinality.allowsMany(getBaseExpression().getCardinality())) { Expression base = getBaseExpression(); base.setParentExpression(getParentExpression()); return base; if (getBaseExpression() instanceof Choose) { Choose choose = (Choose) getBaseExpression(); for (int i = 0; i < choose.size(); i++) { AdjacentTextNodeMerger atm2 = new AdjacentTextNodeMerger(choose.getAction(i)); choose.setAction(i, atm2.typeCheck(visitor, contextInfo)); if (getBaseExpression() instanceof Block) { Block block = (Block) getBaseExpression(); Operand[] actions = block.getOperanda(); boolean prevtext = false;
/** * Get the static type of the expression as a UType, following precisely the type * inference rules defined in the XSLT 3.0 specification. * * @param contextItemType the static type of the context item * @return the static item type of the expression according to the XSLT 3.0 defined rules */ @Override public UType getStaticUType(UType contextItemType) { return getBaseExpression().getStaticUType(contextItemType); }
Receiver out = context.getReceiver(); FastStringBuffer fsb = new FastStringBuffer(FastStringBuffer.C256); SequenceIterator iter = getBaseExpression().iterate(context); boolean prevText = false; Item item; while ((item = iter.next()) != null) { if (isTextNode(item)) { CharSequence s = item.getStringValueCS(); if (s.length() > 0) {
/** * Make an AdjacentTextNodeMerger expression with a given operand, or a simpler equivalent expression if appropriate * * @param base the operand expression * @return an AdjacentTextNodeMerger or equivalent expression */ public static Expression makeAdjacentTextNodeMerger(Expression base) { if (base instanceof Literal && ((Literal) base).getValue() instanceof AtomicSequence) { return base; } else { return new AdjacentTextNodeMerger(base); } }
public Item next() throws XPathException { Item current = next; if (current == null) { return null; } next = base.next(); if (AdjacentTextNodeMerger.isTextNode(current)) { FastStringBuffer fsb = new FastStringBuffer(FastStringBuffer.C256); fsb.append(current.getStringValueCS()); while (AdjacentTextNodeMerger.isTextNode(next)) { fsb.append(next.getStringValueCS() /*.toString() */); // NOTE: toString() shouldn't be necessary - added 2011-05-05 for bug workaround; removed again 2011-07-14 next = base.next(); } if (fsb.isEmpty()) { return next(); } else { Orphan o = new Orphan(((NodeInfo) current).getConfiguration()); o.setNodeKind(Type.TEXT); o.setStringValue(fsb); current = o; return current; } } else { return current; } }
/** * Construct an expression that implements the rules of "constructing simple content": * given an expression to select the base sequence, and an expression to compute the separator, * build an (unoptimized) expression to produce the value of the node as a string. * * @param select the expression that selects the base sequence * @param separator the expression that computes the separator * @param env the static context * @return an expression that returns a string containing the string value of the constructed node */ public static Expression makeSimpleContentConstructor(Expression select, Expression separator, StaticContext env) { RetainedStaticContext rsc = select.getLocalRetainedStaticContext(); if (rsc == null) { rsc = env.makeRetainedStaticContext(); } // Merge adjacent text nodes select = AdjacentTextNodeMerger.makeAdjacentTextNodeMerger(select); // Atomize the result select = Atomizer.makeAtomizer(select, null); // Convert each atomic value to a string select = new AtomicSequenceConverter(select, BuiltInAtomicType.STRING); select.setRetainedStaticContext(rsc); ((AtomicSequenceConverter) select).allocateConverterStatically(env.getConfiguration(), false); // Join the resulting strings with a separator if (select.getCardinality() != StaticProperty.EXACTLY_ONE) { select = SystemFunction.makeCall("string-join", rsc, select, separator); } // All that's left for the instruction to do is to construct the right kind of node return select; }
@Override public Expression typeCheck(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException { getOperand().typeCheck(visitor, contextInfo); if (th.relationship(getBaseExpression().getItemType(), NodeKindTest.TEXT) == TypeHierarchy.DISJOINT) { Expression base = getBaseExpression(); base.setParentExpression(getParentExpression()); return base; if (!Cardinality.allowsMany(getBaseExpression().getCardinality())) { Expression base = getBaseExpression(); base.setParentExpression(getParentExpression()); return base; if (getBaseExpression() instanceof Choose) { Choose choose = (Choose) getBaseExpression(); for (int i = 0; i < choose.size(); i++) { AdjacentTextNodeMerger atm2 = new AdjacentTextNodeMerger(choose.getAction(i)); choose.setAction(i, atm2.typeCheck(visitor, contextInfo)); if (getBaseExpression() instanceof Block) { Block block = (Block) getBaseExpression(); Operand[] actions = block.getOperanda(); boolean prevtext = false;
/** * Determine the data type of the expression, if possible. The default * implementation for unary expressions returns the item type of the operand * * @return the item type of the items in the result sequence, insofar as this * is known statically. */ /*@NotNull*/ @Override public ItemType getItemType() { return getBaseExpression().getItemType(); }
Receiver out = context.getReceiver(); FastStringBuffer fsb = new FastStringBuffer(FastStringBuffer.C256); SequenceIterator iter = getBaseExpression().iterate(context); boolean prevText = false; Item item; while ((item = iter.next()) != null) { if (isTextNode(item)) { CharSequence s = item.getStringValueCS(); if (s.length() > 0) {
/** * Make an AdjacentTextNodeMerger expression with a given operand, or a simpler equivalent expression if appropriate * * @param base the operand expression * @return an AdjacentTextNodeMerger or equivalent expression */ public static Expression makeAdjacentTextNodeMerger(Expression base) { if (base instanceof Literal && ((Literal) base).getValue() instanceof AtomicSequence) { return base; } else { return new AdjacentTextNodeMerger(base); } }
public Item next() throws XPathException { Item current = next; if (current == null) { return null; } next = base.next(); if (AdjacentTextNodeMerger.isTextNode(current)) { FastStringBuffer fsb = new FastStringBuffer(FastStringBuffer.C256); fsb.append(current.getStringValueCS()); while (AdjacentTextNodeMerger.isTextNode(next)) { fsb.append(next.getStringValueCS() /*.toString() */); // NOTE: toString() shouldn't be necessary - added 2011-05-05 for bug workaround; removed again 2011-07-14 next = base.next(); } if (fsb.isEmpty()) { return next(); } else { Orphan o = new Orphan(((NodeInfo) current).getConfiguration()); o.setNodeKind(Type.TEXT); o.setStringValue(fsb); current = o; return current; } } else { return current; } }
/** * Construct an expression that implements the rules of "constructing simple content": * given an expression to select the base sequence, and an expression to compute the separator, * build an (unoptimized) expression to produce the value of the node as a string. * * @param select the expression that selects the base sequence * @param separator the expression that computes the separator * @param env the static context * @return an expression that returns a string containing the string value of the constructed node */ public static Expression makeSimpleContentConstructor(Expression select, Expression separator, StaticContext env) { RetainedStaticContext rsc = select.getLocalRetainedStaticContext(); if (rsc == null) { rsc = env.makeRetainedStaticContext(); } // Merge adjacent text nodes select = AdjacentTextNodeMerger.makeAdjacentTextNodeMerger(select); // Atomize the result select = Atomizer.makeAtomizer(select); // Convert each atomic value to a string select = new AtomicSequenceConverter(select, BuiltInAtomicType.STRING); select.setRetainedStaticContext(rsc); ((AtomicSequenceConverter) select).allocateConverterStatically(env.getConfiguration(), false); // Join the resulting strings with a separator if (select.getCardinality() != StaticProperty.EXACTLY_ONE) { select = SystemFunction.makeCall("string-join", rsc, select, separator); } // All that's left for the instruction to do is to construct the right kind of node return select; }
/** * Get the static type of the expression as a UType, following precisely the type * inference rules defined in the XSLT 3.0 specification. * * @param contextItemType the static type of the context item * @return the static item type of the expression according to the XSLT 3.0 defined rules */ @Override public UType getStaticUType(UType contextItemType) { return getBaseExpression().getStaticUType(contextItemType); }
/** * Copy an expression. This makes a deep copy. * * @return the copy of the original expression * @param rebindings */ /*@NotNull*/ public Expression copy(RebindingMap rebindings) { AdjacentTextNodeMerger a2 = new AdjacentTextNodeMerger(getBaseExpression().copy(rebindings)); ExpressionTool.copyLocationInfo(this, a2); return a2; }
/** * Determine the data type of the expression, if possible. The default * implementation for unary expressions returns the item type of the operand * * @return the item type of the items in the result sequence, insofar as this * is known statically. */ /*@NotNull*/ @Override public ItemType getItemType() { return getBaseExpression().getItemType(); }
@Override public int computeCardinality() { return getBaseExpression().getCardinality() | StaticProperty.ALLOWS_ZERO; }
@Override public int computeCardinality() { return getBaseExpression().getCardinality() | StaticProperty.ALLOWS_ZERO; }
@Override public Expression simplify() throws XPathException { Expression operand = getBaseExpression(); if (operand instanceof Literal && ((Literal) operand).getValue() instanceof AtomicValue) { return operand; } else { return super.simplify(); } }
@Override public Expression simplify() throws XPathException { Expression operand = getBaseExpression(); if (operand instanceof Literal && ((Literal) operand).getValue() instanceof AtomicValue) { return operand; } else { return super.simplify(); } }