org.neo4j.cypherdsl.parser.CypherDslASTFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neo4j-cypher-dsl-parser Show documentation
Show all versions of neo4j-cypher-dsl-parser Show documentation
Building on top of the Neo4j 4.4 JavaCC parsers it provides a way from Cypher to Cypher-DSL Ast.
/*
* Copyright (c) 2019-2024 "Neo4j,"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* 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
*
* https://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 org.neo4j.cypherdsl.parser;
import static org.apiguardian.api.API.Status.INTERNAL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
import org.apiguardian.api.API;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.neo4j.cypher.internal.ast.factory.ASTFactory;
import org.neo4j.cypher.internal.ast.factory.ASTFactory.NULL;
import org.neo4j.cypher.internal.parser.common.ast.factory.AccessType;
import org.neo4j.cypher.internal.parser.common.ast.factory.ActionType;
import org.neo4j.cypher.internal.parser.common.ast.factory.CallInTxsOnErrorBehaviourType;
import org.neo4j.cypher.internal.parser.common.ast.factory.ConstraintType;
import org.neo4j.cypher.internal.parser.common.ast.factory.CreateIndexTypes;
import org.neo4j.cypher.internal.parser.common.ast.factory.HintIndexType;
import org.neo4j.cypher.internal.parser.common.ast.factory.ParameterType;
import org.neo4j.cypher.internal.parser.common.ast.factory.ParserCypherTypeName;
import org.neo4j.cypher.internal.parser.common.ast.factory.ParserNormalForm;
import org.neo4j.cypher.internal.parser.common.ast.factory.ParserTrimSpecification;
import org.neo4j.cypher.internal.parser.common.ast.factory.ScopeType;
import org.neo4j.cypher.internal.parser.common.ast.factory.ShowCommandFilterTypes;
import org.neo4j.cypher.internal.parser.common.ast.factory.SimpleEither;
import org.neo4j.cypherdsl.core.Case;
import org.neo4j.cypherdsl.core.Clause;
import org.neo4j.cypherdsl.core.Clauses;
import org.neo4j.cypherdsl.core.Cypher;
import org.neo4j.cypherdsl.core.ExposesRelationships;
import org.neo4j.cypherdsl.core.Expression;
import org.neo4j.cypherdsl.core.Finish;
import org.neo4j.cypherdsl.core.FunctionInvocation;
import org.neo4j.cypherdsl.core.Hint;
import org.neo4j.cypherdsl.core.KeyValueMapEntry;
import org.neo4j.cypherdsl.core.LabelExpression;
import org.neo4j.cypherdsl.core.MapExpression;
import org.neo4j.cypherdsl.core.MapProjection;
import org.neo4j.cypherdsl.core.MergeAction;
import org.neo4j.cypherdsl.core.NamedPath;
import org.neo4j.cypherdsl.core.Node;
import org.neo4j.cypherdsl.core.Operation;
import org.neo4j.cypherdsl.core.Parameter;
import org.neo4j.cypherdsl.core.PatternComprehension;
import org.neo4j.cypherdsl.core.PatternElement;
import org.neo4j.cypherdsl.core.Property;
import org.neo4j.cypherdsl.core.PropertyLookup;
import org.neo4j.cypherdsl.core.QuantifiedPathPattern;
import org.neo4j.cypherdsl.core.Relationship;
import org.neo4j.cypherdsl.core.RelationshipPattern;
import org.neo4j.cypherdsl.core.Return;
import org.neo4j.cypherdsl.core.Set;
import org.neo4j.cypherdsl.core.SortItem;
import org.neo4j.cypherdsl.core.Statement;
import org.neo4j.cypherdsl.core.StringLiteral;
import org.neo4j.cypherdsl.core.SymbolicName;
import org.neo4j.cypherdsl.core.Where;
import org.neo4j.cypherdsl.core.ast.TypedSubtree;
import org.neo4j.cypherdsl.core.ast.Visitable;
/**
* An implementation of Neo4j's {@link ASTFactory} that creates Cypher-DSL AST elements that can be used for creating
* conditions, patterns to match etc.
*
* @author Michael J. Simons
* @since 2021.3.0
*/
@API(status = INTERNAL, since = "2021.3.0")
final class CypherDslASTFactory implements ASTFactory<
Statements,
Statement,
Statement,
Clause,
Finish,
Return,
Expression,
List,
SortItem,
PatternElement,
NodeAtom,
PathAtom,
PathLength,
Clause,
Expression,
Expression,
Expression,
Hint,
Expression,
LabelExpression,
Expression,
Parameter>,
Expression,
Property,
Expression,
Clause,
Statement,
Statement,
Statement,
Clause,
Where,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
InputPosition,
EntityType,
QuantifiedPathPattern.Quantifier,
PatternAtom,
DatabaseName,
NULL,
NULL,
PatternElement> {
private static CypherDslASTFactory instanceFromDefaultOptions;
static CypherDslASTFactory getInstance(Options options) {
CypherDslASTFactory instance;
if (options != null && !options.areDefault()) {
instance = new CypherDslASTFactory(options);
} else {
instance = instanceFromDefaultOptions;
if (instance == null) {
synchronized (CypherDslASTFactory.class) {
instance = instanceFromDefaultOptions;
if (instance == null) {
instanceFromDefaultOptions = new CypherDslASTFactory(Optional.ofNullable(options).orElseGet(Options::defaultOptions));
instance = instanceFromDefaultOptions;
}
}
}
}
return instance;
}
private final Options options;
private CypherDslASTFactory(Options options) {
this.options = options;
}
private String[] computeFinalLabelList(LabelParsedEventType event, List> inputLabels) {
return inputLabels == null ? new String[0] : this.options.getLabelFilter()
.apply(event, inputLabels.stream().map(v -> v.string).toList())
.toArray(new String[0]);
}
private Optional computeFinalLabelList(LabelParsedEventType event, LabelExpression inputLabels) {
if (inputLabels == null) {
return Optional.of(new String[0]);
}
if (inputLabels.type() == LabelExpression.Type.COLON_CONJUNCTION || (inputLabels.type() == LabelExpression.Type.LEAF && inputLabels.value() != null)) {
return Optional.of(this.options.getLabelFilter()
.apply(event, inputLabels.value())
.toArray(new String[0]));
}
return Optional.empty();
}
private String[] computeFinalTypeList(TypeParsedEventType event, LabelExpression inputTypes) {
if (inputTypes == null) {
return new String[0];
}
if ((inputTypes.negated() && inputTypes.value().size() > 1) || inputTypes.type() == LabelExpression.Type.CONJUNCTION) {
throw new UnsupportedOperationException("Expressions for relationship types are not supported in Cypher-DSL");
}
List types = new ArrayList<>();
traverseTypeExpression(types, inputTypes);
return this.options.getTypeFilter()
.apply(event, types)
.toArray(new String[0]);
}
void traverseTypeExpression(List types, LabelExpression expression) {
if (expression.type() == LabelExpression.Type.LEAF || expression.type() == LabelExpression.Type.COLON_DISJUNCTION) {
types.addAll(expression.value());
} else {
traverseTypeExpression(types, expression.lhs());
traverseTypeExpression(types, expression.rhs());
}
}
static void isInstanceOf(Class> type, Object obj, String message) {
if (type == null) {
throw new IllegalArgumentException("Type to check against must not be null");
}
if (!type.isInstance(obj)) {
throw new IllegalArgumentException(message);
}
}
private static void notNull(Object object, String message) {
if (object == null) {
throw new IllegalArgumentException(message);
}
}
private T applyCallbacksFor(ExpressionCreatedEventType type, T newExpression) {
return applyCallbacksFor(type, List.of(newExpression)).get(0);
}
@SuppressWarnings("unchecked")
private List applyCallbacksFor(ExpressionCreatedEventType type, List expressions) {
var callbacks = this.options.getOnNewExpressionCallbacks().getOrDefault(type, List.of());
if (callbacks.isEmpty()) {
return expressions;
}
var chainedCallbacks = callbacks.stream().reduce(Function.identity(), Function::andThen);
return expressions.stream().map(e -> (T) chainedCallbacks.apply(e)).toList();
}
@SuppressWarnings("unchecked")
private T applyCallbacksFor(InvocationCreatedEventType type, T newExpression) {
var callbacks = this.options.getOnNewInvocationCallbacks().getOrDefault(type, List.of());
if (callbacks.isEmpty()) {
return newExpression;
}
Visitable result = newExpression;
for (UnaryOperator callback : callbacks) {
result = callback.apply(result);
}
return (T) result;
}
private static SymbolicName assertSymbolicName(@Nullable Expression v) {
if (v == null) {
return null;
}
isInstanceOf(SymbolicName.class, v, "An invalid type has been generated where a SymbolicName was required. Generated type was " + v.getClass().getName());
return (SymbolicName) v;
}
@Override
public Statements statements(List statements) {
return new Statements(statements);
}
@Override
public Statement newSingleQuery(InputPosition p, List clauses) {
return newSingleQuery(clauses);
}
@Override
public Statement newSingleQuery(List clauses) {
return Statement.of(clauses);
}
@Override
public Statement newUnion(InputPosition p, Statement lhs, Statement rhs, boolean all) {
if (all) {
return Cypher.unionAll(lhs, rhs);
} else {
return Cypher.union(lhs, rhs);
}
}
@Override
public Clause directUseClause(InputPosition p, DatabaseName databaseName) {
throw new UnsupportedOperationException();
}
@Override
public Clause functionUseClause(InputPosition p, Expression function) {
throw new UnsupportedOperationException();
}
@Override
public Finish newFinishClause(InputPosition p) {
return Finish.create();
}
public List newReturnItems(InputPosition p, boolean returnAll, List returnItems) {
var finalReturnItems = returnItems;
if (returnAll) {
finalReturnItems = Stream.concat(Stream.of(Cypher.asterisk()), finalReturnItems.stream()).toList();
}
if (finalReturnItems.isEmpty()) {
if (!returnAll) {
throw new IllegalArgumentException("Cannot return nothing.");
}
finalReturnItems = Collections.singletonList(Cypher.asterisk());
}
return finalReturnItems;
}
@Override
public Return newReturnClause(InputPosition p, boolean distinct, List returnItems, List sortItems,
InputPosition orderPos, Expression skip, InputPosition skipPosition, Expression limit,
InputPosition limitPosition) {
return options.getReturnClauseFactory().apply(new ReturnDefinition(distinct, returnItems, sortItems, skip, limit));
}
@Override
public Expression newReturnItem(InputPosition p, Expression e, Expression v) {
var s = assertSymbolicName(v);
return applyCallbacksFor(ExpressionCreatedEventType.ON_RETURN_ITEM, e.as(s));
}
@Override
public Expression newReturnItem(InputPosition p, Expression e, int eStartOffset, int eEndOffset) {
return applyCallbacksFor(ExpressionCreatedEventType.ON_RETURN_ITEM, e);
}
@Override
public SortItem orderDesc(InputPosition p, Expression e) {
return e.descending();
}
@Override
public SortItem orderAsc(InputPosition p, Expression e) {
return e.ascending();
}
@Override
public Clause withClause(InputPosition p, Return returnClause, Where where) {
return Clauses.with(returnClause, where);
}
@Override
public Clause matchClause(InputPosition p, boolean optional, NULL matchMode, List patternElements, InputPosition patternPos, List hints, Where whereIn) {
var patternElementCallbacks = this.options.getOnNewPatternElementCallbacks().getOrDefault(PatternElementCreatedEventType.ON_MATCH, List.of());
List openForTransformation = new ArrayList<>();
for (PatternElement patternElement : patternElements) {
if (patternElement instanceof NodeAtom nodeAtom) {
openForTransformation.add(nodeAtom.value());
} else {
openForTransformation.add(patternElement);
}
}
var transformedPatternElements = transformIfPossible(patternElementCallbacks, openForTransformation);
return options.getMatchClauseFactory().apply(new MatchDefinition(optional, transformedPatternElements, whereIn, hints));
}
private List transformIfPossible(List> callbacks,
List patternElements) {
if (callbacks.isEmpty()) {
return patternElements;
}
@SuppressWarnings("squid:S4276") // The function is needed due to the assigment below
var transformer = Function.identity();
for (UnaryOperator callback : callbacks) {
transformer = transformer.andThen(callback);
}
return patternElements.stream().map(transformer)
.filter(Objects::nonNull)
.toList();
}
@Override
public Hint usingIndexHint(InputPosition p, Expression v, String labelOrRelType, List properties,
boolean seekOnly, HintIndexType indexType) {
// We build nodes here. As of now, the node isn't used anyway, but only the label
// will be used down further the AST.
// It is easier than introduce a new common abstraction of label and relationship type (probably
// in line with the decision made for the parser)
var node = Cypher.node(labelOrRelType).named(assertSymbolicName(v));
return Hint.useIndexFor(seekOnly, properties.stream().map(node::property).toArray(Property[]::new));
}
@Override
public Hint usingJoin(InputPosition p, List joinVariables) {
return Hint.useJoinOn(joinVariables.stream().map(CypherDslASTFactory::assertSymbolicName).toArray(SymbolicName[]::new));
}
@Override
public Hint usingScan(InputPosition p, Expression v, String label) {
var s = assertSymbolicName(v);
// Same note applies as with usingIndexHint in regard to relationships
return Hint.useScanFor(Cypher.node(label).named(s));
}
@Override
public Clause createClause(InputPosition p, List patternElements) {
var callbacks = this.options.getOnNewPatternElementCallbacks().getOrDefault(PatternElementCreatedEventType.ON_CREATE, List.of());
return Clauses.create(transformIfPossible(callbacks, patternElements.stream().map(v -> v instanceof NodeAtom n ? n.value() : v).toList()));
}
@Override
public Clause insertClause(InputPosition p, List patternElements) {
throw new UnsupportedOperationException();
}
@Override
public Clause setClause(InputPosition p, List setItems) {
return Clauses.set(setItems);
}
@Override
public Operation setProperty(Property property, Expression value) {
return applyCallbacksFor(ExpressionCreatedEventType.ON_SET_PROPERTY, property.to(value));
}
@Override
public Expression setDynamicProperty(Expression dynamicProperty, Expression value) {
return applyCallbacksFor(ExpressionCreatedEventType.ON_SET_PROPERTY, Cypher.set(dynamicProperty, value));
}
@Override
public Operation setVariable(Expression v, Expression value) {
return applyCallbacksFor(ExpressionCreatedEventType.ON_SET_VARIABLE, Cypher.set(v, value));
}
@Override
public Operation addAndSetVariable(Expression v, Expression value) {
return applyCallbacksFor(ExpressionCreatedEventType.ON_ADD_AND_SET_VARIABLE, Cypher.mutate(v, value));
}
@Override
public Expression setLabels(Expression v, List> values, List dynamicLabels, boolean containsIs) {
var s = assertSymbolicName(v);
var labels = computeFinalLabelList(LabelParsedEventType.ON_SET, values);
return applyCallbacksFor(ExpressionCreatedEventType.ON_SET_LABELS, Cypher.setLabel(Cypher.anyNode(s), labels));
}
@Override
public Clause removeClause(InputPosition p, List removeItems) {
return Clauses.remove(removeItems);
}
@Override
public Expression removeProperty(Property property) {
return applyCallbacksFor(ExpressionCreatedEventType.ON_REMOVE_PROPERTY, property);
}
@Override
public Expression removeDynamicProperty(Expression dynamicProperty) {
return applyCallbacksFor(ExpressionCreatedEventType.ON_REMOVE_PROPERTY, dynamicProperty);
}
@Override
public Expression removeLabels(Expression v, List> values,
List dynamicLabels, boolean containsIs) {
var s = assertSymbolicName(v);
var labels = computeFinalLabelList(LabelParsedEventType.ON_REMOVE, values);
return applyCallbacksFor(ExpressionCreatedEventType.ON_REMOVE_LABELS, Cypher.removeLabel(Cypher.anyNode(s), labels));
}
@Override
public Clause deleteClause(InputPosition p, boolean detach, List expressions) {
return Clauses.delete(detach, applyCallbacksFor(ExpressionCreatedEventType.ON_DELETE_ITEM, expressions));
}
@Override
public Clause unwindClause(InputPosition p, Expression e, Expression v) {
return Clauses.unwind(e, assertSymbolicName(v));
}
@Override
public Clause mergeClause(InputPosition p, PatternElement patternElementIn, List setClauses,
List actionTypes, List positions) {
var patternElement = patternElementIn instanceof NodeAtom n ? n.value() : patternElementIn;
var mergeActions = new ArrayList();
if (setClauses != null && !setClauses.isEmpty() && actionTypes != null && !actionTypes.isEmpty()) {
var iteratorClauses = setClauses.iterator();
var iteratorTypes = actionTypes.iterator();
while (iteratorClauses.hasNext() && iteratorTypes.hasNext()) {
var type = iteratorTypes.next();
switch (type) {
case OnCreate ->
mergeActions.add(MergeAction.of(MergeAction.Type.ON_CREATE, (Set) iteratorClauses.next()));
case OnMatch ->
mergeActions.add(MergeAction.of(MergeAction.Type.ON_MATCH, (Set) iteratorClauses.next()));
default -> throw new IllegalArgumentException("Unsupported MergeActionType: " + type);
}
}
}
var callbacks = this.options.getOnNewPatternElementCallbacks().getOrDefault(PatternElementCreatedEventType.ON_MERGE, List.of());
return Clauses.merge(transformIfPossible(callbacks, List.of(patternElement)), mergeActions);
}
@Override
public Clause callClause(InputPosition p, InputPosition namespacePosition, InputPosition procedureNamePosition,
InputPosition procedureResultPosition, List namespace, String name, List arguments,
boolean yieldAll, List resultItems, Where where, boolean optional) {
var intermediateResult = Clauses.callClause(namespace, name, arguments,
yieldAll && resultItems == null ? List.of(Cypher.asterisk()) : resultItems, where);
if (optional) {
throw new IllegalArgumentException("Cannot render optional call clause");
}
return applyCallbacksFor(InvocationCreatedEventType.ON_CALL, intermediateResult);
}
@Override
public Expression callResultItem(InputPosition p, String name, Expression alias) {
var finalName = Cypher.name(name);
if (alias != null) {
return finalName.as(assertSymbolicName(alias));
}
return finalName;
}
@Override
public PatternElement patternWithSelector(NULL aNull, PatternElement patternPart) {
return null;
}
@Override
public PatternElement namedPattern(Expression v, PatternElement patternElement) {
return Cypher.path(assertSymbolicName(v)).definedBy(patternElement);
}
@Override
public PatternElement shortestPathPattern(InputPosition p, PatternElement patternElement) {
isInstanceOf(RelationshipPattern.class, patternElement,
"Only relationship patterns are supported for the shortestPath function.");
return new ExpressionAsPatternElementWrapper(
FunctionInvocation.create(PatternElementFunctions.SHORTEST_PATH, patternElement));
}
@Override
public PatternElement allShortestPathsPattern(InputPosition p, PatternElement patternElement) {
isInstanceOf(RelationshipPattern.class, patternElement,
"Only relationship patterns are supported for the allShortestPaths function.");
return new ExpressionAsPatternElementWrapper(
FunctionInvocation.create(PatternElementFunctions.ALL_SHORTEST_PATHS, patternElement));
}
@Override
public PatternElement pathPattern(PatternElement patternElement) {
return patternElement;
}
@Override
public PatternElement insertPathPattern(List patternAtoms) {
throw new UnsupportedOperationException();
}
static class PatternJuxtaposition extends TypedSubtree implements PatternElement {
PatternJuxtaposition(Collection children) {
super(children);
}
@Override
public String separator() {
return " ";
}
}
static class PatternList extends TypedSubtree implements PatternElement {
PatternList(Collection children) {
super(children);
}
}
@SuppressWarnings("squid:S3776") // Yep, it's complex
@Override
public PatternElement patternElement(List atoms) {
if (atoms.isEmpty()) {
throw new IllegalArgumentException(
"Cannot create a PatternElement from an empty list of patterns.");
}
if (atoms.size() == 1 && atoms.get(0) instanceof ParenthesizedPathPatternAtom atom) {
return atom.asPatternElement();
}
List patternElements = new ArrayList<>();
NodeAtom lastNodeAtom = null;
PathAtom lastPathAtom = null;
ExposesRelationships> relationshipPattern = null;
List patternList = null;
for (PatternAtom atom : atoms) {
if (atom instanceof ParenthesizedPathPatternAtom specificAtom) {
if (lastNodeAtom != null) {
patternElements.add(lastNodeAtom.value());
}
if (relationshipPattern != null) {
patternElements.add((PatternElement) relationshipPattern);
}
if (patternList != null) {
patternElements.add(new PatternList(patternList));
}
lastNodeAtom = null;
lastPathAtom = null;
relationshipPattern = null;
patternList = null;
patternElements.add(specificAtom.asPatternElement());
} else if (atom instanceof NodeAtom nodeAtom) {
if (relationshipPattern != null) {
relationshipPattern = lastPathAtom.asRelationshipBetween(relationshipPattern, nodeAtom,
options.isAlwaysCreateRelationshipsLTR());
} else if (lastNodeAtom == null) {
lastNodeAtom = nodeAtom;
} else {
relationshipPattern = lastNodeAtom.value();
lastNodeAtom = null;
// Will be added to the pattern elements either on the occurrence of a parenthesized pattern or
// after iterating all atoms.
relationshipPattern = lastPathAtom.asRelationshipBetween(relationshipPattern, nodeAtom,
options.isAlwaysCreateRelationshipsLTR());
if ((lastPathAtom.getDirection() == Relationship.Direction.RTL || patternList != null)
&& options.isAlwaysCreateRelationshipsLTR()) {
if (patternList == null) {
patternList = new ArrayList<>();
}
patternList.add(((PatternElement) relationshipPattern));
relationshipPattern = null;
lastNodeAtom = nodeAtom;
}
}
} else if (atom instanceof PathAtom pathAtom) {
lastPathAtom = pathAtom;
}
}
if (relationshipPattern == null && patternList != null && patternList.size() == 1 && patternList.get(0) instanceof RelationshipPattern singleListItem) {
relationshipPattern = singleListItem;
patternList = null;
}
if (relationshipPattern != null) {
patternElements.add((PatternElement) relationshipPattern);
} else if (patternList != null) {
patternElements.add(new PatternList(patternList));
} else if (lastNodeAtom != null) {
patternElements.add(lastNodeAtom.value());
}
return patternElements.size() == 1 ? patternElements.get(0) : new PatternJuxtaposition(patternElements);
}
@Override
public NULL anyPathSelector(String count, InputPosition countPosition, InputPosition position) {
throw new UnsupportedOperationException();
}
@Override
public NULL allPathSelector(InputPosition position) {
throw new UnsupportedOperationException();
}
@Override
public NULL anyShortestPathSelector(String count, InputPosition countPosition, InputPosition position) {
throw new UnsupportedOperationException();
}
@Override
public NULL allShortestPathSelector(InputPosition position) {
throw new UnsupportedOperationException();
}
@Override
public NULL shortestGroupsSelector(String count, InputPosition countPosition, InputPosition position) {
throw new UnsupportedOperationException();
}
@Override
public NodeAtom nodePattern(InputPosition p, Expression v, LabelExpression labels, Expression properties, Expression predicate) {
Node node;
if (labels == null) {
node = Cypher.anyNode();
} else {
var finalLabels = computeFinalLabelList(LabelParsedEventType.ON_NODE_PATTERN, labels);
node = finalLabels.map(l -> {
var primaryLabel = l[0];
var additionalLabels = Arrays.stream(l).skip(1).toList();
return Cypher.node(primaryLabel, additionalLabels);
}).orElseGet(() -> Cypher.node(labels));
}
if (v != null) {
node = node.named(assertSymbolicName(v));
}
if (properties != null) {
node = node.withProperties((MapExpression) properties);
}
if (predicate != null) {
node = (Node) node.where(predicate);
}
return new NodeAtom(node);
}
@Override
public PathAtom relationshipPattern(InputPosition p, boolean left, boolean right, Expression v, LabelExpression relTypes, PathLength pathLength, Expression properties, Expression predicate) {
return PathAtom.of(assertSymbolicName(v), pathLength, left, right,
computeFinalTypeList(TypeParsedEventType.ON_RELATIONSHIP_PATTERN, relTypes), (MapExpression) properties,
relTypes != null && relTypes.negated(), predicate);
}
@Override
public PathLength pathLength(InputPosition p, InputPosition pMin, InputPosition pMax, String minLength,
String maxLength) {
return PathLength.of(minLength, maxLength);
}
@Override
public QuantifiedPathPattern.Quantifier intervalPathQuantifier(InputPosition p, InputPosition posLowerBound, InputPosition posUpperBound, String lowerBound, String upperBound) {
return QuantifiedPathPattern.interval(lowerBound == null ? null : Integer.parseInt(lowerBound), upperBound == null ? null : Integer.parseInt(upperBound));
}
@Override
public QuantifiedPathPattern.Quantifier fixedPathQuantifier(InputPosition p, InputPosition valuePos, String value) {
throw new UnsupportedOperationException();
}
@Override
public QuantifiedPathPattern.Quantifier plusPathQuantifier(InputPosition p) {
return QuantifiedPathPattern.plus();
}
@Override
public QuantifiedPathPattern.Quantifier starPathQuantifier(InputPosition p) {
return QuantifiedPathPattern.star();
}
@Override
public NULL repeatableElements(InputPosition p) {
throw new UnsupportedOperationException();
}
@Override
public NULL differentRelationships(InputPosition p) {
throw new UnsupportedOperationException();
}
@Override
public PatternAtom parenthesizedPathPattern(InputPosition p, PatternElement internalPattern, Expression where, QuantifiedPathPattern.Quantifier pathPatternQuantifier) {
return new ParenthesizedPathPatternAtom((RelationshipPattern) internalPattern, pathPatternQuantifier, where);
}
@Override
public PatternAtom quantifiedRelationship(PathAtom rel, QuantifiedPathPattern.Quantifier pathPatternQuantifier) {
return rel.withQuantifier(pathPatternQuantifier);
}
@Override
public Clause loadCsvClause(InputPosition p, boolean headers, Expression source, Expression v,
String fieldTerminator) {
isInstanceOf(StringLiteral.class, source, "Only string literals are supported as source for the LOAD CSV clause.");
return Clauses.loadCSV(headers, (StringLiteral) source, assertSymbolicName(v), fieldTerminator);
}
@Override
public Clause foreachClause(InputPosition p, Expression v, Expression list, List objects) {
return Clauses.forEach(assertSymbolicName(v), list, objects);
}
@Override
public Clause subqueryClause(InputPosition p, Statement subquery, NULL inTransactions, boolean scopeAll,
boolean hasScope, List expressions, boolean optional) {
if (optional) {
throw new IllegalArgumentException("Cannot render optional subquery clause");
}
return Clauses.callClause(subquery);
}
@Override
public NULL subqueryInTransactionsParams(InputPosition p, NULL batchParams, NULL concurrencyParams,
NULL errorParams, NULL reportParams) {
throw new UnsupportedOperationException();
}
@Override
public Clause yieldClause(InputPosition p, boolean returnAll, List expressions,
InputPosition returnItemsPosition, List orderBy, InputPosition orderPos, Expression skip,
InputPosition skipPosition, Expression limit, InputPosition limitPosition, Where where) {
throw new UnsupportedOperationException();
}
@Override
public Clause showIndexClause(InputPosition p, ShowCommandFilterTypes indexType, Where where, Clause yieldClause) {
throw new UnsupportedOperationException();
}
@Override
public Clause showConstraintClause(InputPosition p, ShowCommandFilterTypes constraintType, Where where,
Clause yieldClause) {
throw new UnsupportedOperationException();
}
@Override
public Clause showProcedureClause(InputPosition p, boolean currentUser, String user, Where where,
Clause yieldClause) {
throw new UnsupportedOperationException();
}
@Override
public Clause showFunctionClause(InputPosition p, ShowCommandFilterTypes functionType, boolean currentUser,
String user, Where where, Clause yieldClause) {
throw new UnsupportedOperationException();
}
@Override
public Statement useGraph(Statement command, Clause useGraph) {
throw new UnsupportedOperationException();
}
@Override
public Statement showRoles(InputPosition p, boolean withUsers, boolean showAll, Clause yieldExpr,
Return returnWithoutGraph, Where where) {
throw new UnsupportedOperationException();
}
@Override
public Statement grantRoles(InputPosition p, List, Parameter>>> roles,
List, Parameter>>> users) {
throw new UnsupportedOperationException();
}
@Override
public Statement revokeRoles(InputPosition p, List, Parameter>>> roles,
List, Parameter>>> users) {
throw new UnsupportedOperationException();
}
@Override
public Statement createUser(InputPosition p, boolean replace, boolean ifNotExists,
SimpleEither, Parameter>> username, Boolean suspended, DatabaseName homeDatabase,
List nulls, List systemAuthAttributes) {
throw new UnsupportedOperationException();
}
@Override
public Statement dropUser(InputPosition p, boolean ifExists,
SimpleEither, Parameter>> username) {
throw new UnsupportedOperationException();
}
@Override
public Statement renameUser(InputPosition p, SimpleEither, Parameter>> fromUserName,
SimpleEither, Parameter>> toUserName, boolean ifExists) {
throw new UnsupportedOperationException();
}
@Override
public Statement setOwnPassword(InputPosition p, Expression currentPassword, Expression newPassword) {
throw new UnsupportedOperationException();
}
@Override
public NULL auth(String provider, List nulls, InputPosition p) {
throw new UnsupportedOperationException();
}
@Override
public NULL authId(InputPosition s, Expression id) {
throw new UnsupportedOperationException();
}
@Override
public NULL password(InputPosition p, Expression password, boolean encrypted) {
throw new UnsupportedOperationException();
}
@Override
public NULL passwordChangeRequired(InputPosition p, boolean changeRequired) {
throw new UnsupportedOperationException();
}
@Override
public Statement alterUser(InputPosition p, boolean ifExists,
SimpleEither, Parameter>> username, Boolean suspended, DatabaseName homeDatabase,
boolean removeHome, List nulls, List systemAuthAttributes, boolean removeAllAuth,
List removeAuths) {
throw new UnsupportedOperationException();
}
@Override public Expression passwordExpression(Parameter> password) {
throw new UnsupportedOperationException();
}
@Override
public Expression passwordExpression(InputPosition s, InputPosition e, String password) {
throw new UnsupportedOperationException();
}
@Override
public Statement showUsers(InputPosition p, Clause yieldExpr, Return returnWithoutGraph, Where where,
boolean withAuth) {
throw new UnsupportedOperationException();
}
@Override
public Statement showCurrentUser(InputPosition p, Clause yieldExpr, Return returnWithoutGraph, Where where) {
throw new UnsupportedOperationException();
}
@Override
public Statement showSupportedPrivileges(InputPosition p, Clause yieldExpr, Return returnWithoutGraph, Where where) {
throw new UnsupportedOperationException();
}
@Override
public Statement showAllPrivileges(InputPosition p, boolean asCommand, boolean asRevoke, Clause yieldExpr, Return returnWithoutGraph, Where where) {
throw new UnsupportedOperationException();
}
@Override
public Statement showRolePrivileges(InputPosition p,
List, Parameter>>> roles, boolean asCommand, boolean asRevoke,
Clause yieldExpr, Return returnWithoutGraph, Where where) {
throw new UnsupportedOperationException();
}
@Override
public Statement showUserPrivileges(InputPosition p,
List, Parameter>>> users, boolean asCommand, boolean asRevoke,
Clause yieldExpr, Return returnWithoutGraph, Where where) {
throw new UnsupportedOperationException();
}
@Override
public Statement grantPrivilege(InputPosition p, List, Parameter>>> roles,
NULL privilege) {
throw new UnsupportedOperationException();
}
@Override
public Statement denyPrivilege(InputPosition p, List, Parameter>>> roles,
NULL privilege) {
throw new UnsupportedOperationException();
}
@Override
public Statement revokePrivilege(InputPosition p, List, Parameter>>> roles,
NULL privilege, boolean revokeGrant, boolean revokeDeny) {
throw new UnsupportedOperationException();
}
@SuppressWarnings("HiddenField") // The database options are quite different options than ours ;)
public Statement createDatabase(InputPosition p, boolean replace, DatabaseName databaseName, boolean ifNotExists,
NULL aNull, SimpleEither
© 2015 - 2025 Weber Informatics LLC | Privacy Policy