From 7743fee10616ecf4b5f396d7a9861bc1188b6e02 Mon Sep 17 00:00:00 2001
From: Daniel Lowe <dnllowe2@gmail.com>
Date: Sat, 16 May 2020 11:44:28 -0400
Subject: [PATCH 1/2] Adds preserve order logic for fromRdf and test case

---
 lib/fromRdf.js |  7 +++--
 tests/misc.js  | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/lib/fromRdf.js b/lib/fromRdf.js
index fb3567c8..e4cf0bad 100644
--- a/lib/fromRdf.js
+++ b/lib/fromRdf.js
@@ -47,7 +47,8 @@ api.fromRDF = async (
   {
     useRdfType = false,
     useNativeTypes = false,
-    rdfDirection = null
+    rdfDirection = null,
+    preserveOrder = false,
   }
 ) => {
   const defaultGraph = {};
@@ -246,13 +247,13 @@ api.fromRDF = async (
   }
 
   const result = [];
-  const subjects = Object.keys(defaultGraph).sort();
+  const subjects = preserveOrder ? Object.keys(defaultGraph): Object.keys(defaultGraph).sort();
   for(const subject of subjects) {
     const node = defaultGraph[subject];
     if(subject in graphMap) {
       const graph = node['@graph'] = [];
       const graphObject = graphMap[subject];
-      const graphSubjects = Object.keys(graphObject).sort();
+      const graphSubjects = preserveOrder ? Object.keys(graphObject) : Object.keys(graphObject).sort();
       for(const graphSubject of graphSubjects) {
         const node = graphObject[graphSubject];
         // only add full subjects to top-level
diff --git a/tests/misc.js b/tests/misc.js
index 1c3758e0..ac004aa8 100644
--- a/tests/misc.js
+++ b/tests/misc.js
@@ -159,6 +159,80 @@ describe('other toRDF tests', () => {
       done();
     });
   });
+  it('should preserve object and property order when specified', done => {
+    const nq = `
+      <http://example.com/Subject3/Property3> <http://example.com/value> "3" <http://example.com/Subject3> .\n
+      <http://example.com/Subject3/Property1> <http://example.com/value> "1" <http://example.com/Subject3> .\n
+      <http://example.com/Subject3/Property2> <http://example.com/value> "2" <http://example.com/Subject3> .\n
+
+      <http://example.com/Subject1/Property3> <http://example.com/value> "3" <http://example.com/Subject1> .\n
+      <http://example.com/Subject1/Property1> <http://example.com/value> "1" <http://example.com/Subject1> .\n
+      <http://example.com/Subject1/Property2> <http://example.com/value> "2" <http://example.com/Subject1> .\n
+
+      <http://example.com/Subject2/Property3> <http://example.com/value> "3" <http://example.com/Subject2> .\n
+      <http://example.com/Subject2/Property1> <http://example.com/value> "1" <http://example.com/Subject2> .\n
+      <http://example.com/Subject2/Property2> <http://example.com/value> "2" <http://example.com/Subject2> .\n
+    `;
+    const p = jsonld.fromRDF(nq, {preserveOrder: true});
+    assert(p instanceof Promise);
+    p.catch(e => {
+      assert.ifError(e);
+    }).then(output => {
+      assert.deepEqual(
+        output,
+        [
+          {"@id": "http://example.com/Subject3",
+          "@graph": [
+            {
+            "@id": "http://example.com/Subject3/Property3",
+            "http://example.com/value": [{"@value": "3"}]
+            },
+            {
+              "@id": "http://example.com/Subject3/Property1",
+              "http://example.com/value": [{"@value": "1"}]
+            },
+            {
+              "@id": "http://example.com/Subject3/Property2",
+              "http://example.com/value": [{"@value": "2"}]
+            }
+          ]
+        },
+        {"@id": "http://example.com/Subject1",
+          "@graph": [
+            {
+            "@id": "http://example.com/Subject1/Property3",
+            "http://example.com/value": [{"@value": "3"}]
+            },
+            {
+              "@id": "http://example.com/Subject1/Property1",
+              "http://example.com/value": [{"@value": "1"}]
+            },
+            {
+              "@id": "http://example.com/Subject1/Property2",
+              "http://example.com/value": [{"@value": "2"}]
+            }
+          ]
+        },
+        {"@id": "http://example.com/Subject2",
+          "@graph": [
+            {
+            "@id": "http://example.com/Subject2/Property3",
+            "http://example.com/value": [{"@value": "3"}]
+            },
+            {
+              "@id": "http://example.com/Subject2/Property1",
+              "http://example.com/value": [{"@value": "1"}]
+            },
+            {
+              "@id": "http://example.com/Subject2/Property2",
+              "http://example.com/value": [{"@value": "2"}]
+            }
+          ]
+        }
+      ]);
+      done();
+    });
+  });
 });
 
 describe('other fromRDF tests', () => {

From 1c2c4618e6651cdb55ab37412cd2e523955871c3 Mon Sep 17 00:00:00 2001
From: Daniel Lowe <dnllowe2@gmail.com>
Date: Sat, 23 May 2020 14:31:46 -0400
Subject: [PATCH 2/2] Moves test to correct block

Adds test for default fromRdf ordering behavior
---
 tests/misc.js | 224 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 150 insertions(+), 74 deletions(-)

diff --git a/tests/misc.js b/tests/misc.js
index ac004aa8..5d23c441 100644
--- a/tests/misc.js
+++ b/tests/misc.js
@@ -159,80 +159,6 @@ describe('other toRDF tests', () => {
       done();
     });
   });
