UNPKG

@openactive/data-models

Version:

Data models used to drive that OpenActive validator, developer documentation, and model libraries

151 lines (136 loc) 4.72 kB
const getContext = require('./getContext'); const mergeContexts = require('./mergeContexts'); const deriveVersion = require('./helpers/deriveVersion'); const KEYWORD_REGEX = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)$/; /** * @param {string} value * @param {string} version * @param {Array<Record<string, any>>} contexts * @returns {{prefix: string|null, namespace: string|null, label: string|null, alias: string|null}} */ const getFullyQualifiedProperty = (value, version, contexts = []) => { const specVersion = deriveVersion(version); let contextsArg = contexts; // Sort the contexts if (typeof contextsArg === 'object') { if (contextsArg === null) { contextsArg = []; } else if (!(contextsArg instanceof Array)) { // @ts-ignore Object is of type 'unknown' contextsArg = [{ ...contextsArg }]; } else { contextsArg = contexts.slice(); } } else if (typeof contextsArg === 'string') { contextsArg = [contextsArg]; } else { contextsArg = []; } // Add the openactive context to the top-level contextsArg.unshift({ '@context': getContext(specVersion) }); // Return value const qualifiedProperty = { prefix: null, namespace: null, label: null, alias: null, }; let valueToTest = value; // Merge the contexts into a flat structure const mergedContext = mergeContexts(contextsArg); const urlsToCheck = []; // Check for aliases first for (const key in mergedContext) { if (Object.prototype.hasOwnProperty.call(mergedContext, key)) { const prop = mergedContext[key]; if ( typeof prop === 'string' && !key.match(/^@/) && !prop.match(/^https?:\/\//) ) { if (valueToTest === prop) { qualifiedProperty.alias = key; } else if (valueToTest === key) { qualifiedProperty.alias = key; valueToTest = prop; } } else if ( typeof prop === 'object' && typeof prop['@id'] === 'string' ) { if (valueToTest === prop['@id']) { qualifiedProperty.alias = key; } else if (valueToTest === key) { qualifiedProperty.alias = key; valueToTest = prop['@id']; } } else if ( typeof prop === 'string' && !key.match(/^@/) && prop.match(/^https?:\/\//) ) { urlsToCheck.push({ prefix: key, namespace: prop, }); } } } // Check for keywords if (valueToTest.match(KEYWORD_REGEX)) { qualifiedProperty.label = valueToTest; return qualifiedProperty; } // Then check if we've got this namespace for (const prefixMap of urlsToCheck) { if ( valueToTest.substr(0, prefixMap.namespace.length) === prefixMap.namespace ) { qualifiedProperty.prefix = prefixMap.prefix; qualifiedProperty.namespace = prefixMap.namespace; qualifiedProperty.label = valueToTest.substr(prefixMap.namespace.length); // Late check for an alias... if ( typeof mergedContext[qualifiedProperty.label] !== 'undefined' && ( mergedContext[qualifiedProperty.label] === `${qualifiedProperty.prefix}:${qualifiedProperty.label}` || ( typeof mergedContext[qualifiedProperty.label] === 'object' && typeof mergedContext[qualifiedProperty.label]['@id'] === 'string' && mergedContext[qualifiedProperty.label]['@id'] === `${qualifiedProperty.prefix}:${qualifiedProperty.label}` ) ) ) { qualifiedProperty.alias = qualifiedProperty.label; } return qualifiedProperty; } if ( valueToTest.substr(0, prefixMap.prefix.length + 1) === `${prefixMap.prefix}:` ) { qualifiedProperty.prefix = prefixMap.prefix; qualifiedProperty.namespace = prefixMap.namespace; qualifiedProperty.label = valueToTest.substr(prefixMap.prefix.length + 1); return qualifiedProperty; } } // Then check if we've got a default namespace if (typeof mergedContext['@vocab'] !== 'undefined' && valueToTest.match(/^[a-zA-Z0-9_]+$/) ) { qualifiedProperty.label = valueToTest; for (const prefixMap of urlsToCheck) { if (prefixMap.namespace === mergedContext['@vocab']) { qualifiedProperty.prefix = prefixMap.prefix; qualifiedProperty.namespace = prefixMap.namespace; return qualifiedProperty; } } qualifiedProperty.prefix = null; qualifiedProperty.namespace = mergedContext['@vocab']; return qualifiedProperty; } qualifiedProperty.label = valueToTest; return qualifiedProperty; }; module.exports = getFullyQualifiedProperty;