Implement descendant-objects and descendant-pairs
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/functions/builtin-functions.xml b/vxquery-core/src/main/java/org/apache/vxquery/functions/builtin-functions.xml
index 1cbda7a..93f2cb3 100644
--- a/vxquery-core/src/main/java/org/apache/vxquery/functions/builtin-functions.xml
+++ b/vxquery-core/src/main/java/org/apache/vxquery/functions/builtin-functions.xml
@@ -1220,10 +1220,25 @@
         <return type="item()*"/>
         <runtime type="scalar" class="org.apache.vxquery.runtime.functions.json.LibjnFlattenScalarEvaluatorFactory"/>
     </function>
+
     <!-- libjn:values($sequence as item()*) as item()* -->
     <function name="libjn:values">
         <param name="sequence" type="item()*"/>
         <return type="item()*"/>
         <runtime type="scalar" class="org.apache.vxquery.runtime.functions.json.LibjnValuesScalarEvaluatorFactory"/>
     </function>
+
+    <!-- libjn:descendant-objects($sequence as item()*) as object()* -->
+    <function name="libjn:descendant-objects">
+        <param name="sequence" type="item()*"/>
+        <return type="object()*"/>
+        <runtime type="scalar" class="org.apache.vxquery.runtime.functions.json.LibjnDescendantObjectsScalarEvaluatorFactory"/>
+    </function>
+
+    <!-- libjn:descendant-pairs($sequence as item()*) object()* -->
+    <function name="libjn:descendant-pairs">
+        <param name="sequence" type="item()*"/>
+        <return type="object()*"/>
+        <runtime type="scalar" class="org.apache.vxquery.runtime.functions.json.LibjnDescendantPairsScalarEvaluatorFactory"/>
+    </function>
 </functions>
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/AbstractLibjnDescendantScalarEvaluator.java b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/AbstractLibjnDescendantScalarEvaluator.java
new file mode 100644
index 0000000..7083291
--- /dev/null
+++ b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/AbstractLibjnDescendantScalarEvaluator.java
@@ -0,0 +1,120 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.vxquery.runtime.functions.json;
+
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.UTF8StringPointable;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+import org.apache.vxquery.datamodel.accessors.SequencePointable;
+import org.apache.vxquery.datamodel.accessors.TaggedValuePointable;
+import org.apache.vxquery.datamodel.accessors.jsonitem.ArrayPointable;
+import org.apache.vxquery.datamodel.accessors.jsonitem.ObjectPointable;
+import org.apache.vxquery.datamodel.builders.sequence.SequenceBuilder;
+import org.apache.vxquery.datamodel.values.ValueTag;
+import org.apache.vxquery.exceptions.ErrorCode;
+import org.apache.vxquery.exceptions.SystemException;
+import org.apache.vxquery.runtime.functions.base.AbstractTaggedValueArgumentScalarEvaluator;
+
+import java.io.IOException;
+
+public abstract class AbstractLibjnDescendantScalarEvaluator extends AbstractTaggedValueArgumentScalarEvaluator {
+    protected final IHyracksTaskContext ctx;
+    protected final UTF8StringPointable stringp;
+    protected final SequencePointable sp, sp1;
+    protected final SequenceBuilder sb;
+    protected final ArrayBackedValueStorage abvs;
+
+    public AbstractLibjnDescendantScalarEvaluator(IHyracksTaskContext ctx, IScalarEvaluator[] args) {
+        super(args);
+        this.ctx = ctx;
+        stringp = (UTF8StringPointable) UTF8StringPointable.FACTORY.createPointable();
+        sp = (SequencePointable) SequencePointable.FACTORY.createPointable();
+        sp1 = (SequencePointable) SequencePointable.FACTORY.createPointable();
+        sb = new SequenceBuilder();
+        abvs = new ArrayBackedValueStorage();
+    }
+
+    @Override
+    protected void evaluate(TaggedValuePointable[] args, IPointable result) throws SystemException {
+        try {
+            abvs.reset();
+            sb.reset(abvs);
+            TaggedValuePointable tvp = args[0];
+            if (tvp.getTag() == ValueTag.SEQUENCE_TAG) {
+                TaggedValuePointable tempTvp = ppool.takeOne(TaggedValuePointable.class);
+                tvp.getValue(sp);
+                int size = sp.getEntryCount();
+                for (int i = 0; i < size; i++) {
+                    sp.getEntry(i, tempTvp);
+                    process(tempTvp);
+                }
+                ppool.giveBack(tempTvp);
+            } else {
+                process(tvp);
+            }
+            sb.finish();
+            result.set(abvs);
+        } catch (IOException e) {
+            throw new SystemException(ErrorCode.SYSE0001, e);
+        }
+    }
+
+    protected void processObject(TaggedValuePointable tvp) throws IOException {
+        TaggedValuePointable tempTvp = ppool.takeOne(TaggedValuePointable.class);
+        ObjectPointable tempOp = ppool.takeOne(ObjectPointable.class);
+        tvp.getValue(tempOp);
+        tempOp.getKeys(tempTvp);
+        if (tempTvp.getTag() == ValueTag.XS_STRING_TAG) {
+            processPair(tempTvp, tempOp);
+            process(tempTvp);
+        } else if (tempTvp.getTag() == ValueTag.SEQUENCE_TAG) {
+            tempTvp.getValue(sp1);
+            int size = sp1.getEntryCount();
+            for (int i = 0; i < size; i++) {
+                sp1.getEntry(i, tempTvp);
+                processPair(tempTvp, tempOp);
+                process(tempTvp);
+            }
+        }
+        ppool.giveBack(tempOp);
+        ppool.giveBack(tempTvp);
+    }
+
+    protected abstract void processPair(TaggedValuePointable tempTvp, ObjectPointable tempOp) throws IOException;
+
+    protected void process(TaggedValuePointable tvp) throws IOException {
+        if (tvp.getTag() == ValueTag.OBJECT_TAG) {
+            processObject(tvp);
+        } else if (tvp.getTag() == ValueTag.ARRAY_TAG) {
+            processArray(tvp);
+        }
+    }
+
+    protected void processArray(TaggedValuePointable tvp) throws IOException {
+        ArrayPointable ap = ppool.takeOne(ArrayPointable.class);
+        tvp.getValue(ap);
+        TaggedValuePointable tempTvp = ppool.takeOne(TaggedValuePointable.class);
+        for (int i = 0; i < ap.getEntryCount(); i++) {
+            ap.getEntry(i, tempTvp);
+            process(tempTvp);
+        }
+        ppool.giveBack(ap);
+        ppool.giveBack(tempTvp);
+    }
+}
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/LibjnDescendantObjectsScalarEvaluator.java b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/LibjnDescendantObjectsScalarEvaluator.java
new file mode 100644
index 0000000..898f596
--- /dev/null
+++ b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/LibjnDescendantObjectsScalarEvaluator.java
@@ -0,0 +1,43 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.vxquery.runtime.functions.json;
+
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.vxquery.datamodel.accessors.TaggedValuePointable;
+import org.apache.vxquery.datamodel.accessors.jsonitem.ObjectPointable;
+
+import java.io.IOException;
+
+public class LibjnDescendantObjectsScalarEvaluator extends AbstractLibjnDescendantScalarEvaluator {
+
+    public LibjnDescendantObjectsScalarEvaluator(IHyracksTaskContext ctx, IScalarEvaluator[] args) {
+        super(ctx, args);
+    }
+
+    @Override
+    protected void processPair(TaggedValuePointable tvp, ObjectPointable op) {
+        tvp.getValue(stringp);
+        op.getValue(stringp, tvp);
+    }
+
+    @Override
+    protected void processObject(TaggedValuePointable tvp) throws IOException {
+        sb.addItem(tvp);
+        super.processObject(tvp);
+    }
+}
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/LibjnDescendantObjectsScalarEvaluatorFactory.java b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/LibjnDescendantObjectsScalarEvaluatorFactory.java
new file mode 100644
index 0000000..f905493
--- /dev/null
+++ b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/LibjnDescendantObjectsScalarEvaluatorFactory.java
@@ -0,0 +1,39 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.vxquery.runtime.functions.json;
+
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.vxquery.runtime.functions.base.AbstractTaggedValueArgumentScalarEvaluatorFactory;
+
+public class LibjnDescendantObjectsScalarEvaluatorFactory extends AbstractTaggedValueArgumentScalarEvaluatorFactory {
+
+    private static final long serialVersionUID = 1L;
+
+    public LibjnDescendantObjectsScalarEvaluatorFactory(IScalarEvaluatorFactory[] args) {
+        super(args);
+    }
+
+    @Override
+    protected IScalarEvaluator createEvaluator(IHyracksTaskContext ctx, IScalarEvaluator[] args)
+            throws AlgebricksException {
+        return new LibjnDescendantObjectsScalarEvaluator(ctx, args);
+    }
+
+}
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/LibjnDescendantPairsScalarEvaluator.java b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/LibjnDescendantPairsScalarEvaluator.java
new file mode 100644
index 0000000..12f2c47
--- /dev/null
+++ b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/LibjnDescendantPairsScalarEvaluator.java
@@ -0,0 +1,49 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.vxquery.runtime.functions.json;
+
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+import org.apache.vxquery.datamodel.accessors.TaggedValuePointable;
+import org.apache.vxquery.datamodel.accessors.jsonitem.ObjectPointable;
+import org.apache.vxquery.datamodel.builders.jsonitem.ObjectBuilder;
+
+import java.io.IOException;
+
+public class LibjnDescendantPairsScalarEvaluator extends AbstractLibjnDescendantScalarEvaluator {
+
+    private final ObjectBuilder ob;
+    private final ArrayBackedValueStorage abvs1;
+
+    public LibjnDescendantPairsScalarEvaluator(IHyracksTaskContext ctx, IScalarEvaluator[] args) {
+        super(ctx, args);
+        abvs1 = new ArrayBackedValueStorage();
+        ob = new ObjectBuilder();
+    }
+
+    @Override
+    protected void processPair(TaggedValuePointable tvp, ObjectPointable op) throws IOException {
+        abvs1.reset();
+        ob.reset(abvs1);
+        tvp.getValue(stringp);
+        op.getValue(stringp, tvp);
+        ob.addItem(stringp, tvp);
+        ob.finish();
+        sb.addItem(abvs1);
+    }
+}
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/LibjnDescendantPairsScalarEvaluatorFactory.java b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/LibjnDescendantPairsScalarEvaluatorFactory.java
new file mode 100644
index 0000000..b2bfa9d
--- /dev/null
+++ b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/json/LibjnDescendantPairsScalarEvaluatorFactory.java
@@ -0,0 +1,39 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.vxquery.runtime.functions.json;
+
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.vxquery.runtime.functions.base.AbstractTaggedValueArgumentScalarEvaluatorFactory;
+
+public class LibjnDescendantPairsScalarEvaluatorFactory extends AbstractTaggedValueArgumentScalarEvaluatorFactory {
+
+    private static final long serialVersionUID = 1L;
+
+    public LibjnDescendantPairsScalarEvaluatorFactory(IScalarEvaluatorFactory[] args) {
+        super(args);
+    }
+
+    @Override
+    protected IScalarEvaluator createEvaluator(IHyracksTaskContext ctx, IScalarEvaluator[] args)
+            throws AlgebricksException {
+        return new LibjnDescendantPairsScalarEvaluator(ctx, args);
+    }
+
+}
diff --git a/vxquery-xtest/src/test/resources/ExpectedTestResults/Json/Libraries/descendant_objects.txt b/vxquery-xtest/src/test/resources/ExpectedTestResults/Json/Libraries/descendant_objects.txt
new file mode 100644
index 0000000..fb50329
--- /dev/null
+++ b/vxquery-xtest/src/test/resources/ExpectedTestResults/Json/Libraries/descendant_objects.txt
@@ -0,0 +1,5 @@
+{"foo":{"bar":[1,2]}}
+{"bar":[1,2]}
+{"foo":"bar","bar":"foo","array":["x",{"name":"riyafa","key":"value"},122,{"xy":123}]}
+{"name":"riyafa","key":"value"}
+{"xy":123}
\ No newline at end of file
diff --git a/vxquery-xtest/src/test/resources/ExpectedTestResults/Json/Libraries/descendant_pairs.txt b/vxquery-xtest/src/test/resources/ExpectedTestResults/Json/Libraries/descendant_pairs.txt
new file mode 100644
index 0000000..211a80a
--- /dev/null
+++ b/vxquery-xtest/src/test/resources/ExpectedTestResults/Json/Libraries/descendant_pairs.txt
@@ -0,0 +1,4 @@
+{"foo":{"bar":[1,2]}}
+{"bar":[1,2]}
+{"foo":"bar"}
+{"bar":"foo"}
\ No newline at end of file
diff --git a/vxquery-xtest/src/test/resources/Queries/XQuery/Json/Libraries/descendant_objects.xq b/vxquery-xtest/src/test/resources/Queries/XQuery/Json/Libraries/descendant_objects.xq
new file mode 100644
index 0000000..7cd1b14
--- /dev/null
+++ b/vxquery-xtest/src/test/resources/Queries/XQuery/Json/Libraries/descendant_objects.xq
@@ -0,0 +1,56 @@
+(: Licensed to the Apache Software Foundation (ASF) under one
+   or more contributor license agreements.  See the NOTICE file
+   distributed with this work for additional information
+   regarding copyright ownership.  The ASF licenses this file
+   to you under the Apache License, Version 2.0 (the
+   "License"); you may not use this file except in compliance
+   with the License.  You may obtain a copy of the License at
+   
+     http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing,
+   software distributed under the License is distributed on an
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, either express or implied.  See the License for the
+   specific language governing permissions and limitations
+   under the License. :)
+
+(: JSONiq libjn:descendant_objects :)
+libjn:descendant-objects(
+    (
+        {
+            "foo":{
+                "bar":[
+                    1,
+                    2
+                ]
+            }
+        },
+        [
+            [
+                {
+                    "foo":"bar",
+                    "bar":"foo",
+                    "array":[
+                        "x",
+                        {
+                            "name":"riyafa",
+                            "key":"value"
+                        },
+                        122,
+                        {
+                            "xy":123
+                        }
+                    ]
+                }
+            ]
+        ],
+        true(),
+        1,
+        jn:null()
+    )
+),
+
+libjn:descendant-objects([1, 2, 3]),
+
+libjn:descendant-objects(null)
diff --git a/vxquery-xtest/src/test/resources/Queries/XQuery/Json/Libraries/descendant_pairs.xq b/vxquery-xtest/src/test/resources/Queries/XQuery/Json/Libraries/descendant_pairs.xq
new file mode 100644
index 0000000..91d2124
--- /dev/null
+++ b/vxquery-xtest/src/test/resources/Queries/XQuery/Json/Libraries/descendant_pairs.xq
@@ -0,0 +1,27 @@
+(: Licensed to the Apache Software Foundation (ASF) under one
+   or more contributor license agreements.  See the NOTICE file
+   distributed with this work for additional information
+   regarding copyright ownership.  The ASF licenses this file
+   to you under the Apache License, Version 2.0 (the
+   "License"); you may not use this file except in compliance
+   with the License.  You may obtain a copy of the License at
+   
+     http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing,
+   software distributed under the License is distributed on an
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, either express or implied.  See the License for the
+   specific language governing permissions and limitations
+   under the License. :)
+
+(: JSONiq libjn:descendant_pairs :)
+libjn:descendant-pairs(
+    (
+        { "foo" : { "bar" : [ 1, 2 ] } },
+        [ [ { "foo" : "bar", "bar" : "foo" } ] ],
+        true(),
+        1,
+        jn:null()
+    )
+)
diff --git a/vxquery-xtest/src/test/resources/cat/LibrariesInJSONiq.xml b/vxquery-xtest/src/test/resources/cat/LibrariesInJSONiq.xml
index 4de12e4..fcd0eac 100644
--- a/vxquery-xtest/src/test/resources/cat/LibrariesInJSONiq.xml
+++ b/vxquery-xtest/src/test/resources/cat/LibrariesInJSONiq.xml
@@ -40,9 +40,20 @@
       <query name="flatten" date="2016-07-20"/>
       <output-file compare="Text">flatten.txt</output-file>
    </test-case>
+
     <test-case name="values" FilePath="Json/Libraries/" Creator="Riyafa Abdul Hameed">
         <description>Json Libraries.</description>
         <query name="values" date="2016-07-31"/>
         <output-file compare="Text">values.txt</output-file>
     </test-case>
+    <test-case name="descendant_objects" FilePath="Json/Libraries/" Creator="Riyafa Abdul Hameed">
+        <description>Json Libraries.</description>
+        <query name="descendant_objects" date="2016-07-28"/>
+        <output-file compare="Text">descendant_objects.txt</output-file>
+    </test-case>
+    <test-case name="descendant_pairs" FilePath="Json/Libraries/" Creator="Riyafa Abdul Hameed">
+        <description>Json Libraries.</description>
+        <query name="descendant_pairs" date="2016-07-29"/>
+        <output-file compare="Text">descendant_pairs.txt</output-file>
+    </test-case>
 </test-group>