Search in sources :

Example 1 with ArrayType

use of org.exist.xquery.functions.array.ArrayType in project exist by eXist-db.

the class JSON method readValue.

private static Item readValue(XQueryContext context, JsonParser parser, Item parent, String handleDuplicates) throws IOException, XPathException {
    JsonToken token;
    Item next = null;
    while ((token = parser.nextValue()) != null) {
        if (token == JsonToken.END_OBJECT || token == JsonToken.END_ARRAY) {
            return parent;
        }
        switch(token) {
            case START_OBJECT:
                next = new MapType(context, null);
                readValue(context, parser, next, handleDuplicates);
                break;
            case START_ARRAY:
                next = new ArrayType(context, Sequence.EMPTY_SEQUENCE);
                readValue(context, parser, next, handleDuplicates);
                break;
            case VALUE_FALSE:
                next = BooleanValue.FALSE;
                break;
            case VALUE_TRUE:
                next = BooleanValue.TRUE;
                break;
            case VALUE_NUMBER_FLOAT:
            case VALUE_NUMBER_INT:
                // according to spec, all numbers are converted to double
                next = new StringValue(parser.getText()).convertTo(Type.DOUBLE);
                break;
            case VALUE_NULL:
                next = null;
                break;
            default:
                next = new StringValue(parser.getText());
                break;
        }
        if (parent != null) {
            switch(parent.getType()) {
                case Type.ARRAY:
                    ((ArrayType) parent).add(next == null ? Sequence.EMPTY_SEQUENCE : next.toSequence());
                    break;
                case Type.MAP:
                    final String currentName = parser.getCurrentName();
                    if (currentName == null) {
                        throw new XPathException(ErrorCodes.FOJS0001, "Invalid JSON object");
                    }
                    final StringValue name = new StringValue(currentName);
                    final MapType map = (MapType) parent;
                    if (map.contains(name)) {
                        // handle duplicate keys
                        if (handleDuplicates.equals(OPTION_DUPLICATES_REJECT)) {
                            throw new XPathException(ErrorCodes.FOJS0003, "Duplicate key: " + currentName);
                        }
                        if (handleDuplicates.equals(OPTION_DUPLICATES_USE_LAST)) {
                            map.add(name, next == null ? Sequence.EMPTY_SEQUENCE : next.toSequence());
                        }
                    } else {
                        map.add(name, next == null ? Sequence.EMPTY_SEQUENCE : next.toSequence());
                    }
                    break;
            }
        }
    }
    return next;
}
Also used : ArrayType(org.exist.xquery.functions.array.ArrayType) JsonToken(com.fasterxml.jackson.core.JsonToken) MapType(org.exist.xquery.functions.map.MapType)

Example 2 with ArrayType

use of org.exist.xquery.functions.array.ArrayType in project exist by eXist-db.

the class FunDeepEqual method deepEquals.

