no.hasmac.jsonld.framing.Frame Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hasmac-json-ld Show documentation
Show all versions of hasmac-json-ld Show documentation
A more performant JSON-LD 1.1 Processor & API forked from Titanium JSON-LD.
The newest version!
/*
* Copyright 2020 APICATALOG and HASMAC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package no.hasmac.jsonld.framing;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonString;
import jakarta.json.JsonStructure;
import jakarta.json.JsonValue;
import no.hasmac.jsonld.JsonLdEmbed;
import no.hasmac.jsonld.JsonLdError;
import no.hasmac.jsonld.JsonLdErrorCode;
import no.hasmac.jsonld.json.JsonUtils;
import no.hasmac.jsonld.lang.DefaultObject;
import no.hasmac.jsonld.lang.Keywords;
import no.hasmac.jsonld.lang.ListObject;
import no.hasmac.jsonld.lang.NodeObject;
import no.hasmac.jsonld.lang.ValueObject;
import no.hasmac.jsonld.uri.UriUtils;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public final class Frame {
public static final Frame EMPTY = new Frame(JsonValue.EMPTY_JSON_OBJECT);
private final JsonObject frameObject;
private Frame(final JsonObject frameObject) {
this.frameObject = frameObject;
}
public static Frame of(final JsonStructure structure) throws JsonLdError {
final JsonObject frameObject;
// 1.
if (JsonUtils.isArray(structure)) {
if (structure.asJsonArray().size() != 1
|| JsonUtils.isNotObject(structure.asJsonArray().get(0))
) {
throw new JsonLdError(JsonLdErrorCode.INVALID_FRAME, "Frame is not JSON object nor an array containing JSON object [" + structure + "]");
}
frameObject = structure.asJsonArray().getJsonObject(0);
} else if (JsonUtils.isObject(structure)) {
frameObject = structure.asJsonObject();
} else {
throw new JsonLdError(JsonLdErrorCode.INVALID_FRAME, "Frame is not JSON object. [" + structure + "]");
}
// 1.2.
if (frameObject.containsKey(Keywords.ID) && !validateFrameId(frameObject)) {
throw new JsonLdError(JsonLdErrorCode.INVALID_FRAME, "Frame @id value is not valid [@id = " + frameObject.get(Keywords.ID) + "].");
}
// 1.3.
if (frameObject.containsKey(Keywords.TYPE) && !validateFrameType(frameObject)) {
throw new JsonLdError(JsonLdErrorCode.INVALID_FRAME, "Frame @type value i not valid [@type = " + frameObject.get(Keywords.TYPE) + "].");
}
return new Frame(frameObject);
}
public JsonLdEmbed getEmbed(final JsonLdEmbed defaultValue) throws JsonLdError {
if (frameObject.containsKey(Keywords.EMBED)) {
JsonValue embed = frameObject.get(Keywords.EMBED);
if (JsonUtils.isNull(embed)) {
return defaultValue;
}
if (ValueObject.isValueObject(embed)) {
embed = ValueObject.getValue(embed).orElseThrow(() -> new JsonLdError(JsonLdErrorCode.INVALID_KEYWORD_EMBED_VALUE));
}
if (JsonUtils.isString(embed)) {
String stringValue = ((JsonString)embed).getString();
if (Keywords.noneMatch(stringValue, Keywords.ALWAYS, Keywords.ONCE, Keywords.NEVER)) {
throw new JsonLdError(JsonLdErrorCode.INVALID_KEYWORD_EMBED_VALUE, "The value for @embed is not one recognized for the object embed flag [@embed = " + stringValue + "].");
}
return JsonLdEmbed.valueOf(stringValue.substring(1).toUpperCase());
} else if (JsonUtils.isFalse(embed)) {
return JsonLdEmbed.NEVER;
} else if (JsonUtils.isTrue(embed)) {
return JsonLdEmbed.ONCE;
}
throw new JsonLdError(JsonLdErrorCode.INVALID_KEYWORD_EMBED_VALUE, "The value for @embed is not one recognized for the object embed flag [@embed = " + embed + "].");
}
return defaultValue;
}
public boolean getExplicit(boolean defaultValue) throws JsonLdError {
return getBoolean(frameObject, Keywords.EXPLICIT, defaultValue);
}
public boolean getRequireAll(boolean defaultValue) throws JsonLdError {
return getBoolean(frameObject, Keywords.REQUIRE_ALL, defaultValue);
}
public static boolean getBoolean(JsonObject frame, String key, boolean defaultValue) throws JsonLdError {
if (frame.containsKey(key)) {
JsonValue value = frame.get(key);
if (JsonUtils.isNull(value)) {
return defaultValue;
}
if (ValueObject.isValueObject(value)) {
value = ValueObject.getValue(value).orElseThrow(() -> new JsonLdError(JsonLdErrorCode.INVALID_FRAME));
}
if (JsonUtils.isString(value)) {
if ("true".equalsIgnoreCase(((JsonString)value).getString())) {
return true;
} else if ("false".equalsIgnoreCase(((JsonString)value).getString())) {
return false;
}
}
if (JsonUtils.isNotBoolean(value)) {
throw new JsonLdError(JsonLdErrorCode.INVALID_FRAME);
}
return JsonUtils.isTrue(value);
}
return defaultValue;
}
private static boolean validateFrameId(JsonObject frame) {
final JsonValue id = frame.get(Keywords.ID);
if (JsonUtils.isNonEmptyArray(id)) {
final JsonArray idArray = id.asJsonArray();
return ((idArray.size() == 1 && JsonUtils.isEmptyObject(idArray.get(0)))
|| idArray
.stream()
.noneMatch(item -> JsonUtils.isNotString(item)
|| UriUtils.isNotAbsoluteUri(((JsonString)item).getString(), true)));
}
return JsonUtils.isString(id) && UriUtils.isAbsoluteUri(((JsonString)id).getString(), true);
}
private static boolean validateFrameType(JsonObject frame) {
final JsonValue type = frame.get(Keywords.TYPE);
if (JsonUtils.isNonEmptyArray(type)) {
final JsonArray typeArray = type.asJsonArray();
return ((typeArray.size() == 1
&& (JsonUtils.isEmptyObject(typeArray.get(0))
|| (JsonUtils.containsKey(typeArray.get(0), Keywords.DEFAULT))
)
)
|| typeArray
.stream()
.noneMatch(item -> JsonUtils.isNotString(item)
|| UriUtils.isNotAbsoluteUri(((JsonString)item).getString(), true)));
}
return JsonUtils.isEmptyArray(type)
|| JsonUtils.isEmptyObject(type)
|| JsonUtils.isString(type) && UriUtils.isAbsoluteUri(((JsonString)type).getString(), true);
}
public Set keys() {
return frameObject.keySet();
}
public JsonValue get(String property) {
return frameObject.get(property);
}
public boolean contains(String property) {
return frameObject.containsKey(property);
}
public boolean containsOnly(String property) {
return frameObject.containsKey(property) && ValuePatternMatcher.isWildcard(frameObject, property);
}
public boolean isWildCard() {
return ValuePatternMatcher.isWildcard(frameObject);
}
public boolean isWildCard(String property) {
return frameObject.containsKey(property)
&& ValuePatternMatcher.isWildcard(frameObject.get(property));
}
public boolean isNone(String property) {
return frameObject.containsKey(property)
&& ValuePatternMatcher.isNone(frameObject.get(property));
}
public Collection getCollection(String property) {
return frameObject.containsKey(property)
? JsonUtils.toJsonArray(frameObject.get(property))
: JsonValue.EMPTY_JSON_ARRAY;
}
@Override
public String toString() {
return frameObject.toString();
}
public boolean isValuePattern() {
return ValueObject.isValueObject(frameObject);
}
public boolean matchValue(JsonValue value) {
return JsonUtils.isObject(value) && ValuePatternMatcher.with(frameObject, value.asJsonObject()).match();
}
public boolean isDefaultObject(String property) {
return DefaultObject.isDefaultObject(frameObject.get(property))
|| JsonUtils.isArray(frameObject.get(property))
&& frameObject.get(property).asJsonArray().size() == 1
&& DefaultObject.isDefaultObject(frameObject.get(property).asJsonArray().get(0))
;
}
public boolean isNodePattern() {
return NodeObject.isNodeObject(frameObject);
}
public boolean isNodeReference() {
return NodeObject.isNodeReference(frameObject);
}
public boolean matchNode(FramingState state, JsonValue value, boolean requireAll) throws JsonLdError {
if (JsonUtils.isNotObject(value) || !value.asJsonObject().containsKey(Keywords.ID)) {
return false;
}
final Optional