Skip to content

Commit e2eb98b

Browse files
committed
Scoping on @type.
1 parent 8ce1224 commit e2eb98b

File tree

4 files changed

+243
-1
lines changed

4 files changed

+243
-1
lines changed

lib/json/ld/compact.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,23 @@ def compact(element, property: nil)
5454
inside_reverse = property == '@reverse'
5555
result, nest_result = {}, nil
5656

57-
element.each_key do |expanded_property|
57+
element.keys.sort.each do |expanded_property|
5858
expanded_value = element[expanded_property]
5959
#log_debug("") {"#{expanded_property}: #{expanded_value.inspect}"}
6060

6161
if %w(@id @type).include?(expanded_property)
6262
compacted_value = [expanded_value].flatten.compact.map do |expanded_type|
6363
context.compact_iri(expanded_type, vocab: (expanded_property == '@type'), log_depth: @options[:log_depth])
6464
end
65+
66+
# If key is @type and any compacted value is a term having a local context, overlay that context.
67+
if expanded_property == '@type'
68+
compacted_value.each do |term|
69+
term_context = self.context.term_definitions[term].context if context.term_definitions[term]
70+
self.context = context.parse(term_context) if term_context
71+
end
72+
end
73+
6574
compacted_value = compacted_value.first if compacted_value.length == 1
6675

6776
al = context.compact_iri(expanded_property, vocab: true, quiet: true)

lib/json/ld/expand.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ def expand(input, active_property, context, ordered: true)
4444
output_object = {}
4545
keys = ordered ? input.keys.kw_sort : input.keys
4646

47+
# See if keys mapping to @type have terms with a local context
48+
input.keys.select do |key|
49+
context.expand_iri(key, vocab: true) == '@type'
50+
end.each do |key|
51+
Array(input[key]).each do |term|
52+
term_context = context.term_definitions[term].context if context.term_definitions[term]
53+
context = term_context ? context.parse(term_context) : context
54+
end
55+
end
56+
4757
# Process each key and value in element. Ignores @nesting content
4858
expand_object(input, active_property, context, output_object, ordered: ordered)
4959

spec/compact_spec.rb

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,128 @@
10381038
end
10391039
end
10401040

