private void runAdjacent() throws SaxonApiException { TreeWriter treeWriter = null; String last = null; boolean open = false; int count = 0; while (source.moreDocuments()) { count++; source.read(); } source.resetReader(); DocumentSequenceIterator xsi = new DocumentSequenceIterator(); // See below xsi.setLast(count); int pos = 0; while (source.moreDocuments()) { XdmNode node = source.read(); pos++; Item item = null; try { XPathCompiler xcomp = runtime.getProcessor().newXPathCompiler(); xcomp.setBaseURI(step.getNode().getBaseURI()); for (String prefix : groupAdjacent.getNamespaceBindings().keySet()) { xcomp.declareNamespace(prefix, groupAdjacent.getNamespaceBindings().get(prefix)); } XPathExecutable xexec = xcomp.compile(groupAdjacent.getString()); // From Michael Kay: http://markmail.org/message/vkb2vaq2miylgndu // // Underneath the s9api XPathExecutable is a net.sf.saxon.sxpath.XPathExpression. XPathExpression xexpr = xexec.getUnderlyingExpression(); // Call createDynamicContext() on this to get an XPathDynamicContext object; XPathDynamicContext xdc = xexpr.createDynamicContext(node.getUnderlyingNode()); // call getXPathContextObject() on that to get the underlying XPathContext. XPathContext xc = xdc.getXPathContextObject(); // Then call XPathContext.setCurrentIterator() // to supply a SequenceIterator whose current() and position() methods return // the context item and position respectively. If there's any risk that the // expression will call the last() method, then it's simplest to make your // iterator's getProperties() return LAST_POSITION_FINDER, and implement the // LastPositionFinder interface, in which case last() will be implemented by // calling the iterator's getLastPosition() method. (Otherwise last() is // implemented by calling getAnother() to clone the iterator and calling next() // on the clone until the end of the sequence is reached). xsi.setPosition(pos); xsi.setItem(node.getUnderlyingNode()); xc.setCurrentIterator(xsi); // Then evaluate the expression by calling iterate() on the // net.sf.saxon.sxpath.XPathExpression object. SequenceIterator results = xexpr.iterate(xdc); item = results.next(); if (item == null) { throw new XProcException( step.getNode(), "The group-adjacent expression returned nothing."); } if (results.next() != null) { throw new XProcException( step.getNode(), "Didn't expect group-adjacent to return a sequence!"); } } catch (XPathException xe) { throw new XProcException(xe); } // // Good luck! // // FIXME: Compute effective boolean value in a more robust way String cur = item.getStringValue(); if (last != null) { if (last.equals(cur)) { treeWriter.addSubtree(node); } else { if (open) { open = false; treeWriter.addEndElement(); treeWriter.endDocument(); result.write(treeWriter.getResult()); } } } if (last == null || !last.equals(cur)) { last = cur; open = true; treeWriter = new TreeWriter(runtime); treeWriter.startDocument(step.getNode().getBaseURI()); treeWriter.addStartElement(wrapper); treeWriter.startContent(); treeWriter.addSubtree(node); } } if (open) { open = false; treeWriter.addEndElement(); treeWriter.endDocument(); result.write(treeWriter.getResult()); } }
private List<?> processRow() throws ExpressionEvaluationException, BlockedException, TeiidComponentException, TeiidProcessingException { List<Object> tuple = new ArrayList<Object>(projectedColumns.size()); for (XMLColumn proColumn : projectedColumns) { if (proColumn.isOrdinal()) { if (rowCount > Integer.MAX_VALUE) { throw new TeiidRuntimeException( new TeiidProcessingException( QueryPlugin.Event.TEIID31174, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31174))); } tuple.add((int) rowCount); } else { try { XPathExpression path = proColumn.getPathExpression(); XPathDynamicContext dynamicContext = path.createDynamicContext(item); SequenceIterator pathIter = path.iterate(dynamicContext); Item colItem = pathIter.next(); if (colItem == null) { if (proColumn.getDefaultExpression() != null) { tuple.add( getEvaluator(Collections.emptyMap()) .evaluate(proColumn.getDefaultExpression(), null)); } else { tuple.add(null); } continue; } if (proColumn.getSymbol().getType() == DataTypeManager.DefaultDataClasses.XML) { XMLType value = table .getXQueryExpression() .createXMLType( pathIter.getAnother(), this.getBufferManager(), false, getContext()); tuple.add(value); continue; } Item next = pathIter.next(); if (next != null) { if (proColumn.getSymbol().getType().isArray()) { ArrayList<Object> vals = new ArrayList<Object>(); vals.add( getValue( proColumn.getSymbol().getType().getComponentType(), colItem, this.table.getXQueryExpression().getConfig(), getContext())); vals.add( getValue( proColumn.getSymbol().getType().getComponentType(), next, this.table.getXQueryExpression().getConfig(), getContext())); while ((next = pathIter.next()) != null) { vals.add( getValue( proColumn.getSymbol().getType().getComponentType(), next, this.table.getXQueryExpression().getConfig(), getContext())); } Object value = new ArrayImpl( vals.toArray( (Object[]) Array.newInstance( proColumn.getSymbol().getType().getComponentType(), vals.size()))); tuple.add(value); continue; } throw new TeiidProcessingException( QueryPlugin.Event.TEIID30171, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30171, proColumn.getName())); } Object value = getValue( proColumn.getSymbol().getType(), colItem, this.table.getXQueryExpression().getConfig(), getContext()); tuple.add(value); } catch (XPathException e) { throw new TeiidProcessingException( QueryPlugin.Event.TEIID30172, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30172, proColumn.getName())); } } } item = null; return tuple; }