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;
}
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());
}
}
}
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]);
}
}
}
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;
}
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);
}
}
Aggregations