public static boolean deepEquals(Item a, Item b, Collator collator) {
    try {
        if (a.getType() == Type.ARRAY || b.getType() == Type.ARRAY) {
            if (a.getType() != b.getType()) {
                return false;
            }
            final ArrayType ar = (ArrayType) a;
            final ArrayType br = (ArrayType) b;
            if (ar.getSize() != br.getSize()) {
                return false;
            }
            for (int i = 0; i < ar.getSize(); i++) {
                if (!deepEqualsSeq(ar.get(i), br.get(i), collator)) {
                    return false;
                }
            }
            return true;
        }
        if (a.getType() == Type.MAP || b.getType() == Type.MAP) {
            if (a.getType() != b.getType()) {
                return false;
            }
            final AbstractMapType amap = (AbstractMapType) a;
            final AbstractMapType bmap = (AbstractMapType) b;
            if (amap.size() != bmap.size()) {
                return false;
            }
            for (final IEntry<AtomicValue, Sequence> aentry : amap) {
                if (!bmap.contains(aentry.key())) {
                    return false;
                }
                if (!deepEqualsSeq(aentry.value(), bmap.get(aentry.key()), collator)) {
                    return false;
                }
            }
            return true;
        }
        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 {
                final AtomicValue av = (AtomicValue) a;
                final AtomicValue bv = (AtomicValue) b;
                if (Type.subTypeOfUnion(av.getType(), Type.NUMBER) && Type.subTypeOfUnion(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, StringTruncationOperator.NONE, Comparison.EQ);
            } catch (final XPathException e) {
                return false;
            }
        }
        if (a.getType() != b.getType()) {
            return false;
        }
        final NodeValue nva = (NodeValue) a;
        final NodeValue nvb = (NodeValue) b;
        if (nva == nvb) {
            return true;
        }
        try {
            // since the symbol table is ignored.
            if (nva.getImplementationType() != NodeValue.IN_MEMORY_NODE && nva.equals(nvb)) // shortcut!
            {
                return true;
            }
        } catch (final XPathException e) {
        // apparently incompatible values, do manual comparison
        }
        final Node na;
        final Node 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).getOwnerDocument();
                nb = nvb instanceof Node ? (Node) nvb : ((NodeProxy) nvb).getOwnerDocument();
                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:
                throw new RuntimeException("unexpected item type " + Type.getTypeName(a.getType()));
        }
    } catch (final XPathException e) {
        logger.error(e.getMessage());
        e.printStackTrace();
        return false;
    }
}
Also used : ArrayType(org.exist.xquery.functions.array.ArrayType) NodeValue(org.exist.xquery.value.NodeValue) XPathException(org.exist.xquery.XPathException) Node(org.w3c.dom.Node) ReferenceNode(org.exist.dom.memtree.ReferenceNode) AtomicValue(org.exist.xquery.value.AtomicValue) Sequence(org.exist.xquery.value.Sequence) NodeProxy(org.exist.dom.persistent.NodeProxy) AbstractMapType(org.exist.xquery.functions.map.AbstractMapType)

Example 3 with ArrayType

use of org.exist.xquery.functions.array.ArrayType in project exist by eXist-db.

the class FunHigherOrderFun method eval.

