Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand expansion map to support calling when a relative IRI is detected #452

Merged
merged 16 commits into from
Jun 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 92 additions & 9 deletions lib/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -1041,19 +1041,102 @@ function _expandIri(activeCtx, value, relativeTo, localCtx, defined, options) {
}
}

// prepend vocab
if(relativeTo.vocab && '@vocab' in activeCtx) {
return activeCtx['@vocab'] + value;
// A flag that captures whether the iri being expanded is
// the value for an @type
let typeExpansion = false;

if(options !== undefined && options.typeExpansion !== undefined) {
typeExpansion = options.typeExpansion;
}

// prepend base
if(relativeTo.base && '@base' in activeCtx) {
if(activeCtx['@base']) {
// The null case preserves value as potentially relative
return prependBase(prependBase(options.base, activeCtx['@base']), value);
if(relativeTo.vocab && '@vocab' in activeCtx) {
// prepend vocab
const prependedResult = activeCtx['@vocab'] + value;
let expansionMapResult = undefined;
if(options && options.expansionMap) {
// if we are about to expand the value by prepending
// @vocab then call the expansion map to inform
// interested callers that this is occurring

// TODO: use `await` to support async
expansionMapResult = options.expansionMap({
prependedIri: {
type: '@vocab',
vocab: activeCtx['@vocab'],
value,
result: prependedResult,
typeExpansion,
},
activeCtx,
options
});

}
if(expansionMapResult !== undefined) {
value = expansionMapResult;
} else {
// the null case preserves value as potentially relative
value = prependedResult;
}
} else if(relativeTo.base) {
return prependBase(options.base, value);
// prepend base
let prependedResult;
let expansionMapResult;
let base;
if('@base' in activeCtx) {
if(activeCtx['@base']) {
base = prependBase(options.base, activeCtx['@base']);
prependedResult = prependBase(base, value);
} else {
base = activeCtx['@base'];
prependedResult = value;
}
} else {
base = options.base;
prependedResult = prependBase(options.base, value);
}
if(options && options.expansionMap) {
// if we are about to expand the value by pre-pending
// @base then call the expansion map to inform
// interested callers that this is occurring

// TODO: use `await` to support async
expansionMapResult = options.expansionMap({
prependedIri: {
dlongley marked this conversation as resolved.
Show resolved Hide resolved
type: '@base',
base,
value,
result: prependedResult,
typeExpansion,
},
activeCtx,
options
});
}
if(expansionMapResult !== undefined) {
value = expansionMapResult;
} else {
// the null case preserves value as potentially relative
value = prependedResult;
}
}

if(!_isAbsoluteIri(value) && options && options.expansionMap) {
// if the result of the expansion is not an absolute iri then
// call the expansion map to inform interested callers that
// the resulting value is a relative iri, which can result in
// it being dropped when converting to other RDF representations

// TODO: use `await` to support async
const expandedResult = options.expansionMap({
relativeIri: value,
activeCtx,
typeExpansion,
options
});
if(expandedResult !== undefined) {
value = expandedResult;
}
}

return value;
Expand Down
18 changes: 14 additions & 4 deletions lib/expand.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ api.expand = async ({
typeScopedContext = null,
expansionMap = () => undefined
}) => {

// add expansion map to the processing options
options = {...options, expansionMap};

tplooker marked this conversation as resolved.
Show resolved Hide resolved
// nothing to expand
if(element === null || element === undefined) {
return null;
Expand Down Expand Up @@ -420,11 +424,14 @@ async function _expandObject({
const nests = [];
let unexpandedValue;

// add expansion map to the processing options
options = {...options, expansionMap};
dlongley marked this conversation as resolved.
Show resolved Hide resolved
tplooker marked this conversation as resolved.
Show resolved Hide resolved

// Figure out if this is the type for a JSON literal
const isJsonType = element[typeKey] &&
_expandIri(activeCtx,
(_isArray(element[typeKey]) ? element[typeKey][0] : element[typeKey]),
{vocab: true}, options) === '@json';
{vocab: true}, {...options, typeExpansion: true}) === '@json';

for(const key of keys) {
let value = element[key];
Expand Down Expand Up @@ -520,7 +527,8 @@ async function _expandObject({
value = Object.fromEntries(Object.entries(value).map(([k, v]) => [
_expandIri(typeScopedContext, k, {vocab: true}),
_asArray(v).map(vv =>
_expandIri(typeScopedContext, vv, {base: true, vocab: true})
_expandIri(typeScopedContext, vv, {base: true, vocab: true},
{...options, typeExpansion: true})
)
]));
}
Expand All @@ -530,7 +538,8 @@ async function _expandObject({
_asArray(value).map(v =>
_isString(v) ?
_expandIri(typeScopedContext, v,
{base: true, vocab: true}, options) : v),
{base: true, vocab: true},
{...options, typeExpansion: true}) : v),
{propertyIsArray: options.isFrame});
continue;
}
Expand Down Expand Up @@ -930,7 +939,8 @@ function _expandValue({activeCtx, activeProperty, value, options}) {
if(expandedProperty === '@id') {
return _expandIri(activeCtx, value, {base: true}, options);
} else if(expandedProperty === '@type') {
return _expandIri(activeCtx, value, {vocab: true, base: true}, options);
return _expandIri(activeCtx, value, {vocab: true, base: true},
{...options, typeExpansion: true});
}

// get type definition from context
Expand Down
2 changes: 1 addition & 1 deletion lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ api.parseLinkHeader = header => {
while((match = REGEX_LINK_HEADER_PARAMS.exec(params))) {
result[match[1]] = (match[2] === undefined) ? match[3] : match[2];
}
const rel = result['rel'] || '';
const rel = result.rel || '';
if(Array.isArray(rval[rel])) {
rval[rel].push(result);
} else if(rval.hasOwnProperty(rel)) {
Expand Down
Loading