use of org.exist.xquery.value.Item in project exist by eXist-db.
the class DeferredFunctionCallTest method ensure_argumentsToDeferredFunctionCall_AreNotLost_AfterReset_And_BeforeEval.
/**
* resetState() make be called on the UserDefinedFunction of a DeferredFunctionCall
* before the function is eval'd, this is because the evaluation is deferred!
* resetState() clears the currentArguments to the function, however for a deferred
* function call we must ensure that we still have these when eval() is called
* otherwise we will get an NPE!
*
* This test tries to prove that eval can be called after resetState without
* causing problems for a DeferredFunctionCall
*
* The test implementation, due to the nature of the code under test, is rather horrible
* and mostly consists of tightly coupled mocking code making it very brittle.
* The interesting aspect of this test case is at the bottom of the function itself.
*/
@Test
public void ensure_argumentsToDeferredFunctionCall_AreNotLost_AfterReset_And_BeforeEval() throws XPathException {
// mocks for FunctionCall constructor
XQueryContext mockContext = EasyMock.createNiceMock(XQueryContext.class);
// mocks for evalFunction()
Sequence mockContextSequence = EasyMock.createMock(Sequence.class);
Item mockContextItem = EasyMock.createMock(Item.class);
Sequence[] mockSeq = { Sequence.EMPTY_SEQUENCE };
int nextExpressionId = 1234;
SequenceType[] mockArgumentTypes = { new SequenceType(Type.NODE, Cardinality.EMPTY_SEQUENCE) };
// mock for functionDef
FunctionSignature mockFunctionSignature = EasyMock.createMock(FunctionSignature.class);
SequenceType mockReturnType = EasyMock.createMock(SequenceType.class);
LocalVariable mockMark = EasyMock.createMock(LocalVariable.class);
Expression mockExpression = EasyMock.createMock(Expression.class);
// expectations for UserDefinedFunction constructor
expect(mockContext.nextExpressionId()).andReturn(nextExpressionId++);
expect(mockExpression.simplify()).andReturn(mockExpression);
// expectations for FunctionCall constructor
expect(mockContext.nextExpressionId()).andReturn(nextExpressionId++);
// expectations for FunctionCall.setFunction
expect(mockFunctionSignature.getReturnType()).andReturn(mockReturnType);
expect(mockReturnType.getCardinality()).andReturn(Cardinality.ZERO_OR_MORE);
expect(mockReturnType.getPrimaryType()).andReturn(Type.NODE).times(4);
expect(mockContext.nextExpressionId()).andReturn(nextExpressionId++);
// expectations for functionCall.evalFunction
expect(mockContext.isProfilingEnabled()).andReturn(false);
// expectations for DeferredFunctionCallImpl.setup
expect(mockFunctionSignature.getReturnType()).andReturn(mockReturnType);
expect(mockReturnType.getCardinality()).andReturn(Cardinality.ZERO_OR_MORE);
expect(mockReturnType.getPrimaryType()).andReturn(Type.NODE).times(4);
expect(mockContext.nextExpressionId()).andReturn(nextExpressionId++);
// expectations for DeferredFunctionCall.execute
mockContext.pushDocumentContext();
mockContext.functionStart(mockFunctionSignature);
mockContext.stackEnter((Expression) anyObject());
expect(mockContext.declareVariableBinding((LocalVariable) anyObject())).andReturn(null);
expect(mockFunctionSignature.getArgumentTypes()).andReturn(mockArgumentTypes);
expect(mockExpression.eval(null, null)).andReturn(Sequence.EMPTY_SEQUENCE);
mockExpression.resetState(true);
mockContext.stackLeave((Expression) anyObject());
mockContext.functionEnd();
mockContext.popDocumentContext();
replay(mockContext, mockFunctionSignature, mockReturnType, mockExpression);
UserDefinedFunction userDefinedFunction = new UserDefinedFunction(mockContext, mockFunctionSignature);
userDefinedFunction.addVariable("testParam");
userDefinedFunction.setFunctionBody(mockExpression);
FunctionCall functionCall = new FunctionCall(mockContext, userDefinedFunction);
// ensure DeferredFunction
functionCall.setRecursive(true);
/**
* this is the interesting bit **
*/
// 1) Call reset, this should set current arguments to null
functionCall.resetState(true);
// ensure DeferredFunction
functionCall.setRecursive(true);
// 2) check UserDefinedFunction.currentArguments == null
assertNull(userDefinedFunction.getCurrentArguments());
// so the currentArguments have been set to null, but deferredFunction should have its own copy
// 3) Call functionCall.eval, if we dont get an NPE on reading currentArguments, then success :-)
DeferredFunctionCall dfc = (DeferredFunctionCall) functionCall.evalFunction(mockContextSequence, mockContextItem, mockSeq);
dfc.execute();
/**
* end interesting bit **
*/
verify(mockContext, mockFunctionSignature, mockReturnType, mockExpression);
}
use of org.exist.xquery.value.Item in project exist by eXist-db.
the class IntersectTest method persistent_intersect_memtree.
/**
* Tests the XQuery `intersect` operator against a
* persistent node on the left and an in-memory node on the right
*/
@Test
public void persistent_intersect_memtree() throws XPathException, NoSuchMethodException {
final XQueryContext mockContext = createMock(XQueryContext.class);
final PathExpr mockLeft = createMock(PathExpr.class);
final PathExpr mockRight = createMock(PathExpr.class);
final Sequence mockContextSequence = createMock(Sequence.class);
final Item mockContextItem = createMock(Item.class);
final Profiler mockProfiler = createMock(Profiler.class);
final DocumentImpl mockPersistentDoc = createMock(DocumentImpl.class);
final NodeProxy mockPersistentNode = createMockBuilder(NodeProxy.class).withConstructor(DocumentImpl.class, NodeId.class).withArgs(mockPersistentDoc, new DLN(1)).addMockedMethods(NodeProxy.class.getMethod("isEmpty", new Class[] {}), NodeProxy.class.getMethod("getItemType", new Class[] {}), NodeProxy.class.getMethod("equals", new Class[] { Object.class })).createMock();
expect(mockContext.nextExpressionId()).andReturn(1);
expect(mockContext.getProfiler()).andReturn(mockProfiler);
// persistent node
expect(mockLeft.eval(mockContextSequence, mockContextItem)).andReturn(mockPersistentNode);
// memtree node
expect(mockRight.eval(mockContextSequence, mockContextItem)).andReturn((org.exist.dom.memtree.ElementImpl) createInMemoryDocument().getDocumentElement());
expect(mockPersistentNode.isEmpty()).andReturn(false);
expect(mockPersistentNode.getItemType()).andReturn(Type.NODE);
expect(mockPersistentDoc.getDocId()).andReturn(1).times(2);
expect(mockContext.getProfiler()).andReturn(mockProfiler);
replay(mockPersistentDoc, mockPersistentNode, mockRight, mockLeft, mockContext);
// test
final Intersect intersect = new Intersect(mockContext, mockLeft, mockRight);
final Sequence result = intersect.eval(mockContextSequence, mockContextItem);
assertEquals(0, ((ValueSequence) result).size());
verify(mockPersistentDoc, mockPersistentNode, mockRight, mockLeft, mockContext);
}
use of org.exist.xquery.value.Item in project exist by eXist-db.
the class DecodeExiFunction method eval.
@Override
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
if (args[0].isEmpty()) {
return Sequence.EMPTY_SEQUENCE;
}
try {
BinaryValue exiBinary = ((BinaryValue) args[0].itemAt(0));
context.pushDocumentContext();
try {
MemTreeBuilder builder = context.getDocumentBuilder();
// create default factory and EXI grammar for schema
EXIFactory exiFactory = DefaultEXIFactory.newInstance();
if (args.length > 1) {
if (!args[1].isEmpty()) {
Item xsdItem = args[1].itemAt(0);
try (InputStream xsdInputStream = EXIUtils.getInputStream(xsdItem, context)) {
GrammarFactory grammarFactory = GrammarFactory.newInstance();
Grammars grammar = grammarFactory.createGrammars(xsdInputStream);
exiFactory.setGrammars(grammar);
}
}
}
SAXDecoder decoder = new SAXDecoder(exiFactory);
SAXAdapter adapter = new AppendingSAXAdapter(builder);
decoder.setContentHandler(adapter);
try (InputStream inputStream = exiBinary.getInputStream()) {
decoder.parse(new InputSource(inputStream));
}
return (NodeValue) builder.getDocument().getDocumentElement();
} finally {
context.popDocumentContext();
}
} catch (EXIException | SAXException | IOException exie) {
throw new XPathException(this, new JavaErrorCode(exie.getCause()), exie.getMessage());
}
}
use of org.exist.xquery.value.Item in project exist by eXist-db.
the class FunResolveURI method eval.
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 (contextItem != null) {
contextSequence = contextItem.toSequence();
}
AnyURIValue base;
if (getArgumentCount() == 1) {
if (!context.isBaseURIDeclared()) {
throw new XPathException(this, ErrorCodes.FONS0005, "base URI of the static context has not been assigned a value.");
}
base = context.getBaseURI();
} else {
try {
final Item item = getArgument(1).eval(contextSequence).itemAt(0).convertTo(Type.ANY_URI);
base = (AnyURIValue) item;
} catch (final XPathException e) {
throw new XPathException(this, ErrorCodes.FORG0002, "invalid argument to fn:resolve-uri(): " + e.getMessage(), null, e);
}
}
Sequence result;
final Sequence seq = getArgument(0).eval(contextSequence);
if (seq.isEmpty()) {
result = Sequence.EMPTY_SEQUENCE;
} else {
AnyURIValue relative;
try {
final Item item = seq.itemAt(0).convertTo(Type.ANY_URI);
relative = (AnyURIValue) item;
} catch (final XPathException e) {
throw new XPathException(this, ErrorCodes.FORG0002, "invalid argument to fn:resolve-uri(): " + e.getMessage(), seq, e);
}
URI relativeURI;
URI baseURI;
try {
relativeURI = new URI(relative.getStringValue());
baseURI = new URI(base.getStringValue());
} catch (final URISyntaxException e) {
throw new XPathException(this, ErrorCodes.FORG0009, "unable to resolve a relative URI against a base URI in fn:resolve-uri(): " + e.getMessage(), null, e);
}
if (relativeURI.isAbsolute()) {
result = relative;
} else {
result = new AnyURIValue(baseURI.resolve(relativeURI));
}
}
if (context.getProfiler().isEnabled()) {
context.getProfiler().end(this, "", result);
}
return result;
}
use of org.exist.xquery.value.Item in project exist by eXist-db.
the class FunSort method sort.
private Sequence sort(Sequence seq, ArrayList<Sequence> keys, Collator collator) throws XPathException {
final Holder<XPathException> exception = new Holder<>();
// preparing
final int size = seq.getItemCount();
final Integer[] order = new Integer[size];
for (int i = 0; i < size; i++) order[i] = i;
// sorting
try {
Arrays.sort(order, (i1, i2) -> {
Sequence seq1 = keys.get(i1);
Sequence seq2 = keys.get(i2);
int size1 = seq1.getItemCount();
int size2 = seq2.getItemCount();
int minSize = Math.min(size1, size2);
if (size1 == 0) {
return -size2;
}
for (int pos = 0; pos < minSize; pos++) {
Item item1 = seq1.itemAt(pos);
Item item2 = seq2.itemAt(pos);
// int res;
// if (item1 instanceof org.exist.dom.memtree.NodeImpl && (!(item2 instanceof org.exist.dom.memtree.NodeImpl))) {
// res = Constants.INFERIOR;
// } else if (item1 instanceof Comparable && item2 instanceof Comparable) {
// res = ((Comparable) item1).compareTo(item2);
// } else {
// res = Constants.INFERIOR;
// }
int res = Constants.EQUAL;
if (FunDeepEqual.deepEquals(item1, item2, collator)) {
continue;
}
if (Type.subTypeOfUnion(item1.getType(), Type.NUMBER) && ((NumericValue) item1).isNaN()) {
res = Constants.INFERIOR;
} else if (Type.subTypeOf(item1.getType(), Type.STRING) && Type.subTypeOf(item2.getType(), Type.STRING)) {
try {
res = Collations.compare(collator, item1.getStringValue(), item2.getStringValue());
} catch (XPathException e) {
exception.set(e);
}
} else if (item1 instanceof AtomicValue && item2 instanceof AtomicValue) {
try {
// throw type error if values cannot be compared with lt
ValueComparison.compareAtomic(collator, (AtomicValue) item1, (AtomicValue) item2, Constants.StringTruncationOperator.NONE, Constants.Comparison.LT);
res = ((AtomicValue) item1).compareTo(collator, (AtomicValue) item2);
} catch (XPathException e) {
exception.set(e);
throw new IllegalArgumentException();
}
// } else if (item1 instanceof Comparable && item2 instanceof Comparable) {
// res = ((Comparable) item1).compareTo(item2);
} else {
res = Constants.INFERIOR;
}
if (res != Constants.EQUAL) {
return res;
}
}
return (size1 - size2);
});
} catch (IllegalArgumentException e) {
if (exception.get() != null) {
throw new XPathException(FunSort.this, ErrorCodes.XPTY0004, exception.get());
} else {
throw new XPathException(FunSort.this, ErrorCodes.XPTY0004, e.getMessage());
}
}
// form final sequence
final ValueSequence result = new ValueSequence(seq.getItemCount());
result.keepUnOrdered(true);
for (int i = 0; i < size; i++) {
result.add(seq.itemAt(order[i]));
}
return result;
}
Aggregations