]> Lady’s Gitweb - Etiquette/commitdiff
Allow “silent” persisting of tags
authorLady <redacted>
Mon, 29 May 2023 06:16:00 +0000 (23:16 -0700)
committerLady <redacted>
Wed, 14 Jun 2023 02:07:32 +0000 (19:07 -0700)
This simplifies the algorithm a little bit in the case that no output
is needed. Diffs are still necessary for properties with inverses.

model.js
model.test.js

index 9f7962dce8df217f77239f1ecbb730159bc34f7c..76bf615bc2aaf4a5318af3cd75ec40bde4be7894 100644 (file)
--- a/model.js
+++ b/model.js
@@ -1036,6 +1036,9 @@ class Tag {
    * serialization of a Tag Activity representing any changes, or
    * `null` if no changes were made.
    *
+   * If the second argument is `true`, the `Tag` will be persisted but
+   * no serialization will be made. This is somewhat more efficient.
+   *
    * ※ Persistence can imply side‐effects on other objects, which are
    * not noted explicitly in the activity. For example, marking a tag
    * as broader than another causes the other tag to reciprocally be
@@ -1044,17 +1047,19 @@ class Tag {
    * ※ The inverse terms `hasInCanon`, `isIncludedIn`, and `narrower`
    * will never appear in the predicates of generated activities.
    */
-  persist() {
+  persist(silent = false) {
     const system = this.#system;
     const storage = this.#storage;
     const persistedData = this.#persistedData;
     const data = this.#data;
     const diffs = {};
     for (const [key, value] of Object.entries(data)) {
-      // Iterate over each entry of the tag data and create a diff with
-      // the last persisted information.
-      if (SKIP_IN_DIFF.has(key)) {
+      // Iterate over each entry of the tag data and create a diff
+      // with the last persisted information.
+      if (SKIP_IN_DIFF.has(key) || silent && LITERAL_TERMS.has(key)) {
         // The current property is one which is skipped in diffs.
+        //
+        // In a silent persist, this includes any literal terms.
         /* do nothing */
       } else {
         // The current property should be diffed.
@@ -1130,7 +1135,7 @@ class Tag {
       this.#identifier = storage.add(this);
     }
     const persistedIdentifier = this.#identifier;
-    this.#persistedData = tagData(data); // need to clone here
+    this.#persistedData = tagData(data); // cloning here is necessary
     for (
       const [term, inverse] of [
         ["broader", "narrower"],
@@ -1166,131 +1171,138 @@ class Tag {
         }
       }
     }
-    const activity = {
-      "@context": taggingDiscoveryContext,
-      "@type": [
-        "TagActivity",
-        identifier == null ? "Create" : "Update",
-      ],
-      context: `${system.iri}`,
-      object: `${this.iri}`,
-      endTime: new Date().toISOString(),
-      ...(() => {
-        const statements = {
-          unstates: [],
-          states: [],
-        };
-        const { unstates, states } = statements;
-        if (identifier == null) {
-          // This is a Create activity.
-          states.push({ predicate: "a", object: `${this.kind}` });
-        } else {
-          // This is an Update activity.
-          /* do nothing */
-        }
-        for (
-          const [term, {
-            old: oldValues,
-            new: newValues,
-          }] of Object.entries(diffs)
-        ) {
-          // Iterate over the diffs of each term and state/unstate
-          // things as needed.
-          for (const oldValue of oldValues) {
-            // Iterate over removals and unstate them.
-            if (LITERAL_TERMS.has(term)) {
-              // This is a literal term; push the change wrapped in an
-              // object.
-              unstates.push({
-                predicate: term,
-                object: Object(oldValue) === oldValue
-                  ? { ...langString(oldValue) }
-                  : { "@value": `${oldValue}` },
-              });
-            } else {
-              // This is a named term; attempt to get its I·R·I and
-              // push it.
-              try {
-                // Attempt to resolve the value and push the change.
-                const tag = storage.get(oldValue);
-                if (!this.#isTagInStorage(tag)) {
-                  // The value did not resolve to a tag in storage.
+    if (silent) {
+      // This is a silent persist.
+      return undefined;
+    } else {
+      // This is not a silent persist; an activity needs to be
+      // generated if a change was made.
+      const activity = {
+        "@context": taggingDiscoveryContext,
+        "@type": [
+          "TagActivity",
+          identifier == null ? "Create" : "Update",
+        ],
+        context: `${system.iri}`,
+        object: `${this.iri}`,
+        endTime: new Date().toISOString(),
+        ...(() => {
+          const statements = {
+            unstates: [],
+            states: [],
+          };
+          const { unstates, states } = statements;
+          if (identifier == null) {
+            // This is a Create activity.
+            states.push({ predicate: "a", object: `${this.kind}` });
+          } else {
+            // This is an Update activity.
+            /* do nothing */
+          }
+          for (
+            const [term, {
+              old: oldValues,
+              new: newValues,
+            }] of Object.entries(diffs)
+          ) {
+            // Iterate over the diffs of each term and state/unstate
+            // things as needed.
+            for (const oldValue of oldValues) {
+              // Iterate over removals and unstate them.
+              if (LITERAL_TERMS.has(term)) {
+                // This is a literal term; push the change wrapped in an
+                // object.
+                unstates.push({
+                  predicate: term,
+                  object: Object(oldValue) === oldValue
+                    ? { ...langString(oldValue) }
+                    : { "@value": `${oldValue}` },
+                });
+              } else {
+                // This is a named term; attempt to get its I·R·I and
+                // push it.
+                try {
+                  // Attempt to resolve the value and push the change.
+                  const tag = storage.get(oldValue);
+                  if (!this.#isTagInStorage(tag)) {
+                    // The value did not resolve to a tag in storage.
+                    /* do nothing */
+                  } else {
+                    // The value resolved; push its I·R·I.
+                    unstates.push({
+                      predicate: term,
+                      object: tag.iri,
+                    });
+                  }
+                } catch {
+                  // Value resolution failed for some reason; perhaps the
+                  // tag was deleted.
                   /* do nothing */
-                } else {
-                  // The value resolved; push its I·R·I.
-                  unstates.push({
-                    predicate: term,
-                    object: tag.iri,
-                  });
                 }
-              } catch {
-                // Value resolution failed for some reason; perhaps the
-                // tag was deleted.
-                /* do nothing */
               }
             }
-          }
-          for (const newValue of newValues) {
-            // Iterate over additions and state them.
-            if (LITERAL_TERMS.has(term)) {
-              // This is a literal term; push the change wrapped in an
-              // object.
-              states.push({
-                predicate: term,
-                object: Object(newValue) === newValue
-                  ? { ...langString(newValue) }
-                  : { "@value": `${newValue}` },
-              });
-            } else {
-              // This is a named term; attempt to get its I·R·I and
-              // push it.
-              try {
-                // Attempt to resolve the value and push the change.
-                const tag = storage.get(newValue);
-                if (!this.#isTagInStorage(tag)) {
-                  // The value did not resolve to a tag in storage.
+            for (const newValue of newValues) {
+              // Iterate over additions and state them.
+              if (LITERAL_TERMS.has(term)) {
+                // This is a literal term; push the change wrapped in an
+                // object.
+                states.push({
+                  predicate: term,
+                  object: Object(newValue) === newValue
+                    ? { ...langString(newValue) }
+                    : { "@value": `${newValue}` },
+                });
+              } else {
+                // This is a named term; attempt to get its I·R·I and
+                // push it.
+                try {
+                  // Attempt to resolve the value and push the change.
+                  const tag = storage.get(newValue);
+                  if (!this.#isTagInStorage(tag)) {
+                    // The value did not resolve to a tag in storage.
+                    /* do nothing */
+                  } else {
+                    // The value resolved; push its I·R·I.
+                    states.push({
+                      predicate: term,
+                      object: tag.iri,
+                    });
+                  }
+                } catch {
+                  // Value resolution failed for some reason; perhaps the
+                  // tag was deleted.
                   /* do nothing */
-                } else {
-                  // The value resolved; push its I·R·I.
-                  states.push({
-                    predicate: term,
-                    object: tag.iri,
-                  });
                 }
-              } catch {
-                // Value resolution failed for some reason; perhaps the
-                // tag was deleted.
-                /* do nothing */
               }
             }
           }
-        }
-        if (unstates.length == 0) {
-          // Nothing was unstated.
-          delete statements.unstates;
-        } else {
-          // Things were stated.
-          /* do nothing */
-        }
-        if (states.length == 0) {
-          // Nothing was stated.
-          delete statements.states;
-        } else {
-          // Things were stated.
-          /* do nothing */
-        }
-        return statements;
-      })(),
-    };
-    if (
-      !Object.hasOwn(activity, "states") &&
-      !Object.hasOwn(activity, "unstates")
-    ) {
-      // No meaningful changes were actually persisted.
-      return null;
-    } else {
-      // There were meaningful changes persisted regarding this `Tag`.
-      return activity;
+          if (unstates.length == 0) {
+            // Nothing was unstated.
+            delete statements.unstates;
+          } else {
+            // Things were stated.
+            /* do nothing */
+          }
+          if (states.length == 0) {
+            // Nothing was stated.
+            delete statements.states;
+          } else {
+            // Things were stated.
+            /* do nothing */
+          }
+          return statements;
+        })(),
+      };
+      if (
+        !Object.hasOwn(activity, "states") &&
+        !Object.hasOwn(activity, "unstates")
+      ) {
+        // No meaningful changes were actually persisted.
+        return null;
+      } else {
+        // There were meaningful changes persisted regarding this `Tag`.
+        return activity;
+      }
     }
   }
 
index 7944238493a1e5c4da4c398252171b6487737c17..a648d4f736b8e6fb44dcb06c681c6bf739615a59 100644 (file)
@@ -849,6 +849,15 @@ describe("TagSystem", () => {
         const activity = tag.persist();
         assertStrictEquals(activity, null);
       });
+
+      it("[[Call]] returns undefined for a silent persist", () => {
+        const broader = new Tag();
+        broader.persist();
+        const tag = new Tag();
+        tag.prefLabel = "etaoin";
+        tag.addBroaderTag(broader);
+        assertStrictEquals(tag.persist(true), undefined);
+      });
     });
 
     describe("::prefLabel", () => {
This page took 0.039516 seconds and 4 git commands to generate.