From ae4d998d1cad23492ae1ad36d13f175d111017e5 Mon Sep 17 00:00:00 2001 From: Filip Date: Mon, 4 Dec 2023 22:55:21 +0100 Subject: [PATCH 1/4] Bump version to 1.4.0-SNAPSHOT --- pom.xml | 2 +- pom_jre8.xml | 2 +- pom_parent.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 07a530f7..97506896 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.apicatalog titanium - 1.3.4-SNAPSHOT + 1.4.0-SNAPSHOT pom_parent.xml titanium-json-ld diff --git a/pom_jre8.xml b/pom_jre8.xml index 3968d769..bbad8524 100644 --- a/pom_jre8.xml +++ b/pom_jre8.xml @@ -6,7 +6,7 @@ com.apicatalog titanium - 1.3.4-SNAPSHOT + 1.4.0-SNAPSHOT pom_parent.xml titanium-json-ld-jre8 diff --git a/pom_parent.xml b/pom_parent.xml index 836982ed..b85b4a49 100644 --- a/pom_parent.xml +++ b/pom_parent.xml @@ -6,7 +6,7 @@ 4.0.0 com.apicatalog titanium - 1.3.4-SNAPSHOT + 1.4.0-SNAPSHOT pom Titanium JSON-LD 1.1 From 5816977f59ff9d5a21b7958fb3a6041144a3469f Mon Sep 17 00:00:00 2001 From: Filip Date: Tue, 5 Dec 2023 19:13:18 +0100 Subject: [PATCH 2/4] Minor tweaks --- .../jsonld/compaction/Compaction.java | 308 ++++++++--------- .../jsonld/context/TermDefinitionBuilder.java | 184 +++++----- .../jsonld/expansion/ArrayExpansion.java | 39 +-- .../jsonld/expansion/ObjectExpansion.java | 146 ++++---- .../jsonld/expansion/ObjectExpansion1314.java | 319 ++++++++---------- .../jsonld/expansion/UriExpansion.java | 29 +- .../jsonld/expansion/ValueExpansion.java | 22 +- .../jsonld/json/JsonMapBuilder.java | 14 +- .../com/apicatalog/jsonld/lang/Keywords.java | 4 +- .../com/apicatalog/jsonld/lang/Utils.java | 2 +- 10 files changed, 505 insertions(+), 562 deletions(-) diff --git a/src/main/java/com/apicatalog/jsonld/compaction/Compaction.java b/src/main/java/com/apicatalog/jsonld/compaction/Compaction.java index e985843e..d6c61a29 100644 --- a/src/main/java/com/apicatalog/jsonld/compaction/Compaction.java +++ b/src/main/java/com/apicatalog/jsonld/compaction/Compaction.java @@ -16,6 +16,7 @@ package com.apicatalog.jsonld.compaction; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -45,11 +46,19 @@ /** * - * @see Compaction Algorithm + * @see Compaction + * Algorithm * */ public final class Compaction { + private static final Collection DILV_KEYWORDS = Arrays.asList( + Keywords.DIRECTION, + Keywords.INDEX, + Keywords.LANGUAGE, + Keywords.VALUE); + // required private final ActiveContext context; @@ -107,10 +116,10 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 3.2.1. final JsonValue compactedItem = Compaction - .with(activeContext) - .compactArrays(compactArrays) - .ordered(ordered) - .compact(activeProperty, item); + .with(activeContext) + .compactArrays(compactArrays) + .ordered(ordered) + .compact(activeProperty, item); // 3.2.2. if (JsonUtils.isNotNull(compactedItem)) { resultBuilder.add(compactedItem); @@ -127,8 +136,7 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t || Keywords.SET.equals(activeProperty) || activePropertyDefinition .filter(d -> d.hasContainerMapping(Keywords.LIST) || d.hasContainerMapping(Keywords.SET)) - .isPresent() - ) { + .isPresent()) { return result; } @@ -144,27 +152,24 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t if (activeContext.getPreviousContext() != null && !elementObject.containsKey(Keywords.VALUE) && !(elementObject.containsKey(Keywords.ID) - && elementObject.size() == 1) - ) { + && elementObject.size() == 1)) { activeContext = activeContext.getPreviousContext(); } // 6. if (activePropertyDefinition.map(TermDefinition::getLocalContext).isPresent()) { - activeContext = - activeContext - .newContext() - .overrideProtected(true) - .create(activePropertyDefinition.get().getLocalContext(), - activePropertyDefinition.get().getBaseUrl()); + activeContext = activeContext + .newContext() + .overrideProtected(true) + .create(activePropertyDefinition.get().getLocalContext(), + activePropertyDefinition.get().getBaseUrl()); } // 7. if ((elementObject.containsKey(Keywords.VALUE) || elementObject.containsKey(Keywords.ID)) - && (!activeContext.getOptions().isRdfStar() || !elementObject.containsKey(Keywords.ANNOTATION)) - ) { + && (!activeContext.getOptions().isRdfStar() || !elementObject.containsKey(Keywords.ANNOTATION))) { final JsonValue result = activeContext.valueCompaction().compact(elementObject, activeProperty); @@ -172,8 +177,7 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t || activePropertyDefinition .map(TermDefinition::getTypeMapping) .filter(Keywords.JSON::equals) - .isPresent() - ) { + .isPresent()) { return result; } @@ -182,14 +186,13 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 8. if (ListObject.isListObject(element) - && activePropertyDefinition.filter(d -> d.hasContainerMapping(Keywords.LIST)).isPresent() - ) { + && activePropertyDefinition.filter(d -> d.hasContainerMapping(Keywords.LIST)).isPresent()) { return Compaction - .with(activeContext) - .compactArrays(compactArrays) - .ordered(ordered) - .compact(activeProperty, elementObject.get(Keywords.LIST)); + .with(activeContext) + .compactArrays(compactArrays) + .ordered(ordered) + .compact(activeProperty, elementObject.get(Keywords.LIST)); } // 9. @@ -204,7 +207,7 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t final List compactedTypes = new ArrayList<>(); for (final JsonValue type : JsonUtils.toCollection(elementObject.get(Keywords.TYPE))) { - compactedTypes.add(activeContext.uriCompaction().vocab(true).compact(((JsonString)type).getString())); + compactedTypes.add(activeContext.uriCompaction().vocab(true).compact(((JsonString) type).getString())); } Collections.sort(compactedTypes); @@ -216,11 +219,10 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 11.1. if (termDefinition.filter(TermDefinition::hasLocalContext).isPresent()) { - activeContext = - activeContext - .newContext() - .propagate(false) - .create(termDefinition.get().getLocalContext(), termDefinition.get().getBaseUrl()); + activeContext = activeContext + .newContext() + .propagate(false) + .create(termDefinition.get().getLocalContext(), termDefinition.get().getBaseUrl()); } } } @@ -237,14 +239,14 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.1.1. if (JsonUtils.isString(expandedValue)) { - compactedValue = JsonUtils.toJsonValue(activeContext.uriCompaction().compact(((JsonString)expandedValue).getString())); + compactedValue = JsonUtils.toJsonValue(activeContext.uriCompaction().compact(((JsonString) expandedValue).getString())); - // json-ld-star + // json-ld-star } else if (activeContext.getOptions().isRdfStar() && NodeObject.isEmbeddedNode(expandedValue)) { compactedValue = Compaction.with(activeContext) - .compactArrays(compactArrays) - .ordered(ordered) - .compact(expandedValue); + .compactArrays(compactArrays) + .ordered(ordered) + .compact(expandedValue); } // 12.1.2. @@ -263,9 +265,9 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.2.1. if (JsonUtils.isString(expandedValue)) { - compactedValue = JsonUtils.toJsonValue(typeContext.uriCompaction().vocab(true).compact(((JsonString)expandedValue).getString())); + compactedValue = JsonUtils.toJsonValue(typeContext.uriCompaction().vocab(true).compact(((JsonString) expandedValue).getString())); - // 12.2.2. + // 12.2.2. } else if (JsonUtils.isArray(expandedValue)) { // 12.2.2.1. @@ -275,11 +277,10 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t for (final JsonValue expandedType : expandedValue.asJsonArray()) { compactedArray.add( - typeContext - .uriCompaction() - .vocab(true) - .compact(((JsonString)expandedType).getString()) - ); + typeContext + .uriCompaction() + .vocab(true) + .compact(((JsonString) expandedType).getString())); } compactedValue = compactedArray.build(); @@ -293,9 +294,8 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.2.4. final boolean asArray = !compactArrays - || (activeContext.inMode(JsonLdVersion.V1_1) - && activeContext.getTerm(alias).filter(t -> t.hasContainerMapping(Keywords.SET)).isPresent() - ); + || (activeContext.inMode(JsonLdVersion.V1_1) + && activeContext.getTerm(alias).filter(t -> t.hasContainerMapping(Keywords.SET)).isPresent()); // 12.2.5. result.add(alias, compactedValue, asArray); @@ -309,11 +309,11 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.3.1. final JsonObject compactedMap = Compaction - .with(activeContext) - .compactArrays(compactArrays) - .ordered(ordered) - .compact(Keywords.REVERSE, expandedValue) - .asJsonObject(); + .with(activeContext) + .compactArrays(compactArrays) + .ordered(ordered) + .compact(Keywords.REVERSE, expandedValue) + .asJsonObject(); JsonObjectBuilder remaining = null; @@ -325,10 +325,10 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.3.2.1.1 final boolean asArray = !compactArrays - || activeContext - .getTerm(entry.getKey()) - .filter(td -> td.hasContainerMapping(Keywords.SET)) - .isPresent(); + || activeContext + .getTerm(entry.getKey()) + .filter(td -> td.hasContainerMapping(Keywords.SET)) + .isPresent(); // 12.3.2.1.2. result.add(entry.getKey(), entry.getValue(), asArray); @@ -363,10 +363,10 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.4.1. final JsonValue compactedValue = Compaction - .with(activeContext) - .compactArrays(compactArrays) - .ordered(ordered) - .compact(activeProperty, expandedValue); + .with(activeContext) + .compactArrays(compactArrays) + .ordered(ordered) + .compact(activeProperty, expandedValue); // 12.4.2. if (!JsonUtils.isEmptyArray(compactedValue)) { @@ -377,17 +377,12 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.5. if (Keywords.INDEX.equals(expandedProperty) - && activePropertyDefinition.filter(d -> d.hasContainerMapping(Keywords.INDEX)).isPresent() - ) { + && activePropertyDefinition.filter(d -> d.hasContainerMapping(Keywords.INDEX)).isPresent()) { continue; - // 12.6. - } else if (Keywords.anyMatch(expandedProperty, - Keywords.DIRECTION, - Keywords.INDEX, - Keywords.LANGUAGE, - Keywords.VALUE - )) { + // 12.6. + } else if (DILV_KEYWORDS.contains(expandedProperty)) { + // 12.6.1. final String alias = activeContext.uriCompaction().vocab(true).compact(expandedProperty); @@ -402,15 +397,15 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.7.1. final String itemActiveProperty = activeContext - .uriCompaction() - .value(expandedValue) - .vocab(true) - .reverse(insideReverse) - .compact(expandedProperty); + .uriCompaction() + .value(expandedValue) + .vocab(true) + .reverse(insideReverse) + .compact(expandedProperty); // 12.7.2. final Optional nestProperty = activeContext - .getTerm(itemActiveProperty) - .map(TermDefinition::getNestValue); + .getTerm(itemActiveProperty) + .map(TermDefinition::getNestValue); if (nestProperty.isPresent()) { @@ -424,8 +419,7 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.7.2.3. result.getMapBuilder(nestTerm).add(itemActiveProperty, JsonValue.EMPTY_JSON_ARRAY); - - // 12.7.3. + // 12.7.3. } else { result.add(itemActiveProperty, JsonValue.EMPTY_JSON_ARRAY); } @@ -437,19 +431,19 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.8.1. final String itemActiveProperty = activeContext - .uriCompaction() - .value(expandedItem) - .vocab(true) - .reverse(insideReverse) - .compact(expandedProperty); + .uriCompaction() + .value(expandedItem) + .vocab(true) + .reverse(insideReverse) + .compact(expandedProperty); JsonMapBuilder nestResult = null; String nestResultKey = null; // 12.8.2. final Optional nestProperty = activeContext - .getTerm(itemActiveProperty) - .map(TermDefinition::getNestValue); + .getTerm(itemActiveProperty) + .map(TermDefinition::getNestValue); if (nestProperty.isPresent()) { @@ -464,22 +458,22 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t nestResult = result.getMapBuilder(nestTerm); nestResultKey = nestTerm; - // 12.8.3. + // 12.8.3. } else { nestResult = result; } // 12.8.4. final Collection container = activeContext - .getTerm(itemActiveProperty) - .map(TermDefinition::getContainerMapping) - .orElseGet(() -> Collections.emptyList()); + .getTerm(itemActiveProperty) + .map(TermDefinition::getContainerMapping) + .orElseGet(() -> Collections.emptyList()); // 12.8.5. final boolean asArray = container.contains(Keywords.SET) - || Keywords.GRAPH.equals(itemActiveProperty) - || Keywords.LIST.equals(itemActiveProperty) - || !compactArrays; + || Keywords.GRAPH.equals(itemActiveProperty) + || Keywords.LIST.equals(itemActiveProperty) + || !compactArrays; // 12.8.6. JsonValue expandedItemValue = expandedItem; @@ -492,10 +486,10 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t } JsonValue compactedItem = Compaction - .with(activeContext) - .compactArrays(compactArrays) - .ordered(ordered) - .compact(itemActiveProperty, expandedItemValue); + .with(activeContext) + .compactArrays(compactArrays) + .ordered(ordered) + .compact(itemActiveProperty, expandedItemValue); // 12.8.7. if (ListObject.isListObject(expandedItem)) { @@ -517,19 +511,19 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t String indexKey = activeContext.uriCompaction().vocab(true).compact(Keywords.INDEX); compactedItem = JsonProvider.instance().createObjectBuilder(compactedItem.asJsonObject()) - .add(indexKey, expandedItem.asJsonObject().get(Keywords.INDEX)) - .build(); + .add(indexKey, expandedItem.asJsonObject().get(Keywords.INDEX)) + .build(); } // 12.8.7.2.3. nestResult.add(itemActiveProperty, compactedItem, asArray); - // 12.8.7.3. + // 12.8.7.3. } else { nestResult.put(itemActiveProperty, compactedItem); } - // 12.8.8. + // 12.8.8. } else if (GraphObject.isGraphObject(expandedItem)) { boolean followup = false; @@ -551,34 +545,31 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.8.8.1.3. nestResult.getMapBuilder(itemActiveProperty).add(mapKey, compactedItem, asArray); - // 12.8.8.2. + // 12.8.8.2. } else if (container.contains(Keywords.GRAPH) - && container.contains(Keywords.INDEX) - && GraphObject.isSimpleGraphObject(expandedItem) - ) { + && container.contains(Keywords.INDEX) + && GraphObject.isSimpleGraphObject(expandedItem)) { // 12.8.8.2.2. final String mapKey = expandedItem.asJsonObject().containsKey(Keywords.INDEX) - ? expandedItem.asJsonObject().getString(Keywords.INDEX) - : Keywords.NONE; + ? expandedItem.asJsonObject().getString(Keywords.INDEX) + : Keywords.NONE; // 12.8.8.2.3. nestResult.getMapBuilder(itemActiveProperty).add(mapKey, compactedItem, asArray); - // 12.8.8.3. + // 12.8.8.3. } else if (container.contains(Keywords.GRAPH) - && GraphObject.isSimpleGraphObject(expandedItem) - ) { + && GraphObject.isSimpleGraphObject(expandedItem)) { // 12.8.8.3.1. if (JsonUtils.isArray(compactedItem) && compactedItem.asJsonArray().size() > 1) { compactedItem = JsonProvider.instance().createObjectBuilder().add( - activeContext - .uriCompaction() - .vocab(true) - .compact(Keywords.INCLUDED), - compactedItem - ).build(); + activeContext + .uriCompaction() + .vocab(true) + .compact(Keywords.INCLUDED), + compactedItem).build(); } // 12.8.8.3.2. @@ -593,26 +584,25 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.8.8.4.1. compactedItem = JsonProvider.instance().createObjectBuilder().add( activeContext - .uriCompaction() - .vocab(true) - .compact(Keywords.GRAPH), - compactedItem - ).build(); + .uriCompaction() + .vocab(true) + .compact(Keywords.GRAPH), + compactedItem).build(); // 12.8.8.4.2. if (expandedItem.asJsonObject().containsKey(Keywords.ID)) { compactedItem = JsonProvider.instance().createObjectBuilder(compactedItem.asJsonObject()).add( activeContext - .uriCompaction() - .vocab(true) - .compact(Keywords.ID), + .uriCompaction() + .vocab(true) + .compact(Keywords.ID), activeContext - .uriCompaction() - .compact(expandedItem.asJsonObject().getString(Keywords.ID)) + .uriCompaction() + .compact(expandedItem.asJsonObject().getString(Keywords.ID)) - ).build(); + ).build(); } // 12.8.8.4.3. @@ -620,24 +610,22 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t compactedItem = JsonProvider.instance().createObjectBuilder(compactedItem.asJsonObject()).add( activeContext - .uriCompaction() - .vocab(true) - .compact(Keywords.INDEX), - expandedItem.asJsonObject().getString(Keywords.INDEX) - ).build(); + .uriCompaction() + .vocab(true) + .compact(Keywords.INDEX), + expandedItem.asJsonObject().getString(Keywords.INDEX)).build(); } // 12.8.8.4.4. nestResult.add(itemActiveProperty, compactedItem, asArray); } - // 12.8.9. + // 12.8.9. } else if ((container.contains(Keywords.LANGUAGE) - || container.contains(Keywords.INDEX) - || container.contains(Keywords.ID) - || container.contains(Keywords.TYPE)) - && !container.contains(Keywords.GRAPH) - ) { + || container.contains(Keywords.INDEX) + || container.contains(Keywords.ID) + || container.contains(Keywords.TYPE)) + && !container.contains(Keywords.GRAPH)) { // 12.8.9.2. String keyToCompact = null; @@ -659,16 +647,15 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.8.9.3. final String indexKey = activeContext - .getTerm(itemActiveProperty) - .map(TermDefinition::getIndexMapping) - .orElse(Keywords.INDEX); + .getTerm(itemActiveProperty) + .map(TermDefinition::getIndexMapping) + .orElse(Keywords.INDEX); String mapKey = null; // 12.8.9.4. if (container.contains(Keywords.LANGUAGE) - && expandedItem.asJsonObject().containsKey(Keywords.VALUE) - ) { + && expandedItem.asJsonObject().containsKey(Keywords.VALUE)) { if (JsonUtils.isObject(compactedItem)) { compactedItem = compactedItem.asJsonObject().get(Keywords.VALUE); @@ -679,24 +666,24 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t mapKey = expandedItem.asJsonObject().getString(Keywords.LANGUAGE); } - // 12.8.9.5. + // 12.8.9.5. } else if (container.contains(Keywords.INDEX) - && Keywords.INDEX.equals(indexKey)) { + && Keywords.INDEX.equals(indexKey)) { if (expandedItem.asJsonObject().containsKey(Keywords.INDEX)) { mapKey = expandedItem.asJsonObject().getString(Keywords.INDEX); } - // 12.8.9.6. + // 12.8.9.6. } else if (container.contains(Keywords.INDEX) - && !Keywords.INDEX.equals(indexKey)) { + && !Keywords.INDEX.equals(indexKey)) { // 12.8.9.6.1. containerKey = activeContext - .uriCompaction() - .vocab(true) - .compact(activeContext.uriExpansion().expand(indexKey)); + .uriCompaction() + .vocab(true) + .compact(activeContext.uriExpansion().expand(indexKey)); // 12.8.9.6.2. if (JsonUtils.containsKey(compactedItem, containerKey)) { @@ -704,7 +691,7 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t final JsonValue containerValue = compactedItem.asJsonObject().get(containerKey); if (JsonUtils.isString(containerValue)) { - mapKey = ((JsonString)containerValue).getString(); + mapKey = ((JsonString) containerValue).getString(); // 12.8.9.6.3. compactedItem = JsonProvider.instance().createObjectBuilder(compactedItem.asJsonObject()).remove(containerKey).build(); @@ -726,9 +713,9 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t } compactedItem = JsonProvider.instance().createObjectBuilder(compactedItem.asJsonObject()) - .remove(containerKey) - .add(containerKey, containerKeyValue) - .build(); + .remove(containerKey) + .add(containerKey, containerKeyValue) + .build(); } else { compactedItem = JsonProvider.instance().createObjectBuilder(compactedItem.asJsonObject()).remove(containerKey).build(); @@ -736,7 +723,7 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t } } - // 12.8.9.7. + // 12.8.9.7. } else if (container.contains(Keywords.ID)) { if (JsonUtils.containsKey(compactedItem, containerKey)) { @@ -746,7 +733,7 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t compactedItem = JsonProvider.instance().createObjectBuilder(compactedItem.asJsonObject()).remove(containerKey).build(); } - // 12.8.9.8. + // 12.8.9.8. } else if (container.contains(Keywords.TYPE)) { // 12.8.9.8.1. @@ -772,15 +759,14 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t } compactedItem = JsonProvider.instance().createObjectBuilder(compactedItem.asJsonObject()) - .remove(containerKey) - .add(containerKey, compactedKeyArrayValue) - .build(); + .remove(containerKey) + .add(containerKey, compactedKeyArrayValue) + .build(); } else { compactedItem = JsonProvider.instance().createObjectBuilder(compactedItem.asJsonObject()).remove(containerKey).build(); } - } else { compactedItem = JsonProvider.instance().createObjectBuilder(compactedItem.asJsonObject()).remove(containerKey).build(); } @@ -796,8 +782,8 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t JsonObject map = JsonProvider.instance().createObjectBuilder().add(Keywords.ID, expandedItem.asJsonObject().get(Keywords.ID)).build(); compactedItem = Compaction - .with(activeContext) - .compact(itemActiveProperty, map); + .with(activeContext) + .compact(itemActiveProperty, map); } } } @@ -810,7 +796,7 @@ public JsonValue compact(final String activeProperty, final JsonValue element) t // 12.8.9.10. nestResult.getMapBuilder(itemActiveProperty).add(mapKey, compactedItem, asArray); - // 12.8.10. + // 12.8.10. } else { nestResult.add(itemActiveProperty, compactedItem, asArray); } diff --git a/src/main/java/com/apicatalog/jsonld/context/TermDefinitionBuilder.java b/src/main/java/com/apicatalog/jsonld/context/TermDefinitionBuilder.java index be764dd0..2ddf0d9e 100644 --- a/src/main/java/com/apicatalog/jsonld/context/TermDefinitionBuilder.java +++ b/src/main/java/com/apicatalog/jsonld/context/TermDefinitionBuilder.java @@ -17,6 +17,7 @@ import java.net.URI; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -51,6 +52,28 @@ public final class TermDefinitionBuilder { private static final Logger LOGGER = Logger.getLogger(TermDefinitionBuilder.class.getName()); + private static final Collection CONTAINER_KEYWORDS = Arrays.asList( + Keywords.GRAPH, + Keywords.ID, + Keywords.INDEX, + Keywords.LANGUAGE, + Keywords.LIST, + Keywords.SET, + Keywords.TYPE); + + private static final Collection PROTECTED_KEYWORDS = Arrays.asList( + Keywords.ID, + Keywords.REVERSE, + Keywords.CONTAINER, + Keywords.CONTEXT, + Keywords.DIRECTION, + Keywords.INDEX, + Keywords.LANGUAGE, + Keywords.NEST, + Keywords.PREFIX, + Keywords.PROTECTED, + Keywords.TYPE); + // mandatory private final ActiveContext activeContext; @@ -160,7 +183,7 @@ public void create(final String term) throws JsonLdError { throw new JsonLdError(JsonLdErrorCode.KEYWORD_REDEFINITION); } - // 5. + // 5. } else if (Keywords.contains(term)) { throw new JsonLdError(JsonLdErrorCode.KEYWORD_REDEFINITION, "A keyword [" + term + "] redefinition has been detected."); @@ -184,14 +207,14 @@ public void create(final String term) throws JsonLdError { idValue = JsonValue.NULL; simpleTerm = false; - // 8. + // 8. } else if (JsonUtils.isString(value)) { valueObject = Collections.emptyMap(); idValue = value; simpleTerm = true; - // 9. + // 9. } else if (JsonUtils.isObject(value)) { valueObject = value.asJsonObject(); @@ -232,13 +255,12 @@ public void create(final String term) throws JsonLdError { } // 12.2. - final String expandedTypeString = - activeContext - .uriExpansion() - .localContext(localContext) - .defined(defined) - .vocab(true) - .expand(((JsonString) type).getString()); + final String expandedTypeString = activeContext + .uriExpansion() + .localContext(localContext) + .defined(defined) + .vocab(true) + .expand(((JsonString) type).getString()); if (expandedTypeString == null) { throw new JsonLdError(JsonLdErrorCode.INVALID_TYPE_MAPPING); @@ -282,7 +304,7 @@ public void create(final String term) throws JsonLdError { // 13.4. definition.setUriMapping( - activeContext + activeContext .uriExpansion() .localContext(localContext) .defined(defined) @@ -306,7 +328,7 @@ public void create(final String term) throws JsonLdError { final String containerString = ((JsonString) container).getString(); - if (Keywords.anyMatch(containerString, Keywords.SET, Keywords.INDEX)) { + if (Keywords.SET.equals(containerString) || Keywords.INDEX.equals(containerString)) { definition.addContainerMapping(containerString); } else { @@ -345,12 +367,12 @@ public void create(final String term) throws JsonLdError { // 14.2.3 definition.setUriMapping( - activeContext - .uriExpansion() - .localContext(localContext) - .defined(defined) - .vocab(true) - .expand(idValueString)); + activeContext + .uriExpansion() + .localContext(localContext) + .defined(defined) + .vocab(true) + .expand(idValueString)); if (Keywords.CONTEXT.equals(definition.getUriMapping())) { throw new JsonLdError(JsonLdErrorCode.INVALID_KEYWORD_ALIAS); @@ -369,13 +391,12 @@ public void create(final String term) throws JsonLdError { defined.put(term, Boolean.TRUE); // 14.2.4.2 - final String expandedTerm = - activeContext - .uriExpansion() - .localContext(localContext) - .defined(defined) - .vocab(true) - .expand(term); + final String expandedTerm = activeContext + .uriExpansion() + .localContext(localContext) + .defined(defined) + .vocab(true) + .expand(term); if (expandedTerm == null || !expandedTerm.equals(definition.getUriMapping())) { throw new JsonLdError(JsonLdErrorCode.INVALID_IRI_MAPPING); @@ -385,20 +406,16 @@ public void create(final String term) throws JsonLdError { // 14.2.5 if (definition.isNotPrefix()) { definition.setPrefix(!term.contains(":") - && !term.contains("/") - && simpleTerm - && (definition.getUriMapping() != null - && (( - UriUtils.endsWithGenDelim(definition.getUriMapping()) - && UriUtils.isURI(definition.getUriMapping().substring(0, definition.getUriMapping().length() - 1)) - ) - || BlankNode.hasPrefix(definition.getUriMapping())) - ) - ); + && !term.contains("/") + && simpleTerm + && (definition.getUriMapping() != null + && ((UriUtils.endsWithGenDelim(definition.getUriMapping()) + && UriUtils.isURI(definition.getUriMapping().substring(0, definition.getUriMapping().length() - 1))) + || BlankNode.hasPrefix(definition.getUriMapping())))); } } - // 15. + // 15. } else if (term.indexOf(':', 1) != -1) { final CompactUri compactUri = CompactUri.create(term); @@ -412,38 +429,37 @@ public void create(final String term) throws JsonLdError { if (compactUri != null && compactUri.isNotBlank() && activeContext.containsTerm(compactUri.getPrefix())) { definition.setUriMapping( - activeContext - .getTerm(compactUri.getPrefix()) - .map(TermDefinition::getUriMapping) - .map(u -> u.concat(compactUri.getSuffix())) - .orElse(null) - ); - - // 15.3. + activeContext + .getTerm(compactUri.getPrefix()) + .map(TermDefinition::getUriMapping) + .map(u -> u.concat(compactUri.getSuffix())) + .orElse(null)); + + // 15.3. } else if (UriUtils.isURI(term) || BlankNode.hasPrefix(term)) { definition.setUriMapping(term); } - // 16. + // 16. } else if (term.contains("/")) { definition.setUriMapping( - activeContext - .uriExpansion() - .localContext(localContext) - .defined(defined) - .vocab(true) - .expand(term)); + activeContext + .uriExpansion() + .localContext(localContext) + .defined(defined) + .vocab(true) + .expand(term)); if (UriUtils.isNotURI(definition.getUriMapping())) { throw new JsonLdError(JsonLdErrorCode.INVALID_IRI_MAPPING); } - // 17. + // 17. } else if (Keywords.TYPE.equals(term)) { definition.setUriMapping(Keywords.TYPE); - // 18. + // 18. } else if (activeContext.getVocabularyMapping() == null) { throw new JsonLdError(JsonLdErrorCode.INVALID_IRI_MAPPING); @@ -463,10 +479,10 @@ public void create(final String term) throws JsonLdError { // 19.3. JsonUtils.toStream(containerValue) - .filter(JsonUtils::isString) - .map(JsonString.class::cast) - .map(JsonString::getString) - .forEach(definition::addContainerMapping); + .filter(JsonUtils::isString) + .map(JsonString.class::cast) + .map(JsonString::getString) + .forEach(definition::addContainerMapping); // 19.4. if (definition.getContainerMapping().contains(Keywords.TYPE)) { @@ -501,13 +517,12 @@ public void create(final String term) throws JsonLdError { final String indexString = ((JsonString) index).getString(); - final String expandedIndex = - activeContext - .uriExpansion() - .localContext(localContext) - .defined(defined) - .vocab(true) - .expand(indexString); + final String expandedIndex = activeContext + .uriExpansion() + .localContext(localContext) + .defined(defined) + .vocab(true) + .expand(indexString); if (expandedIndex == null || UriUtils.isNotURI(expandedIndex)) { throw new JsonLdError(JsonLdErrorCode.INVALID_TERM_DEFINITION); @@ -553,8 +568,8 @@ public void create(final String term) throws JsonLdError { if (JsonUtils.isNull(language) || JsonUtils.isString(language)) { - if (JsonUtils.isString(language) && !LanguageTag.isWellFormed(((JsonString)language).getString())) { - LOGGER.log(Level.WARNING, "Language tag [{0}] is not well formed.", ((JsonString)language).getString()); + if (JsonUtils.isString(language) && !LanguageTag.isWellFormed(((JsonString) language).getString())) { + LOGGER.log(Level.WARNING, "Language tag [{0}] is not well formed.", ((JsonString) language).getString()); } definition.setLanguageMapping(language); @@ -642,9 +657,7 @@ public void create(final String term) throws JsonLdError { } // 26. - if (!Keywords.allMatch(valueObject.keySet(), Keywords.ID, Keywords.REVERSE, Keywords.CONTAINER, - Keywords.CONTEXT, Keywords.DIRECTION, Keywords.INDEX, Keywords.LANGUAGE, Keywords.NEST, Keywords.PREFIX, - Keywords.PROTECTED, Keywords.TYPE)) { + if (!PROTECTED_KEYWORDS.containsAll(valueObject.keySet())) { throw new JsonLdError(JsonLdErrorCode.INVALID_TERM_DEFINITION); } @@ -677,28 +690,19 @@ private final boolean validateContainer(final JsonValue value) { if (activeContext.inMode(JsonLdVersion.V1_0)) { return JsonUtils.isString(container) - && Keywords.noneMatch( - ((JsonString)container).getString(), - Keywords.GRAPH, - Keywords.ID, - Keywords.TYPE - ); + && Keywords.noneMatch( + ((JsonString) container).getString(), + Keywords.GRAPH, + Keywords.ID, + Keywords.TYPE); } if (JsonUtils.isArray(container) && container.asJsonArray().size() == 1) { container = container.asJsonArray().get(0); } - if (JsonUtils.isString(container) ) { - - return Keywords.anyMatch(((JsonString)container).getString(), - Keywords.GRAPH, - Keywords.ID, - Keywords.INDEX, - Keywords.LANGUAGE, - Keywords.LIST, - Keywords.SET, - Keywords.TYPE); + if (JsonUtils.isString(container)) { + return CONTAINER_KEYWORDS.contains(((JsonString) container).getString()); } return JsonUtils.isArray(container) && validateContainerArray(container.asJsonArray()); @@ -712,20 +716,18 @@ private static final boolean validateContainerArray(final JsonArray containers) if (JsonUtils.contains(Keywords.GRAPH, containers) && (JsonUtils.contains(Keywords.ID, containers) - || JsonUtils.contains(Keywords.INDEX, containers)) - ) { + || JsonUtils.contains(Keywords.INDEX, containers))) { return containers.size() == 2 || JsonUtils.contains(Keywords.SET, containers); } return containers.size() == 2 - && JsonUtils.contains(Keywords.SET, containers) - && (JsonUtils.contains(Keywords.GRAPH, containers) + && JsonUtils.contains(Keywords.SET, containers) + && (JsonUtils.contains(Keywords.GRAPH, containers) || JsonUtils.contains(Keywords.ID, containers) || JsonUtils.contains(Keywords.INDEX, containers) || JsonUtils.contains(Keywords.LANGUAGE, containers) - || JsonUtils.contains(Keywords.TYPE, containers) - ); + || JsonUtils.contains(Keywords.TYPE, containers)); } } \ No newline at end of file diff --git a/src/main/java/com/apicatalog/jsonld/expansion/ArrayExpansion.java b/src/main/java/com/apicatalog/jsonld/expansion/ArrayExpansion.java index df459058..2bf7025c 100644 --- a/src/main/java/com/apicatalog/jsonld/expansion/ArrayExpansion.java +++ b/src/main/java/com/apicatalog/jsonld/expansion/ArrayExpansion.java @@ -16,7 +16,6 @@ package com.apicatalog.jsonld.expansion; import java.net.URI; -import java.util.Optional; import com.apicatalog.jsonld.JsonLdError; import com.apicatalog.jsonld.context.ActiveContext; @@ -85,46 +84,40 @@ public ArrayExpansion fromMap(boolean value) { public JsonArray expand() throws JsonLdError { - // 5.1 final JsonArrayBuilder result = JsonProvider.instance().createArrayBuilder(); // 5.2. for (final JsonValue item : element) { // 5.2.1 - JsonValue expanded = - Expansion - .with(activeContext, item, activeProperty, baseUrl) - .frameExpansion(frameExpansion) - .ordered(ordered) - .fromMap(fromMap) - .compute(); - - final Optional definition = activeContext.getTerm(activeProperty); + JsonValue expanded = Expansion + .with(activeContext, item, activeProperty, baseUrl) + .frameExpansion(frameExpansion) + .ordered(ordered) + .fromMap(fromMap) + .compute(); // 5.2.2 - if (definition - .map(TermDefinition::getContainerMapping) - .filter(c -> c.contains(Keywords.LIST)).isPresent() - && JsonUtils.isArray(expanded)) { + if (JsonUtils.isArray(expanded) + && activeContext.getTerm(activeProperty) + .map(TermDefinition::getContainerMapping) + .filter(c -> c.contains(Keywords.LIST)).isPresent()) { expanded = ListObject.toListObject(expanded); } // 5.2.3 if (JsonUtils.isArray(expanded)) { + expanded.asJsonArray() + .stream() + .filter(JsonUtils::isNotNull) + .forEach(result::add); - // append array - expanded - .asJsonArray() - .stream() - .filter(JsonUtils::isNotNull) - .forEach(result::add); - - // append non-null element + // append non-null element } else if (JsonUtils.isNotNull(expanded)) { result.add(expanded); } + } // 5.3 diff --git a/src/main/java/com/apicatalog/jsonld/expansion/ObjectExpansion.java b/src/main/java/com/apicatalog/jsonld/expansion/ObjectExpansion.java index 5873f6c8..1e217c36 100644 --- a/src/main/java/com/apicatalog/jsonld/expansion/ObjectExpansion.java +++ b/src/main/java/com/apicatalog/jsonld/expansion/ObjectExpansion.java @@ -16,10 +16,9 @@ package com.apicatalog.jsonld.expansion; import java.net.URI; +import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import com.apicatalog.jsonld.JsonLdError; import com.apicatalog.jsonld.JsonLdErrorCode; @@ -111,26 +110,26 @@ public JsonValue expand() throws JsonLdError { final JsonMapBuilder result = JsonMapBuilder.create(); ObjectExpansion1314 - .with(activeContext, element, activeProperty, baseUrl) - .inputType(inputType) - .result(result) - .typeContext(typeContext) - .nest(new LinkedHashMap<>()) - .frameExpansion(frameExpansion) - .ordered(ordered) - .expand(); + .with(activeContext, element, activeProperty, baseUrl) + .inputType(inputType) + .result(result) + .typeContext(typeContext) + .nest(new LinkedHashMap<>()) + .frameExpansion(frameExpansion) + .ordered(ordered) + .expand(); // 15. if (result.containsKey(Keywords.VALUE)) { return normalizeValue(result); - // 16. + // 16. } else if (result.containsKey(Keywords.TYPE)) { return normalizeType(result); - // 17. + // 17. } else if (result.containsKey(Keywords.LIST) || result.containsKey(Keywords.SET)) { return normalizeContainer(result); @@ -142,17 +141,15 @@ public JsonValue expand() throws JsonLdError { private void initPropertyContext() throws JsonLdError { // 8. if (propertyContext != null) { - activeContext = activeContext - .newContext() - .overrideProtected(true) - .create( - propertyContext, - activeContext - .getTerm(activeProperty) - .map(TermDefinition::getBaseUrl) - .orElse(null) - ); + .newContext() + .overrideProtected(true) + .create( + propertyContext, + activeContext + .getTerm(activeProperty) + .map(TermDefinition::getBaseUrl) + .orElse(null)); } } @@ -173,11 +170,10 @@ private void initPreviousContext() throws JsonLdError { for (final String key : Utils.index(element.keySet(), true)) { - final String expandedKey = - activeContext - .uriExpansion() - .vocab(true) - .expand(key); + final String expandedKey = activeContext + .uriExpansion() + .vocab(true) + .expand(key); if (Keywords.VALUE.equals(expandedKey) || (Keywords.ID.equals(expandedKey) && (element.size() == 1))) { revert = false; @@ -194,10 +190,9 @@ private void initPreviousContext() throws JsonLdError { private void initLocalContext() throws JsonLdError { // 9. if (element.containsKey(Keywords.CONTEXT)) { - activeContext = activeContext - .newContext() - .create(element.get(Keywords.CONTEXT), baseUrl); + .newContext() + .create(element.get(Keywords.CONTEXT), baseUrl); } } @@ -208,11 +203,10 @@ private String processTypeScoped(final ActiveContext typeContext) throws JsonLdE // 11. for (final String key : Utils.index(element.keySet(), true)) { - final String expandedKey = - activeContext - .uriExpansion() - .vocab(true) - .expand(key); + final String expandedKey = activeContext + .uriExpansion() + .vocab(true) + .expand(key); if (!Keywords.TYPE.equals(expandedKey)) { continue; @@ -222,31 +216,28 @@ private String processTypeScoped(final ActiveContext typeContext) throws JsonLdE } // 11.2 - final List terms = JsonUtils - .toStream(element.get(key)) - .filter(JsonUtils::isString) - .map(JsonString.class::cast) - .map(JsonString::getString) - .sorted() - .collect(Collectors.toList()); + final Iterator terms = JsonUtils + .toStream(element.get(key)) + .filter(JsonUtils::isString) + .map(JsonString.class::cast) + .map(JsonString::getString) + .sorted() + .iterator(); - for (final String term : terms) { + while (terms.hasNext()) { - Optional localContext = typeContext.getTerm(term).map(TermDefinition::getLocalContext); + final String term = terms.next(); - if (localContext.isPresent()) { - - Optional valueDefinition = activeContext.getTerm(term); + final Optional localContext = typeContext.getTerm(term).map(TermDefinition::getLocalContext); - activeContext = - activeContext - .newContext() - .propagate(false) - .create(localContext.get(), - valueDefinition - .map(TermDefinition::getBaseUrl) - .orElse(null) - ); + if (localContext.isPresent()) { + activeContext = activeContext + .newContext() + .propagate(false) + .create(localContext.get(), + activeContext.getTerm(term) + .map(TermDefinition::getBaseUrl) + .orElse(null)); } } } @@ -268,13 +259,13 @@ private String findInputType(final String typeKey) throws JsonLdError { if (JsonUtils.isArray(type)) { final String lastValue = type.asJsonArray() - .stream() - .filter(JsonUtils::isString) - .map(JsonString.class::cast) - .map(JsonString::getString) - .sorted() - .reduce((first, second) -> second) - .orElse(null); + .stream() + .filter(JsonUtils::isString) + .map(JsonString.class::cast) + .map(JsonString::getString) + .sorted() + .reduce((first, second) -> second) + .orElse(null); if (lastValue != null) { return activeContext.uriExpansion().vocab(true).expand(lastValue); @@ -312,16 +303,15 @@ private JsonValue normalizeValue(final JsonMapBuilder result) throws JsonLdError if (value.map(v -> JsonUtils.isNull(v) || (JsonUtils.isArray(v) && v.asJsonArray().isEmpty())).orElse(true)) { return JsonValue.NULL; - // 15.4 + // 15.4 } else if (!frameExpansion && JsonUtils.isNotString(value.get()) && result.containsKey(Keywords.LANGUAGE)) { throw new JsonLdError(JsonLdErrorCode.INVALID_LANGUAGE_TAGGED_VALUE); - // 15.5 + // 15.5 } else if (!frameExpansion - && type.filter(t -> JsonUtils.isNotString(t) - || UriUtils.isNotURI(((JsonString) t).getString())) - .isPresent() - ) { + && type.filter(t -> JsonUtils.isNotString(t) + || UriUtils.isNotURI(((JsonString) t).getString())) + .isPresent()) { throw new JsonLdError(JsonLdErrorCode.INVALID_TYPED_VALUE); } } @@ -331,11 +321,10 @@ private JsonValue normalizeValue(final JsonMapBuilder result) throws JsonLdError private JsonValue normalizeType(final JsonMapBuilder result) throws JsonLdError { - result - .get(Keywords.TYPE) - .filter(JsonUtils::isNotArray) - .filter(JsonUtils::isNotNull) - .ifPresent(value -> result.put(Keywords.TYPE, JsonProvider.instance().createArrayBuilder().add(value).build())); + result.get(Keywords.TYPE) + .filter(JsonUtils::isNotArray) + .filter(JsonUtils::isNotNull) + .ifPresent(value -> result.put(Keywords.TYPE, JsonProvider.instance().createArrayBuilder().add(value).build())); return normalize(result); } @@ -355,7 +344,7 @@ private JsonValue normalizeContainer(final JsonMapBuilder result) throws JsonLdE return normalize(JsonMapBuilder.create(set.map(JsonValue::asJsonObject).get())); } else if (set.isPresent()) { - return set.get(); + return set.get(); } return normalize(result); @@ -366,10 +355,9 @@ private JsonValue normalize(final JsonMapBuilder result) throws JsonLdError { // Extension: JSON-LD-STAR (Experimental) if (result.containsKey(Keywords.ANNOTATION) && (StringUtils.isBlank(activeProperty) - || Keywords.GRAPH.equals(activeProperty) - || Keywords.INCLUDED.equals(activeProperty) - || result.get(Keywords.ANNOTATION).filter(NodeObject::isNotAnnotationObject).isPresent()) - ) { + || Keywords.GRAPH.equals(activeProperty) + || Keywords.INCLUDED.equals(activeProperty) + || result.get(Keywords.ANNOTATION).filter(NodeObject::isNotAnnotationObject).isPresent())) { throw new JsonLdError(JsonLdErrorCode.INVALID_ANNOTATION); } diff --git a/src/main/java/com/apicatalog/jsonld/expansion/ObjectExpansion1314.java b/src/main/java/com/apicatalog/jsonld/expansion/ObjectExpansion1314.java index 9423da37..5c892796 100644 --- a/src/main/java/com/apicatalog/jsonld/expansion/ObjectExpansion1314.java +++ b/src/main/java/com/apicatalog/jsonld/expansion/ObjectExpansion1314.java @@ -136,12 +136,11 @@ public void expand() throws JsonLdError { } // 13.2. - String expandedProperty = - activeContext - .uriExpansion() - .documentRelative(false) - .vocab(true) - .expand(key); + String expandedProperty = activeContext + .uriExpansion() + .documentRelative(false) + .vocab(true) + .expand(key); // 13.3. if (expandedProperty == null || (!expandedProperty.contains(":") && !Keywords.contains(expandedProperty))) { @@ -165,9 +164,9 @@ public void expand() throws JsonLdError { && Keywords.noneMatch(expandedProperty, Keywords.INCLUDED, Keywords.TYPE)) { throw new JsonLdError(JsonLdErrorCode.COLLIDING_KEYWORDS, - "Two properties which expand to the same keyword have been detected. A property '" + key + "'" - + " expands to '" + expandedProperty + "'" - + " but the '" + expandedProperty + "' property is already present." ); + "Two properties which expand to the same keyword have been detected. A property '" + key + "'" + + " expands to '" + expandedProperty + "'" + + " but the '" + expandedProperty + "' property is already present."); } // 13.4.3 @@ -180,35 +179,32 @@ public void expand() throws JsonLdError { } else if (activeContext.getOptions().isRdfStar() && JsonUtils.isNonEmptyObject(value)) { expandedValue = Expansion - .with(activeContext, value, null, baseUrl) - .frameExpansion(frameExpansion) - .ordered(ordered) - .compute(); + .with(activeContext, value, null, baseUrl) + .frameExpansion(frameExpansion) + .ordered(ordered) + .compute(); if (!NodeObject.isEmbeddedNode(expandedValue)) { throw new JsonLdError(JsonLdErrorCode.INVALID_EMBEDDED_NODE); } - // 13.4.3.1 + // 13.4.3.1 } else if (!frameExpansion && JsonUtils.isNotString(value) && (!activeContext.getOptions().isNumericId() || JsonUtils.isNotNumber(value)) || frameExpansion && JsonUtils.isNotString(value) && JsonUtils.isNonEmptyObject(value) && (JsonUtils.isNotArray(value) - || value.asJsonArray().stream().anyMatch(JsonUtils::isNotString) - ) - ) { + || value.asJsonArray().stream().anyMatch(JsonUtils::isNotString))) { throw new JsonLdError(JsonLdErrorCode.INVALID_KEYWORD_ID_VALUE, "An @id entry was encountered whose value [" + value + "] was not a string."); - // 13.4.3.2 + // 13.4.3.2 } else if (JsonUtils.isString(value)) { - final String expandedStringValue = - activeContext - .uriExpansion() - .documentRelative(true) - .vocab(false) - .expand(((JsonString) value).getString()); + final String expandedStringValue = activeContext + .uriExpansion() + .documentRelative(true) + .vocab(false) + .expand(((JsonString) value).getString()); if (expandedStringValue != null) { @@ -223,12 +219,11 @@ public void expand() throws JsonLdError { } else if (JsonUtils.isNumber(value)) { - final String expandedStringValue = - activeContext - .uriExpansion() - .documentRelative(true) - .vocab(false) - .expand(((JsonNumber) value).toString()); + final String expandedStringValue = activeContext + .uriExpansion() + .documentRelative(true) + .vocab(false) + .expand(((JsonNumber) value).toString()); if (expandedStringValue != null) { @@ -249,18 +244,17 @@ public void expand() throws JsonLdError { expandedValue = JsonValue.EMPTY_JSON_ARRAY; - } else if (JsonUtils.isArray(value)) { + } else if (JsonUtils.isArray(value)) { final JsonArrayBuilder array = JsonProvider.instance().createArrayBuilder(); for (final JsonValue item : JsonUtils.toCollection(value)) { - String expandedStringValue = - activeContext - .uriExpansion() - .documentRelative(true) - .vocab(false) - .expand(((JsonString) item).getString()); + String expandedStringValue = activeContext + .uriExpansion() + .documentRelative(true) + .vocab(false) + .expand(((JsonString) item).getString()); if (expandedStringValue != null) { array.add(expandedStringValue); @@ -278,22 +272,19 @@ else if (Keywords.TYPE.equals(expandedProperty)) { if ((!frameExpansion && JsonUtils.isNotString(value) && (JsonUtils.isNotArray(value) - || value.asJsonArray().stream().anyMatch(JsonUtils::isNotString) - )) + || value.asJsonArray().stream().anyMatch(JsonUtils::isNotString))) || frameExpansion && JsonUtils.isNotString(value) && JsonUtils.isNonEmptyObject(value) && (JsonUtils.isNotArray(value) - || value.asJsonArray().stream().anyMatch(JsonUtils::isNotString) - ) + || value.asJsonArray().stream().anyMatch(JsonUtils::isNotString)) && !DefaultObject.isDefaultObject(value) && DefaultObject.getValue(value) - .filter(JsonUtils::isString) - .map(JsonString.class::cast) - .map(JsonString::getString) - .map(UriUtils::isNotURI) - .orElse(true) - ) { + .filter(JsonUtils::isString) + .map(JsonString.class::cast) + .map(JsonString::getString) + .map(UriUtils::isNotURI) + .orElse(true)) { throw new JsonLdError(JsonLdErrorCode.INVALID_TYPE_VALUE, "@type value is not valid [" + value + "]."); } @@ -302,7 +293,7 @@ else if (Keywords.TYPE.equals(expandedProperty)) { if (JsonUtils.isEmptyObject(value)) { expandedValue = value; - // 13.4.4.3 + // 13.4.4.3 } else if (DefaultObject.isDefaultObject(value)) { final Optional defaultValue = DefaultObject.getValue(value); @@ -320,17 +311,16 @@ else if (Keywords.TYPE.equals(expandedProperty)) { .build(); } - // 13.4.4.4 + // 13.4.4.4 } else { if (JsonUtils.isString(value)) { - String expandedStringValue = - typeContext - .uriExpansion() - .vocab(true) - .documentRelative(true) - .expand(((JsonString) value).getString()); + String expandedStringValue = typeContext + .uriExpansion() + .vocab(true) + .documentRelative(true) + .expand(((JsonString) value).getString()); if (expandedStringValue != null) { expandedValue = JsonProvider.instance().createValue(expandedStringValue); @@ -344,12 +334,11 @@ else if (Keywords.TYPE.equals(expandedProperty)) { if (JsonUtils.isString(item)) { - final String expandedStringValue = - typeContext - .uriExpansion() - .vocab(true) - .documentRelative(true) - .expand(((JsonString) item).getString()); + final String expandedStringValue = typeContext + .uriExpansion() + .vocab(true) + .documentRelative(true) + .expand(((JsonString) item).getString()); if (expandedStringValue != null) { array.add(JsonProvider.instance().createValue(expandedStringValue)); @@ -378,11 +367,10 @@ else if (Keywords.TYPE.equals(expandedProperty)) { else if (Keywords.GRAPH.equals(expandedProperty)) { expandedValue = JsonUtils.toJsonArray(Expansion - .with(typeContext, value, Keywords.GRAPH, baseUrl) - .frameExpansion(frameExpansion) - .ordered(ordered) - .compute() - ); + .with(typeContext, value, Keywords.GRAPH, baseUrl) + .frameExpansion(frameExpansion) + .ordered(ordered) + .compute()); } // 13.4.6 @@ -395,10 +383,10 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { // 13.4.6.2 expandedValue = Expansion - .with(activeContext, value, null, baseUrl) - .frameExpansion(frameExpansion) - .ordered(ordered) - .compute(); + .with(activeContext, value, null, baseUrl) + .frameExpansion(frameExpansion) + .ordered(ordered) + .compute(); if (JsonUtils.isNotNull(expandedValue)) { @@ -446,16 +434,14 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { expandedValue = value; - // 13.4.7.2 + // 13.4.7.2 } else if (JsonUtils.isNull(value) - || JsonUtils.isScalar(value) - || frameExpansion - && (JsonUtils.isEmptyObject(value) - || JsonUtils.isEmptyArray(value) - || JsonUtils.isArray(value) - && value.asJsonArray().stream().allMatch(JsonUtils::isScalar) - ) - ) { + || JsonUtils.isScalar(value) + || frameExpansion + && (JsonUtils.isEmptyObject(value) + || JsonUtils.isEmptyArray(value) + || JsonUtils.isArray(value) + && value.asJsonArray().stream().allMatch(JsonUtils::isScalar))) { expandedValue = value; @@ -481,18 +467,16 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { if (JsonUtils.isString(value) || frameExpansion && (JsonUtils.isEmptyObject(value) - || JsonUtils.isEmptyArray(value) - || JsonUtils.isArray(value) - && value.asJsonArray().stream().allMatch(JsonUtils::isString) - ) - ) { - - if (JsonUtils.isString(value) && !LanguageTag.isWellFormed(((JsonString)value).getString())) { - LOGGER.log(Level.WARNING, "Language tag [{0}] is not well formed.", ((JsonString)value).getString()); + || JsonUtils.isEmptyArray(value) + || JsonUtils.isArray(value) + && value.asJsonArray().stream().allMatch(JsonUtils::isString))) { + + if (JsonUtils.isString(value) && !LanguageTag.isWellFormed(((JsonString) value).getString())) { + LOGGER.log(Level.WARNING, "Language tag [{0}] is not well formed.", ((JsonString) value).getString()); } // 13.4.8.2 - expandedValue = JsonUtils.isString(value) ? JsonProvider.instance().createValue(((JsonString)value).getString().toLowerCase()) : value; + expandedValue = JsonUtils.isString(value) ? JsonProvider.instance().createValue(((JsonString) value).getString().toLowerCase()) : value; if (frameExpansion) { expandedValue = JsonUtils.toJsonArray(expandedValue); @@ -517,9 +501,7 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { && (JsonUtils.isEmptyObject(value) || JsonUtils.isEmptyArray(value) || JsonUtils.isArray(value) - && value.asJsonArray().stream().allMatch(JsonUtils::isString) - ) - ) { + && value.asJsonArray().stream().allMatch(JsonUtils::isString))) { // 13.4.9.3. expandedValue = value; @@ -555,10 +537,10 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { // 13.4.11.1 expandedValue = Expansion - .with(activeContext, value, activeProperty, baseUrl) - .frameExpansion(frameExpansion) - .ordered(ordered) - .compute(); + .with(activeContext, value, activeProperty, baseUrl) + .frameExpansion(frameExpansion) + .ordered(ordered) + .compute(); if (JsonUtils.isNotArray(expandedValue)) { expandedValue = JsonProvider.instance().createArrayBuilder().add(expandedValue).build(); @@ -569,10 +551,10 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { if (Keywords.SET.equals(expandedProperty)) { expandedValue = Expansion - .with(activeContext, value, activeProperty, baseUrl) - .frameExpansion(frameExpansion) - .ordered(ordered) - .compute(); + .with(activeContext, value, activeProperty, baseUrl) + .frameExpansion(frameExpansion) + .ordered(ordered) + .compute(); } // 13.4.13 @@ -585,10 +567,10 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { // 13.4.13.2. expandedValue = Expansion - .with(activeContext, value, Keywords.REVERSE, baseUrl) - .frameExpansion(frameExpansion) - .ordered(ordered) - .compute(); + .with(activeContext, value, Keywords.REVERSE, baseUrl) + .frameExpansion(frameExpansion) + .ordered(ordered) + .compute(); if (JsonUtils.isObject(expandedValue)) { @@ -607,7 +589,6 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { if (expandedValueObject.size() > 1 || !expandedValueObject.containsKey(Keywords.REVERSE)) { - final JsonMapBuilder reverseMap = result.getMapBuilder(Keywords.REVERSE); // 13.4.13.4.2 @@ -677,13 +658,12 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { || Keywords.EMBED.equals(expandedProperty) || Keywords.EXPLICIT.equals(expandedProperty) || Keywords.OMIT_DEFAULT.equals(expandedProperty) - || Keywords.REQUIRE_ALL.equals(expandedProperty)) - ) { + || Keywords.REQUIRE_ALL.equals(expandedProperty))) { expandedValue = Expansion.with(activeContext, value, expandedProperty, baseUrl) - .frameExpansion(frameExpansion) - .ordered(ordered) - .compute(); + .frameExpansion(frameExpansion) + .ordered(ordered) + .compute(); } // 13.4.16 @@ -701,8 +681,8 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { final Optional keyTermDefinition = activeContext.getTerm(key); final Collection containerMapping = keyTermDefinition - .map(TermDefinition::getContainerMapping) - .orElseGet(() -> Collections.emptyList()); + .map(TermDefinition::getContainerMapping) + .orElse(Collections.emptyList()); JsonValue expandedValue = null; @@ -712,7 +692,7 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { expandedValue = JsonProvider.instance().createObjectBuilder().add(Keywords.VALUE, value) .add(Keywords.TYPE, Keywords.JSON).build(); - // 13.7. + // 13.7. } else if (containerMapping.contains(Keywords.LANGUAGE) && JsonUtils.isObject(value)) { // 13.7.1. @@ -720,9 +700,8 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { // 13.7.2. final DirectionType direction = keyTermDefinition - .map(TermDefinition::getDirectionMapping) - .orElseGet(() -> activeContext.getDefaultBaseDirection()) - ; + .map(TermDefinition::getDirectionMapping) + .orElseGet(() -> activeContext.getDefaultBaseDirection()); final JsonObject valueObject = value.asJsonObject(); @@ -755,11 +734,10 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { // 13.7.4.2.4. if (!Keywords.NONE.equals(langCode)) { - final String expandedLangCode = - activeContext - .uriExpansion() - .vocab(true) - .expand(langCode); + final String expandedLangCode = activeContext + .uriExpansion() + .vocab(true) + .expand(langCode); if (!Keywords.NONE.equals(expandedLangCode)) { @@ -781,7 +759,7 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { } } - // 13.8. + // 13.8. } else if ((containerMapping.contains(Keywords.INDEX) || containerMapping.contains(Keywords.TYPE) || containerMapping.contains(Keywords.ID)) && JsonUtils.isObject(value)) { @@ -790,8 +768,8 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { // 13.8.2. final String indexKey = keyTermDefinition - .map(TermDefinition::getIndexMapping) - .orElse(Keywords.INDEX); + .map(TermDefinition::getIndexMapping) + .orElse(Keywords.INDEX); // 13.8.3. for (final String index : Utils.index(value.asJsonObject().keySet(), ordered)) { @@ -811,13 +789,11 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { final Optional indexTermDefinition = mapContext.getTerm(index); if (containerMapping.contains(Keywords.TYPE) - && indexTermDefinition.map(TermDefinition::getLocalContext).isPresent() - ) { + && indexTermDefinition.map(TermDefinition::getLocalContext).isPresent()) { - mapContext = - mapContext - .newContext() - .create( + mapContext = mapContext + .newContext() + .create( indexTermDefinition.get().getLocalContext(), indexTermDefinition.get().getBaseUrl()); } @@ -828,11 +804,10 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { } // 13.8.3.4. - String expandedIndex = - activeContext - .uriExpansion() - .vocab(true) - .expand(index); + String expandedIndex = activeContext + .uriExpansion() + .vocab(true) + .expand(index); // 13.8.3.5. if (JsonUtils.isNotArray(indexValue)) { @@ -860,11 +835,10 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { .expand(JsonProvider.instance().createValue(index), indexKey); // 13.8.3.7.2.2. - final String expandedIndexKey = - activeContext - .uriExpansion() - .vocab(true) - .expand(indexKey); + final String expandedIndexKey = activeContext + .uriExpansion() + .vocab(true) + .expand(indexKey); // 13.8.3.7.2.3. final JsonArrayBuilder indexPropertyValues = JsonProvider.instance().createArrayBuilder().add(reExpandedIndex); @@ -884,34 +858,33 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { item = JsonProvider.instance().createObjectBuilder(item.asJsonObject()) .add(expandedIndexKey, indexPropertyValues).build(); - // 13.8.3.7.2.5. if (ValueObject.isValueObject(item) && item.asJsonObject().size() > 1) { throw new JsonLdError(JsonLdErrorCode.INVALID_VALUE_OBJECT); } - // 13.8.3.7.3. + // 13.8.3.7.3. } else if (containerMapping.contains(Keywords.INDEX) && !item.asJsonObject().containsKey(Keywords.INDEX) && !Keywords.NONE.equals(expandedIndex)) { item = JsonProvider.instance().createObjectBuilder(item.asJsonObject()).add(Keywords.INDEX, index).build(); - // 13.8.3.7.4. + // 13.8.3.7.4. } else if (containerMapping.contains(Keywords.ID) && !item.asJsonObject().containsKey(Keywords.ID) && !Keywords.NONE.equals(expandedIndex)) { expandedIndex = activeContext - .uriExpansion() - .vocab(false) - .documentRelative(true) - .expand(index); + .uriExpansion() + .vocab(false) + .documentRelative(true) + .expand(index); item = JsonProvider.instance().createObjectBuilder(item.asJsonObject()).add(Keywords.ID, expandedIndex) .build(); - // 13.8.3.7.5. + // 13.8.3.7.5. } else if (containerMapping.contains(Keywords.TYPE) && !Keywords.NONE.equals(expandedIndex)) { final JsonArrayBuilder types = JsonProvider.instance().createArrayBuilder().add(expandedIndex); @@ -936,14 +909,13 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { } } - // 13.9. + // 13.9. } else { - expandedValue = Expansion - .with(activeContext, value, key, baseUrl) - .frameExpansion(frameExpansion) - .ordered(ordered) - .compute(); + .with(activeContext, value, key, baseUrl) + .frameExpansion(frameExpansion) + .ordered(ordered) + .compute(); } // 13.10. @@ -964,9 +936,9 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { final JsonArrayBuilder array = JsonProvider.instance().createArrayBuilder(); JsonUtils - .toStream(expandedValue) - .map(GraphObject::toGraphObject) - .forEach(array::add); + .toStream(expandedValue) + .map(GraphObject::toGraphObject) + .forEach(array::add); expandedValue = array.build(); } @@ -989,8 +961,7 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { result.getMapBuilder(Keywords.REVERSE).add(expandedProperty, item); } - - // 13.14 + // 13.14 } else { result.add(expandedProperty, expandedValue); } @@ -1005,25 +976,21 @@ else if (Keywords.INCLUDED.equals(expandedProperty)) { private void recurse() throws JsonLdError { // step 3 - final JsonValue propertyContext = activeContext + final Optional propertyContext = activeContext .getTerm(activeProperty) - .map(TermDefinition::getLocalContext) - .orElse(null); - + .map(TermDefinition::getLocalContext); // step 8 - if (propertyContext != null) { - + if (propertyContext.isPresent()) { activeContext = activeContext - .newContext() - .overrideProtected(true) - .create( - propertyContext, - activeContext - .getTerm(activeProperty) - .map(TermDefinition::getBaseUrl) - .orElse(null) - ); + .newContext() + .overrideProtected(true) + .create( + propertyContext.get(), + activeContext + .getTerm(activeProperty) + .map(TermDefinition::getBaseUrl) + .orElse(null)); } // steps 13-14 @@ -1045,9 +1012,9 @@ private final void processNest() throws JsonLdError { for (final String nestedValueKey : nestValue.asJsonObject().keySet()) { if (Keywords.VALUE.equals(typeContext - .uriExpansion() - .vocab(true) - .expand(nestedValueKey))) { + .uriExpansion() + .vocab(true) + .expand(nestedValueKey))) { throw new JsonLdError(JsonLdErrorCode.INVALID_KEYWORD_NEST_VALUE); } diff --git a/src/main/java/com/apicatalog/jsonld/expansion/UriExpansion.java b/src/main/java/com/apicatalog/jsonld/expansion/UriExpansion.java index cfe14806..eae9f749 100644 --- a/src/main/java/com/apicatalog/jsonld/expansion/UriExpansion.java +++ b/src/main/java/com/apicatalog/jsonld/expansion/UriExpansion.java @@ -108,16 +108,16 @@ public String expand(final String value) throws JsonLdError { initLocalContext(value); - Optional definition = activeContext.getTerm(value); + final Optional definition = activeContext.getTerm(value); // 4. if active context has a term definition for value, // and the associated IRI mapping is a keyword, return that keyword. // 5. If vocab is true and the active context has a term definition for value, // return the associated IRI mapping - if (definition.isPresent() && (Keywords.contains(definition.get().getUriMapping()) || vocab)) { + if (definition.isPresent() && (vocab || Keywords.contains(definition.get().getUriMapping()))) { return definition.get().getUriMapping(); } - + String result = value; // 6. If value contains a colon (:) anywhere after the first character, it is @@ -157,11 +157,11 @@ private void initLocalContext(final String value) throws JsonLdError { */ if (localContext != null && localContext.containsKey(value)) { - JsonValue entryValue = localContext.get(value); + final JsonValue entryValue = localContext.get(value); if (JsonUtils.isString(entryValue)) { - String entryValueString = ((JsonString) entryValue).getString(); + final String entryValueString = ((JsonString) entryValue).getString(); if (!defined.containsKey(entryValueString) || Boolean.FALSE.equals(defined.get(entryValueString))) { activeContext.newTerm(localContext, defined).create(value); @@ -178,28 +178,21 @@ private String initPropertyContext(final String prefix, final String suffix, fin } // 6.4. - final Optional prefixDefinition = activeContext.getTerm(prefix); - - if (prefixDefinition.map(TermDefinition::getUriMapping).isPresent() - && prefixDefinition.filter(TermDefinition::isPrefix).isPresent()) { - - // deepcode ignore checkIsPresent~Optional: false positive - return prefixDefinition.map(TermDefinition::getUriMapping).map(m -> m.concat(suffix)).get(); - } - - return result; + return activeContext.getTerm(prefix) + .filter(TermDefinition::isPrefix) + .map(TermDefinition::getUriMapping) + .map(uriMapping -> uriMapping.concat(suffix)) + .orElse(result); } private String expandResult(final String result) { // 7. If vocab is true, and active context has a vocabulary mapping, // return the result of concatenating the vocabulary mapping with value. if (vocab && activeContext.getVocabularyMapping() != null) { - return activeContext.getVocabularyMapping().concat(result); - // 8. + // 8. } else if (documentRelative) { - return UriResolver.resolve(activeContext.getBaseUri(), result); } diff --git a/src/main/java/com/apicatalog/jsonld/expansion/ValueExpansion.java b/src/main/java/com/apicatalog/jsonld/expansion/ValueExpansion.java index 6d588aec..1cb247bb 100644 --- a/src/main/java/com/apicatalog/jsonld/expansion/ValueExpansion.java +++ b/src/main/java/com/apicatalog/jsonld/expansion/ValueExpansion.java @@ -69,7 +69,7 @@ public JsonObject expand(final JsonValue value, final String activeProperty) thr if (JsonUtils.isString(value)) { idValue = ((JsonString) value).getString(); - // custom extension allowing to process numeric ids + // custom extension allowing to process numeric ids } else if (activeContext.getOptions().isNumericId() && JsonUtils.isNumber(value)) { idValue = ((JsonNumber) value).toString(); } @@ -81,7 +81,7 @@ public JsonObject expand(final JsonValue value, final String activeProperty) thr return JsonProvider.instance().createObjectBuilder().add(Keywords.ID, expandedValue).build(); } - // 2. + // 2. } else if (Keywords.VOCAB.equals(typeMapping.get()) && JsonUtils.isString(value)) { String expandedValue = activeContext.uriExpansion().documentRelative(true) @@ -96,8 +96,8 @@ public JsonObject expand(final JsonValue value, final String activeProperty) thr // 4. if (typeMapping - .filter(t -> !Keywords.ID.equals(t) && !Keywords.VOCAB.equals(t) && !Keywords.NONE.equals(t)) - .isPresent()) { + .filter(t -> !Keywords.ID.equals(t) && !Keywords.VOCAB.equals(t) && !Keywords.NONE.equals(t)) + .isPresent()) { result.add(Keywords.TYPE, typeMapping.get()); @@ -114,14 +114,16 @@ private void buildStringValue(final JsonObjectBuilder result) { // 5.1. final JsonValue language = definition - .map(TermDefinition::getLanguageMapping) - .orElseGet(() -> activeContext.getDefaultLanguage() != null - ? JsonProvider.instance().createValue(activeContext.getDefaultLanguage()) - : null); + .map(TermDefinition::getLanguageMapping) + .orElseGet(() -> activeContext.getDefaultLanguage() != null + ? JsonProvider.instance().createValue(activeContext.getDefaultLanguage()) + : null + ); + // 5.2. final DirectionType direction = definition - .map(TermDefinition::getDirectionMapping) - .orElseGet(() -> activeContext.getDefaultBaseDirection()); + .map(TermDefinition::getDirectionMapping) + .orElseGet(() -> activeContext.getDefaultBaseDirection()); // 5.3. if (JsonUtils.isNotNull(language)) { diff --git a/src/main/java/com/apicatalog/jsonld/json/JsonMapBuilder.java b/src/main/java/com/apicatalog/jsonld/json/JsonMapBuilder.java index 461bc8ad..411c082b 100644 --- a/src/main/java/com/apicatalog/jsonld/json/JsonMapBuilder.java +++ b/src/main/java/com/apicatalog/jsonld/json/JsonMapBuilder.java @@ -15,6 +15,8 @@ */ package com.apicatalog.jsonld.json; +import java.util.Arrays; +import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; @@ -29,6 +31,14 @@ public final class JsonMapBuilder { + private static final Collection VALUE_KEYWORDS = Arrays.asList( + Keywords.TYPE, + Keywords.VALUE, + Keywords.DIRECTION, + Keywords.LANGUAGE, + Keywords.INDEX, + Keywords.ANNOTATION); + private final Map map; private JsonMapBuilder(Map map) { @@ -105,9 +115,9 @@ public Optional get(String key) { } throw new IllegalStateException(); } - + public boolean isNotValueObject() { - return !Keywords.allMatch(map.keySet(), Keywords.TYPE, Keywords.VALUE, Keywords.DIRECTION, Keywords.LANGUAGE, Keywords.INDEX, Keywords.ANNOTATION); + return !VALUE_KEYWORDS.containsAll(map.keySet()); } public JsonArray valuesToArray() { diff --git a/src/main/java/com/apicatalog/jsonld/lang/Keywords.java b/src/main/java/com/apicatalog/jsonld/lang/Keywords.java index 78895a48..916e2e2c 100644 --- a/src/main/java/com/apicatalog/jsonld/lang/Keywords.java +++ b/src/main/java/com/apicatalog/jsonld/lang/Keywords.java @@ -135,7 +135,7 @@ public static boolean matchForm(final String value) { public static boolean noneMatch(final String key, final String... keywords) { // vanilla approach is 3 times faster than stream.noneMatch - for (String k : keywords) { + for (final String k : keywords) { if (k.equals(key)) { return false; } @@ -143,10 +143,12 @@ public static boolean noneMatch(final String key, final String... keywords) { return true; } + @Deprecated public static boolean anyMatch(final String key, final String... keywords) { return Arrays.asList(keywords).contains(key); } + @Deprecated public static boolean allMatch(final Collection values, final String... keywords) { return Arrays.asList(keywords).containsAll(values); } diff --git a/src/main/java/com/apicatalog/jsonld/lang/Utils.java b/src/main/java/com/apicatalog/jsonld/lang/Utils.java index 4dc4b795..05afcbc1 100644 --- a/src/main/java/com/apicatalog/jsonld/lang/Utils.java +++ b/src/main/java/com/apicatalog/jsonld/lang/Utils.java @@ -25,7 +25,7 @@ private Utils() {} public static final Collection index(final Collection keys, final boolean ordered) { - if (keys == null) { + if (keys == null || keys.isEmpty()) { return Collections.emptyList(); } From d20122a7f4e273f759482d4378b6116d3496486c Mon Sep 17 00:00:00 2001 From: Filip Date: Tue, 5 Dec 2023 20:16:14 +0100 Subject: [PATCH 3/4] Minor tweaks --- .../jsonld/context/ActiveContextBuilder.java | 89 ++++++------ .../jsonld/context/InverseContext.java | 6 +- .../jsonld/context/InverseContextBuilder.java | 130 ++++++++---------- .../jsonld/context/TermSelector.java | 26 ++-- .../jsonld/expansion/UriExpansion.java | 24 ++-- 5 files changed, 135 insertions(+), 140 deletions(-) diff --git a/src/main/java/com/apicatalog/jsonld/context/ActiveContextBuilder.java b/src/main/java/com/apicatalog/jsonld/context/ActiveContextBuilder.java index dca369ac..10b3d9fc 100644 --- a/src/main/java/com/apicatalog/jsonld/context/ActiveContextBuilder.java +++ b/src/main/java/com/apicatalog/jsonld/context/ActiveContextBuilder.java @@ -120,11 +120,10 @@ public ActiveContext create(final JsonValue localContext, final URI baseUrl) thr // its value MUST be boolean true or false, set propagate to that value. if (JsonUtils.isObject(localContext)) { - final JsonObject localContextObject = localContext.asJsonObject(); + final JsonValue propagateValue = localContext.asJsonObject() + .get(Keywords.PROPAGATE); - if (localContextObject.containsKey(Keywords.PROPAGATE)) { - - final JsonValue propagateValue = localContextObject.get(Keywords.PROPAGATE); + if (propagateValue != null) { if (JsonUtils.isNotBoolean(propagateValue)) { throw new JsonLdError(JsonLdErrorCode.INVALID_KEYWORD_PROPAGATE_VALUE); @@ -171,7 +170,7 @@ public ActiveContext create(final JsonValue localContext, final URI baseUrl) thr // 5.2. if context is a string, if (JsonUtils.isString(itemContext)) { - fetch(((JsonString)itemContext).getString(), baseUrl); + fetch(((JsonString) itemContext).getString(), baseUrl); // 5.2.7 continue; @@ -186,10 +185,10 @@ public ActiveContext create(final JsonValue localContext, final URI baseUrl) thr // 5.4. Otherwise, context is a context definition JsonObject contextDefinition = itemContext.asJsonObject(); - // 5.5. If context has an @version - if (contextDefinition.containsKey(Keywords.VERSION)) { + final JsonValue version = contextDefinition.get(Keywords.VERSION); - final JsonValue version = contextDefinition.get(Keywords.VERSION); + // 5.5. If context has an @version + if (version != null) { String versionString = null; @@ -250,10 +249,10 @@ public ActiveContext create(final JsonValue localContext, final URI baseUrl) thr } importedStructure = importedDocument - .getJsonContent() - .orElseThrow(() -> new JsonLdError(JsonLdErrorCode.INVALID_KEYWORD_IMPORT_VALUE)); + .getJsonContent() + .orElseThrow(() -> new JsonLdError(JsonLdErrorCode.INVALID_KEYWORD_IMPORT_VALUE)); - // 5.6.5 + // 5.6.5 } catch (JsonLdError e) { throw new JsonLdError(JsonLdErrorCode.INVALID_KEYWORD_IMPORT_VALUE, e); } @@ -263,27 +262,27 @@ public ActiveContext create(final JsonValue localContext, final URI baseUrl) thr throw new JsonLdError(JsonLdErrorCode.INVALID_REMOTE_CONTEXT); } - JsonObject importedContext = importedStructure.asJsonObject(); + final JsonValue importedContext = importedStructure.asJsonObject().get(Keywords.CONTEXT); - if (!importedContext.containsKey(Keywords.CONTEXT) - || JsonUtils.isNotObject(importedContext.get(Keywords.CONTEXT))) { + if (importedContext == null + || JsonUtils.isNotObject(importedContext)) { throw new JsonLdError(JsonLdErrorCode.INVALID_REMOTE_CONTEXT); } - importedContext = importedContext.getJsonObject(Keywords.CONTEXT); + final JsonObject importedContextObject = importedContext.asJsonObject(); // 5.6.7 - if (importedContext.containsKey(Keywords.IMPORT)) { + if (importedContextObject.containsKey(Keywords.IMPORT)) { throw new JsonLdError(JsonLdErrorCode.INVALID_CONTEXT_ENTRY); } // 5.6.8 - contextDefinition = JsonUtils.merge(importedContext, contextDefinition); + contextDefinition = JsonUtils.merge(importedContextObject, contextDefinition); } // 5.7. If context has an @base entry and remote contexts is empty, // i.e., the currently being processed context is not a remote context: - if (contextDefinition.containsKey(Keywords.BASE) /*&& remoteContexts.isEmpty()*/) { + if (contextDefinition.containsKey(Keywords.BASE) /* && remoteContexts.isEmpty() */) { // 5.7.1 JsonValue value = contextDefinition.get(Keywords.BASE); @@ -303,18 +302,18 @@ public ActiveContext create(final JsonValue localContext, final URI baseUrl) thr if (valueUri.isAbsolute()) { result.setBaseUri(valueUri); - // 5.7.4 + // 5.7.4 } else if (result.getBaseUri() != null) { result.setBaseUri(UriResolver.resolveAsUri(result.getBaseUri(), valueUri)); } else { LOGGER.log(Level.FINE, - "5.7.4: valueString={0}, localContext={1}, baseUrl={2}", - new Object[] {valueString, localContext, baseUrl}); + "5.7.4: valueString={0}, localContext={1}, baseUrl={2}", + new Object[] { valueString, localContext, baseUrl }); throw new JsonLdError(JsonLdErrorCode.INVALID_BASE_IRI, "A relative base IRI cannot be resolved [@base = " + valueString + - "]. Please use JsonLdOptions.setBase() method to set an absolute IRI."); + "]. Please use JsonLdOptions.setBase() method to set an absolute IRI."); } } else if (StringUtils.isNotBlank(valueString)) { @@ -338,19 +337,18 @@ public ActiveContext create(final JsonValue localContext, final URI baseUrl) thr if (JsonUtils.isNull(value)) { result.setVocabularyMapping(null); - // 5.8.3 + // 5.8.3 } else if (JsonUtils.isString(value)) { final String valueString = ((JsonString) value).getString(); if (StringUtils.isBlank(valueString) || BlankNode.hasPrefix(valueString) || UriUtils.isURI(valueString)) { - final String vocabularyMapping = - result - .uriExpansion() - .vocab(true) - .documentRelative(true) - .expand(valueString); + final String vocabularyMapping = result + .uriExpansion() + .vocab(true) + .documentRelative(true) + .expand(valueString); if (BlankNode.hasPrefix(valueString) || UriUtils.isURI(vocabularyMapping)) { result.setVocabularyMapping(vocabularyMapping); @@ -378,10 +376,10 @@ public ActiveContext create(final JsonValue localContext, final URI baseUrl) thr if (JsonUtils.isNull(value)) { result.setDefaultLanguage(null); - // 5.9.3 + // 5.9.3 } else if (JsonUtils.isString(value)) { - result.setDefaultLanguage(((JsonString)value).getString()); + result.setDefaultLanguage(((JsonString) value).getString()); if (!LanguageTag.isWellFormed(result.getDefaultLanguage())) { LOGGER.log(Level.WARNING, "Language tag [{0}] is not well formed.", result.getDefaultLanguage()); @@ -407,7 +405,7 @@ public ActiveContext create(final JsonValue localContext, final URI baseUrl) thr if (JsonUtils.isNull(value)) { result.setDefaultBaseDirection(DirectionType.NULL); - // 5.10.4. + // 5.10.4. } else if (JsonUtils.isString(value)) { final String direction = ((JsonString) value).getString(); @@ -439,11 +437,10 @@ public ActiveContext create(final JsonValue localContext, final URI baseUrl) thr } } - final TermDefinitionBuilder termBuilder = - result - .newTerm(contextDefinition, new HashMap<>()) - .baseUrl(baseUrl) - .overrideProtectedFlag(overrideProtected); + final TermDefinitionBuilder termBuilder = result + .newTerm(contextDefinition, new HashMap<>()) + .baseUrl(baseUrl) + .overrideProtectedFlag(overrideProtected); // 5.13 for (final String key : contextDefinition.keySet()) { @@ -452,9 +449,9 @@ public ActiveContext create(final JsonValue localContext, final URI baseUrl) thr Keywords.PROPAGATE, Keywords.PROTECTED, Keywords.VERSION, Keywords.VOCAB)) { termBuilder - .protectedFlag(JsonUtils.isTrue(contextDefinition.get(Keywords.PROTECTED))) - .remoteContexts(new ArrayList<>(remoteContexts)) - .create(key); + .protectedFlag(JsonUtils.isTrue(contextDefinition.get(Keywords.PROTECTED))) + .remoteContexts(new ArrayList<>(remoteContexts)) + .create(key); } } } @@ -534,7 +531,7 @@ private void fetch(final String context, final URI baseUrl) throws JsonLdError { remoteImport = activeContext.getOptions().getDocumentLoader().loadDocument(contextUri, loaderOptions); - // 5.2.5.1. + // 5.2.5.1. } catch (JsonLdError e) { throw new JsonLdError(JsonLdErrorCode.LOADING_REMOTE_CONTEXT_FAILED, e); } @@ -545,7 +542,7 @@ private void fetch(final String context, final URI baseUrl) throws JsonLdError { } final JsonStructure importedStructure = remoteImport.getJsonContent() - .orElseThrow(() -> new JsonLdError(JsonLdErrorCode.INVALID_REMOTE_CONTEXT, "Imported context is null.")); + .orElseThrow(() -> new JsonLdError(JsonLdErrorCode.INVALID_REMOTE_CONTEXT, "Imported context is null.")); // 5.2.5.2. if (JsonUtils.isNotObject(importedStructure)) { @@ -575,10 +572,10 @@ private void fetch(final String context, final URI baseUrl) throws JsonLdError { // 5.2.6 try { result = result - .newContext() - .remoteContexts(new ArrayList<>(remoteContexts)) - .validateScopedContext(validateScopedContext) - .create(importedContext, remoteImport.getDocumentUrl()); + .newContext() + .remoteContexts(new ArrayList<>(remoteContexts)) + .validateScopedContext(validateScopedContext) + .create(importedContext, remoteImport.getDocumentUrl()); if (result.getOptions() != null && result.getOptions().getContextCache() != null && !validateScopedContext) { result.getOptions().getContextCache().put(contextKey, importedContext); diff --git a/src/main/java/com/apicatalog/jsonld/context/InverseContext.java b/src/main/java/com/apicatalog/jsonld/context/InverseContext.java index d29f5fab..6840b396 100644 --- a/src/main/java/com/apicatalog/jsonld/context/InverseContext.java +++ b/src/main/java/com/apicatalog/jsonld/context/InverseContext.java @@ -53,9 +53,9 @@ public boolean contains(final String variable, final String container, final Str public boolean contains(final String variable, final String container, final String type, final String key) { return contains(variable) - && context.get(variable).containsKey(container) - && context.get(variable).get(container).containsKey(type) - && context.get(variable).get(container).get(type).containsKey(key); + && context.get(variable).containsKey(container) + && context.get(variable).get(container).containsKey(type) + && context.get(variable).get(container).get(type).containsKey(key); } public InverseContext setIfAbsent(final String variable, final String container, final String type, final String key, final String value) { diff --git a/src/main/java/com/apicatalog/jsonld/context/InverseContextBuilder.java b/src/main/java/com/apicatalog/jsonld/context/InverseContextBuilder.java index e806594f..da19154d 100644 --- a/src/main/java/com/apicatalog/jsonld/context/InverseContextBuilder.java +++ b/src/main/java/com/apicatalog/jsonld/context/InverseContextBuilder.java @@ -28,7 +28,9 @@ /** * - * @see Inverse Context Creation + * @see Inverse + * Context Creation * */ public final class InverseContextBuilder { @@ -50,27 +52,24 @@ public InverseContext build() { // 2. final String defaultLanguage = activeContext.getDefaultLanguage() != null - ? activeContext.getDefaultLanguage().toLowerCase() - : Keywords.NONE; + ? activeContext.getDefaultLanguage().toLowerCase() + : Keywords.NONE; // 3 activeContext.getTerms() - .stream() - .filter(termName -> activeContext - .getTerm(termName) - .map(TermDefinition::getUriMapping) - .isPresent()) - .sorted() - - .forEach(termName -> - processTerm( - termName, - result, - activeContext - .getTerm(termName) - .map(TermDefinition::getUriMapping) - .get(), - defaultLanguage) - ); + .stream() + .filter(termName -> activeContext + .getTerm(termName) + .map(TermDefinition::getUriMapping) + .isPresent()) + .sorted() + .forEach(termName -> processTerm( + termName, + result, + activeContext + .getTerm(termName) + .map(TermDefinition::getUriMapping) + .get(), + defaultLanguage)); // 4. return result; @@ -80,13 +79,13 @@ private void processTerm(final String termName, InverseContext result, final Str // 3.2. final String container = activeContext - .getTerm(termName) - .map(TermDefinition::getContainerMapping) - .filter(collection -> !collection.isEmpty()) - .orElseGet(() -> Arrays.asList(Keywords.NONE)) - .stream() - .sorted() - .collect(Collectors.joining()); + .getTerm(termName) + .map(TermDefinition::getContainerMapping) + .filter(collection -> !collection.isEmpty()) + .orElseGet(() -> Arrays.asList(Keywords.NONE)) + .stream() + .sorted() + .collect(Collectors.joining()); result.setIfAbsent(variableValue, container, Keywords.ANY, Keywords.NONE, termName); @@ -95,7 +94,6 @@ private void processTerm(final String termName, InverseContext result, final Str // 3.10.1 result.setIfAbsent(variableValue, container, Keywords.TYPE, Keywords.REVERSE, termName); - return; } @@ -104,10 +102,8 @@ private void processTerm(final String termName, InverseContext result, final Str // 3.11. if (typeMapping.filter(Keywords.NONE::equals).isPresent()) { - result - .setIfAbsent(variableValue, container, Keywords.LANGUAGE, Keywords.ANY, termName) - .setIfAbsent(variableValue, container, Keywords.TYPE, Keywords.ANY, termName); - + result.setIfAbsent(variableValue, container, Keywords.LANGUAGE, Keywords.ANY, termName) + .setIfAbsent(variableValue, container, Keywords.TYPE, Keywords.ANY, termName); return; } @@ -119,16 +115,13 @@ private void processTerm(final String termName, InverseContext result, final Str return; } - final Optional languageMapping = - activeContext - .getTerm(termName) - .map(TermDefinition::getLanguageMapping); - - final Optional directionMapping = - activeContext - .getTerm(termName) - .map(TermDefinition::getDirectionMapping); + final Optional languageMapping = activeContext + .getTerm(termName) + .map(TermDefinition::getLanguageMapping); + final Optional directionMapping = activeContext + .getTerm(termName) + .map(TermDefinition::getDirectionMapping); if (languageMapping.isPresent()) { @@ -147,16 +140,16 @@ private void processTerm(final String termName, InverseContext result, final Str if (direction != DirectionType.NULL) { - langDir = ((JsonString)language).getString() - .concat("_") - .concat(direction.name()) - .toLowerCase(); - // 3.13.3. + langDir = ((JsonString) language).getString() + .concat("_") + .concat(direction.name()) + .toLowerCase(); + // 3.13.3. } else { - langDir = ((JsonString)language).getString().toLowerCase(); + langDir = ((JsonString) language).getString().toLowerCase(); } - // 3.13.4. + // 3.13.4. } else if (direction != DirectionType.NULL) { langDir = "_".concat(direction.name().toLowerCase()); @@ -167,43 +160,40 @@ private void processTerm(final String termName, InverseContext result, final Str } else { langDir = JsonUtils.isString(language) - ? ((JsonString)language).getString().toLowerCase() - : Keywords.NULL; + ? ((JsonString) language).getString().toLowerCase() + : Keywords.NULL; } // 3.13.5. result.setIfAbsent(variableValue, container, Keywords.LANGUAGE, langDir, termName); - // 3.15. + // 3.15. } else if (directionMapping.isPresent()) { // 3.15.1. final String direction = directionMapping - .filter(d -> d != DirectionType.NULL) - .map(d -> "_".concat(d.name().toLowerCase())) - .orElse(Keywords.NONE); + .filter(d -> d != DirectionType.NULL) + .map(d -> "_".concat(d.name().toLowerCase())) + .orElse(Keywords.NONE); // 3.15.2. result.setIfAbsent(variableValue, container, Keywords.LANGUAGE, direction, termName); - // 3.16. + // 3.16. } else { final String langDir = activeContext.getDefaultBaseDirection() != null - - ? (activeContext.getDefaultLanguage() != null - ? activeContext.getDefaultLanguage() - : "" - ) - .concat("_") - .concat(activeContext.getDefaultBaseDirection().name()) - .toLowerCase() - - : defaultLanguage; - - result - .setIfAbsent(variableValue, container, Keywords.LANGUAGE, langDir, termName) - .setIfAbsent(variableValue, container, Keywords.LANGUAGE, Keywords.NONE, termName) - .setIfAbsent(variableValue, container, Keywords.TYPE, Keywords.NONE, termName); + ? (activeContext.getDefaultLanguage() != null + ? activeContext.getDefaultLanguage() + : "") + .concat("_") + .concat(activeContext.getDefaultBaseDirection().name()) + .toLowerCase() + + : defaultLanguage; + + result.setIfAbsent(variableValue, container, Keywords.LANGUAGE, langDir, termName) + .setIfAbsent(variableValue, container, Keywords.LANGUAGE, Keywords.NONE, termName) + .setIfAbsent(variableValue, container, Keywords.TYPE, Keywords.NONE, termName); } } } diff --git a/src/main/java/com/apicatalog/jsonld/context/TermSelector.java b/src/main/java/com/apicatalog/jsonld/context/TermSelector.java index 7788f304..7c4f10d8 100644 --- a/src/main/java/com/apicatalog/jsonld/context/TermSelector.java +++ b/src/main/java/com/apicatalog/jsonld/context/TermSelector.java @@ -21,7 +21,8 @@ /** * - * @see Term Selection + * @see Term + * Selection * */ public final class TermSelector { @@ -49,25 +50,24 @@ public static TermSelector with(final ActiveContext activeContext, final String public Optional match(final Collection preferredValues) { // 1. If the active context has a null inverse context, - // set inverse context in active context to the result of calling - // the Inverse Context Creation algorithm using active context. + // set inverse context in active context to the result of calling + // the Inverse Context Creation algorithm using active context. if (activeContext.getInverseContext() == null) { activeContext.createInverseContext(); } - // 2. Initialize inverse context to the value of inverse context in active context. + // 2. Initialize inverse context to the value of inverse context in active + // context. final InverseContext inverseContext = activeContext.getInverseContext(); // 4. return containers - .stream() - .filter(container -> inverseContext.contains(variable, container, typeLanguage)) - - .flatMap(container -> preferredValues - .stream() - .map(item -> inverseContext.get(variable, container, typeLanguage, item))) - - .flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty)) - .findFirst(); + .stream() + .filter(container -> inverseContext.contains(variable, container, typeLanguage)) + .flatMap(container -> preferredValues + .stream() + .map(item -> inverseContext.get(variable, container, typeLanguage, item))) + .flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty)) + .findFirst(); } } \ No newline at end of file diff --git a/src/main/java/com/apicatalog/jsonld/expansion/UriExpansion.java b/src/main/java/com/apicatalog/jsonld/expansion/UriExpansion.java index eae9f749..bb7eb73b 100644 --- a/src/main/java/com/apicatalog/jsonld/expansion/UriExpansion.java +++ b/src/main/java/com/apicatalog/jsonld/expansion/UriExpansion.java @@ -108,35 +108,43 @@ public String expand(final String value) throws JsonLdError { initLocalContext(value); - final Optional definition = activeContext.getTerm(value); + final Optional definition = activeContext.getTerm(value) + .filter(term -> vocab || Keywords.contains(term.getUriMapping())); // 4. if active context has a term definition for value, // and the associated IRI mapping is a keyword, return that keyword. // 5. If vocab is true and the active context has a term definition for value, // return the associated IRI mapping - if (definition.isPresent() && (vocab || Keywords.contains(definition.get().getUriMapping()))) { + if (definition.isPresent()) { return definition.get().getUriMapping(); } - + String result = value; // 6. If value contains a colon (:) anywhere after the first character, it is // either an IRI, // a compact IRI, or a blank node identifier - if (result.indexOf(':', 1) != -1) { + final int splitIndex = result.indexOf(':', 1); + + if (splitIndex != -1) { // 6.1. Split value into a prefix and suffix at the first occurrence of a colon // (:). - String[] split = result.split(":", 2); - // 6.2. If prefix is underscore (_) or suffix begins with double-forward-slash // (//), // return value as it is already an IRI or a blank node identifier. - if ("_".equals(split[0]) || split[1].startsWith("//")) { + if (result.charAt(0) == '_' || (((splitIndex + 2) < result.length()) + && result.charAt(splitIndex + 1) == '/' + && result.charAt(splitIndex + 2) == '/')) { return result; } - result = initPropertyContext(split[0], split[1], result); + result = initPropertyContext( + result.substring(0, splitIndex), + (splitIndex + 1) < result.length() + ? result.substring(splitIndex + 1) + : "", + result); // 6.5 if (BlankNode.hasPrefix(result) || UriUtils.isAbsoluteUri(result, uriValidation)) { From 0bdecb687ea6db3e324c4531b9bf5052aafce6fc Mon Sep 17 00:00:00 2001 From: Filip Date: Tue, 5 Dec 2023 20:38:23 +0100 Subject: [PATCH 4/4] RE minor improvements --- .../jsonld/expansion/UriExpansion.java | 16 ++- .../jsonld/http/link/LinkHeaderParser.java | 103 +++++++++--------- .../jsonld/lang/LanguageTagParser.java | 40 ++++--- .../java/com/apicatalog/jsonld/uri/Path.java | 38 +++---- 4 files changed, 102 insertions(+), 95 deletions(-) diff --git a/src/main/java/com/apicatalog/jsonld/expansion/UriExpansion.java b/src/main/java/com/apicatalog/jsonld/expansion/UriExpansion.java index bb7eb73b..3a6397bf 100644 --- a/src/main/java/com/apicatalog/jsonld/expansion/UriExpansion.java +++ b/src/main/java/com/apicatalog/jsonld/expansion/UriExpansion.java @@ -122,20 +122,18 @@ public String expand(final String value) throws JsonLdError { String result = value; // 6. If value contains a colon (:) anywhere after the first character, it is - // either an IRI, // a compact IRI, or a blank node identifier final int splitIndex = result.indexOf(':', 1); if (splitIndex != -1) { - - // 6.1. Split value into a prefix and suffix at the first occurrence of a colon - // (:). + // 6.1. Split value into a prefix and suffix + // at the first occurrence of a colon (:). // 6.2. If prefix is underscore (_) or suffix begins with double-forward-slash - // (//), - // return value as it is already an IRI or a blank node identifier. - if (result.charAt(0) == '_' || (((splitIndex + 2) < result.length()) - && result.charAt(splitIndex + 1) == '/' - && result.charAt(splitIndex + 2) == '/')) { + // (//), return value as it is already an IRI or a blank node identifier. + if ((splitIndex == 1 && result.charAt(0) == '_') + || (((splitIndex + 2) < result.length()) + && result.charAt(splitIndex + 1) == '/' + && result.charAt(splitIndex + 2) == '/')) { return result; } diff --git a/src/main/java/com/apicatalog/jsonld/http/link/LinkHeaderParser.java b/src/main/java/com/apicatalog/jsonld/http/link/LinkHeaderParser.java index 1dd6dae1..05a59780 100644 --- a/src/main/java/com/apicatalog/jsonld/http/link/LinkHeaderParser.java +++ b/src/main/java/com/apicatalog/jsonld/http/link/LinkHeaderParser.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; import com.apicatalog.jsonld.StringUtils; import com.apicatalog.jsonld.http.HttpAlphabet; @@ -32,7 +33,8 @@ /** * - * @see Appendix B. Algorithms for Parsing Link Header Fields + * @see Appendix B. + * Algorithms for Parsing Link Header Fields * */ final class LinkHeaderParser { @@ -41,8 +43,12 @@ final class LinkHeaderParser { private static final String ANCHOR = "anchor"; private static final String TYPE = "type"; - private enum State { INIT, URI_REF, PARAMS, PARAM_NAME_BEGIN, PARAM_NAME, PARAM_NAME_END, PARAM_VALUE, - STRING_VALUE, LITERAL_VALUE, ESCAPE, UNEXPECTED } + private static final Pattern REL_SPLIT_RE = Pattern.compile("[\\s\\t]+"); + + private enum State { + INIT, URI_REF, PARAMS, PARAM_NAME_BEGIN, PARAM_NAME, PARAM_NAME_END, PARAM_VALUE, + STRING_VALUE, LITERAL_VALUE, ESCAPE, UNEXPECTED + } private URI baseUri; @@ -71,50 +77,50 @@ public List parse(String httpLink) { for (final char ch : linkHeader) { switch (state) { - case INIT: - initParser(ch); - break; - - case URI_REF: - parseTargetUri(ch); - break; - - case PARAMS: - parseParameters(ch); - break; - - case PARAM_NAME_BEGIN: - parseParamNameBegin(ch); - break; - - case PARAM_NAME: - parseParamName(ch); - break; - - case PARAM_NAME_END: - parseParamNameEnd(ch); - break; - - case PARAM_VALUE: - parseParamValue(ch); - break; - - case LITERAL_VALUE: - parseLiteral(ch); - break; - - case STRING_VALUE: - parseString(ch); - break; - - case ESCAPE: - escape(ch); - break; - - default: - addParameter(); - addLink(); - return links; + case INIT: + initParser(ch); + break; + + case URI_REF: + parseTargetUri(ch); + break; + + case PARAMS: + parseParameters(ch); + break; + + case PARAM_NAME_BEGIN: + parseParamNameBegin(ch); + break; + + case PARAM_NAME: + parseParamName(ch); + break; + + case PARAM_NAME_END: + parseParamNameEnd(ch); + break; + + case PARAM_VALUE: + parseParamValue(ch); + break; + + case LITERAL_VALUE: + parseLiteral(ch); + break; + + case STRING_VALUE: + parseString(ch); + break; + + case ESCAPE: + escape(ch); + break; + + default: + addParameter(); + addLink(); + return links; } } @@ -158,7 +164,7 @@ private final void addLink() { MediaType type = null; if (attributes.containsKey(REL) && attributes.get(REL) != null) { - rel = new HashSet<>(Arrays.asList(StringUtils.strip(attributes.get(REL).get(0).value()).split("[\\s\\t]+"))); + rel = new HashSet<>(Arrays.asList(REL_SPLIT_RE.split(StringUtils.strip(attributes.get(REL).get(0).value())))); attributes.remove(REL); } if (attributes.containsKey(ANCHOR) && attributes.get(ANCHOR) != null) { @@ -346,7 +352,6 @@ private final void parseParamValue(final char ch) { state = State.UNEXPECTED; } - private final void parseString(final char ch) { if (ch == '"') { attributeValue = valueBuilder.toString(); diff --git a/src/main/java/com/apicatalog/jsonld/lang/LanguageTagParser.java b/src/main/java/com/apicatalog/jsonld/lang/LanguageTagParser.java index d9b7d5ab..da3aed16 100644 --- a/src/main/java/com/apicatalog/jsonld/lang/LanguageTagParser.java +++ b/src/main/java/com/apicatalog/jsonld/lang/LanguageTagParser.java @@ -18,17 +18,21 @@ import java.util.ArrayList; import java.util.function.Consumer; import java.util.function.IntPredicate; +import java.util.regex.Pattern; import com.apicatalog.jsonld.lang.LanguageTag.Extension; import com.apicatalog.rdf.lang.RdfAlphabet; /** - * Language tags are used to help identify languages and are defined by RFC 5646. + * Language tags are used to help identify languages and are defined by + * RFC 5646. * * @see RFC 5643 */ final class LanguageTagParser { + static final Pattern LANG_DEL_RE = Pattern.compile("-"); + final String languageTag; final String[] tags; @@ -71,16 +75,14 @@ private static final LanguageTagParser create(final String languageTag, boolean final String stripped = languageTag.trim(); - // must start with ALPHA and ends with ALPHANUM + // must start with ALPHA and ends with ALPHANUM if (stripped.length() == 0 || RdfAlphabet.ASCII_ALPHA.negate().test(stripped.codePointAt(0)) - || RdfAlphabet.ASCII_ALPHA_NUM.negate().test(stripped.codePointAt(stripped.length() - 1)) - ) { + || RdfAlphabet.ASCII_ALPHA_NUM.negate().test(stripped.codePointAt(stripped.length() - 1))) { return new LanguageTagParser(languageTag, null, verifierMode); } - final String[] tags = stripped.split("-"); - + final String[] tags = LANG_DEL_RE.split(stripped); if (tags == null || tags.length == 0) { return new LanguageTagParser(languageTag, null, verifierMode); @@ -88,6 +90,7 @@ private static final LanguageTagParser create(final String languageTag, boolean return new LanguageTagParser(languageTag, tags, verifierMode); } + /** * Parses the language tag. * @@ -116,10 +119,10 @@ LanguageTag parse() throws IllegalArgumentException { acceptAlpha(3, tag::addLanguageExtension); } - // reserved 4ALPHA or registered for future use 5*8ALPHA + // reserved 4ALPHA or registered for future use 5*8ALPHA } else if (acceptAlpha(4, 8, tag::setLanguage)) { - // private use + // private use } else if (acceptPrivateUse(tag)) { if (tagIndex != tags.length) { @@ -136,14 +139,15 @@ LanguageTag parse() throws IllegalArgumentException { acceptAlpha(4, tag::setScript); // script = 4ALPHA // ["-" region] - if (!acceptAlpha(2, tag::setRegion)) { // region = 2ALPHA | 3DIGIT + if (!acceptAlpha(2, tag::setRegion)) { // region = 2ALPHA | 3DIGIT acceptDigit(3, tag::setRegion); } // *("-" variant) // variant = 5*8alphanum | (DIGIT 3alphanum) while (acceptAlphaNun(5, 8, tag::addVariant) - || (digitRange(0, 1) && alphaNumRange(1, 3) && accept(4, tag::addVariant))); + || (digitRange(0, 1) && alphaNumRange(1, 3) && accept(4, tag::addVariant))) + ; // *("-" extension) // extension = singleton 1*("-" (2*8alphanum)) @@ -158,7 +162,8 @@ LanguageTag parse() throws IllegalArgumentException { break; } - while (acceptAlphaNun(2, 8, extension::addTag)); + while (acceptAlphaNun(2, 8, extension::addTag)) + ; tag.addExtension(extension); } @@ -182,7 +187,8 @@ boolean acceptPrivateUse(final LanguageTag tag) { tagIndex--; } else { - while (acceptAlphaNun(1, 8, tag::addPrivateUse)); + while (acceptAlphaNun(1, 8, tag::addPrivateUse)) + ; return true; } } @@ -259,11 +265,9 @@ boolean digitRange(int index, int length) { } boolean range(int index, int length, IntPredicate predicate) { - return - tagIndex < tags.length - && index < tags[tagIndex].length() - && (index + length) <= tags[tagIndex].length() - && tags[tagIndex].substring(index, index + length).chars().allMatch(predicate) - ; + return tagIndex < tags.length + && index < tags[tagIndex].length() + && (index + length) <= tags[tagIndex].length() + && tags[tagIndex].substring(index, index + length).chars().allMatch(predicate); } } \ No newline at end of file diff --git a/src/main/java/com/apicatalog/jsonld/uri/Path.java b/src/main/java/com/apicatalog/jsonld/uri/Path.java index 1bf66385..81c5223d 100644 --- a/src/main/java/com/apicatalog/jsonld/uri/Path.java +++ b/src/main/java/com/apicatalog/jsonld/uri/Path.java @@ -19,6 +19,7 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; +import java.util.regex.Pattern; import com.apicatalog.jsonld.StringUtils; @@ -26,6 +27,8 @@ public final class Path { public static final Path EMPTY = new Path(new ArrayList<>(), null, true); + private static final Pattern SEGMENTS_DEL_RE = Pattern.compile("/"); + private final List segments; private final String last; private final boolean relative; @@ -41,17 +44,15 @@ public static final Path of(final String path) { final boolean relative = !path.startsWith("/"); final List segments = new ArrayList<>( - Arrays.asList( - (relative - ? path - : path.substring(1) - ) - .split("/") - ) - ); + Arrays.asList( + SEGMENTS_DEL_RE.split( + (relative + ? path + : path.substring(1))))); + final String last = (path.length() > 1 && path.endsWith("/")) - ? null - : segments.remove(segments.size() - 1); + ? null + : segments.remove(segments.size() - 1); return new Path(segments, (last == null || StringUtils.isBlank(last)) ? null : last, relative); } @@ -105,13 +106,13 @@ public Path relativize(final Path base) { if (!segments.get(segments.size() - rightIndex - 1).equals(base.segments.get(base.segments.size() - rightIndex - 1))) { break; } - diff.add(".."); //TOD ?!? + diff.add(".."); // TOD ?!? } - for (int i=0; i < (base.segments.size() - leftIndex - rightIndex); i++) { + for (int i = 0; i < (base.segments.size() - leftIndex - rightIndex); i++) { diff.add(".."); } - for (int i=0; i < (segments.size() - leftIndex - rightIndex ); i++) { + for (int i = 0; i < (segments.size() - leftIndex - rightIndex); i++) { diff.add(segments.get(i + leftIndex)); } @@ -133,12 +134,11 @@ public boolean isRelative() { @Override public String toString() { return (relative - ? "" - : "/") - .concat(String.join("/", segments)) - .concat(segments.isEmpty() ? "" : "/") - .concat(last != null ? last : "") - ; + ? "" + : "/") + .concat(String.join("/", segments)) + .concat(segments.isEmpty() ? "" : "/") + .concat(last != null ? last : ""); } public String getLeaf() {