From b6a1ef18c2f701d4332c766dda84a7ca768511dd Mon Sep 17 00:00:00 2001 From: Bruce Herr II Date: Wed, 27 Sep 2023 20:06:15 -0400 Subject: [PATCH] Added support for graph digital objects --- src/enrichment/enrich-graph.js | 80 ++++++++++++++++++++++++++++ src/enrichment/enrich.js | 5 ++ src/normalization/normalize-graph.js | 33 ++++++++++++ src/normalization/normalize.js | 5 ++ 4 files changed, 123 insertions(+) create mode 100644 src/enrichment/enrich-graph.js create mode 100644 src/normalization/normalize-graph.js diff --git a/src/enrichment/enrich-graph.js b/src/enrichment/enrich-graph.js new file mode 100644 index 0000000..0584b70 --- /dev/null +++ b/src/enrichment/enrich-graph.js @@ -0,0 +1,80 @@ +import { existsSync, readFileSync } from 'fs'; +import { load } from 'js-yaml'; +import { resolve } from 'path'; +import { error, info } from '../utils/logging.js'; +import { convert, merge } from '../utils/robot.js'; +import { cleanTemporaryFiles, convertNormalizedDataToOwl, convertNormalizedMetadataToRdf, logOutput } from './utils.js'; + +export function enrichGraphMetadata(context) { + const { selectedDigitalObject: obj } = context; + const normalizedPath = resolve(obj.path, 'normalized/normalized-metadata.yaml'); + const enrichedPath = resolve(obj.path, 'enriched/enriched-metadata.ttl'); + convertNormalizedMetadataToRdf(context, normalizedPath, enrichedPath, 'basic'); +} + +export function enrichGraphData(context) { + try { + const { selectedDigitalObject: obj } = context; + + const normalizedPath = resolve(obj.path, 'normalized/normalized.yaml'); + const baseGraphPath = resolve(obj.path, 'enriched/base-input.ttl'); + convertNormalizedDataToOwl(context, normalizedPath, baseGraphPath, 'basic'); + logOutput(baseGraphPath); + + info(`Reading data: ${normalizedPath}`); + const digitalObjects = load(readFileSync(normalizedPath))['data']; + + info('Validating digital objects in the graph...'); + validateGraph(context, digitalObjects); + + const toMerge = [baseGraphPath]; + for (const inputRdfFile of digitalObjects) { + const inputRdf = resolve(obj.path, 'raw', inputRdfFile); + const extension = inputRdfFile.split('.').slice(-1)[0]; + if (extension === 'ttl') { + toMerge.push(inputRdf); + } else { + const outputTtl = resolve(obj.path, 'enriched', inputRdfFile + '.ttl'); + convert(inputRdf, outputTtl, 'ttl'); + toMerge.push(outputTtl); + } + } + + const enrichedMergePath = resolve(obj.path, 'enriched/enriched-merge.owl'); + merge(toMerge, enrichedMergePath); + logOutput(enrichedMergePath); + + const enrichedPath = resolve(obj.path, 'enriched/enriched.ttl'); + info(`Creating graph: ${enrichedPath}`); + convert(enrichedMergePath, enrichedPath, 'ttl'); + + info('Optimizing graph...') + const redundantPath = resolve(obj.path, 'enriched/redundant.ttl'); + runCompleteClosure(enrichedPath, redundantPath); + logOutput(redundantPath); + + } catch (e) { + error(e); + } finally { + // Clean up + info('Cleaning up temporary files.'); + cleanTemporaryFiles(context); + info('Done.'); + } +} + +function validateGraph(context, data) { + const { path } = context.selectedDigitalObject; + let isValid = true; + if (!context.skipValidation) { + for (const collectedObj of data) { + if (!existsSync(resolve(path, 'raw', collectedObj))) { + error(`${collectedObj} does not exist or is invalid`); + isValid = false; + } + } + } + if (!isValid) { + throw new Error(`Cannot enrich ${obj.doString} until all referenced datatable items are found.`); + } +} diff --git a/src/enrichment/enrich.js b/src/enrichment/enrich.js index 6e3dde2..8fab4d3 100644 --- a/src/enrichment/enrich.js +++ b/src/enrichment/enrich.js @@ -5,6 +5,7 @@ import { enrich2dFtuData, enrich2dFtuMetadata } from './enrich-2d-ftu.js'; import { enrichAsctbData, enrichAsctbMetadata } from './enrich-asct-b.js'; import { enrichBasicData, enrichBasicMetadata } from './enrich-basic.js'; import { enrichCollectionData, enrichCollectionMetadata } from './enrich-collection.js'; +import { enrichGraphData, enrichGraphMetadata } from './enrich-graph.js'; import { enrichRefOrganData, enrichRefOrganMetadata } from './enrich-ref-organ.js'; export function enrich(context) { @@ -29,6 +30,10 @@ export function enrich(context) { enrichCollectionMetadata(context); enrichCollectionData(context); break; + case 'graph': + enrichGraphMetadata(context); + enrichGraphData(context); + break; default: warning(`"${obj.type}" digital object type is using basic processing.`); enrichBasicMetadata(context); diff --git a/src/normalization/normalize-graph.js b/src/normalization/normalize-graph.js new file mode 100644 index 0000000..0fde4f3 --- /dev/null +++ b/src/normalization/normalize-graph.js @@ -0,0 +1,33 @@ +import { existsSync } from 'fs'; +import { resolve } from 'path'; +import { error } from '../utils/logging.js'; +import { normalizeMetadata, readMetadata, writeNormalizedData, writeNormalizedMetadata } from './utils.js'; + +export function normalizeGraphMetadata(context) { + const rawMetadata = readMetadata(context); + const normalizedMetadata = normalizeMetadata(context, rawMetadata); + writeNormalizedMetadata(context, normalizedMetadata); +} + +export function normalizeGraphData(context) { + const metadata = readMetadata(context); + const data = metadata.datatable; + checkGraphItems(context, data); + writeNormalizedData(context, data); +} + +function checkGraphItems(context, data) { + const { path } = context.selectedDigitalObject; + let isValid = true; + if (!context.skipValidation) { + for (const collectedObj of data) { + if (!existsSync(resolve(path, 'raw', collectedObj))) { + error(`${collectedObj} does not exist or is invalid`); + isValid = false; + } + } + } + if (!isValid) { + throw new Error(`Cannot normalize ${obj.doString} until all referenced datatable items are found.`); + } +} diff --git a/src/normalization/normalize.js b/src/normalization/normalize.js index c3c7bbf..be49051 100644 --- a/src/normalization/normalize.js +++ b/src/normalization/normalize.js @@ -6,6 +6,7 @@ import { normalize2dFtuData, normalize2dFtuMetadata } from './normalize-2d-ftu.j import { normalizeAsctbData, normalizeAsctbMetadata } from './normalize-asct-b.js'; import { normalizeBasicData, normalizeBasicMetadata } from './normalize-basic.js'; import { normalizeCollectionData, normalizeCollectionMetadata } from './normalize-collection.js'; +import { normalizeGraphData, normalizeGraphMetadata } from './normalize-graph.js'; import { normalizeRefOrganData, normalizeRefOrganMetadata } from './normalize-ref-organ.js'; export async function normalize(context) { @@ -30,6 +31,10 @@ export async function normalize(context) { normalizeCollectionMetadata(context); normalizeCollectionData(context); break; + case 'graph': + normalizeGraphMetadata(context); + normalizeGraphData(context); + break; default: warning(`"${obj.type}" digital object type is using basic processing.`); normalizeBasicMetadata(context);