com.arcadedb.graphql.schema.GraphQLResultSet Maven / Gradle / Ivy
The newest version!
/*
* Copyright © 2021-present Arcade Data Ltd ([email protected])
*
* 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-FileCopyrightText: 2021-present Arcade Data Ltd ([email protected])
* SPDX-License-Identifier: Apache-2.0
*/
package com.arcadedb.graphql.schema;
import com.arcadedb.database.Document;
import com.arcadedb.graph.Edge;
import com.arcadedb.graph.Vertex;
import com.arcadedb.graphql.parser.AbstractField;
import com.arcadedb.graphql.parser.Argument;
import com.arcadedb.graphql.parser.Directive;
import com.arcadedb.graphql.parser.Directives;
import com.arcadedb.graphql.parser.Field;
import com.arcadedb.graphql.parser.FieldDefinition;
import com.arcadedb.graphql.parser.ObjectTypeDefinition;
import com.arcadedb.graphql.parser.Selection;
import com.arcadedb.graphql.parser.SelectionSet;
import com.arcadedb.query.sql.executor.ExecutionPlan;
import com.arcadedb.query.sql.executor.Result;
import com.arcadedb.query.sql.executor.ResultInternal;
import com.arcadedb.query.sql.executor.ResultSet;
import java.util.*;
/**
* @author Luca Garulli ([email protected])
*/
public class GraphQLResultSet implements ResultSet {
private final GraphQLSchema schema;
private final ResultSet resultSet;
private final List projections;
private final ObjectTypeDefinition returnType;
private static class Projection {
final String name;
final AbstractField field;
final ObjectTypeDefinition type;
final List set;
private Projection(final String name, final Field field, final ObjectTypeDefinition type, final List set) {
this.name = name;
this.field = field;
this.type = type;
this.set = set;
}
}
public GraphQLResultSet(final GraphQLSchema schema, final ResultSet resultSet, final List projections, final ObjectTypeDefinition returnType) {
if (resultSet == null)
throw new IllegalArgumentException("NULL resultSet");
this.schema = schema;
this.resultSet = resultSet;
this.projections = projections;
this.returnType = returnType;
}
@Override
public boolean hasNext() {
return resultSet.hasNext();
}
@Override
public Result next() {
return projections != null ? mapBySelections(resultSet.next(), projections) : mapByReturnType(resultSet.next(), returnType);
}
private GraphQLResult mapByReturnType(final Result current, final ObjectTypeDefinition type) {
final List projections = new ArrayList<>(type.getFieldDefinitions().size());
// ADD ALL THE TYPE FIELDS AUTOMATICALLY
for (final FieldDefinition fieldDefinition : type.getFieldDefinitions()) {
final ObjectTypeDefinition subType = schema.getTypeFromField(fieldDefinition);
projections.add(new Projection(fieldDefinition.getName(), null, subType, null));
}
return mapProjections(current, projections);
}
private GraphQLResult mapBySelections(final Result current, final List definedProjections) {
final List projections = new ArrayList<>(definedProjections.size());
for (final Selection fieldDefinition : definedProjections) {
final SelectionSet set = fieldDefinition.getField().getSelectionSet();
projections.add(new Projection(fieldDefinition.getName(), fieldDefinition.getField(), null, set != null ? set.getSelections() : null));
}
return mapProjections(current, projections);
}
@Override
public void close() {
resultSet.close();
}
@Override
public Optional getExecutionPlan() {
return Optional.empty();
}
private Object evaluateDirectives(final Result current, final AbstractField fieldDefinition) {
Object projectionValue = null;
if (fieldDefinition != null) {
final Directives directives = fieldDefinition.getDirectives();
if (directives != null) {
for (final Directive directive : directives.getDirectives()) {
if ("relationship".equals(directive.getName())) {
if (directive.getArguments() != null) {
String type = null;
Vertex.DIRECTION direction = Vertex.DIRECTION.BOTH;
for (final Argument argument : directive.getArguments().getList()) {
if ("type".equals(argument.getName())) {
type = argument.getValueWithVariable().getValue().getValue().toString();
} else if ("direction".equals(argument.getName())) {
direction = Vertex.DIRECTION.valueOf(argument.getValueWithVariable().getValue().getValue().toString());
}
}
if (current.getElement().isPresent()) {
final Vertex vertex = current.getElement().get().asVertex();
final Iterable connected = type != null ? vertex.getVertices(direction, type) : vertex.getVertices(direction);
projectionValue = connected;
} else if (current.getIdentity().isPresent()) {
final Vertex vertex = current.getIdentity().get().asVertex();
final Iterable connected = type != null ? vertex.getVertices(direction, type) : vertex.getVertices(direction);
projectionValue = connected;
}
}
}
}
}
}
return projectionValue;
}
private GraphQLResult mapProjections(final Result current, final List projections) {
final Map map = new HashMap<>();
if (current.getElement().isPresent()) {
final Document element = current.getElement().get();
map.put("@rid", element.getIdentity());
map.put("@type", element.getTypeName());
map.put("@cat", element instanceof Vertex ? "v" : element instanceof Edge ? "e" : "d");
}
for (final Projection entry : projections) {
final String projName = entry.name;
Object projectionValue = current.getProperty(projName);
if (projectionValue == null) {
// TRY THE FIELD FIRST
projectionValue = evaluateDirectives(current, entry.field);
if (projectionValue == null) {
// SEARCH IN THE SCHEMA
final AbstractField fieldDefinition = returnType.getFieldDefinitionByName(projName);
projectionValue = evaluateDirectives(current, fieldDefinition);
}
}
final AbstractField field = entry.field;
if (projectionValue == null && field != null) {
if (field.getDirectives() != null) {
for (final Directive directive : field.getDirectives().getDirectives()) {
if ("rid".equals(directive.getName())) {
if (current.getElement().isPresent())
projectionValue = current.getElement().get().getIdentity();
} else if ("type".equals(directive.getName())) {
if (current.getElement().isPresent())
projectionValue = current.getElement().get().getTypeName();
}
}
}
}
final List selectionSet = entry.set;
final ObjectTypeDefinition projectionType = entry.type;
if (selectionSet != null) {
if (projectionValue instanceof Map)
projectionValue = mapBySelections(new ResultInternal((Map) projectionValue), selectionSet);
else if (projectionValue instanceof Result)
projectionValue = mapBySelections((Result) projectionValue, selectionSet);
else if (projectionValue instanceof Iterable) {
final List subResults = new ArrayList<>();
for (final Object o : ((Iterable) projectionValue)) {
final Result item;
if (o instanceof Document)
item = mapBySelections(new ResultInternal((Document) o), selectionSet);
else if (o instanceof Result)
item = mapBySelections((Result) o, selectionSet);
else
continue;
subResults.add(item);
}
projectionValue = subResults;
} else
continue;
} else if (projectionType != null) {
if (projectionValue instanceof Map)
projectionValue = mapByReturnType(new ResultInternal((Map) projectionValue), projectionType);
else if (projectionValue instanceof Result)
projectionValue = mapByReturnType((Result) projectionValue, projectionType);
else if (projectionValue instanceof Iterable) {
final List subResults = new ArrayList<>();
for (final Object o : ((Iterable) projectionValue)) {
final Result item;
if (o instanceof Document)
item = mapByReturnType(new ResultInternal((Document) o), projectionType);
else if (o instanceof Result)
item = mapByReturnType((Result) o, projectionType);
else
continue;
subResults.add(item);
}
projectionValue = subResults;
} else
continue;
}
map.put(projName, projectionValue);
}
return new GraphQLResult(map);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy