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

net.sf.saxon.s9api.XdmValue Maven / Gradle / Ivy

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2015 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.s9api;

import net.sf.saxon.Configuration;
import net.sf.saxon.event.PipelineConfiguration;
import net.sf.saxon.event.SequenceReceiver;
import net.sf.saxon.om.*;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.value.AtomicValue;
import net.sf.saxon.value.ObjectValue;
import net.sf.saxon.value.SequenceExtent;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * An value in the XDM data model. A value is a sequence of zero or more items,
 * each item being either an atomic value or a node.
 * 

*

An XdmValue is immutable.

*

*

A sequence consisting of a single item may be represented as an instance of {@link XdmItem}, * which is a subtype of XdmValue. However, there is no guarantee that a sequence of length one * will always be an instance of XdmItem.

*

*

Similarly, a zero-length sequence may be represented as an instance of {@link XdmEmptySequence}, * but there is no guarantee that every sequence of length zero will always be an instance of * XdmEmptySequence.

* * @since 9.0 */ public class XdmValue implements Iterable { private Sequence value; // this must be a materialized value protected XdmValue() { // must be followed by setValue() } /** * Create an XdmValue as a sequence of XdmItem objects * * @param items a sequence of XdmItem objects. Note that if this is supplied as a list or similar * collection, subsequent changes to the list/collection will have no effect on the XdmValue. * @since 9.0.0.4 */ public XdmValue(Iterable items) { List values = new ArrayList(); for (XdmItem item : items) { values.add((Item) item.getUnderlyingValue()); } value = new SequenceExtent(values); } /** * Create an XdmValue containing the items returned by an XdmSequenceIterator * * @param iterator the iterator that supplies the values * @throws SaxonApiException if an error occurs reading values from the supplied iterator * @since 9.6 */ public XdmValue(XdmSequenceIterator iterator) throws SaxonApiException { try { List values = new ArrayList(); while (iterator.hasNext()) { values.add((Item) iterator.next().getUnderlyingValue()); } value = new SequenceExtent(values); } catch (SaxonApiUncheckedException e) { throw new SaxonApiException(e.getCause()); } } protected XdmValue(Sequence value) { setValue(value); } protected void setValue(Sequence value) { this.value = value; } /** * Create an XdmValue that wraps an existing Saxon Sequence * * @param value the supplied Sequence (which may be a singleton Item), * @return an XdmValue corresponding to the supplied Sequence. If the * supplied value is null, an empty sequence is returned. If the supplied * value is an atomic value, the result will be an instance of XdmAtomicValue. * If the supplied value is a node, the result will be an instance of XdmNode. * If the supplied value is a function item (including map items), the result will be an instance of * XdmFunctionItem. * @throws SaxonApiUncheckedException if the supplied Sequence is not yet fully evaluated, and evaluation * of the underlying expression fails with a dynamic error. * @since 9.5 (previously a protected method) */ public static XdmValue wrap(Sequence value) { if (value == null) { return XdmEmptySequence.getInstance(); } GroundedValue gv; try { gv = SequenceTool.toGroundedValue(value); } catch (XPathException e) { throw new SaxonApiUncheckedException(e); } if (gv.getLength() == 0) { return XdmEmptySequence.getInstance(); } else if (gv.getLength() == 1) { Item first = gv.head(); if (first instanceof NodeInfo) { return new XdmNode((NodeInfo) first); } else if (first instanceof AtomicValue) { return new XdmAtomicValue((AtomicValue) first); } else if (first instanceof Function) { return new XdmFunctionItem((Function) first); } else { return new XdmExternalObject(((ObjectValue)first).getObject()); } } else { return new XdmValue(gv); } } /** * Create a new XdmValue by concatenating the contents of this XdmValue and another * XdmValue. The two input XdmValue objects are unaffected by this operation. *

Note: creating a sequence of N values by successive calls on this method * takes time proportional to N-squared.

* * @param otherValue the value to be appended * @return a new XdmValue containing the concatenation of the two input XdmValue objects * @since 9.2 */ public XdmValue append(XdmValue otherValue) { List values = new ArrayList(); for (XdmItem item : this) { values.add((Item) item.getUnderlyingValue()); } for (XdmItem item : otherValue) { values.add((Item) item.getUnderlyingValue()); } return new XdmValue(new SequenceExtent(values)); } /** * Get the number of items in the sequence * * @return the number of items in the value * @throws SaxonApiUncheckedException if the value is lazily evaluated and the delayed * evaluation fails with a dynamic error. */ public int size() { try { return SequenceTool.getLength(value); } catch (XPathException err) { throw new SaxonApiUncheckedException(err); } } /** * Get the n'th item in the value, counting from zero. * * @param n the item that is required, counting the first item in the sequence as item zero * @return the n'th item in the sequence making up the value, counting from zero * @throws IndexOutOfBoundsException if n is less than zero or greater than or equal to the number * of items in the value * @throws SaxonApiUncheckedException if the value is lazily evaluated and the delayed * evaluation fails with a dynamic error. */ public XdmItem itemAt(int n) throws IndexOutOfBoundsException, SaxonApiUncheckedException { if (n < 0 || n >= size()) { throw new IndexOutOfBoundsException("" + n); } try { Item item = SequenceTool.itemAt(value, n); return (XdmItem) XdmItem.wrap(item); } catch (XPathException e) { throw new SaxonApiUncheckedException(e); } } /** * Get an iterator over the items in this value. * * @return an Iterator over the items in this value. * @throws SaxonApiUncheckedException if the value is lazily evaluated and the delayed * evaluation fails with a dynamic error. */ public XdmSequenceIterator iterator() throws SaxonApiUncheckedException { try { Sequence v = getUnderlyingValue(); return new XdmSequenceIterator(v.iterate()); } catch (XPathException e) { throw new SaxonApiUncheckedException(e); } } /** * Get the underlying implementation object representing the value. This method allows * access to lower-level Saxon functionality, including classes and methods that offer * no guarantee of stability across releases. * * @return the underlying implementation object representing the value */ public Sequence getUnderlyingValue() { return value; } /** * Create a string representation of the value. The is the result of serializing * the value using the adaptive serialization method. * @return a string representation of the value */ public String toString() { try { Configuration config = null; SequenceIterator iter = value.iterate(); Item item; while ((item = iter.next()) != null) { if (item instanceof NodeInfo) { config = ((NodeInfo)item).getConfiguration(); break; } } if (config == null) { config = Configuration.newConfiguration(); } StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); PipelineConfiguration pipe = config.makePipelineConfiguration(); Properties properties = new Properties(); properties.setProperty(OutputKeys.METHOD, "adaptive"); properties.setProperty(OutputKeys.INDENT, "true"); properties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "true"); SequenceReceiver r = config.getSerializerFactory().getReceiver(result, pipe, properties); iter = value.iterate(); while ((item = iter.next()) != null) { r.append(item); } return writer.toString(); } catch (XPathException e) { return super.toString(); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy