Search in sources :

Example 1 with QNameValue

use of org.exist.xquery.value.QNameValue in project exist by eXist-db.

the class FunMin method eval.

/* (non-Javadoc)
	 * @see org.exist.xquery.Expression#eval(org.exist.dom.persistent.DocumentSet, org.exist.xquery.value.Sequence, org.exist.xquery.value.Item)
	 */
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().start(this);
        context.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
        if (contextSequence != null) {
            context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
        }
        if (contextItem != null) {
            context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT ITEM", contextItem.toSequence());
        }
    }
    boolean computableProcessing = false;
    Sequence result;
    final Sequence arg = getArgument(0).eval(contextSequence, contextItem);
    if (arg.isEmpty()) {
        result = Sequence.EMPTY_SEQUENCE;
    } else {
        // TODO : test if a range index is defined *iff* it is compatible with the collator
        final Collator collator = getCollator(contextSequence, contextItem, 2);
        final SequenceIterator iter = arg.unorderedIterator();
        AtomicValue min = null;
        while (iter.hasNext()) {
            final Item item = iter.nextItem();
            if (item instanceof QNameValue) {
                throw new XPathException(this, ErrorCodes.FORG0006, "Cannot compare " + Type.getTypeName(item.getType()), arg);
            }
            AtomicValue value = item.atomize();
            // Duration values must either all be xs:yearMonthDuration values or must all be xs:dayTimeDuration values.
            if (Type.subTypeOf(value.getType(), Type.DURATION)) {
                value = ((DurationValue) value).wrap();
                if (value.getType() == Type.YEAR_MONTH_DURATION) {
                    if (min != null && min.getType() != Type.YEAR_MONTH_DURATION) {
                        throw new XPathException(this, ErrorCodes.FORG0006, "Cannot compare " + Type.getTypeName(min.getType()) + " and " + Type.getTypeName(value.getType()), value);
                    }
                } else if (value.getType() == Type.DAY_TIME_DURATION) {
                    if (min != null && min.getType() != Type.DAY_TIME_DURATION) {
                        throw new XPathException(this, ErrorCodes.FORG0006, "Cannot compare " + Type.getTypeName(min.getType()) + " and " + Type.getTypeName(value.getType()), value);
                    }
                } else {
                    throw new XPathException(this, ErrorCodes.FORG0006, "Cannot compare " + Type.getTypeName(value.getType()), value);
                }
            // Any value of type xdt:untypedAtomic is cast to xs:double
            } else if (value.getType() == Type.UNTYPED_ATOMIC) {
                value = value.convertTo(Type.DOUBLE);
            }
            if (min == null) {
                min = value;
            } else {
                if (Type.getCommonSuperType(min.getType(), value.getType()) == Type.ATOMIC) {
                    throw new XPathException(this, ErrorCodes.FORG0006, "Cannot compare " + Type.getTypeName(min.getType()) + " and " + Type.getTypeName(value.getType()), value);
                }
                // Any value of type xdt:untypedAtomic is cast to xs:double
                if (value.getType() == Type.ATOMIC) {
                    value = value.convertTo(Type.DOUBLE);
                }
                // Numeric tests
                if (Type.subTypeOfUnion(value.getType(), Type.NUMBER)) {
                    // Don't mix comparisons
                    if (!Type.subTypeOfUnion(min.getType(), Type.NUMBER)) {
                        throw new XPathException(this, ErrorCodes.FORG0006, "Cannot compare " + Type.getTypeName(min.getType()) + " and " + Type.getTypeName(value.getType()), min);
                    }
                    if (((NumericValue) value).isNaN()) {
                        // Type NaN correctly
                        value = value.promote(min);
                        if (value.getType() == Type.FLOAT) {
                            min = FloatValue.NaN;
                        } else {
                            min = DoubleValue.NaN;
                        }
                        // although result will be NaN, we need to continue on order to type correctly
                        continue;
                    }
                    min = min.promote(value);
                }
                // Ugly test
                if (value instanceof ComputableValue) {
                    if (!(min instanceof ComputableValue)) {
                        throw new XPathException(this, ErrorCodes.FORG0006, "Cannot compare " + Type.getTypeName(min.getType()) + " and " + Type.getTypeName(value.getType()), min);
                    }
                    // Type value correctly
                    value = value.promote(min);
                    min = min.min(collator, value);
                    computableProcessing = true;
                } else {
                    if (computableProcessing) {
                        throw new XPathException(this, ErrorCodes.FORG0006, "Cannot compare " + Type.getTypeName(min.getType()) + " and " + Type.getTypeName(value.getType()), value);
                    }
                    if (Collations.compare(collator, value.getStringValue(), min.getStringValue()) < 0) {
                        min = value;
                    }
                }
            }
        }
        result = min;
    }
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().end(this, "", result);
    }
    return result;
}
Also used : Item(org.exist.xquery.value.Item) ComputableValue(org.exist.xquery.value.ComputableValue) SequenceIterator(org.exist.xquery.value.SequenceIterator) XPathException(org.exist.xquery.XPathException) QNameValue(org.exist.xquery.value.QNameValue) AtomicValue(org.exist.xquery.value.AtomicValue) Sequence(org.exist.xquery.value.Sequence) NumericValue(org.exist.xquery.value.NumericValue) Collator(com.ibm.icu.text.Collator)

Example 2 with QNameValue

use of org.exist.xquery.value.QNameValue in project exist by eXist-db.

the class FunOnFunctions method eval.

@Override
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
    try {
        if (isCalledAs("function-lookup")) {
            final QName fname = ((QNameValue) args[0].itemAt(0)).getQName();
            final int arity = ((IntegerValue) args[1].itemAt(0)).getInt();
            FunctionCall call;
            try {
                call = NamedFunctionReference.lookupFunction(this, context, fname, arity);
            } catch (final XPathException e) {
                if (e.getErrorCode() == ErrorCodes.XPST0017) {
                    // return empty sequence for all "function not found" related errors
                    return Sequence.EMPTY_SEQUENCE;
                }
                throw e;
            }
            return call == null ? Sequence.EMPTY_SEQUENCE : new FunctionReference(call);
        } else if (isCalledAs("function-name")) {
            final FunctionReference ref = (FunctionReference) args[0].itemAt(0);
            final QName qname = ref.getSignature().getName();
            if (qname == null || qname == InlineFunction.INLINE_FUNCTION_QNAME) {
                return Sequence.EMPTY_SEQUENCE;
            } else {
                return new QNameValue(context, qname);
            }
        } else {
            // isCalledAs("function-arity")
            final FunctionReference ref = (FunctionReference) args[0].itemAt(0);
            return new IntegerValue(ref.getSignature().getArgumentCount());
        }
    } catch (final Exception e) {
        if (e instanceof XPathException) {
            throw (XPathException) e;
        } else {
            throw new XPathException(this, ErrorCodes.XPST0017, e.getMessage());
        }
    }
}
Also used : QName(org.exist.dom.QName) QNameValue(org.exist.xquery.value.QNameValue) IntegerValue(org.exist.xquery.value.IntegerValue) FunctionReference(org.exist.xquery.value.FunctionReference)

Example 3 with QNameValue

use of org.exist.xquery.value.QNameValue in project exist by eXist-db.

the class FunResolveQName method eval.

public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().start(this);
        context.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
        if (contextSequence != null) {
            context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
        }
    }
    final Sequence qnameSeq = args[0];
    if (qnameSeq.isEmpty()) {
        return EmptySequence.EMPTY_SEQUENCE;
    } else {
        context.pushInScopeNamespaces();
        final String qnameString = args[0].getStringValue();
        if (QName.isQName(qnameString) == VALID.val) {
            try {
                String prefix = QName.extractPrefix(qnameString);
                if (prefix == null) {
                    prefix = "";
                }
                String uri = null;
                final NodeValue node = (NodeValue) args[1].itemAt(0);
                if (node.getImplementationType() == NodeValue.PERSISTENT_NODE) {
                    NodeProxy proxy = (NodeProxy) node;
                    final NodeSet ancestors = proxy.getAncestors(contextId, true);
                    for (NodeProxy ancestor : ancestors) {
                        proxy = ancestor;
                        final ElementImpl e = (ElementImpl) proxy.getNode();
                        uri = findNamespaceURI(e, prefix);
                        if (uri != null) {
                            break;
                        }
                    }
                } else {
                    NodeImpl next = (NodeImpl) node;
                    do {
                        uri = findNamespaceURI((org.exist.dom.memtree.ElementImpl) next, prefix);
                        if (uri != null) {
                            break;
                        } else {
                            next = (NodeImpl) next.getParentNode();
                        }
                    } while (next != null && next.getNodeType() == Node.ELEMENT_NODE);
                }
                if (uri == null && prefix != null && !prefix.isEmpty()) {
                    throw new XPathException(this, ErrorCodes.FONS0004, "No namespace found for prefix. No binding for prefix '" + prefix + "' was found.", args[0]);
                }
                final String localPart = QName.extractLocalName(qnameString);
                final QName qn = new QName(localPart, uri, prefix);
                final QNameValue result = new QNameValue(context, qn);
                if (context.getProfiler().isEnabled()) {
                    context.getProfiler().end(this, "", result);
                }
                context.popInScopeNamespaces();
                return result;
            } catch (final QName.IllegalQNameException e) {
                throw new XPathException(this, ErrorCodes.FOCA0002, "Invalid lexical value. '" + qnameString + "' is not a QName.", args[0]);
            }
        } else {
            throw new XPathException(this, ErrorCodes.FOCA0002, "Invalid lexical value. '" + qnameString + "' is not a QName.", args[0]);
        }
    }
}
Also used : NodeSet(org.exist.dom.persistent.NodeSet) NodeValue(org.exist.xquery.value.NodeValue) NodeImpl(org.exist.dom.memtree.NodeImpl) XPathException(org.exist.xquery.XPathException) QName(org.exist.dom.QName) QNameValue(org.exist.xquery.value.QNameValue) EmptySequence(org.exist.xquery.value.EmptySequence) Sequence(org.exist.xquery.value.Sequence) NodeProxy(org.exist.dom.persistent.NodeProxy) ElementImpl(org.exist.dom.persistent.ElementImpl)

Example 4 with QNameValue

use of org.exist.xquery.value.QNameValue in project exist by eXist-db.

the class FunQName method eval.

/* (non-Javadoc)
	 * @see org.exist.xquery.BasicFunction#eval(org.exist.xquery.value.Sequence[], org.exist.xquery.value.Sequence)
	 */
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().start(this);
        context.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
        if (contextSequence != null) {
            context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
        }
    }
    // TODO : currently useless (but for empty sequences) since the type is forced :-(
    if (!args[0].isEmpty() && args[0].getItemType() != Type.STRING) {
        throw new XPathException(this, ErrorCodes.XPTY0004, "Namespace URI is of type '" + Type.getTypeName(args[0].getItemType()) + "', 'xs:string' expected", args[0]);
    }
    String namespace;
    if (args[0].isEmpty()) {
        namespace = "";
    } else {
        namespace = args[0].getStringValue();
    }
    final String param = args[1].getStringValue();
    String prefix = null;
    String localName = null;
    try {
        prefix = QName.extractPrefix(param);
        localName = QName.extractLocalName(param);
    } catch (final QName.IllegalQNameException e) {
        final ValueSequence argsSeq = new ValueSequence(args[0]);
        argsSeq.addAll(args[1]);
        throw new XPathException(this, ErrorCodes.FOCA0002, "Invalid lexical form of either prefix or local name.", argsSeq);
    }
    if ((prefix != null && !prefix.isEmpty()) && (namespace == null || namespace.isEmpty())) {
        final ValueSequence argsSeq = new ValueSequence(args[0]);
        argsSeq.addAll(args[1]);
        throw new XPathException(this, ErrorCodes.FOCA0002, "Non-empty namespace prefix with empty namespace URI", argsSeq);
    }
    if (namespace != null) {
        if (namespace.equalsIgnoreCase(Namespaces.XMLNS_NS)) {
            if (prefix == null)
                throw new XPathException(this, ErrorCodes.XQDY0044, "'" + Namespaces.XMLNS_NS + "' can't be use with no prefix");
            else if (!prefix.equalsIgnoreCase("xmlns"))
                throw new XPathException(this, ErrorCodes.XQDY0044, "'" + Namespaces.XMLNS_NS + "' can't be use with prefix '" + prefix + "'");
        }
        if (namespace.equalsIgnoreCase(Namespaces.XML_NS)) {
            if (prefix == null)
                throw new XPathException(this, ErrorCodes.XQDY0044, "'" + Namespaces.XML_NS + "' can't be use with no prefix");
            else if (!prefix.equalsIgnoreCase("xml"))
                throw new XPathException(this, ErrorCodes.XQDY0044, "'" + Namespaces.XML_NS + "' can't be use with prefix '" + prefix + "'");
        }
    }
    if (prefix != null) {
        if (prefix.equalsIgnoreCase("xml") && !namespace.equalsIgnoreCase(Namespaces.XML_NS)) {
            throw new XPathException(this, ErrorCodes.XQDY0044, "prefix 'xml' can be used only with '" + Namespaces.XML_NS + "'");
        }
    }
    final QName qname = new QName(localName, namespace, prefix);
    if (prefix != null && namespace != null) {
        if (context.getURIForPrefix(prefix) == null) {
            // TOCHECK : context.declareInScopeNamespace(prefix, uri) ?
            context.declareNamespace(prefix, namespace);
        }
    // context.declareInScopeNamespace(prefix, namespace);
    }
    if (!XMLNames.isName(qname.getLocalPart())) {
        throw new XPathException(this, ErrorCodes.FOCA0002, "'" + qname.getLocalPart() + "' is not a valid local name.");
    }
    final Sequence result = new QNameValue(context, qname);
    if (context.getProfiler().isEnabled()) {
        context.getProfiler().end(this, "", result);
    }
    return result;
}
Also used : XPathException(org.exist.xquery.XPathException) QName(org.exist.dom.QName) QNameValue(org.exist.xquery.value.QNameValue) ValueSequence(org.exist.xquery.value.ValueSequence) ValueSequence(org.exist.xquery.value.ValueSequence) Sequence(org.exist.xquery.value.Sequence)

Example 5 with QNameValue

use of org.exist.xquery.value.QNameValue in project exist by eXist-db.

the class ElementConstructor method eval.