-  it('should preserve object and property order when specified', done => {
-    const nq = `
-      <http://example.com/Subject3/Property3> <http://example.com/value> "3" <http://example.com/Subject3> .\n
-      <http://example.com/Subject3/Property1> <http://example.com/value> "1" <http://example.com/Subject3> .\n
-      <http://example.com/Subject3/Property2> <http://example.com/value> "2" <http://example.com/Subject3> .\n
-
-      <http://example.com/Subject1/Property3> <http://example.com/value> "3" <http://example.com/Subject1> .\n
-      <http://example.com/Subject1/Property1> <http://example.com/value> "1" <http://example.com/Subject1> .\n
-      <http://example.com/Subject1/Property2> <http://example.com/value> "2" <http://example.com/Subject1> .\n
-
-      <http://example.com/Subject2/Property3> <http://example.com/value> "3" <http://example.com/Subject2> .\n
-      <http://example.com/Subject2/Property1> <http://example.com/value> "1" <http://example.com/Subject2> .\n
-      <http://example.com/Subject2/Property2> <http://example.com/value> "2" <http://example.com/Subject2> .\n
-    `;
-    const p = jsonld.fromRDF(nq, {preserveOrder: true});
-    assert(p instanceof Promise);
-    p.catch(e => {
-      assert.ifError(e);
-    }).then(output => {
-      assert.deepEqual(
-        output,
-        [
-          {"@id": "http://example.com/Subject3",
-          "@graph": [
-            {
-            "@id": "http://example.com/Subject3/Property3",
-            "http://example.com/value": [{"@value": "3"}]
-            },
-            {
-              "@id": "http://example.com/Subject3/Property1",
-              "http://example.com/value": [{"@value": "1"}]
-            },
-            {
-              "@id": "http://example.com/Subject3/Property2",
-              "http://example.com/value": [{"@value": "2"}]
-            }
-          ]
-        },
-        {"@id": "http://example.com/Subject1",
-          "@graph": [
-            {
-            "@id": "http://example.com/Subject1/Property3",
-            "http://example.com/value": [{"@value": "3"}]
-            },
-            {
-              "@id": "http://example.com/Subject1/Property1",
-              "http://example.com/value": [{"@value": "1"}]
-            },
-            {
-              "@id": "http://example.com/Subject1/Property2",
-              "http://example.com/value": [{"@value": "2"}]
-            }
-          ]
-        },
-        {"@id": "http://example.com/Subject2",
-          "@graph": [
-            {
-            "@id": "http://example.com/Subject2/Property3",
-            "http://example.com/value": [{"@value": "3"}]
-            },
-            {
-              "@id": "http://example.com/Subject2/Property1",
-              "http://example.com/value": [{"@value": "1"}]
-            },
-            {
-              "@id": "http://example.com/Subject2/Property2",
-              "http://example.com/value": [{"@value": "2"}]
-            }
-          ]
-        }
-      ]);
-      done();
-    });
-  });
 });
 
 describe('other fromRDF tests', () => {
@@ -324,6 +250,156 @@ describe('other fromRDF tests', () => {
       done();
     });
   });
