com.apicatalog.jsonld.framing.FrameMatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of titanium-json-ld Show documentation
Show all versions of titanium-json-ld Show documentation
A JSON-LD 1.1 Processor & API
/*
* Copyright 2020 the original author or authors.
*
* 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.
*/
package com.apicatalog.jsonld.framing;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.apicatalog.jsonld.JsonLdError;
import com.apicatalog.jsonld.json.JsonUtils;
import com.apicatalog.jsonld.lang.Keywords;
import com.apicatalog.jsonld.lang.ListObject;
import com.apicatalog.jsonld.lang.NodeObject;
import com.apicatalog.jsonld.lang.ValueObject;
import jakarta.json.JsonArray;
import jakarta.json.JsonStructure;
import jakarta.json.JsonValue;
public final class FrameMatcher {
// required
private FramingState state;
private Frame frame;
private boolean requireAll;
private FrameMatcher(FramingState state, Frame frame, boolean requireAll) {
this.state = state;
this.frame = frame;
this.requireAll = requireAll;
}
public static final FrameMatcher with(FramingState state, Frame frame, boolean requireAll) {
return new FrameMatcher(state, frame, requireAll);
}
public List match(final Collection subjects) throws JsonLdError {
// 1. if frame is empty then all subject match
if (frame.isWildCard()) {
return new ArrayList<>(subjects);
}
final List result = new ArrayList<>();
for (final String subject : subjects) {
if (match(state.getGraphMap().get(state.getGraphName(), subject))) {
result.add(subject);
}
}
return result;
}
public boolean match(final Map node) throws JsonLdError {
int count = 0;
boolean nonKeywordProperty = false;
for (final String property : frame.keys()) {
JsonValue nodeValue = node.get(property);
// 2.1.
if (Keywords.ID.equals(property)) {
nodeValue = JsonUtils.toJsonArray(nodeValue);
if (JsonUtils.toStream(frame.get(property)).anyMatch(nodeValue.asJsonArray()::contains)
|| frame.isWildCard(Keywords.ID)
|| frame.isNone(Keywords.ID)
) {
if (requireAll) {
count++;
continue;
}
return true;
}
return false;
// 2.2.
} else if (Keywords.TYPE.equals(property)) {
if ((JsonUtils.isNotNull(nodeValue) && !nodeValue.asJsonArray().isEmpty() && frame.isWildCard(property))
|| ((JsonUtils.isNull(nodeValue) || nodeValue.asJsonArray().isEmpty()) && frame.isNone(property))
|| frame.isDefaultObject(property)
|| (JsonUtils.isNotNull(nodeValue) && frame.getCollection(property).stream().anyMatch(nodeValue.asJsonArray()::contains))
){
if (requireAll) {
count++;
continue;
}
return true;
}
return false;
// skip other keywords
} else if (Keywords.matchForm(property)) {
continue;
}
nonKeywordProperty = true;
JsonValue propertyValue = frame.get(property);
final Frame propertyFrame =
(JsonUtils.isNotNull(propertyValue) && JsonUtils.isNonEmptyArray(propertyValue))
? Frame.of((JsonStructure)propertyValue)
: null;
final JsonArray nodeValues = nodeValue != null
? JsonUtils.toJsonArray(nodeValue)
: JsonValue.EMPTY_JSON_ARRAY;
// 2.5.
if (nodeValues.isEmpty()
&& propertyFrame != null
&& propertyFrame.containsOnly(Keywords.DEFAULT)
) {
continue;
}
// 2.6.
if (nodeValues.isEmpty() && frame.isNone(property)) {
if (requireAll) {
count++;
continue;
}
return true;
} else if (!nodeValues.isEmpty() && frame.isNone(property)) {
return false;
}
// 2.7.
if (!nodeValues.isEmpty() && propertyFrame != null && propertyFrame.isWildCard()) {
if (requireAll) {
count++;
continue;
}
return true;
}
if (propertyFrame == null) {
if (nodeValues.isEmpty()) {
if (requireAll) {
count++;
continue;
}
return true;
}
} else {
if (propertyFrame.isListObject()) {
JsonValue listValue = propertyFrame.get(Keywords.LIST);
if (!nodeValues.isEmpty() && ListObject.isListObject(nodeValues.get(0))) {
JsonValue nodeListValue = nodeValues.get(0).asJsonObject().get(Keywords.LIST);
if (ValueObject.isValueObject(listValue.asJsonArray().get(0))) {
boolean match = false;
for (final JsonValue value : JsonUtils.toCollection(nodeListValue)) {
match = Frame.of((JsonStructure)listValue).matchValue(value);
if (match) {
break;
}
}
if (match) {
if (requireAll) {
count++;
continue;
}
return true;
}
} else if (NodeObject.isNodeObject(listValue.asJsonArray().get(0)) || NodeObject.isNodeReference(listValue.asJsonArray().get(0))) {
boolean match = false;
for (final JsonValue value : JsonUtils.toCollection(nodeListValue)) {
match = Frame.of((JsonStructure)listValue).matchNode(state, value, requireAll);
if (match) {
break;
}
}
if (match) {
if (requireAll) {
count++;
continue;
}
return true;
}
}
}
} else if (propertyFrame.isValuePattern()) {
if (nodeValues.stream().anyMatch(propertyFrame::matchValue)) {
if (requireAll) {
count++;
continue;
}
return true;
}
} else if (propertyFrame.isNodeReference()) {
boolean match = false;
if (!nodeValues.isEmpty()) {
for (JsonValue values : nodeValues) {
match = propertyFrame.matchNode(state, values, requireAll);
if (match) {
break;
}
}
}
if (match) {
if (requireAll) {
count++;
continue;
}
return true;
}
} else {
if (!nodeValues.isEmpty()) {
if (requireAll) {
count++;
continue;
}
return true;
}
}
}
if (requireAll) {
return false;
}
}
return !nonKeywordProperty || count > 0;
}
}