« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/data/composite/wiki-data/withReverseReferenceList.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/data/composite/wiki-data/withReverseReferenceList.js')
-rw-r--r--src/data/composite/wiki-data/withReverseReferenceList.js158
1 files changed, 12 insertions, 146 deletions
diff --git a/src/data/composite/wiki-data/withReverseReferenceList.js b/src/data/composite/wiki-data/withReverseReferenceList.js
index 1f8c082f..906f5bc5 100644
--- a/src/data/composite/wiki-data/withReverseReferenceList.js
+++ b/src/data/composite/wiki-data/withReverseReferenceList.js
@@ -1,170 +1,36 @@
 // Check out the info on reverseReferenceList!
 // This is its composable form.
-//
-// This implementation uses a global cache (via WeakMap) to attempt to speed
-// up subsequent similar accesses.
-//
-// This has absolutely not been rigorously tested with altering properties of
-// data objects in a wiki data array which is reused. If a new wiki data array
-// is used, a fresh cache will always be created.
-//
-// Note that this implementation is mirrored in withReverseContributionList,
-// so any changes should be reflected there (until these are combined).
 
 import {input, templateCompositeFrom} from '#composite';
-import {stitchArrays} from '#sugar';
-
-import {exitWithoutDependency, raiseOutputWithoutDependency}
-  from '#composite/control-flow';
-import {withMappedList} from '#composite/data';
 
+import gobbleSoupyReverse from './gobbleSoupyReverse.js';
+import inputSoupyReverse from './inputSoupyReverse.js';
 import inputWikiData from './inputWikiData.js';
 
-// Mapping of reference list property to WeakMap.
-// Each WeakMap maps a wiki data array to another weak map,
-// which in turn maps each referenced thing to an array of
-// things referencing it.
-const caches = new Map();
+import withResolvedReverse from './helpers/withResolvedReverse.js';
 
 export default templateCompositeFrom({
   annotation: `withReverseReferenceList`,
 
   inputs: {
-    data: inputWikiData({allowMixedTypes: false}),
-    list: input({type: 'string'}),
+    data: inputWikiData({allowMixedTypes: true}),
+    reverse: inputSoupyReverse(),
   },
 
   outputs: ['#reverseReferenceList'],
 
   steps: () => [
-    // Common behavior --
-
-    // Early exit with an empty array if the data list isn't available.
-    exitWithoutDependency({
-      dependency: input('data'),
-      value: input.value([]),
+    gobbleSoupyReverse({
+      reverse: input('reverse'),
     }),
 
-    // Raise an empty array (don't early exit) if the data list is empty.
-    raiseOutputWithoutDependency({
-      dependency: input('data'),
-      mode: input.value('empty'),
-      output: input.value({'#reverseReferenceList': []}),
-    }),
-
-    // Check for an existing cache record which corresponds to this
-    // input('list') and input('data'). If it exists, query it for the
-    // current thing, and raise that; if it doesn't, create it, put it
-    // where it needs to be, and provide it so the next steps can fill
-    // it in.
-    {
-      dependencies: [input('list'), input('data'), input.myself()],
-
-      compute: (continuation, {
-        [input('list')]: list,
-        [input('data')]: data,
-        [input.myself()]: myself,
-      }) => {
-        if (!caches.has(list)) {
-          const cache = new WeakMap();
-          caches.set(list, cache);
-
-          const cacheRecord = new WeakMap();
-          cache.set(data, cacheRecord);
-
-          return continuation({
-            ['#cacheRecord']: cacheRecord,
-          });
-        }
-
-        const cache = caches.get(list);
-
-        if (!cache.has(data)) {
-          const cacheRecord = new WeakMap();
-          cache.set(data, cacheRecord);
+    // TODO: Check that the reverse spec returns a list.
 
-          return continuation({
-            ['#cacheRecord']: cacheRecord,
-          });
-        }
-
-        return continuation.raiseOutput({
-          ['#reverseReferenceList']:
-            cache.get(data).get(myself) ?? [],
-        });
-      },
-    },
-
-    // Unique behavior for reference lists --
-
-    {
-      dependencies: [input('list')],
-      compute: (continuation, {
-        [input('list')]: list,
-      }) => continuation({
-        ['#referenceMap']:
-          thing => thing[list],
-      }),
-    },
-
-    withMappedList({
-      list: input('data'),
-      map: '#referenceMap',
+    withResolvedReverse({
+      data: input('data'),
+      reverse: '#reverse',
     }).outputs({
-      '#mappedList': '#referencedThings',
+      '#resolvedReverse': '#reverseReferenceList',
     }),
-
-    {
-      dependencies: [input('data')],
-      compute: (continuation, {
-        [input('data')]: data,
-      }) => continuation({
-        ['#referencingThings']:
-          data,
-      }),
-    },
-
-    // Common behavior --
-
-    // Actually fill in the cache record. Since we're building up a *reverse*
-    // reference list, track connections in terms of the referenced thing.
-    // No newly-provided dependencies here since we're mutating the cache
-    // record, which is properly in store and will probably be reused in the
-    // future (and certainly in the next step).
-    {
-      dependencies: ['#cacheRecord', '#referencingThings', '#referencedThings'],
-      compute: (continuation, {
-        ['#cacheRecord']: cacheRecord,
-        ['#referencingThings']: referencingThings,
-        ['#referencedThings']: referencedThings,
-      }) => {
-        stitchArrays({
-          referencingThing: referencingThings,
-          referencedThings: referencedThings,
-        }).forEach(({referencingThing, referencedThings}) => {
-            for (const referencedThing of referencedThings) {
-              if (cacheRecord.has(referencedThing)) {
-                cacheRecord.get(referencedThing).push(referencingThing);
-              } else {
-                cacheRecord.set(referencedThing, [referencingThing]);
-              }
-            }
-          });
-
-        return continuation();
-      },
-    },
-
-    // Then just pluck out the current object from the now-filled cache record!
-    {
-      dependencies: ['#cacheRecord', input.myself()],
-      compute: (continuation, {
-        ['#cacheRecord']: cacheRecord,
-        [input.myself()]: myself,
-      }) => continuation({
-        ['#reverseReferenceList']:
-          cacheRecord.get(myself) ?? [],
-      }),
-    },
   ],
 });