@Override
public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException {
    context.expressionStart(this);
    context.pushInScopeNamespaces();
    if (newDocumentContext) {
        context.pushDocumentContext();
    }
    try {
        final MemTreeBuilder builder = context.getDocumentBuilder();
        // declare namespaces
        if (namespaceDecls != null) {
            for (QName namespaceDecl : namespaceDecls) {
                // if ("".equals(namespaceDecls[i].getNamespaceURI())) {
                // TODO: the specs are unclear here: should we throw XQST0085 or not?
                // context.inScopeNamespaces.remove(namespaceDecls[i].getLocalPart());
                // if (context.inScopeNamespaces.remove(namespaceDecls[i].getLocalPart()) == null)
                // throw new XPathException(getAS      TNode(), "XQST0085 : can not undefine '" + namespaceDecls[i] + "'");
                // } else
                context.declareInScopeNamespace(namespaceDecl.getLocalPart(), namespaceDecl.getNamespaceURI());
            }
        }
        // process attributes
        final AttributesImpl attrs = new AttributesImpl();
        if (attributes != null) {
            // first, search for xmlns attributes and declare in-scope namespaces
            for (final AttributeConstructor constructor : attributes) {
                if (constructor.isNamespaceDeclaration()) {
                    final int p = constructor.getQName().indexOf(':');
                    if (p == Constants.STRING_NOT_FOUND) {
                        context.declareInScopeNamespace(XMLConstants.DEFAULT_NS_PREFIX, constructor.getLiteralValue());
                    } else {
                        final String prefix = constructor.getQName().substring(p + 1);
                        context.declareInScopeNamespace(prefix, constructor.getLiteralValue());
                    }
                }
            }
            String v = null;
            // process the remaining attributes
            for (int i = 0; i < attributes.length; i++) {
                context.proceed(this, builder);
                final AttributeConstructor constructor = attributes[i];
                final Sequence attrValues = constructor.eval(contextSequence, contextItem);
                QName attrQName;
                try {
                    attrQName = QName.parse(context, constructor.getQName(), XMLConstants.NULL_NS_URI);
                } catch (final QName.IllegalQNameException e) {
                    throw new XPathException(this, ErrorCodes.XPTY0004, "'" + constructor.getQName() + "' is not a valid attribute name");
                }
                final String namespaceURI = attrQName.getNamespaceURI();
                if (namespaceURI != null && !namespaceURI.isEmpty() && attrQName.getPrefix() == null) {
                    String prefix = context.getPrefixForURI(namespaceURI);
                    if (prefix != null) {
                        attrQName = new QName(attrQName.getLocalPart(), attrQName.getNamespaceURI(), prefix);
                    } else {
                        // generate prefix
                        for (final int n = 1; i < 100; i++) {
                            prefix = "eXnsp" + n;
                            if (context.getURIForPrefix(prefix) == null) {
                                attrQName = new QName(attrQName.getLocalPart(), attrQName.getNamespaceURI(), prefix);
                                break;
                            }
                            prefix = null;
                        }
                        if (prefix == null) {
                            throw new XPathException(this, "Prefix can't be generated.");
                        }
                    }
                }
                if (attrs.getIndex(attrQName.getNamespaceURI(), attrQName.getLocalPart()) != -1) {
                    throw new XPathException(this, ErrorCodes.XQST0040, "'" + attrQName.getLocalPart() + "' is a duplicate attribute name");
                }
                v = DynamicAttributeConstructor.normalize(this, attrQName, attrValues.getStringValue());
                attrs.addAttribute(attrQName.getNamespaceURI(), attrQName.getLocalPart(), attrQName.getStringValue(), "CDATA", v);
            }
        }
        context.proceed(this, builder);
        // create the element
        final Sequence qnameSeq = qnameExpr.eval(contextSequence, contextItem);
        if (!qnameSeq.hasOne()) {
            throw new XPathException(this, ErrorCodes.XPTY0004, "Type error: the node name should evaluate to a single item");
        }
        final Item qnitem = qnameSeq.itemAt(0);
        QName qn;
        if (qnitem instanceof QNameValue) {
            qn = ((QNameValue) qnitem).getQName();
        } else {
            // Do we have the same result than Atomize there ? -pb
            try {
                qn = QName.parse(context, qnitem.getStringValue());
            } catch (final QName.IllegalQNameException e) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "'" + qnitem.getStringValue() + "' is not a valid element name");
            } catch (final XPathException e) {
                e.setLocation(getLine(), getColumn(), getSource());
                throw e;
            }
            /*
                 if (qn.getPrefix() == null && context.inScopeNamespaces.get("xmlns") != null) {
                     qn.setNamespaceURI((String)context.inScopeNamespaces.get("xmlns"));
                 }
                 */
            if (qn.getPrefix() == null && context.getInScopeNamespace(XMLConstants.DEFAULT_NS_PREFIX) != null) {
                qn = new QName(qn.getLocalPart(), context.getInScopeNamespace(XMLConstants.DEFAULT_NS_PREFIX), qn.getPrefix());
            }
        }
        // Not in the specs but... makes sense
        if (!XMLNames.isName(qn.getLocalPart())) {
            throw new XPathException(this, ErrorCodes.XPTY0004, "'" + qnitem.getStringValue() + "' is not a valid element name");
        }
        // add namespace declaration nodes
        final int nodeNr = builder.startElement(qn, attrs);
        if (namespaceDecls != null) {
            for (QName namespaceDecl : namespaceDecls) {
                builder.namespaceNode(namespaceDecl);
            }
        }
        // do we need to add a namespace declaration for the current node?
        if (qn.hasNamespace()) {
            if (context.getInScopePrefix(qn.getNamespaceURI()) == null) {
                String prefix = qn.getPrefix();
                if (prefix == null) {
                    prefix = XMLConstants.DEFAULT_NS_PREFIX;
                }
                context.declareInScopeNamespace(prefix, qn.getNamespaceURI());
                builder.namespaceNode(new QName(prefix, qn.getNamespaceURI(), XMLConstants.XMLNS_ATTRIBUTE));
            }
        } else if ((qn.getPrefix() == null || qn.getPrefix().length() == 0) && context.getInheritedNamespace(XMLConstants.DEFAULT_NS_PREFIX) != null) {
            context.declareInScopeNamespace(XMLConstants.DEFAULT_NS_PREFIX, XMLConstants.NULL_NS_URI);
            builder.namespaceNode(new QName("", XMLConstants.NULL_NS_URI, XMLConstants.XMLNS_ATTRIBUTE));
        } else if (qn.getPrefix() == null || qn.getPrefix().length() == 0) {
            context.declareInScopeNamespace(XMLConstants.DEFAULT_NS_PREFIX, XMLConstants.NULL_NS_URI);
        }
        // process element contents
        if (content != null) {
            content.eval(contextSequence, contextItem);
        }
        builder.endElement();
        final NodeImpl node = builder.getDocument().getNode(nodeNr);
        return node;
    } finally {
        context.popInScopeNamespaces();
        if (newDocumentContext) {
            context.popDocumentContext();
        }
        context.expressionEnd(this);
    }
}
Also used : Item(org.exist.xquery.value.Item) AttributesImpl(org.xml.sax.helpers.AttributesImpl) MemTreeBuilder(org.exist.dom.memtree.MemTreeBuilder) NodeImpl(org.exist.dom.memtree.NodeImpl) QName(org.exist.dom.QName) QNameValue(org.exist.xquery.value.QNameValue) Sequence(org.exist.xquery.value.Sequence)

Aggregations

QNameValue (org.exist.xquery.value.QNameValue)11 QName (org.exist.dom.QName)9 Sequence (org.exist.xquery.value.Sequence)9 XPathException (org.exist.xquery.XPathException)7 Item (org.exist.xquery.value.Item)5 AtomicValue (org.exist.xquery.value.AtomicValue)3 Collator (com.ibm.icu.text.Collator)2 NodeImpl (org.exist.dom.memtree.NodeImpl)2 ComputableValue (org.exist.xquery.value.ComputableValue)2 IntegerValue (org.exist.xquery.value.IntegerValue)2 NodeValue (org.exist.xquery.value.NodeValue)2 NumericValue (org.exist.xquery.value.NumericValue)2 SequenceIterator (org.exist.xquery.value.SequenceIterator)2 INode (org.exist.dom.INode)1 MemTreeBuilder (org.exist.dom.memtree.MemTreeBuilder)1 ElementImpl (org.exist.dom.persistent.ElementImpl)1 NodeProxy (org.exist.dom.persistent.NodeProxy)1 NodeSet (org.exist.dom.persistent.NodeSet)1 NativeValueIndex (org.exist.storage.NativeValueIndex)1 org.exist.xquery (org.exist.xquery)1