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()); } Sequence seq; Sequence result; if (contextItem != null) contextSequence = contextItem.toSequence(); /* if (contextSequence == null || contextSequence.isEmpty()) result = Sequence.EMPTY_SEQUENCE; */ // If we have one argument, we take it into account if (getSignature().getArgumentCount() > 0) seq = getArgument(0).eval(contextSequence, contextItem); // Otherwise, we take the context sequence and we iterate over it else seq = contextSequence; if (seq == null) throw new XPathException(this, "XPDY0002: Undefined context item"); if (seq.isEmpty()) // Bloody specs ! result = StringValue.EMPTY_STRING; else { Item item = seq.itemAt(0); if (!Type.subTypeOf(item.getType(), Type.NODE)) throw new XPathException( this, "XPTY0004: item is not a node; got '" + Type.getTypeName(item.getType()) + "'"); // TODO : how to improve performance ? Node n = ((NodeValue) item).getNode(); if (n instanceof QNameable) result = new StringValue(((QNameable) n).getQName().getStringValue()); else result = StringValue.EMPTY_STRING; } if (context.getProfiler().isEnabled()) context.getProfiler().end(this, "", result); return result; }
public String toString() { StringBuilder result = new StringBuilder(); result.append(expression.toString()); result.append(" castable as "); result.append(Type.getTypeName(requiredType)); return result.toString(); }
public QNameRangeIndexSpec(Map namespaces, String name, String typeStr) throws DatabaseConfigurationException { try { this.type = Type.getType(typeStr); } catch (XPathException e) { throw new DatabaseConfigurationException("Unknown type: " + typeStr); } boolean isAttribute = false; if (name.startsWith("@")) { isAttribute = true; name = name.substring(1); } String prefix = QName.extractPrefix(name); String localName = QName.extractLocalName(name); String namespaceURI = ""; if (prefix != null) { namespaceURI = (String) namespaces.get(prefix); if (namespaceURI == null) { throw new DatabaseConfigurationException( "No namespace defined for prefix: " + prefix + " in index definition"); } } qname = new QName(localName, namespaceURI, prefix); if (isAttribute) qname.setNameType(ElementValue.ATTRIBUTE); }
/** * Add all items from the given sequence to the node set. All items have to be a subtype of node. * * @param other * @throws XPathException */ public void addAll(Sequence other) throws XPathException { if (!other.isEmpty() && !Type.subTypeOf(other.getItemType(), Type.NODE)) throw new XPathException("sequence argument is not a node sequence"); for (SequenceIterator i = other.iterate(); i.hasNext(); ) { add(i.nextItem()); } }
/** * @param requiredCardinality * @param context * @param expr * @param requiredType */ public CastableExpression( XQueryContext context, Expression expr, int requiredType, int requiredCardinality) { super(context); this.expression = expr; this.requiredType = requiredType; this.requiredCardinality = requiredCardinality; if (!Type.subTypeOf(expression.returnsType(), Type.ATOMIC)) expression = new Atomize(context, expression); }
private static String serialize(DBBroker broker, Item item) throws SAXException, XPathException { Serializer serializer = broker.getSerializer(); serializer.reset(); String value; if (Type.subTypeOf(item.getType(), Type.NODE)) { value = serializer.serialize((NodeValue) item); } else { value = item.getStringValue(); } return value; }
@Override public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException { NodeImpl report = null; try { // Only match documents that match these URLs List<String> toBeMatchedURIs = new ArrayList<>(); Sequence pathSeq = getArgumentCount() == 2 ? args[0] : contextSequence; if (pathSeq == null) return Sequence.EMPTY_SEQUENCE; // Get first agument, these are the documents / collections to search in for (SequenceIterator i = pathSeq.iterate(); i.hasNext(); ) { String path; Item item = i.nextItem(); if (Type.subTypeOf(item.getType(), Type.NODE)) { if (((NodeValue) item).isPersistentSet()) { path = ((NodeProxy) item).getDocument().getURI().toString(); } else { path = item.getStringValue(); } } else { path = item.getStringValue(); } toBeMatchedURIs.add(path); } // Get second argument, this is the query String query; if (getArgumentCount() == 1) query = args[0].itemAt(0).getStringValue(); else query = args[1].itemAt(0).getStringValue(); // Get the lucene worker LuceneIndexWorker index = (LuceneIndexWorker) context.getBroker().getIndexController().getWorkerByIndexId(LuceneIndex.ID); // Perform search report = index.search(context, toBeMatchedURIs, query); } catch (XPathException ex) { // Log and rethrow logger.error(ex); throw ex; } // Return list of matching files. return report; }
/* (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); } Sequence result; // return 0 if the argument sequence is empty // TODO : return empty sequence ? if (args[0].isEmpty()) result = IntegerValue.ZERO; else { int count = 0; for (SequenceIterator i = args[0].iterate(); i.hasNext(); ) { Item next = i.nextItem(); if (Type.subTypeOf(next.getType(), Type.NODE)) { NodeValue nv = (NodeValue) next; if (nv.getImplementationType() != NodeValue.PERSISTENT_NODE) throw new XPathException( getASTNode(), getName() + " cannot be applied to in-memory nodes."); NodeProxy np = (NodeProxy) nv; Match match = np.getMatches(); while (match != null) { if (match.getNodeId().isDescendantOrSelfOf(np.getNodeId())) { count += match.getFrequency(); } match = match.getNextMatch(); } } } result = new IntegerValue(count); } if (context.getProfiler().isEnabled()) context.getProfiler().end(this, "", result); return result; }
/** @see BasicFunction#eval(Sequence[], Sequence) */ public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException { // Check input parameters if (args.length != 1 && args.length != 2) { return Sequence.EMPTY_SEQUENCE; } InputStream is = null; ValidationReport vr = null; try { // Get inputstream of XML instance document if (args[0].getItemType() == Type.ANY_URI || args[0].getItemType() == Type.STRING) { // anyURI provided String url = args[0].getStringValue(); // Fix URL if (url.startsWith("/")) { url = "xmldb:exist://" + url; } is = new URL(url).openStream(); } else if (args[0].getItemType() == Type.ELEMENT || args[0].getItemType() == Type.DOCUMENT) { // Node provided is = new NodeInputStream(context, args[0].iterate()); // new NodeInputStream() } else { LOG.error("Wrong item type " + Type.getTypeName(args[0].getItemType())); throw new XPathException( getASTNode(), "wrong item type " + Type.getTypeName(args[0].getItemType())); } // Perform validation if (args.length == 1) { // Validate using system catalog vr = validator.validate(is); } else { // Validate using resource speciefied in second parameter String url = args[1].getStringValue(); if (url.startsWith("/")) { url = "xmldb:exist://" + url; } vr = validator.validate(is, url); } } catch (MalformedURLException ex) { LOG.error(ex); throw new XPathException(getASTNode(), "Invalid resource URI", ex); } catch (ExistIOException ex) { LOG.error(ex.getCause()); throw new XPathException(getASTNode(), "eXistIOexception", ex.getCause()); } catch (Exception ex) { LOG.error(ex); throw new XPathException(getASTNode(), "exception", ex); } finally { // Force release stream try { is.close(); } catch (IOException ex) { LOG.debug("Attemted to close stream. ignore.", ex); } } // Create response if (isCalledAs("validate")) { Sequence result = new ValueSequence(); result.add(new BooleanValue(vr.isValid())); return result; } else if (isCalledAs("validate-report")) { MemTreeBuilder builder = context.getDocumentBuilder(); NodeImpl result = writeReport(vr, builder); return result; } // Oops LOG.error("invoked with wrong function name"); throw new XPathException("unknown function"); }
/* (non-Javadoc) * @see org.exist.xquery.AbstractExpression#eval(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()); } if (requiredType == Type.ATOMIC || (requiredType == Type.NOTATION && expression.returnsType() != Type.NOTATION)) throw new XPathException( this, "err:XPST0080: cannot convert to " + Type.getTypeName(requiredType)); if (requiredType == Type.ANY_SIMPLE_TYPE || expression.returnsType() == Type.ANY_SIMPLE_TYPE || requiredType == Type.UNTYPED || expression.returnsType() == Type.UNTYPED) throw new XPathException( this, "err:XPST0051: cannot convert to " + Type.getTypeName(requiredType)); Sequence result; // See : http://article.gmane.org/gmane.text.xml.xquery.general/1413 // ... for the rationale // may be more complicated : let's see with following XQTS versions if (requiredType == Type.QNAME && Dependency.dependsOnVar(expression)) result = BooleanValue.FALSE; else { Sequence seq = expression.eval(contextSequence, contextItem); if (seq.isEmpty()) { // If ? is specified after the target type, the result of the cast expression is an empty // sequence. if (Cardinality.checkCardinality(requiredCardinality, Cardinality.ZERO)) result = BooleanValue.TRUE; // If ? is not specified after the target type, a type error is raised [err:XPTY0004]. else // TODO : raise the error ? result = BooleanValue.FALSE; } else { try { seq.itemAt(0).convertTo(requiredType); // If ? is specified after the target type, the result of the cast expression is an empty // sequence. if (Cardinality.checkCardinality(requiredCardinality, seq.getCardinality())) result = BooleanValue.TRUE; // If ? is not specified after the target type, a type error is raised [err:XPTY0004]. else result = BooleanValue.FALSE; // TODO : improve by *not* using a costly exception ? } catch (XPathException e) { result = BooleanValue.FALSE; } } } if (context.getProfiler().isEnabled()) context.getProfiler().end(this, "", result); return result; }
/* (non-Javadoc) * @see org.exist.xquery.Expression#dump(org.exist.xquery.util.ExpressionDumper) */ public void dump(ExpressionDumper dumper) { expression.dump(dumper); dumper.display(" castable as "); dumper.display(Type.getTypeName(requiredType)); }
/** * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, * java.lang.String, org.xml.sax.Attributes) */ public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { // save accumulated character content if (inModification && charBuf.length() > 0) { // String normalized = charBuf.toString(); final String normalized = preserveWhitespace ? charBuf.toString() : charBuf.getNormalizedString(FastStringBuffer.SUPPRESS_BOTH); if (normalized.length() > 0) { final Text text = doc.createTextNode(charBuf.toString()); if (stack.isEmpty()) { // LOG.debug("appending text to fragment: " + text.getData()); contents.add(text); } else { final Element last = stack.peek(); last.appendChild(text); } } charBuf.setLength(0); } if (namespaceURI.equals(XUPDATE_NS)) { String select = null; if (localName.equals(MODIFICATIONS)) { startModifications(atts); return; } else if (localName.equals(VARIABLE)) { // variable declaration startVariableDecl(atts); return; } else if (IF.equals(localName)) { if (inModification) { throw new SAXException("xupdate:if is not allowed inside a modification"); } select = atts.getValue("test"); final Conditional cond = new Conditional(broker, documentSet, select, namespaces, variables); cond.setAccessContext(accessCtx); conditionals.push(cond); return; } else if (VALUE_OF.equals(localName)) { if (!inModification) { throw new SAXException("xupdate:value-of is not allowed outside a modification"); } } else if (APPEND.equals(localName) || INSERT_BEFORE.equals(localName) || INSERT_AFTER.equals(localName) || REMOVE.equals(localName) || RENAME.equals(localName) || UPDATE.equals(localName) || REPLACE.equals(localName)) { if (inModification) { throw new SAXException("nested modifications are not allowed"); } select = atts.getValue("select"); if (select == null) { throw new SAXException(localName + " requires a select attribute"); } doc = builder.newDocument(); contents = new NodeListImpl(); inModification = true; } else if ((ELEMENT.equals(localName) || ATTRIBUTE.equals(localName) || TEXT.equals(localName) || PROCESSING_INSTRUCTION.equals(localName) || COMMENT.equals(localName))) { if (!inModification) { throw new SAXException("creation elements are only allowed inside " + "a modification"); } charBuf.setLength(0); } else { throw new SAXException("Unknown XUpdate element: " + qName); } // start a new modification section if (APPEND.equals(localName)) { final String child = atts.getValue("child"); modification = new Append(broker, documentSet, select, child, namespaces, variables); } else if (UPDATE.equals(localName)) { modification = new Update(broker, documentSet, select, namespaces, variables); } else if (INSERT_BEFORE.equals(localName)) { modification = new Insert(broker, documentSet, select, Insert.INSERT_BEFORE, namespaces, variables); } else if (INSERT_AFTER.equals(localName)) { modification = new Insert(broker, documentSet, select, Insert.INSERT_AFTER, namespaces, variables); } else if (REMOVE.equals(localName)) { modification = new Remove(broker, documentSet, select, namespaces, variables); } else if (RENAME.equals(localName)) { modification = new Rename(broker, documentSet, select, namespaces, variables); } else if (REPLACE.equals(localName)) { modification = new Replace(broker, documentSet, select, namespaces, variables); } // process commands for node creation else if (ELEMENT.equals(localName)) { String name = atts.getValue("name"); if (name == null) { throw new SAXException("element requires a name attribute"); } final int p = name.indexOf(':'); String namespace = null; String prefix = ""; if (p != Constants.STRING_NOT_FOUND) { prefix = name.substring(0, p); if (name.length() == p + 1) { throw new SAXException("illegal prefix in qname: " + name); } name = name.substring(p + 1); namespace = atts.getValue("namespace"); if (namespace == null) { namespace = (String) namespaces.get(prefix); } if (namespace == null) { throw new SAXException("no namespace defined for prefix " + prefix); } } Element elem; if (namespace != null && namespace.length() > 0) { elem = doc.createElementNS(namespace, name); elem.setPrefix(prefix); } else { elem = doc.createElement(name); } if (stack.isEmpty()) { contents.add(elem); } else { final Element last = stack.peek(); last.appendChild(elem); } this.setWhitespaceHandling((Element) stack.push(elem)); } else if (ATTRIBUTE.equals(localName)) { final String name = atts.getValue("name"); if (name == null) { throw new SAXException("attribute requires a name attribute"); } final int p = name.indexOf(':'); String namespace = null; if (p != Constants.STRING_NOT_FOUND) { final String prefix = name.substring(0, p); if (name.length() == p + 1) { throw new SAXException("illegal prefix in qname: " + name); } namespace = atts.getValue("namespace"); if (namespace == null) { namespace = (String) namespaces.get(prefix); } if (namespace == null) { throw new SAXException("no namespace defined for prefix " + prefix); } } Attr attrib = namespace != null && namespace.length() > 0 ? doc.createAttributeNS(namespace, name) : doc.createAttribute(name); if (stack.isEmpty()) { for (int i = 0; i < contents.getLength(); i++) { final Node n = contents.item(i); String ns = n.getNamespaceURI(); final String nname = ns == null ? n.getNodeName() : n.getLocalName(); if (ns == null) { ns = ""; } // check for duplicate attributes if (n.getNodeType() == Node.ATTRIBUTE_NODE && nname.equals(name) && ns.equals(namespace)) { throw new SAXException( "The attribute " + attrib.getNodeName() + " cannot be specified twice"); } } contents.add(attrib); } else { final Element last = (Element) stack.peek(); if (namespace != null && last.hasAttributeNS(namespace, name) || namespace == null && last.hasAttribute(name)) { throw new SAXException( "The attribute " + attrib.getNodeName() + " cannot be specified " + "twice on the same element"); } if (namespace != null) { last.setAttributeNodeNS(attrib); } else { last.setAttributeNode(attrib); } } inAttribute = true; currentNode = attrib; // process value-of } else if (VALUE_OF.equals(localName)) { select = atts.getValue("select"); if (select == null) { throw new SAXException("value-of requires a select attribute"); } final Sequence seq = processQuery(select); if (LOG.isDebugEnabled()) { LOG.debug("Found " + seq.getItemCount() + " items for value-of"); } Item item; try { for (final SequenceIterator i = seq.iterate(); i.hasNext(); ) { item = i.nextItem(); if (Type.subTypeOf(item.getType(), Type.NODE)) { final Node node = NodeSetHelper.copyNode(doc, ((NodeValue) item).getNode()); if (stack.isEmpty()) { contents.add(node); } else { final Element last = (Element) stack.peek(); last.appendChild(node); } } else { final String value = item.getStringValue(); characters(value.toCharArray(), 0, value.length()); } } } catch (final XPathException e) { throw new SAXException(e.getMessage(), e); } } } else if (inModification) { final Element elem = namespaceURI != null && namespaceURI.length() > 0 ? doc.createElementNS(namespaceURI, qName) : doc.createElement(qName); Attr a; for (int i = 0; i < atts.getLength(); i++) { final String name = atts.getQName(i); final String nsURI = atts.getURI(i); if (name.startsWith("xmlns")) { // Why are these showing up? They are supposed to be stripped out? } else { a = nsURI != null ? doc.createAttributeNS(nsURI, name) : doc.createAttribute(name); a.setValue(atts.getValue(i)); if (nsURI != null) { elem.setAttributeNodeNS(a); } else { elem.setAttributeNode(a); } } } if (stack.isEmpty()) { contents.add(elem); } else { final Element last = (Element) stack.peek(); last.appendChild(elem); } this.setWhitespaceHandling((Element) stack.push(elem)); } }
/** * Return the name of the statically determined return type of the query expression. The name is * in a standard form, see {@link org.exist.xquery.value.Type} for a list of possible values. If * the return type cannot be statically determined, it defaults to <code>Type.ITEM</code>, the * universal supertype in XQuery. * * @return the name of the return type of the query being analyzed */ public String returnTypeName() { return org.exist.xquery.value.Type.getTypeName( query instanceof Expression ? ((PathExpr) query).returnsType() : org.exist.xquery.value.Type.ITEM); }
/** Add a sequence item to the node set. The item has to be a subtype of node. */ public void add(Item item) throws XPathException { if (!Type.subTypeOf(item.getType(), Type.NODE)) throw new XPathException("item has wrong type"); add((NodeProxy) item); }
private boolean deepEquals(Item a, Item b, Collator collator) { try { final boolean aAtomic = Type.subTypeOf(a.getType(), Type.ATOMIC); final boolean bAtomic = Type.subTypeOf(b.getType(), Type.ATOMIC); if (aAtomic || bAtomic) { if (!aAtomic || !bAtomic) return false; try { AtomicValue av = (AtomicValue) a; AtomicValue bv = (AtomicValue) b; if (Type.subTypeOf(av.getType(), Type.NUMBER) && Type.subTypeOf(bv.getType(), Type.NUMBER)) { // or if both values are NaN if (((NumericValue) a).isNaN() && ((NumericValue) b).isNaN()) return true; } return ValueComparison.compareAtomic( collator, av, bv, Constants.TRUNC_NONE, Constants.EQ); } catch (XPathException e) { return false; } } // assert Type.subTypeOf(a.getType(), Type.NODE); // assert Type.subTypeOf(b.getType(), Type.NODE); if (a.getType() != b.getType()) return false; NodeValue nva = (NodeValue) a, nvb = (NodeValue) b; if (nva == nvb) return true; try { // Don't use this shortcut for in-memory nodes since the symbol table is ignored. if (nva.getImplementationType() != NodeValue.IN_MEMORY_NODE && nva.equals(nvb)) return true; // shortcut! } catch (XPathException e) { // apparently incompatible values, do manual comparison } Node na, nb; switch (a.getType()) { case Type.DOCUMENT: // NodeValue.getNode() doesn't seem to work for document nodes na = nva instanceof Node ? (Node) nva : ((NodeProxy) nva).getDocument(); nb = nvb instanceof Node ? (Node) nvb : ((NodeProxy) nvb).getDocument(); return compareContents(na, nb); case Type.ELEMENT: na = nva.getNode(); nb = nvb.getNode(); return compareElements(na, nb); case Type.ATTRIBUTE: na = nva.getNode(); nb = nvb.getNode(); return compareNames(na, nb) && safeEquals(na.getNodeValue(), nb.getNodeValue()); case Type.PROCESSING_INSTRUCTION: case Type.NAMESPACE: na = nva.getNode(); nb = nvb.getNode(); return safeEquals(na.getNodeName(), nb.getNodeName()) && safeEquals(nva.getStringValue(), nvb.getStringValue()); case Type.TEXT: case Type.COMMENT: return safeEquals(nva.getStringValue(), nvb.getStringValue()); default: { logger.error("unexpected item type " + Type.getTypeName(a.getType())); throw new RuntimeException("unexpected item type " + Type.getTypeName(a.getType())); } } } catch (XPathException e) { logger.error(e.getMessage()); e.printStackTrace(); return false; } }