Skip to content

Commit ab9b94b

Browse files
gkelloggdavidlehn
authored andcommitted
Prune blank nodes.
1 parent a6771c9 commit ab9b94b

File tree

3 files changed

+29
-45
lines changed

3 files changed

+29
-45
lines changed

lib/compact.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,12 @@ api.removePreserve = (ctx, input, options) => {
869869
// recurse through properties
870870
const graphAlias = api.compactIri({activeCtx: ctx, iri: '@graph', relativeTo: {vocab: true}});
871871
for(const prop in input) {
872+
// potentially remove the id, if it is an unreference bnode
873+
if(prop === idAlias && options.bnodesToClear.includes(input[prop])) {
874+
delete input[idAlias];
875+
continue;
876+
}
877+
872878
let result = api.removePreserve(ctx, input[prop], options);
873879
const container = _getContextValue(ctx, prop, '@container') || [];
874880
if(options.compactArrays && _isArray(result) && result.length === 1 &&

lib/frame.js

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -25,59 +25,38 @@ module.exports = api;
2525
*
2626
* @return the framed output.
2727
*/
28-
api.frameMerged = (input, frame, options) => {
28+
api.frameMergedOrDefault = (input, frame, options) => {
2929
// create framing state
3030
const state = {
3131
options: options,
32-
graph: '@merged',
32+
graph: '@default',
3333
graphMap: {'@default': {}},
3434
graphStack: [],
3535
subjectStack: [],
36-
link: {}
36+
link: {},
37+
bnodeMap: {}
3738
};
3839

3940
// produce a map of all graphs and name each bnode
4041
// FIXME: currently uses subjects from @merged graph only
4142
const issuer = new util.IdentifierIssuer('_:b');
4243
_createNodeMap(input, state.graphMap, '@default', issuer);
43-
state.graphMap['@merged'] = _mergeNodeMapGraphs(state.graphMap);
44-
state.subjects = state.graphMap['@merged'];
44+
if(options.merged) {
45+
state.graphMap['@merged'] = _mergeNodeMapGraphs(state.graphMap);
46+
state.graph = '@merged'
47+
}
48+
state.subjects = state.graphMap[state.graph];
4549

4650
// frame the subjects
4751
const framed = [];
4852
api.frame(state, Object.keys(state.subjects).sort(), frame, framed);
49-
return framed;
50-
};
5153

52-
/**
53-
* Performs JSON-LD `default` framing.
54-
* FIXME: maybe just rename frameMerged and perform selection logic in one place
55-
*
56-
* @param input the expanded JSON-LD to frame.
57-
* @param frame the expanded JSON-LD frame to use.
58-
* @param options the framing options.
59-
*
60-
* @return the framed output.
61-
*/
62-
api.frameDefault = (input, frame, options) => {
63-
// create framing state
64-
const state = {
65-
options: options,
66-
graph: '@default',
67-
graphMap: {'@default': {}},
68-
graphStack: [],
69-
subjectStack: [],
70-
link: {}
71-
};
72-
73-
// produce a map of all graphs and name each bnode
74-
const issuer = new util.IdentifierIssuer('_:b');
75-
_createNodeMap(input, state.graphMap, '@default', issuer);
76-
state.subjects = state.graphMap['@default'];
54+
// If pruning blank nodes, find those to prune
55+
if(options.pruneBlankNodeIdentifiers) {
56+
// remove all blank nodes appearing only once, done in compaction
57+
options.bnodesToClear = Object.keys(state.bnodeMap).filter(id => state.bnodeMap[id].length === 1);
58+
}
7759

78-
// frame the subjects
79-
const framed = [];
80-
api.frame(state, Object.keys(state.subjects).sort(), frame, framed);
8160
return framed;
8261
};
8362

@@ -133,6 +112,9 @@ api.frame = (state, subjects, frame, parent, property = null) => {
133112
// start output for subject
134113
const output = {};
135114
output['@id'] = id;
115+
if(id.indexOf('_:') === 0) {
116+
util.addValue(state.bnodeMap, id, output, {propertyIsArray: true});
117+
}
136118
state.link[id] = output;
137119

138120
// if embed is @never or if a circular reference would be created by an

lib/jsonld.js

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ const {fromRDF: _fromRDF} = require('./fromRdf');
4848
const {toRDF: _toRDF} = require('./toRdf');
4949

5050
const {
51-
frameMerged: _frameMerged,
52-
frameDefault: _frameDefault
51+
frameMergedOrDefault: _frameMergedOrDefault
5352
} = require('./frame');
5453

5554
const {
@@ -426,7 +425,8 @@ jsonld.frame = util.callbackify(async function(input, frame, options) {
426425
explicit: false,
427426
requireAll: true,
428427
omitDefault: false,
429-
pruneBlankNodeIdentifiers: true
428+
pruneBlankNodeIdentifiers: true,
429+
bnodesToClear: []
430430
});
431431

432432
// if frame is a string, attempt to dereference remote document
@@ -463,13 +463,9 @@ jsonld.frame = util.callbackify(async function(input, frame, options) {
463463
// if the unexpanded frame includes a key expanding to @graph, frame the default graph, otherwise, the merged graph
464464
let framed;
465465
// FIXME should look for aliases of @graph
466-
if('@graph' in frame) {
467-
// do default framing
468-
framed = _frameDefault(expanded, expandedFrame, opts);
469-
} else {
470-
// do merged framing
471-
framed = _frameMerged(expanded, expandedFrame, opts);
472-
}
466+
opts.merged = !('@graph' in frame);
467+
// do framing
468+
framed = _frameMergedOrDefault(expanded, expandedFrame, opts);
473469

474470
// compact result (force @graph option to true, skip expansion,
475471
// check for linked embeds)

0 commit comments

Comments
 (0)