* 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
* ※ 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.
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"],
}
}
}
- 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;
+ }
}
}