+
+  it('should preserve object and property order when specified', done => {
+    const nq = `
+      <http://example.com/Subject3/Property3> <http://example.com/value> "3" <http://example.com/Subject3> .\n
+      <http://example.com/Subject3/Property1> <http://example.com/value> "1" <http://example.com/Subject3> .\n
+      <http://example.com/Subject3/Property2> <http://example.com/value> "2" <http://example.com/Subject3> .\n
+
+      <http://example.com/Subject1/Property3> <http://example.com/value> "3" <http://example.com/Subject1> .\n
+      <http://example.com/Subject1/Property1> <http://example.com/value> "1" <http://example.com/Subject1> .\n
+      <http://example.com/Subject1/Property2> <http://example.com/value> "2" <http://example.com/Subject1> .\n
+
+      <http://example.com/Subject2/Property3> <http://example.com/value> "3" <http://example.com/Subject2> .\n
+      <http://example.com/Subject2/Property1> <http://example.com/value> "1" <http://example.com/Subject2> .\n
+      <http://example.com/Subject2/Property2> <http://example.com/value> "2" <http://example.com/Subject2> .\n
+    `;
+    const p = jsonld.fromRDF(nq, {preserveOrder: true});
+    assert(p instanceof Promise);
+    p.catch(e => {
+      assert.ifError(e);
+    }).then(output => {
+      assert.deepEqual(
+        output,
+        [
+          {"@id": "http://example.com/Subject3",
+          "@graph": [
+            {
+            "@id": "http://example.com/Subject3/Property3",
+            "http://example.com/value": [{"@value": "3"}]
+            },
+            {
+              "@id": "http://example.com/Subject3/Property1",
+              "http://example.com/value": [{"@value": "1"}]
+            },
+            {
+              "@id": "http://example.com/Subject3/Property2",
+              "http://example.com/value": [{"@value": "2"}]
+            }
+          ]
+        },
+        {"@id": "http://example.com/Subject1",
+          "@graph": [
+            {
+            "@id": "http://example.com/Subject1/Property3",
+            "http://example.com/value": [{"@value": "3"}]
+            },
+            {
+              "@id": "http://example.com/Subject1/Property1",
+              "http://example.com/value": [{"@value": "1"}]
+            },
+            {
+              "@id": "http://example.com/Subject1/Property2",
+              "http://example.com/value": [{"@value": "2"}]
+            }
+          ]
+        },
+        {"@id": "http://example.com/Subject2",
+          "@graph": [
+            {
+            "@id": "http://example.com/Subject2/Property3",
+            "http://example.com/value": [{"@value": "3"}]
+            },
+            {
+              "@id": "http://example.com/Subject2/Property1",
+              "http://example.com/value": [{"@value": "1"}]
+            },
+            {
+              "@id": "http://example.com/Subject2/Property2",
+              "http://example.com/value": [{"@value": "2"}]
+            }
+          ]
+        }
+      ]);
+      done();
+    });
+  });
+
+  it('orders objects and properties by default or when specified', done => {
+    const nq = `
+      <http://example.com/Subject3/Property3> <http://example.com/value> "3" <http://example.com/Subject3> .\n
+      <http://example.com/Subject3/Property1> <http://example.com/value> "1" <http://example.com/Subject3> .\n
+      <http://example.com/Subject3/Property2> <http://example.com/value> "2" <http://example.com/Subject3> .\n
+
+      <http://example.com/Subject1/Property3> <http://example.com/value> "3" <http://example.com/Subject1> .\n
+      <http://example.com/Subject1/Property1> <http://example.com/value> "1" <http://example.com/Subject1> .\n
+      <http://example.com/Subject1/Property2> <http://example.com/value> "2" <http://example.com/Subject1> .\n
+
+      <http://example.com/Subject2/Property3> <http://example.com/value> "3" <http://example.com/Subject2> .\n
+      <http://example.com/Subject2/Property1> <http://example.com/value> "1" <http://example.com/Subject2> .\n
+      <http://example.com/Subject2/Property2> <http://example.com/value> "2" <http://example.com/Subject2> .\n
+    `;
+    const p = jsonld.fromRDF(nq);
+    assert(p instanceof Promise);
+    p.catch(e => {
+      assert.ifError(e);
+    }).then(output => {
+      assert.deepEqual(
+        output,
+        [
+          {"@id": "http://example.com/Subject1",
+          "@graph": [
+            {
+            "@id": "http://example.com/Subject1/Property1",
+            "http://example.com/value": [{"@value": "1"}]
+            },
+            {
+              "@id": "http://example.com/Subject1/Property2",
+              "http://example.com/value": [{"@value": "2"}]
+            },
+            {
+              "@id": "http://example.com/Subject1/Property3",
+              "http://example.com/value": [{"@value": "3"}]
+            }
+          ]
+        },
+        {"@id": "http://example.com/Subject2",
+          "@graph": [
+            {
+            "@id": "http://example.com/Subject2/Property1",
+            "http://example.com/value": [{"@value": "1"}]
+            },
+            {
+              "@id": "http://example.com/Subject2/Property2",
+              "http://example.com/value": [{"@value": "2"}]
+            },
+            {
+              "@id": "http://example.com/Subject2/Property3",
+              "http://example.com/value": [{"@value": "3"}]
+            }
+          ]
+        },
+        {"@id": "http://example.com/Subject3",
+          "@graph": [
+            {
+            "@id": "http://example.com/Subject3/Property1",
+            "http://example.com/value": [{"@value": "1"}]
+            },
+            {
+              "@id": "http://example.com/Subject3/Property2",
+              "http://example.com/value": [{"@value": "2"}]
+            },
+            {
+              "@id": "http://example.com/Subject3/Property3",
+              "http://example.com/value": [{"@value": "3"}]
+            }
+          ]
+        }
+      ]);
+      done();
+    });
+  });
 });
 
 describe('loading multiple levels of contexts', () => {