Skip to content
Closed
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.DS_store
.classpath
.project
.settings
Expand Down
131 changes: 98 additions & 33 deletions core/src/main/java/com/github/jsonldjava/core/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
import static com.github.jsonldjava.utils.Obj.newMap;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import com.github.jsonldjava.core.JsonLdError.Error;
import com.github.jsonldjava.utils.JsonLdUrl;
Expand Down Expand Up @@ -215,6 +217,18 @@ else if (context instanceof String) {
// 3.3
throw new JsonLdError(Error.INVALID_LOCAL_CONTEXT, context);
}
// 5.5 in 1.1 (https://w3c.github.io/json-ld-api/#context-processing-algorithm)
if (((Map<String, Object>) context).containsKey(JsonLdConsts.VERSION)) {
final Object version = ((Map<String, Object>) context).get(JsonLdConsts.VERSION);
// 5.5.1
if(!version.equals(Double.valueOf(1.1))) {
throw new JsonLdError(Error.INVALID_VERSION_VALUE, context);
}
// 5.5.2
if(options.getProcessingMode().equals(JsonLdOptions.JSON_LD_1_0)) {
throw new JsonLdError(Error.PROCESSING_MODE_CONFLICT, context);
}
}
checkEmptyKey((Map<String, Object>) context);
// 3.4
if (!parsingARemoteContext
Expand Down Expand Up @@ -248,12 +262,15 @@ else if (context instanceof String) {
final Object value = ((Map<String, Object>) context).get(JsonLdConsts.VOCAB);
if (value == null) {
result.remove(JsonLdConsts.VOCAB);
} else if (value instanceof String) {
if (JsonLdUtils.isAbsoluteIri((String) value)) {
result.put(JsonLdConsts.VOCAB, value);
}
// jsonld 1.1: 5.8.3 in https://w3c.github.io/json-ld-api/#algorithm
else if (value instanceof String) {
if (((String) value).startsWith(JsonLdConsts.BLANK_NODE_PREFIX)
|| JsonLdUtils.isAbsoluteIri((String) value) || JsonLdUtils.isRelativeIri((String) value)) {
result.put(JsonLdConsts.VOCAB,
expandIri((String) value, true, true, ((Map<String, Object>) result), null));
} else {
throw new JsonLdError(Error.INVALID_VOCAB_MAPPING,
"@value must be an absolute IRI");
throw new JsonLdError(Error.INVALID_VOCAB_MAPPING, value);
}
} else {
throw new JsonLdError(Error.INVALID_VOCAB_MAPPING,
Expand All @@ -276,8 +293,12 @@ else if (context instanceof String) {
// 3.7
final Map<String, Boolean> defined = new LinkedHashMap<String, Boolean>();
for (final String key : ((Map<String, Object>) context).keySet()) {
if (JsonLdConsts.BASE.equals(key) || JsonLdConsts.VOCAB.equals(key)
|| JsonLdConsts.LANGUAGE.equals(key)) {
// jsonld 1.1: 5.13 in https://w3c.github.io/json-ld-api/#algorithm
if (Arrays
.asList(JsonLdConsts.BASE, JsonLdConsts.DIRECTION, JsonLdConsts.IMPORT,
JsonLdConsts.LANGUAGE, JsonLdConsts.PROPAGATE,
JsonLdConsts.PROTECTED, JsonLdConsts.VERSION, JsonLdConsts.VOCAB)
.contains(key)) {
continue;
}
result.createTermDefinition((Map<String, Object>) context, key, defined);
Expand Down Expand Up @@ -366,15 +387,19 @@ private void createTermDefinition(Map<String, Object> context, String term,
}
throw new JsonLdError(Error.INVALID_TYPE_MAPPING, type, error);
}
// jsonld 1.1: 13.3 in https://w3c.github.io/json-ld-api/#algorithm-0
if (JsonLdOptions.JSON_LD_1_0.equals(options.getProcessingMode())
&& (JsonLdConsts.NONE.equals(type) || JsonLdConsts.JSON.equals(type))) {
throw new JsonLdError(Error.INVALID_TYPE_MAPPING, type);
}
// TODO: fix check for absoluteIri (blank nodes shouldn't count, at
// least not here!)
if (JsonLdConsts.ID.equals(type) || JsonLdConsts.VOCAB.equals(type)
|| (!type.startsWith(JsonLdConsts.BLANK_NODE_PREFIX)
&& JsonLdUtils.isAbsoluteIri(type))) {
definition.put(JsonLdConsts.TYPE, type);
} else {
else if (!JsonLdConsts.ID.equals(type) && !JsonLdConsts.VOCAB.equals(type)
&& !JsonLdConsts.JSON.equals(type) && !JsonLdConsts.NONE.equals(type)
&& (!JsonLdUtils.isAbsoluteIri(type) || type.startsWith(JsonLdConsts.BLANK_NODE_PREFIX))) {
throw new JsonLdError(Error.INVALID_TYPE_MAPPING, type);
}
definition.put(JsonLdConsts.TYPE, type);
}

// 11)
Expand All @@ -396,13 +421,15 @@ private void createTermDefinition(Map<String, Object> context, String term,
}
definition.put(JsonLdConsts.ID, reverse);
if (val.containsKey(JsonLdConsts.CONTAINER)) {
final String container = (String) val.get(JsonLdConsts.CONTAINER);
final Object containerObject = val.get(JsonLdConsts.CONTAINER);
final String container = selectContainer(checkValidContainerEntry(containerObject));
if (container == null || JsonLdConsts.SET.equals(container)
|| JsonLdConsts.INDEX.equals(container)) {
definition.put(JsonLdConsts.CONTAINER, container);
} else {
throw new JsonLdError(Error.INVALID_REVERSE_PROPERTY,
"reverse properties only support set- and index-containers");
"reverse properties only support set- and index-containers, but was: "
+ containerObject);
}
}
definition.put(JsonLdConsts.REVERSE, true);
Expand Down Expand Up @@ -430,7 +457,7 @@ private void createTermDefinition(Map<String, Object> context, String term,
definition.put(JsonLdConsts.ID, res);
} else {
throw new JsonLdError(Error.INVALID_IRI_MAPPING,
"resulting IRI mapping should be a keyword, absolute IRI or blank node");
"resulting IRI mapping should be a keyword, absolute IRI or blank node, but was: " + res);
}
}

Expand Down Expand Up @@ -459,12 +486,16 @@ else if (term.indexOf(":") >= 0) {

// 16)
if (val.containsKey(JsonLdConsts.CONTAINER)) {
final String container = (String) val.get(JsonLdConsts.CONTAINER);
if (!JsonLdConsts.LIST.equals(container) && !JsonLdConsts.SET.equals(container)
&& !JsonLdConsts.INDEX.equals(container)
&& !JsonLdConsts.LANGUAGE.equals(container)) {
throw new JsonLdError(Error.INVALID_CONTAINER_MAPPING,
"@container must be either @list, @set, @index, or @language");
Object containerObject = val.get(JsonLdConsts.CONTAINER);
final List<?> allContainers = checkValidContainerEntry(containerObject);
if (allContainers.isEmpty()) {
throw new JsonLdError(Error.INVALID_CONTAINER_MAPPING, containerObject);
}
String container = selectContainer(allContainers);
if (container == null) {
throw new JsonLdError(Error.NOT_IMPLEMENTED,
"@container must be either @type, @id, @list, @set, @index, or @language, but was: "
+ allContainers);
}
definition.put(JsonLdConsts.CONTAINER, container);
if (JsonLdConsts.TYPE.equals(term)) {
Expand All @@ -490,6 +521,35 @@ else if (term.indexOf(":") >= 0) {
defined.put(term, true);
}

private String selectContainer(final List<?> allContainers) {
Optional<?> supportedContainer = allContainers
.stream().filter(c -> Arrays.asList(JsonLdConsts.TYPE, JsonLdConsts.ID, JsonLdConsts.LIST,
JsonLdConsts.SET, JsonLdConsts.INDEX, JsonLdConsts.LANGUAGE, JsonLdConsts.GRAPH).contains(c))
.findFirst();
return (String) supportedContainer.orElse(null);
}

// jsonld 1.1: 22.1 in https://w3c.github.io/json-ld-api/#create-term-definition
private List<?> checkValidContainerEntry(final Object containerObject) {
List<?> container = (List<?>) (containerObject instanceof List ? containerObject
: Arrays.asList(containerObject));
boolean anyOneOf = Arrays.asList(JsonLdConsts.GRAPH, JsonLdConsts.ID, JsonLdConsts.INDEX,
JsonLdConsts.LANGUAGE, JsonLdConsts.LIST, JsonLdConsts.SET, JsonLdConsts.TYPE)
.stream().anyMatch(v -> container.contains(v)) && container.size() == 1;
boolean graphWithOthers = container.contains(JsonLdConsts.GRAPH)
&& (container.contains(JsonLdConsts.ID) || container.contains(JsonLdConsts.INDEX)
|| container.contains(JsonLdConsts.SET));
boolean setWithOthers = container.contains(JsonLdConsts.SET)
&& Arrays
.asList(JsonLdConsts.INDEX, JsonLdConsts.ID, JsonLdConsts.TYPE,
JsonLdConsts.LANGUAGE)
.stream().anyMatch(v -> container.contains(v));
if (anyOneOf || graphWithOthers || setWithOthers) {
return container;
} else
return Collections.emptyList();
}

/**
* IRI Expansion Algorithm
*
Expand Down Expand Up @@ -553,8 +613,6 @@ String expandIri(String value, boolean relative, boolean vocab, Map<String, Obje
// 6)
else if (relative) {
return JsonLdUrl.resolve((String) this.get(JsonLdConsts.BASE), value);
} else if (context != null && JsonLdUtils.isRelativeIri(value)) {
throw new JsonLdError(Error.INVALID_IRI_MAPPING, "not an absolute IRI: " + value);
}
// 7)
return value;
Expand Down Expand Up @@ -959,18 +1017,28 @@ public int compare(String a, String b) {
typeLanguageMap.put(JsonLdConsts.TYPE, newMap());
containerMap.put(container, typeLanguageMap);
}

// jsonld 1.1: 3.8 in https://w3c.github.io/json-ld-api/#inverse-context-creation
final Map<String, Object> typeMap = (Map<String, Object>) typeLanguageMap
.get(JsonLdConsts.TYPE);
// 3.8)
if (Boolean.TRUE.equals(definition.get(JsonLdConsts.REVERSE))) {
final Map<String, Object> typeMap = (Map<String, Object>) typeLanguageMap
.get(JsonLdConsts.TYPE);
if (!typeMap.containsKey(JsonLdConsts.REVERSE)) {
typeMap.put(JsonLdConsts.REVERSE, term);
}
// 3.9)
} else if (definition.containsKey(JsonLdConsts.TYPE)) {
final Map<String, Object> typeMap = (Map<String, Object>) typeLanguageMap
.get(JsonLdConsts.TYPE);
}
// jsonld 1.1: 3.10 in https://w3c.github.io/json-ld-api/#inverse-context-creation
else if(JsonLdConsts.NONE.equals(definition.get(JsonLdConsts.TYPE))) {
final Map<String, Object> languageMap = (Map<String, Object>) typeLanguageMap
.get(JsonLdConsts.LANGUAGE);
if(!languageMap.containsKey(JsonLdConsts.ANY)) {
languageMap.put(JsonLdConsts.ANY, term);
}
if(!typeMap.containsKey(JsonLdConsts.ANY)) {
typeMap.put(JsonLdConsts.ANY, term);
}
}
// 3.9)
else if (definition.containsKey(JsonLdConsts.TYPE)) {
if (!typeMap.containsKey(definition.get(JsonLdConsts.TYPE))) {
typeMap.put((String) definition.get(JsonLdConsts.TYPE), term);
}
Expand Down Expand Up @@ -998,9 +1066,6 @@ public int compare(String a, String b) {
if (!languageMap.containsKey(JsonLdConsts.NONE)) {
languageMap.put(JsonLdConsts.NONE, term);
}
// 3.11.4)
final Map<String, Object> typeMap = (Map<String, Object>) typeLanguageMap
.get(JsonLdConsts.TYPE);
// 3.11.5)
if (!typeMap.containsKey(JsonLdConsts.NONE)) {
typeMap.put(JsonLdConsts.NONE, term);
Expand Down
Loading