@Override
public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException {
    Sequence result = new ValueSequence();
    if (isCalledAs("for-each")) {
        try (final FunctionReference ref = (FunctionReference) args[1].itemAt(0)) {
            ref.analyze(cachedContextInfo);
            if (funcRefHasDifferentArity(ref, 1)) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "The supplied function (" + ref.getStringValue() + ") has " + ref.getSignature().getArgumentCount() + " arguments - expected 1");
            }
            for (final SequenceIterator i = args[0].iterate(); i.hasNext(); ) {
                final Item item = i.nextItem();
                final Sequence r = ref.evalFunction(null, null, new Sequence[] { item.toSequence() });
                result.addAll(r);
            }
        }
    } else if (isCalledAs("filter")) {
        final FunctionReference refParam;
        final Sequence seq;
        // Hack: switch parameters for backwards compatibility
        if (Type.subTypeOf(args[1].getItemType(), Type.FUNCTION_REFERENCE)) {
            refParam = (FunctionReference) args[1].itemAt(0);
            seq = args[0];
        } else {
            refParam = (FunctionReference) args[0].itemAt(0);
            seq = args[1];
        }
        try (final FunctionReference ref = refParam) {
            ref.analyze(cachedContextInfo);
            if (funcRefHasDifferentArity(ref, 1)) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "The supplied function (" + ref.getStringValue() + ") has " + ref.getSignature().getArgumentCount() + " arguments - expected 1");
            }
            for (final SequenceIterator i = seq.iterate(); i.hasNext(); ) {
                final Item item = i.nextItem();
                final Sequence r = ref.evalFunction(null, null, new Sequence[] { item.toSequence() });
                // two pending tests in exist-core/src/test/xquery/xquery3/fnHigherOrderFunctions.xql
                if (r.effectiveBooleanValue()) {
                    result.add(item);
                }
            }
        }
    } else if (isCalledAs("fold-left")) {
        try (final FunctionReference ref = (FunctionReference) args[2].itemAt(0)) {
            ref.analyze(cachedContextInfo);
            if (funcRefHasDifferentArity(ref, 2)) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "The supplied function (" + ref.getStringValue() + ") has " + ref.getSignature().getArgumentCount() + " arguments - expected 2");
            }
            final Sequence seq = args[0];
            final Sequence zero = args[1];
            result = foldLeft(ref, zero, seq.iterate());
        }
    } else if (isCalledAs("fold-right")) {
        try (final FunctionReference ref = (FunctionReference) args[2].itemAt(0)) {
            ref.analyze(cachedContextInfo);
            if (funcRefHasDifferentArity(ref, 2)) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "The supplied function (" + ref.getStringValue() + ") has " + ref.getSignature().getArgumentCount() + " arguments - expected 2");
            }
            final Sequence zero = args[1];
            final Sequence seq = args[0];
            if (seq instanceof ValueSequence) {
                result = foldRightNonRecursive(ref, zero, ((ValueSequence) seq).iterateInReverse());
            } else if (seq instanceof RangeSequence) {
                result = foldRightNonRecursive(ref, zero, ((RangeSequence) seq).iterateInReverse());
            } else {
                result = foldRight(ref, zero, seq);
            }
        }
    } else if (isCalledAs("for-each-pair")) {
        try (final FunctionReference ref = (FunctionReference) args[2].itemAt(0)) {
            ref.analyze(cachedContextInfo);
            if (funcRefHasDifferentArity(ref, 2)) {
                throw new XPathException(this, ErrorCodes.XPTY0004, "The supplied function (" + ref.getStringValue() + ") has " + ref.getSignature().getArgumentCount() + " arguments - expected 2");
            }
            final SequenceIterator i1 = args[0].iterate();
            final SequenceIterator i2 = args[1].iterate();
            while (i1.hasNext() && i2.hasNext()) {
                final Sequence r = ref.evalFunction(null, null, new Sequence[] { i1.nextItem().toSequence(), i2.nextItem().toSequence() });
                result.addAll(r);
            }
        }
    } else if (isCalledAs("apply")) {
        try (final FunctionReference ref = (FunctionReference) args[0].itemAt(0)) {
            ref.analyze(cachedContextInfo);
            final ArrayType array = (ArrayType) args[1].itemAt(0);
            if (funcRefHasDifferentArity(ref, array.getSize())) {
                throw new XPathException(this, ErrorCodes.FOAP0001, "Number of arguments supplied to fn:apply does not match function signature. Expected: " + ref.getSignature().getArgumentCount() + ", got: " + array.getSize());
            }
            final Sequence[] fargs = array.toArray();
            return ref.evalFunction(null, null, fargs);
        }
    }
    return result;
}
Also used : ArrayType(org.exist.xquery.functions.array.ArrayType) Item(org.exist.xquery.value.Item) SequenceIterator(org.exist.xquery.value.SequenceIterator) ValueSequence(org.exist.xquery.value.ValueSequence) FunctionReference(org.exist.xquery.value.FunctionReference) ValueSequence(org.exist.xquery.value.ValueSequence) Sequence(org.exist.xquery.value.Sequence)

Aggregations

ArrayType (org.exist.xquery.functions.array.ArrayType)3 Sequence (org.exist.xquery.value.Sequence)2 JsonToken (com.fasterxml.jackson.core.JsonToken)1 ReferenceNode (org.exist.dom.memtree.ReferenceNode)1 NodeProxy (org.exist.dom.persistent.NodeProxy)1 XPathException (org.exist.xquery.XPathException)1 AbstractMapType (org.exist.xquery.functions.map.AbstractMapType)1 MapType (org.exist.xquery.functions.map.MapType)1 AtomicValue (org.exist.xquery.value.AtomicValue)1 FunctionReference (org.exist.xquery.value.FunctionReference)1 Item (org.exist.xquery.value.Item)1 NodeValue (org.exist.xquery.value.NodeValue)1 SequenceIterator (org.exist.xquery.value.SequenceIterator)1 ValueSequence (org.exist.xquery.value.ValueSequence)1 Node (org.w3c.dom.Node)1