1041+
context "scoped context on @type" do
1042+
{
1043+
"adding new term" => {
1044+
input: %([
1045+
{
1046+
"http://example/a": [{
1047+
"@type": ["http://example/Foo"],
1048+
"http://example.org/bar": [{"@value": "baz"}]
1049+
}]
1050+
}
1051+
]),
1052+
context: %({
1053+
"@vocab": "http://example/",
1054+
"Foo": {"@context": {"bar": "http://example.org/bar"}}
1055+
}),
1056+
output: %({
1057+
"@context": {
1058+
"@vocab": "http://example/",
1059+
"Foo": {"@context": {"bar": "http://example.org/bar"}}
1060+
},
1061+
"a": {"@type": "Foo", "bar": "baz"}
1062+
})
1063+
},
1064+
"overriding a term" => {
1065+
input: %([
1066+
{
1067+
"http://example/a": [{
1068+
"@type": ["http://example/Foo"],
1069+
"http://example/bar": [{"@id": "http://example/baz"}]
1070+
}]
1071+
}
1072+
]),
1073+
context: %({
1074+
"@vocab": "http://example/",
1075+
"Foo": {"@context": {"bar": {"@type": "@id"}}},
1076+
"bar": {"@type": "http://www.w3.org/2001/XMLSchema#string"}
1077+
}),
1078+
output: %({
1079+
"@context": {
1080+
"@vocab": "http://example/",
1081+
"Foo": {"@context": {"bar": {"@type": "@id"}}},
1082+
"bar": {"@type": "http://www.w3.org/2001/XMLSchema#string"}
1083+
},
1084+
"a": {"@type": "Foo", "bar": "http://example/baz"}
1085+
}),
1086+
},
1087+
"alias of @type" => {
1088+
input: %([
1089+
{
1090+
"http://example/a": [{
1091+
"@type": ["http://example/Foo"],
1092+
"http://example.org/bar": [{"@value": "baz"}]
1093+
}]
1094+
}
1095+
]),
1096+
context: %({
1097+
"@vocab": "http://example/",
1098+
"type": "@type",
1099+
"Foo": {"@context": {"bar": "http://example.org/bar"}}
1100+
}),
1101+
output: %({
1102+
"@context": {
1103+
"@vocab": "http://example/",
1104+
"type": "@type",
1105+
"Foo": {"@context": {"bar": "http://example.org/bar"}}
1106+
},
1107+
"a": {"type": "Foo", "bar": "baz"}
1108+
}),
1109+
},
1110+
"deep @context affects nested nodes" => {
1111+
input: %([
1112+
{
1113+
"@type": ["http://example/Foo"],
1114+
"http://example/bar": [{
1115+
"http://example/baz": [{"@id": "http://example/buzz"}]
1116+
}]
1117+
}
1118+
]),
1119+
context: %({
1120+
"@vocab": "http://example/",
1121+
"Foo": {"@context": {"baz": {"@type": "@vocab"}}}
1122+
}),
1123+
output: %({
1124+
"@context": {
1125+
"@vocab": "http://example/",
1126+
"Foo": {"@context": {"baz": {"@type": "@vocab"}}}
1127+
},
1128+
"@type": "Foo",
1129+
"bar": {"baz": "buzz"}
1130+
}),
1131+
},
1132+
"scoped context layers on intemediate contexts" => {
1133+
input: %([{
1134+
"http://example/a": [{
1135+
"@type": ["http://example/B"],
1136+
"http://example.com/a": [{"@value": "A in example.com"}],
1137+
"http://example.org/c": [{"@value": "C in example.org"}]
1138+
}],
1139+
"http://example/c": [{"@value": "C in example"}]
1140+
}]),
1141+
context: %({
1142+
"@vocab": "http://example/",
1143+
"B": {"@context": {"c": "http://example.org/c"}}
1144+
}),
1145+
output: %({
1146+
"@context": {
1147+
"@vocab": "http://example/",
1148+
"B": {"@context": {"c": "http://example.org/c"}}
1149+
},
1150+
"a": {
1151+
"@type": "B",
1152+
"c": "C in example.org",
1153+
"http://example.com/a": "A in example.com"
1154+
},
1155+
"c": "C in example"
1156+
}),
1157+
},
1158+
}.each_pair do |title, params|
1159+
it(title) {run_compact(params)}
1160+
end
1161+
end
1162+
10411163
context "exceptions" do
10421164
{
10431165
"@list containing @list" => {

spec/expand_spec.rb

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,107 @@
12251225
end
12261226
end
12271227

1228+
context "scoped context on @type" do
1229+
{
1230+
"adding new term" => {
1231+
input: %({
1232+
"@context": {
1233+
"@vocab": "http://example/",
1234+
"Foo": {"@context": {"bar": "http://example.org/bar"}}
1235+
},
1236+
"a": {"@type": "Foo", "bar": "baz"}
1237+
}),
1238+
output: %([
1239+
{
1240+
"http://example/a": [{
1241+
"@type": ["http://example/Foo"],
1242+
"http://example.org/bar": [{"@value": "baz"}]
1243+
}]
1244+
}
1245+
])
1246+
},
1247+
"overriding a term" => {
1248+
input: %({
1249+
"@context": {
1250+
"@vocab": "http://example/",
1251+
"Foo": {"@context": {"bar": {"@type": "@id"}}},
1252+
"bar": {"@type": "http://www.w3.org/2001/XMLSchema#string"}
1253+
},
1254+
"a": {"@type": "Foo", "bar": "http://example/baz"}
1255+
}),
1256+
output: %([
1257+
{
1258+
"http://example/a": [{
1259+
"@type": ["http://example/Foo"],
1260+
"http://example/bar": [{"@id": "http://example/baz"}]
1261+
}]
1262+
}
1263+
])
1264+
},
1265+
"alias of @type" => {
1266+
input: %({
1267+
"@context": {
1268+
"@vocab": "http://example/",
1269+
"type": "@type",
1270+
"Foo": {"@context": {"bar": "http://example.org/bar"}}
1271+
},
1272+
"a": {"type": "Foo", "bar": "baz"}
1273+
}),
1274+
output: %([
1275+
{
1276+
"http://example/a": [{
1277+
"@type": ["http://example/Foo"],
1278+
"http://example.org/bar": [{"@value": "baz"}]
1279+
}]
1280+
}
1281+
])
1282+
},
1283+
"deep @context affects nested nodes" => {
1284+
input: %({
1285+
"@context": {
1286+
"@vocab": "http://example/",
1287+
"Foo": {"@context": {"baz": {"@type": "@vocab"}}}
1288+
},
1289+
"@type": "Foo",
1290+
"bar": {"baz": "buzz"}
1291+
}),
1292+
output: %([
1293+
{
1294+
"@type": ["http://example/Foo"],
1295+
"http://example/bar": [{
1296+
"http://example/baz": [{"@id": "http://example/buzz"}]
1297+
}]
1298+
}
1299+
])
1300+
},
1301+
"scoped context layers on intemediate contexts" => {
1302+
input: %({
1303+
"@context": {
1304+
"@vocab": "http://example/",
1305+
"B": {"@context": {"c": "http://example.org/c"}}
1306+
},
1307+
"a": {
1308+
"@context": {"@vocab": "http://example.com/"},
1309+
"@type": "B",
1310+
"a": "A in example.com",
1311+
"c": "C in example.org"
1312+
},
1313+
"c": "C in example"
1314+
}),
1315+
output: %([{
1316+
"http://example/a": [{
1317+
"@type": ["http://example/B"],
1318+
"http://example.com/a": [{"@value": "A in example.com"}],
1319+
"http://example.org/c": [{"@value": "C in example.org"}]
1320+
}],
1321+
"http://example/c": [{"@value": "C in example"}]
1322+
}])
1323+
},
1324+
}.each do |title, params|
1325+
it(title) {run_expand params}
1326+
end
1327+
end
1328+
12281329
context "@reverse" do
12291330
{
12301331
"@container: @reverse" => {

0 commit comments

Comments
 (0)