From 707f68279859782f09f0726924908dd589c86f42 Mon Sep 17 00:00:00 2001 From: lc0197 Date: Fri, 5 Jun 2020 13:07:03 +0200 Subject: [PATCH] [#49] cleaned up code --- src/main/antlr4/org/s1ck/gdl/GDL.g4 | 17 +- src/main/java/org/s1ck/gdl/GDLHandler.java | 22 +- src/main/java/org/s1ck/gdl/GDLLoader.java | 2471 ++++++----------- .../java/org/s1ck/gdl/GDLLoaderTemporal.java | 655 +++++ src/main/java/org/s1ck/gdl/model/Edge.java | 2 - .../java/org/s1ck/gdl/model/GraphElement.java | 2 +- .../comparables/ComparableExpression.java | 5 +- .../model/comparables/ElementSelector.java | 3 +- .../s1ck/gdl/model/comparables/Literal.java | 5 +- .../model/comparables/PropertySelector.java | 5 +- .../gdl/model/comparables/time/Duration.java | 9 +- .../model/comparables/time/MaxTimePoint.java | 9 +- .../model/comparables/time/MinTimePoint.java | 5 +- .../model/comparables/time/TimeConstant.java | 9 +- .../model/comparables/time/TimeLiteral.java | 15 +- .../gdl/model/comparables/time/TimePoint.java | 12 - .../model/comparables/time/TimeSelector.java | 12 +- .../gdl/model/comparables/time/TimeTerm.java | 4 - .../s1ck/gdl/model/predicates/Predicate.java | 57 - .../gdl/model/predicates/booleans/And.java | 8 +- .../gdl/model/predicates/booleans/Not.java | 9 +- .../gdl/model/predicates/booleans/Or.java | 8 +- .../gdl/model/predicates/booleans/Xor.java | 8 +- .../predicates/expressions/Comparison.java | 18 +- .../org/s1ck/gdl/GDLLoaderTemporalTest.java | 585 +--- src/test/java/org/s1ck/gdl/GDLLoaderTest.java | 12 +- .../gdl/comparables/time/ComparisonTest.java | 1 - .../gdl/comparables/time/DurationTest.java | 4 - .../gdl/comparables/time/MaxTimeTest.java | 26 +- .../gdl/comparables/time/MinTimeTest.java | 19 - .../gdl/comparables/time/PlusTimeTest.java | 146 - .../comparables/time/TimeConstantTest.java | 3 - .../gdl/comparables/time/TimeLiteralTest.java | 28 +- .../comparables/time/TimeSelectorTest.java | 11 +- .../s1ck/gdl/predicates/PredicateTest.java | 413 --- 35 files changed, 1758 insertions(+), 2860 deletions(-) create mode 100644 src/main/java/org/s1ck/gdl/GDLLoaderTemporal.java delete mode 100644 src/test/java/org/s1ck/gdl/comparables/time/PlusTimeTest.java delete mode 100644 src/test/java/org/s1ck/gdl/predicates/PredicateTest.java diff --git a/src/main/antlr4/org/s1ck/gdl/GDL.g4 b/src/main/antlr4/org/s1ck/gdl/GDL.g4 index 2d09e4c..884d585 100644 --- a/src/main/antlr4/org/s1ck/gdl/GDL.g4 +++ b/src/main/antlr4/org/s1ck/gdl/GDL.g4 @@ -139,6 +139,8 @@ literal // time-related //________________________ +// temporal query constraints + temporalComparison : timePoint ComparisonOP timePoint ; @@ -149,13 +151,14 @@ timeFunc | Identifier '.asOf(' timePoint ')' #asOf ; +// intervals + interval : intervalSelector | intervalFromStamps | complexInterval ; - intervalSelector : Identifier '.' IntervalConst | IntervalConst @@ -165,7 +168,6 @@ intervalFromStamps : 'Interval(' timePoint ',' timePoint ')' ; -// TODO: change (only placeholder yet) complexInterval : complexIntervalArgument '.merge(' complexIntervalArgument ')' | complexIntervalArgument '.join(' complexIntervalArgument ')' @@ -176,7 +178,8 @@ complexIntervalArgument | intervalFromStamps ; -// TODO: add functions that yield timePoint +// time points + timePoint : timeLiteral | timeSelector @@ -205,6 +208,9 @@ complexTimePointArgument | timeSelector ; + +// interval functions + intervalFunc : overlapsIntervallOperator | fromToOperator @@ -220,11 +226,11 @@ intervalFunc | lengthAtLeastOperator | lengthAtMostOperator ; + overlapsIntervallOperator : 'overlaps(' interval ')' ; - fromToOperator : 'fromTo(' timePoint ',' timePoint ')' ; @@ -282,6 +288,9 @@ timeConstant | 'Days(' IntegerLiteral ')' ; + +// time stamp/point functions + stampFunc : beforePointOperator | afterPointOperator diff --git a/src/main/java/org/s1ck/gdl/GDLHandler.java b/src/main/java/org/s1ck/gdl/GDLHandler.java index 22e3064..76d680e 100644 --- a/src/main/java/org/s1ck/gdl/GDLHandler.java +++ b/src/main/java/org/s1ck/gdl/GDLHandler.java @@ -40,7 +40,7 @@ public class GDLHandler { /** * GDL listener implementation. */ - private GDLLoader loader; + private final GDLLoader loader; /** * Private constructor to avoid external initialization. @@ -199,11 +199,6 @@ public static class Builder { */ private boolean useDefaultEdgeLabel = true; - /** - * Flag to indicate if the query should be postprocessed, i.e. reduced to simple comparisons. - */ - private boolean processQuery = false; - /** * Strategy for handling parser errors. */ @@ -313,17 +308,6 @@ public Builder setErrorStrategy(ANTLRErrorStrategy errorStrategy) { return this; } - /** - * Sets the processQuery parameter for the {@link GDLLoader}. - * - * @param processQuery processQuery flag (true iff query should be postprocessed) - * @return builder - */ - public Builder setProcessQuery(boolean processQuery){ - this.processQuery = processQuery; - return this; - } - /** * Initialize GDL Handler from given ASCII String. * @@ -340,7 +324,7 @@ public GDLHandler buildFromString(String asciiString) { * * @param stream InputStream (must not be {@code null}). * @return GDL handler - * @throws IOException + * @throws IOException if stream processing fails */ public GDLHandler buildFromStream(InputStream stream) throws IOException { ANTLRInputStream antlrInputStream = new ANTLRInputStream(stream); @@ -383,7 +367,7 @@ private GDLHandler build(ANTLRInputStream antlrInputStream) { parser.setErrorHandler(errorStrategy); GDLLoader loader = new GDLLoader(graphLabel, vertexLabel, edgeLabel, - useDefaultGraphLabel, useDefaultVertexLabel, useDefaultEdgeLabel, processQuery); + useDefaultGraphLabel, useDefaultVertexLabel, useDefaultEdgeLabel); new ParseTreeWalker().walk(loader, parser.database()); return new GDLHandler(loader); } diff --git a/src/main/java/org/s1ck/gdl/GDLLoader.java b/src/main/java/org/s1ck/gdl/GDLLoader.java index b42efec..f414f5a 100644 --- a/src/main/java/org/s1ck/gdl/GDLLoader.java +++ b/src/main/java/org/s1ck/gdl/GDLLoader.java @@ -22,7 +22,6 @@ import org.s1ck.gdl.model.*; import org.s1ck.gdl.model.comparables.ElementSelector; import org.s1ck.gdl.model.comparables.time.*; -import org.s1ck.gdl.model.comparables.time.TimeConstant; import org.s1ck.gdl.model.predicates.booleans.And; import org.s1ck.gdl.model.predicates.expressions.Comparison; import org.s1ck.gdl.model.predicates.Predicate; @@ -37,1656 +36,960 @@ import java.util.*; import java.util.stream.Collectors; -import static org.s1ck.gdl.utils.Comparator.*; - class GDLLoader extends GDLBaseListener { - // used to cache elements which are assigned to user-defined variables - private final Map userGraphCache; - private final Map userVertexCache; - private final Map userEdgeCache; - - // used to map graphs to their elements - private Map> graphElements; - - // used to cache elements which are assigned to auto-generated variables - private final Map autoGraphCache; - private final Map autoVertexCache; - private final Map autoEdgeCache; - - // used to hold the final database elements - private final Set graphs; - private final Set vertices; - private final Set edges; - - // stores the predicates tree for that query - private Predicate predicates; - - private final boolean useDefaultGraphLabel; - private final boolean useDefaultVertexLabel; - private final boolean useDefaultEdgeLabel; - - private final String defaultGraphLabel; - private final String defaultVertexLabel; - private final String defaultEdgeLabel; - - // used to generate sequential ids - private long nextGraphId = 0L; - private long nextVertexId = 0L; - private long nextEdgeId = 0L; - - // flag that tells if the parser is inside a logical graph - private boolean inGraph = false; - // holds the graph of the current graph - private long currentGraphId; - - // used to track vertex and edge ids for correct source and target binding - private Vertex lastSeenVertex; - private Edge lastSeenEdge; - - // used to keep track of filter that are yet to be handled - private Deque currentPredicates; - - // used to generate variable names if none is given - private static final String ANONYMOUS_GRAPH_VARIABLE = "__g%d"; - private static final String ANONYMOUS_VERTEX_VARIABLE = "__v%d"; - private static final String ANONYMOUS_EDGE_VARIABLE = "__e%d"; - - // should predicates be reformulated to simple comparisons? - private boolean processPredicates = true; - - - /** - * Initializes a new GDL Loader. - * - * @param defaultGraphLabel graph label to be used if no label is given in the GDL script - * @param defaultVertexLabel vertex label to be used if no label is given in the GDL script - * @param defaultEdgeLabel edge label to be used if no label is given in the GDL script - */ - GDLLoader(String defaultGraphLabel, String defaultVertexLabel, String defaultEdgeLabel) { - this(defaultGraphLabel, defaultVertexLabel, defaultEdgeLabel, - true, true, true); - } - - /** - * Initializes a new GDL Loader. - * - * @param defaultGraphLabel graph label to be used if no label is given in the GDL script - * @param defaultVertexLabel vertex label to be used if no label is given in the GDL script - * @param defaultEdgeLabel edge label to be used if no label is given in the GDL script - * @param processPredicates true iff predicates should be reformulated to simple (atomic) comparisons - */ - GDLLoader(String defaultGraphLabel, String defaultVertexLabel, String defaultEdgeLabel, - boolean processPredicates) { - this(defaultGraphLabel, defaultVertexLabel, defaultEdgeLabel); - this.processPredicates = processPredicates; - } - - /** - * Initializes a new GDL Loader. - * - * @param defaultGraphLabel graph label to be used if no label is given in the GDL script - * @param defaultVertexLabel vertex label to be used if no label is given in the GDL script - * @param defaultEdgeLabel edge label to be used if no label is given in the GDL script - * @param useDefaultGraphLabel enable default graph label - * @param useDefaultVertexLabel enable default vertex label - * @param useDefaultEdgeLabel enable default edge label - */ - GDLLoader(String defaultGraphLabel, String defaultVertexLabel, String defaultEdgeLabel, - boolean useDefaultGraphLabel, boolean useDefaultVertexLabel, boolean useDefaultEdgeLabel) { - - this.useDefaultGraphLabel = useDefaultGraphLabel; - this.useDefaultVertexLabel = useDefaultVertexLabel; - this.useDefaultEdgeLabel = useDefaultEdgeLabel; - - this.defaultGraphLabel = defaultGraphLabel; - this.defaultVertexLabel = defaultVertexLabel; - this.defaultEdgeLabel = defaultEdgeLabel; - - userGraphCache = new HashMap<>(); - userVertexCache = new HashMap<>(); - userEdgeCache = new HashMap<>(); - - graphElements = new HashMap<>(); - - autoGraphCache = new HashMap<>(); - autoVertexCache = new HashMap<>(); - autoEdgeCache = new HashMap<>(); - - graphs = new HashSet<>(); - vertices = new HashSet<>(); - edges = new HashSet<>(); - - currentPredicates = new ArrayDeque<>(); - } - - /** - * Initializes a new GDL Loader. - * - * @param defaultGraphLabel graph label to be used if no label is given in the GDL script - * @param defaultVertexLabel vertex label to be used if no label is given in the GDL script - * @param defaultEdgeLabel edge label to be used if no label is given in the GDL script - * @param useDefaultGraphLabel enable default graph label - * @param useDefaultVertexLabel enable default vertex label - * @param useDefaultEdgeLabel enable default edge label - */ - GDLLoader(String defaultGraphLabel, String defaultVertexLabel, String defaultEdgeLabel, - boolean useDefaultGraphLabel, boolean useDefaultVertexLabel, boolean useDefaultEdgeLabel, - boolean processPredicates) { - - this(defaultGraphLabel, defaultVertexLabel, defaultEdgeLabel, useDefaultGraphLabel, useDefaultVertexLabel, - useDefaultEdgeLabel); - this.processPredicates = processPredicates; - } - - /** - * Returns the default graph label. - * - * @return default graph label - */ - public String getDefaultGraphLabel() { - return defaultGraphLabel; - } - - /** - * Returns the default vertex label - * - * @return default vertex label - */ - public String getDefaultVertexLabel() { - return defaultVertexLabel; - } - - /** - * Returns the default edge label - * - * @return default edge label - */ - public String getDefaultEdgeLabel() { - return defaultEdgeLabel; - } - - /** - * Returns a collection of all graphs defined in the GDL script. - * - * @return graph collection - */ - Collection getGraphs() { - return graphs; - } - - /** - * Returns a collection of all vertices defined in the GDL script. - * - * @return vertex collection - */ - Collection getVertices() { - return vertices; - } - - /** - * Returns a collection of all edges defined in the GDL script. - * - * @return edge collection - */ - Collection getEdges() { - return edges; - } + // used to cache elements which are assigned to user-defined variables + private final Map userGraphCache; + private final Map userVertexCache; + private final Map userEdgeCache; + + // used to map graphs to their elements + private final Map> graphElements; + + // used to cache elements which are assigned to auto-generated variables + private final Map autoGraphCache; + private final Map autoVertexCache; + private final Map autoEdgeCache; + + // used to hold the final database elements + private final Set graphs; + private final Set vertices; + private final Set edges; + + // stores the predicates tree for that query + private Predicate predicates; + + private final boolean useDefaultGraphLabel; + private final boolean useDefaultVertexLabel; + private final boolean useDefaultEdgeLabel; + + private final String defaultGraphLabel; + private final String defaultVertexLabel; + private final String defaultEdgeLabel; + + // used to generate sequential ids + private long nextGraphId = 0L; + private long nextVertexId = 0L; + private long nextEdgeId = 0L; + + // flag that tells if the parser is inside a logical graph + private boolean inGraph = false; + // holds the graph of the current graph + private long currentGraphId; + + // used to track vertex and edge ids for correct source and target binding + private Vertex lastSeenVertex; + private Edge lastSeenEdge; + + // used to keep track of filter that are yet to be handled + private final Deque currentPredicates; + + // used to generate variable names if none is given + private static final String ANONYMOUS_GRAPH_VARIABLE = "__g%d"; + private static final String ANONYMOUS_VERTEX_VARIABLE = "__v%d"; + private static final String ANONYMOUS_EDGE_VARIABLE = "__e%d"; /** - * Returns the predicates defined by the query. + * Processes the temporal parts of the query + */ + private final GDLLoaderTemporal temporalLoader; + + + /** + * Initializes a new GDL Loader. * - * @return predicates + * @param defaultGraphLabel graph label to be used if no label is given in the GDL script + * @param defaultVertexLabel vertex label to be used if no label is given in the GDL script + * @param defaultEdgeLabel edge label to be used if no label is given in the GDL script */ - Optional getPredicates() { - return predicates != null ? Optional.of(predicates) : Optional.empty(); - } - /** - * Returns a cache that contains a mapping from user-defined variables used in the GDL script to - * graph instances. - * - * @return immutable graph cache - */ - Map getGraphCache() { - return getGraphCache(true, false); - } - - /** - * Returns a cache containing a mapping from variables to graphs. - * - * @param includeUserDefined include user-defined variables - * @param includeAutoGenerated include auto-generated variables - * - * @return immutable graph cache - */ - Map getGraphCache(boolean includeUserDefined, boolean includeAutoGenerated) { - return getCache(userGraphCache, autoGraphCache, includeUserDefined, includeAutoGenerated); - } - - /** - * Returns a cache that contains a mapping from user-defined variables used in the GDL script to - * vertex instances. - * - * @return immutable vertex cache - */ - Map getVertexCache() { - return getVertexCache(true, false); - } - - /** - * Returns a cache containing a mapping from variables to vertices. - * - * @param includeUserDefined include user-defined variables - * @param includeAutoGenerated include auto-generated variables - * - * @return immutable vertex cache - */ - Map getVertexCache(boolean includeUserDefined, boolean includeAutoGenerated) { - return getCache(userVertexCache, autoVertexCache, includeUserDefined, includeAutoGenerated); - } - - /** - * Returns a cache that contains a mapping from user-defined variables used in the GDL script to - * edge instances. - * - * @return immutable edge cache - */ - Map getEdgeCache() { - return getEdgeCache(true, false); - } - - /** - * Returns a cache containing a mapping from variables to edges. - * - * @param includeUserDefined include user-defined variables - * @param includeAutoGenerated include auto-generated variables - * - * @return immutable edge cache - */ - Map getEdgeCache(boolean includeUserDefined, boolean includeAutoGenerated) { - return getCache(userEdgeCache, autoEdgeCache, includeUserDefined, includeAutoGenerated); - } - - /** - * Called when parser enters a graph context. - * - * Checks if the graph has already been created (using its variable). If not, a new graph is - * created and added to the graph cache. - * - * @param graphContext graph context - */ - @Override - public void enterGraph(GDLParser.GraphContext graphContext) { - inGraph = true; - String variable = getVariable(graphContext.header()); - Graph g; - if (variable != null && userGraphCache.containsKey(variable)) { - g = userGraphCache.get(variable); - } else { - g = initNewGraph(graphContext); - - if (variable != null) { - userGraphCache.put(variable, g); - } else { - variable = String.format(ANONYMOUS_GRAPH_VARIABLE, g.getId()); - autoGraphCache.put(variable, g); - } - g.setVariable(variable); - graphs.add(g); - } - currentGraphId = g.getId(); - } - - @Override - public void exitGraph(GDLParser.GraphContext ctx) { - inGraph = false; - } - - /** - * When leaving a query context its save to add the pattern predicates to the filters - * - * @param ctx query context - */ - @Override - public void exitQuery(GDLParser.QueryContext ctx) { - if(processPredicates) { - postprocessPredicates(); - } - ArrayList vars = new ArrayList<>(); - vars.addAll(userEdgeCache.keySet()); - vars.addAll(userVertexCache.keySet()); - vars.addAll(autoEdgeCache.keySet()); - vars.addAll(autoVertexCache.keySet()); - vars.remove(TimeSelector.GLOBAL_SELECTOR); - if(predicates!=null) { - predicates = predicates.replaceGlobalByLocal(vars); + GDLLoader(String defaultGraphLabel, String defaultVertexLabel, String defaultEdgeLabel) { + this(defaultGraphLabel, defaultVertexLabel, defaultEdgeLabel, + true, true, true); } - for(Vertex v : vertices) { - addPredicates(Predicate.fromGraphElement(v, getDefaultVertexLabel())); - } - for(Edge e : edges) { - addPredicates(Predicate.fromGraphElement(e, getDefaultEdgeLabel())); - } - } - - /** - * Reformulates the predicates when leaving the query. First, complex temporal expressions - * like {@code MIN(t1,t2) vars = new ArrayList<>(); - vars.addAll(userEdgeCache.keySet()); - vars.addAll(userVertexCache.keySet()); - vars.addAll(autoEdgeCache.keySet()); - vars.addAll(autoVertexCache.keySet()); - predicates = Predicate.translateGlobalPredicates(predicates, vars, true); - } - } - - /** - * Called when parser enters a vertex context. - * - * Checks if the vertex has already been created (using its variable). If not, a new vertex is - * created and added to the vertex cache. - * - * @param vertexContext vertex context - */ - @Override - public void enterVertex(GDLParser.VertexContext vertexContext) { - String variable = getVariable(vertexContext.header()); - Vertex v; - if (variable != null && userVertexCache.containsKey(variable)) { - v = userVertexCache.get(variable); - } else { - v = initNewVertex(vertexContext); - - if (variable != null) { - userVertexCache.put(variable, v); - } else { - variable = String.format(ANONYMOUS_VERTEX_VARIABLE, v.getId()); - autoVertexCache.put(variable, v); - } - v.setVariable(variable); - vertices.add(v); - } - updateGraphElement(v); - setLastSeenVertex(v); - updateLastSeenEdge(v); - } - - /** - * Called when parser enters an incoming edge context. - * - * @param incomingEdgeContext incoming edge context - */ - @Override - public void enterIncomingEdge(GDLParser.IncomingEdgeContext incomingEdgeContext) { - processEdge(incomingEdgeContext.edgeBody(), true); - } - - /** - * Called when parser enters an outgoing edge context. - * - * @param outgoingEdgeContext outgoing edge context - */ - @Override - public void enterOutgoingEdge(GDLParser.OutgoingEdgeContext outgoingEdgeContext) { - processEdge(outgoingEdgeContext.edgeBody(), false); - } - - /** - * Called when the parser leaves a WHERE expression - * - * Takes care that the filter build from the current expression is stored - * in the graph and that default asOf(now) predicates are added iff there are no constraints - * on any tx_to values - * - * @param ctx where context - */ - @Override - public void exitWhere(GDLParser.WhereContext ctx) { - Predicate predicate = currentPredicates.pop(); - addPredicates(Collections.singletonList(predicate)); - } - - /** - * Builds a {@code Comparison} expression from comparison context - * - * @param ctx comparison context - */ - @Override - public void enterComparisonExpression(GDLParser.ComparisonExpressionContext ctx) { - currentPredicates.add(buildComparison(ctx)); - } - - @Override - public void enterTemporalComparison(GDLParser.TemporalComparisonContext ctx){ - currentPredicates.add(buildTemporalComparison(ctx)); - } - - /** - * Builds a {@code Predicate} from the given Intervall-Function (caller is a interval) - * interval functions are e.g. succeeds(x), between(x,y).... - * - * @param ctx interval function context - */ - @Override - public void enterIntvF(GDLParser.IntvFContext ctx){ - currentPredicates.add(buildIntervalFunction(ctx)); - } - - /** - * Builds a Comparison filter operator from comparison context - * - * @param ctx the comparison context that will be parsed - * @return parsed operator - */ - private Comparison buildTemporalComparison(GDLParser.TemporalComparisonContext ctx) { - ComparableExpression lhs = buildTimePoint(ctx.timePoint(0)); - ComparableExpression rhs = buildTimePoint(ctx.timePoint(1)); - Comparator comp = Comparator.fromString(ctx .ComparisonOP().getText()); - - return new Comparison(lhs, comp, rhs); - } - - /** - * Converts an interval function into a (complex) predicate - * For example, i.between(x,y) would be translated to a predicate ((i.from<= y) AND (i.to>x)) - * @param ctx interval function context - * @return complex predicate that encodes the interval function. Atoms are time stamp comparisons - */ - private Predicate buildIntervalFunction(GDLParser.IntvFContext ctx) { - int predicateSizeBefore = currentPredicates.size(); - TimePoint[] intv = buildIntervall(ctx.interval()); - TimePoint from = intv[0]; - TimePoint to = intv[1]; - Predicate predicate = createIntervalPredicates(from, to, ctx.intervalFunc()); - // additional constraints? - int countConstraints = currentPredicates.size() - predicateSizeBefore; - for(int i = 0; i(); + userVertexCache = new HashMap<>(); + userEdgeCache = new HashMap<>(); + + graphElements = new HashMap<>(); + + autoGraphCache = new HashMap<>(); + autoVertexCache = new HashMap<>(); + autoEdgeCache = new HashMap<>(); + + graphs = new HashSet<>(); + vertices = new HashSet<>(); + edges = new HashSet<>(); + + currentPredicates = new ArrayDeque<>(); + + temporalLoader = new GDLLoaderTemporal(this); } - else if(intervalFunc.longerThanOperator()!=null){ - return createLongerThanPredicates(from, to, intervalFunc.longerThanOperator()); + + + /** + * Returns the default graph label. + * + * @return default graph label + */ + public String getDefaultGraphLabel() { + return defaultGraphLabel; } - else if(intervalFunc.shorterThanOperator()!=null){ - return createShorterThanPredicates(from, to, intervalFunc.shorterThanOperator()); + + /** + * Returns the default vertex label + * + * @return default vertex label + */ + public String getDefaultVertexLabel() { + return defaultVertexLabel; } - else if(intervalFunc.lengthAtLeastOperator()!=null){ - return createLengthAtLeastPredicates(from, to, intervalFunc.lengthAtLeastOperator()); + + /** + * Returns the default edge label + * + * @return default edge label + */ + public String getDefaultEdgeLabel() { + return defaultEdgeLabel; } - else if(intervalFunc.lengthAtMostOperator()!=null){ - return createLengthAtMostPredicates(from, to, intervalFunc.lengthAtMostOperator()); + + /** + * Returns a collection of all graphs defined in the GDL script. + * + * @return graph collection + */ + Collection getGraphs() { + return graphs; } - return null; - } - - /** - * Creates a predicate a.overlaps(b)=max(a.from,b.from)x - * @param from from value of the calling interval - * @param to to value of the calling interval - * @param ctx context of the call, containing x and y - * @return fromTo predicate - */ - private Predicate createFromToPredicates(TimePoint from, TimePoint to, GDLParser.FromToOperatorContext ctx){ - TimePoint x = buildTimePoint(ctx.timePoint(0)); - TimePoint y = buildTimePoint(ctx.timePoint(1)); - return new And( - new Comparison(from, Comparator.LT, y), - new Comparison(to, Comparator.GT, x) - ); - } - - /** - * Creates a predicate a.between(x,y) = a.from<=y AND a.to>x - * @param from from value of the calling interval - * @param to to value of the calling interval - * @param ctx context of the call, containing x and y - * @return between predicate - */ - private Predicate createBetweenPredicates(TimePoint from, TimePoint to, GDLParser.BetweenOperatorContext ctx){ - TimePoint x = buildTimePoint(ctx.timePoint(0)); - TimePoint y = buildTimePoint(ctx.timePoint(1)); - return new And( - new Comparison(from, LTE, y), - new Comparison(to, Comparator.GT, x) - ); - } - - /** - * Creates a predicate a.precedes(b) = a.to <= b.from. - * Function is used for interval and timestamp function {@code precedes}, as they both - * only compare two time stamps - * @param to the time stamp of the caller to compare - * @param ctx the context containing the value to be compared - * @return precedes predicate - */ - private Predicate createPrecedesPredicates(TimePoint to, GDLParser.PrecedesOperatorContext ctx){ - TimePoint[] arg = buildIntervall(ctx.interval()); - TimePoint arg_from = arg[0]; - return new Comparison(to, LTE, arg_from); - } - - /** - * Creates a predicate a.immediatelyPrecedes(b) = (a.to == b.from). - * @param to the time stamp of the caller to compare - * @param ctx the context containing the from value to be compared - * @return immediatelyPrecedes predicate - */ - private Predicate createImmediatelyPrecedesPredicates(TimePoint to, GDLParser.ImmediatelyPrecedesOperatorContext ctx){ - TimePoint[] arg = buildIntervall(ctx.interval()); - TimePoint arg_from = arg[0]; - return new Comparison(to, EQ, arg_from); - } - - /** - * Creates a predicate a.succeeds(b) = a >= b. - * Function is used for interval and timestamp function {@code precedes}, as they both - * only compare two time stamps - * @param point the time stamp of the caller to compare - * @param ctx the context containing the value to be compared - * @return succeeds predicate - */ - private Predicate createSucceedsPredicates(TimePoint point, GDLParser.SucceedsOperatorContext ctx){ - TimePoint[] arg = buildIntervall(ctx.interval()); - TimePoint arg_to = arg[1]; - return new Comparison(point, GTE, arg_to); - } - - /** - * Creates a predicate a.immediatelySucceeds(b) = (a.from == b.to). - * Function is used for interval and timestamp function {@code precedes}, as they both - * only compare two time stamps - * @param from the from value of the caller interval - * @param ctx the context containing the to value of the interval to be compared - * @return immediatelySucceeds predicate - */ - private Predicate createImmediatelySucceedsPredicates(TimePoint from, - GDLParser.ImmediatelySucceedsOperatorContext ctx){ - TimePoint[] arg = buildIntervall(ctx.interval()); - TimePoint arg_to = arg[1]; - return new Comparison(from, EQ, arg_to); - } - - /** - * Creates a predicate a.contains(b) = a.from<=b.from AND a.to>=b.to - * @param from from value of the calling interval - * @param to to value of the calling interval - * @param ctx context of the call, containing b - * @return contains predicate - */ - private Predicate createContainsPredicates(TimePoint from, TimePoint to, GDLParser.ContainsOperatorContext ctx){ - if(ctx.interval()!=null){ - TimePoint[] arg = buildIntervall(ctx.interval()); - TimePoint arg_from = arg[0]; - TimePoint arg_to = arg[1]; - return new And( - new Comparison(from, LTE, arg_from), - new Comparison(to, GTE, arg_to) - ); + + /** + * Returns a collection of all vertices defined in the GDL script. + * + * @return vertex collection + */ + Collection getVertices() { + return vertices; } - // argument is only a timestamp - else{ - TimePoint arg = buildTimePoint(ctx.timePoint()); - return new And( - new Comparison(from, LTE, arg), new Comparison(to, GTE, arg) - ); + + /** + * Returns a collection of all edges defined in the GDL script. + * + * @return edge collection + */ + Collection getEdges() { + return edges; } - } - - /** - * Creates a predicate a.equals(b) = (a.from = b.from AND a.to = b.to). - * @param from from value of the calling interval - * @param to to value of the calling interval - * @param ctx context containing the callee interval - * @return equals predicate - */ - private Predicate createEqualsPredicates(TimePoint from, TimePoint to, GDLParser.EqualsOperatorContext ctx){ - TimePoint[] arg = buildIntervall(ctx.interval()); - TimePoint arg_from = arg[0]; - TimePoint arg_to = arg[1]; - return new And( - new Comparison(from, EQ, arg_from), - new Comparison(to, EQ, arg_to) - ); - } - - /** - * Creates a predicate a.longerThan(b) = (length(a) > length(b)) - * @param from from value of the calling interval - * @param to to value of the calling interval - * @param ctx context containing the callee interval - * @return longerThan predicate - */ - private Predicate createLongerThanPredicates(TimePoint from, TimePoint to, GDLParser.LongerThanOperatorContext ctx){ - Duration rhs = new Duration(from, to); - if(ctx.timeConstant()!=null) { - TimeConstant constant = buildTimeConstant(ctx.timeConstant()); - return new Comparison(rhs, GT, constant); + + /** + * Returns the predicates defined by the query. + * + * @return predicates + */ + Optional getPredicates() { + return predicates != null ? Optional.of(predicates) : Optional.empty(); } - else if(ctx.interval()!=null){ - TimePoint[] interval = buildIntervall(ctx.interval()); - Duration lhs = new Duration(interval[0], interval[1]); - return new Comparison(rhs, GT, lhs); + + /** + * Returns a cache that contains a mapping from user-defined variables used in the GDL script to + * graph instances. + * + * @return immutable graph cache + */ + Map getGraphCache() { + return getGraphCache(true, false); } - return null; - } - - /** - * Creates a predicate a.shorterThan(b) = (length(a) < length(b)) - * @param from from value of the calling interval - * @param to to value of the calling interval - * @param ctx context containing the callee interval - * @return shorterThan predicate - */ - private Predicate createShorterThanPredicates(TimePoint from, TimePoint to, GDLParser.ShorterThanOperatorContext ctx){ - Duration rhs = new Duration(from, to); - if(ctx.timeConstant()!=null) { - TimeConstant constant = buildTimeConstant(ctx.timeConstant()); - return new Comparison(rhs, LT, constant); + + /** + * Returns a cache containing a mapping from variables to graphs. + * + * @param includeUserDefined include user-defined variables + * @param includeAutoGenerated include auto-generated variables + * @return immutable graph cache + */ + Map getGraphCache(boolean includeUserDefined, boolean includeAutoGenerated) { + return getCache(userGraphCache, autoGraphCache, includeUserDefined, includeAutoGenerated); } - else if(ctx.interval()!=null){ - TimePoint[] interval = buildIntervall(ctx.interval()); - Duration lhs = new Duration(interval[0], interval[1]); - return new Comparison(rhs, LT, lhs); + + /** + * Returns a cache that contains a mapping from user-defined variables used in the GDL script to + * vertex instances. + * + * @return immutable vertex cache + */ + Map getVertexCache() { + return getVertexCache(true, false); } - return null; - } - - /** - * Creates a predicate a.lengthAtLeast(b) = (length(a) >= length(b)) - * @param from from value of the calling interval - * @param to to value of the calling interval - * @param ctx context containing the callee interval - * @return lengthAtLeast predicate - */ - private Predicate createLengthAtLeastPredicates(TimePoint from, TimePoint to, - GDLParser.LengthAtLeastOperatorContext ctx){ - Duration rhs = new Duration(from, to); - if(ctx.timeConstant()!=null) { - TimeConstant constant = buildTimeConstant(ctx.timeConstant()); - return new Comparison(rhs, GTE, constant); + + /** + * Returns a cache containing a mapping from variables to vertices. + * + * @param includeUserDefined include user-defined variables + * @param includeAutoGenerated include auto-generated variables + * @return immutable vertex cache + */ + Map getVertexCache(boolean includeUserDefined, boolean includeAutoGenerated) { + return getCache(userVertexCache, autoVertexCache, includeUserDefined, includeAutoGenerated); } - else if(ctx.interval()!=null){ - TimePoint[] interval = buildIntervall(ctx.interval()); - Duration lhs = new Duration(interval[0], interval[1]); - return new Comparison(rhs, GTE, lhs); + + /** + * Returns a cache that contains a mapping from user-defined variables used in the GDL script to + * edge instances. + * + * @return immutable edge cache + */ + Map getEdgeCache() { + return getEdgeCache(true, false); } - return null; - } - - /** - * Creates a predicate a.lengthAtMost(b) = (length(a) <= length(b)) - * @param from from value of the calling interval - * @param to to value of the calling interval - * @param ctx context containing the callee interval - * @return lengthAtMost predicate - */ - private Predicate createLengthAtMostPredicates(TimePoint from, TimePoint to, - GDLParser.LengthAtMostOperatorContext ctx){ - Duration rhs = new Duration(from, to); - if(ctx.timeConstant()!=null) { - TimeConstant constant = buildTimeConstant(ctx.timeConstant()); - return new Comparison(rhs, LTE, constant); + + /** + * Returns a cache containing a mapping from variables to edges. + * + * @param includeUserDefined include user-defined variables + * @param includeAutoGenerated include auto-generated variables + * @return immutable edge cache + */ + Map getEdgeCache(boolean includeUserDefined, boolean includeAutoGenerated) { + return getCache(userEdgeCache, autoEdgeCache, includeUserDefined, includeAutoGenerated); } - else if(ctx.interval()!=null){ - TimePoint[] interval = buildIntervall(ctx.interval()); - Duration lhs = new Duration(interval[0], interval[1]); - return new Comparison(rhs, LTE, lhs); + + /** + * Called when parser enters a graph context. + *

+ * Checks if the graph has already been created (using its variable). If not, a new graph is + * created and added to the graph cache. + * + * @param graphContext graph context + */ + @Override + public void enterGraph(GDLParser.GraphContext graphContext) { + inGraph = true; + String variable = getVariable(graphContext.header()); + Graph g; + if (variable != null && userGraphCache.containsKey(variable)) { + g = userGraphCache.get(variable); + } else { + g = initNewGraph(graphContext); + + if (variable != null) { + userGraphCache.put(variable, g); + } else { + variable = String.format(ANONYMOUS_GRAPH_VARIABLE, g.getId()); + autoGraphCache.put(variable, g); + } + g.setVariable(variable); + graphs.add(g); + } + currentGraphId = g.getId(); } - return null; - } - - /** - * Creates a TimeConstant given a suitable context. Constants can be a constant number - * of days ({@code Days(n)}), hours ({@code Hours(n)}), minutes ({@code Minutes(n)}), - * seconds ({@code Seconds(n)}) or milliseconds ({@code Millis(n)}). - * @param ctx the context containing the constant. - * @return time constant - */ - private TimeConstant buildTimeConstant(GDLParser.TimeConstantContext ctx){ - int value = Integer.parseInt(ctx.IntegerLiteral().getText()); - if(ctx.getText().startsWith("Days(")){ - return new TimeConstant(value,0,0,0,0); + + @Override + public void exitGraph(GDLParser.GraphContext ctx) { + inGraph = false; } - else if(ctx.getText().startsWith("Hours(")){ - return new TimeConstant(0, value, 0, 0, 0); + + /** + * When leaving a query context its save to add the pattern predicates to the filters + * + * @param ctx query context + */ + @Override + public void exitQuery(GDLParser.QueryContext ctx) { + ArrayList vars = new ArrayList<>(); + vars.addAll(userEdgeCache.keySet()); + vars.addAll(userVertexCache.keySet()); + vars.addAll(autoEdgeCache.keySet()); + vars.addAll(autoVertexCache.keySet()); + vars.remove(TimeSelector.GLOBAL_SELECTOR); + if (predicates != null) { + predicates = predicates.replaceGlobalByLocal(vars); + } + for (Vertex v : vertices) { + addPredicates(Predicate.fromGraphElement(v, getDefaultVertexLabel())); + } + for (Edge e : edges) { + addPredicates(Predicate.fromGraphElement(e, getDefaultEdgeLabel())); + } } - else if(ctx.getText().startsWith("Minutes(")){ - return new TimeConstant(0, 0, value, 0, 0); + + /** + * Called when parser enters a vertex context. + *

+ * Checks if the vertex has already been created (using its variable). If not, a new vertex is + * created and added to the vertex cache. + * + * @param vertexContext vertex context + */ + @Override + public void enterVertex(GDLParser.VertexContext vertexContext) { + String variable = getVariable(vertexContext.header()); + Vertex v; + if (variable != null && userVertexCache.containsKey(variable)) { + v = userVertexCache.get(variable); + } else { + v = initNewVertex(vertexContext); + + if (variable != null) { + userVertexCache.put(variable, v); + } else { + variable = String.format(ANONYMOUS_VERTEX_VARIABLE, v.getId()); + autoVertexCache.put(variable, v); + } + v.setVariable(variable); + vertices.add(v); + } + updateGraphElement(v); + setLastSeenVertex(v); + updateLastSeenEdge(v); } - else if(ctx.getText().startsWith("Seconds(")){ - return new TimeConstant(0, 0, 0, value, 0); + + /** + * Called when parser enters an incoming edge context. + * + * @param incomingEdgeContext incoming edge context + */ + @Override + public void enterIncomingEdge(GDLParser.IncomingEdgeContext incomingEdgeContext) { + processEdge(incomingEdgeContext.edgeBody(), true); } - else if(ctx.getText().startsWith("Millis(")){ - return new TimeConstant(0, 0, 0, 0, value); + + /** + * Called when parser enters an outgoing edge context. + * + * @param outgoingEdgeContext outgoing edge context + */ + @Override + public void enterOutgoingEdge(GDLParser.OutgoingEdgeContext outgoingEdgeContext) { + processEdge(outgoingEdgeContext.edgeBody(), false); } - return null; - } - - /** - * Creates an array {@code {from, to}} representing an intervall. - * @param ctx context from which to derive {@code from} and {@code to} - * @return {@code {from, to}} representing an intervall - */ - private TimePoint[] buildIntervall(GDLParser.IntervalContext ctx) { - if (ctx.intervalSelector()!=null){ - GDLParser.IntervalSelectorContext selector = ctx.intervalSelector(); - // throws exception, if variable invalid - return buildIntervalFromSelector(selector); + + /** + * Called when the parser leaves a WHERE expression + *

+ * Takes care that the filter build from the current expression is stored + * in the graph and that default asOf(now) predicates are added iff there are no constraints + * on any tx_to values + * + * @param ctx where context + */ + @Override + public void exitWhere(GDLParser.WhereContext ctx) { + Predicate predicate = currentPredicates.pop(); + addPredicates(Collections.singletonList(predicate)); } - else if(ctx.intervalFromStamps()!=null){ - GDLParser.IntervalFromStampsContext fs = ctx.intervalFromStamps(); - return buildIntervalFromStamps(fs); + + /** + * Builds a {@code Comparison} expression from comparison context + * + * @param ctx comparison context + */ + @Override + public void enterComparisonExpression(GDLParser.ComparisonExpressionContext ctx) { + currentPredicates.add(buildComparison(ctx)); } - else if(ctx.complexInterval()!=null){ - GDLParser.ComplexIntervalArgumentContext arg1 = ctx.complexInterval() - .complexIntervalArgument(0); - GDLParser.ComplexIntervalArgumentContext arg2 = ctx.complexInterval() - .complexIntervalArgument(1); - boolean join = ctx.getText().contains(".join("); - return buildIntervalFromComplex(arg1, arg2, join); + + @Override + public void enterTemporalComparison(GDLParser.TemporalComparisonContext ctx) { + currentPredicates.add(temporalLoader.buildTemporalComparison(ctx)); } - return null; - } - - /** - * Creates an intervall as an array {@code {from, to}} from a selector context. - * I.e., a intervall like {@code a.val} would result in {@code {a.val_from, a.val_to}}. - * What is more, {@code val} results in {@code GLOBAL_SELECTOR.val_from, GLOBAL_SELECTOR.val_to} - * @param ctx context from which to derive the interval - * @return {@code {from, to}} representing the interval - */ - private TimePoint[] buildIntervalFromSelector(GDLParser.IntervalSelectorContext ctx){ - String var = ctx.Identifier()!=null ? - resolveIdentifier(ctx.Identifier().getText()) : TimeSelector.GLOBAL_SELECTOR; - String intId = ctx.IntervalConst().getText(); - TimePoint from = new TimeSelector(var, intId+"_from"); - TimePoint to = new TimeSelector(var, intId+"_to"); - return new TimePoint[]{from, to}; - } - - /** - * Creates an intervall as an array {@code {from, to}} from a interval constant context. - * I.e., a intervall like {@code Interval(1970-01-01, 2020-01-01)} would result in - * {@code {1970-01-01, 2020-01-01}}. - * @param ctx context from which to derive the interval - * @return {@code {from, to}} representing the interval - */ - private TimePoint[] buildIntervalFromStamps(GDLParser.IntervalFromStampsContext ctx){ - TimePoint from = buildTimePoint(ctx.timePoint(0)); - TimePoint to = buildTimePoint(ctx.timePoint(1)); - return new TimePoint[]{from,to}; - } - - /** - * Creates an intervall as an array {@code {from, to}} from a complex interval context, i.e. - * {@code merge} and {@code join} expressions. - * An intervall like {@code a.merge(b)} would result in {@code {max(a.from, b.from), min(a.to, b.to}} - * while {@code a.join(b)} results in {@code {min(a.from, b.from), max(a.to, b.to)}}. - * Furthermore, a constraint {max(a.from, b.from)<= min(a.to, b.to)} is added (intervals must overlap, - * in at least one ms) - * @param arg1 context from which to derive the calling interval - * @param arg2 context from which to derive the callee interval - * @param join true iff join should be performed, false iff merge is desired - * @return {@code {from, to}} representing the interval - */ - private TimePoint[] buildIntervalFromComplex(GDLParser.ComplexIntervalArgumentContext arg1, - GDLParser.ComplexIntervalArgumentContext arg2, - boolean join){ - TimePoint[] i1 = null; - TimePoint[] i2 = null; - if(arg1.intervalFromStamps()!=null){ - i1 = buildIntervalFromStamps(arg1.intervalFromStamps()); + + /** + * Builds a {@code Predicate} from the given interval function (caller is a interval) + * interval functions are e.g. succeeds(x), between(x,y).... + * + * @param ctx interval function context + */ + @Override + public void enterIntvF(GDLParser.IntvFContext ctx) { + currentPredicates.add(temporalLoader.buildIntervalFunction(ctx)); } - else{ - i1 = buildIntervalFromSelector(arg1.intervalSelector()); + + /** + * Builds a {@code Predicate} from the given TimeStamp-Function (caller is a timestamp) + * time stamp functions are e.g. succeeds(x), before(x),... + * + * @param ctx stamp function context + */ + @Override + public void enterStmpF(GDLParser.StmpFContext ctx) { + currentPredicates.add(temporalLoader.buildStampFunction(ctx)); } - if(arg2.intervalFromStamps()!=null){ - i2 = buildIntervalFromStamps(arg2.intervalFromStamps()); + + @Override + public void enterAsOf(GDLParser.AsOfContext ctx) { + currentPredicates.add(temporalLoader.createAsOf(ctx)); } - else{ - i2 = buildIntervalFromSelector(arg2.intervalSelector()); + + /** + * Called when we leave an NotExpression. + * + * Checks if the expression is preceded by a Not and adds the filter in that case. + * + * @param ctx expression context + */ + @Override + public void exitNotExpression(GDLParser.NotExpressionContext ctx) { + if (!ctx.NOT().isEmpty()) { + Predicate not = new Not(currentPredicates.removeLast()); + currentPredicates.add(not); + } } - // constraint: merge and join only when overlapping or meeting - Comparison constraint = new Comparison( - new MaxTimePoint(i1[0], i2[0]), LTE, new MinTimePoint(i1[1], i2[1]) - ); - currentPredicates.addFirst(constraint); - // now build complex intervall from i1, i2 - if(join){ - TimePoint start = new MinTimePoint(i1[0],i2[0]); - TimePoint end = new MaxTimePoint(i1[1],i2[1]); - return new TimePoint[]{start, end}; + + /** + * Called when parser leaves AndExpression + * + * Processes expressions connected by AND + * + * @param ctx expression context + */ + @Override + public void exitAndExpression(GDLParser.AndExpressionContext ctx) { + processConjunctionExpression(ctx.AND()); } - // merge - else{ - TimePoint start = new MaxTimePoint(i1[0],i2[0]); - TimePoint end = new MinTimePoint(i1[1],i2[1]); - return new TimePoint[]{start, end}; + + /** + * Called when parser leaves OrExpression + * + * Processes expressions connected by OR + * + * @param ctx expression context + */ + @Override + public void exitOrExpression(GDLParser.OrExpressionContext ctx) { + processConjunctionExpression(ctx.OR()); } - } - - /** - * Builds a {@code Predicate} from the given TimeStamp-Function (caller is a timestamp) - * time stamp functions are e.g. succeeds(x), before(x),... - * - * @param ctx stamp function context - */ - @Override - public void enterStmpF(GDLParser.StmpFContext ctx){ - currentPredicates.add(buildStampFunction(ctx)); - } - - /** - * Converts a time stamp function into a (potentially complex) {@code Predicate} - * For example, i.before(x) would be translated to a {@code Predicate} i + * Processes expressions connected by XOR + * + * @param ctx expression context + */ + @Override + public void exitXorExpression(GDLParser.XorExpressionContext ctx) { + processConjunctionExpression(ctx.XOR()); } - else if(stampFunc.afterPointOperator()!=null){ - return createAfterPredicates(tp, stampFunc.afterPointOperator()); + + /** + * Processes incoming and outgoing edges. + *

+ * Checks if the edge has already been created (using its variable). If not, a new edge is created + * and added to the edge cache. + * + * @param edgeBodyContext edge body context + * @param isIncoming true, if edge is incoming, false for outgoing edge + */ + private void processEdge(GDLParser.EdgeBodyContext edgeBodyContext, boolean isIncoming) { + String variable = null; + Edge e; + + if (edgeBodyContext != null) { + variable = getVariable(edgeBodyContext.header()); + } + if (variable != null && userEdgeCache.containsKey(variable)) { + e = userEdgeCache.get(variable); + } else { + e = initNewEdge(edgeBodyContext, isIncoming); + + if (variable != null) { + userEdgeCache.put(variable, e); + } else { + variable = String.format(ANONYMOUS_EDGE_VARIABLE, e.getId()); + autoEdgeCache.put(variable, e); + } + e.setVariable(variable); + edges.add(e); + } + updateGraphElement(e); + setLastSeenEdge(e); } - else if(stampFunc.precedesOperator()!=null){ - return createPrecedesPredicates(tp, stampFunc.precedesOperator()); + + /** + * Processes a conjunctive expression (AND, OR, XOR) and connects the filter with the corresponding operator + * + * @param conjunctions list of conjunction operators + */ + private void processConjunctionExpression(List conjunctions) { + Predicate conjunctionReuse; + for (int i = conjunctions.size() - 1; i >= 0; i--) { + Predicate rhs = currentPredicates.removeLast(); + Predicate lhs = currentPredicates.removeLast(); + + switch (conjunctions.get(i).getText().toLowerCase()) { + case "and": + conjunctionReuse = new And(lhs, rhs); + break; + case "or": + conjunctionReuse = new Or(lhs, rhs); + break; + default: + conjunctionReuse = new Xor(lhs, rhs); + break; + } + currentPredicates.add(conjunctionReuse); + } } - else if(stampFunc.succeedsOperator()!=null){ - return createSucceedsPredicates(tp, stampFunc.succeedsOperator()); + + // -------------------------------------------------------------------------------------------- + // Init handlers + // -------------------------------------------------------------------------------------------- + + /** + * Initializes a new graph from a given graph context. + * + * @param graphContext graph context + * @return new graph + */ + private Graph initNewGraph(GDLParser.GraphContext graphContext) { + Graph g = new Graph(); + g.setId(getNewGraphId()); + List labels = getLabels(graphContext.header()); + g.setLabels(labels.isEmpty() ? + useDefaultGraphLabel ? Collections.singletonList(defaultGraphLabel) : Collections.emptyList() + : labels); + g.setProperties(getProperties(graphContext.properties())); + + return g; } - return null; - } - - - /** - * Creates a before {@code Predicate} given the caller (a timestamp) and its context - * - * @param from the caller - * @param ctx its context including the argument - * @return a {@code Predicate} encoding the before function: fromx - */ - private Predicate createAfterPredicates(TimePoint from, GDLParser.AfterPointOperatorContext ctx){ - TimePoint x = buildTimePoint(ctx.timePoint()); - return new Comparison(from, Comparator.GT, x); - } - - /** - * Builds a {@code TimePoint} (can be {@code TimeLiteral}, {@code TimeSelector}, {@code MIN},...) given its context - * - * @param ctx timepoint context - * @return the {@code TimePoint} described by the context - */ - private TimePoint buildTimePoint(GDLParser.TimePointContext ctx) { - if (ctx.timeLiteral() != null){ - return buildTimeLiteral(ctx.timeLiteral()); + + /** + * Initializes a new vertex from a given vertex context. + * + * @param vertexContext vertex context + * @return new vertex + */ + private Vertex initNewVertex(GDLParser.VertexContext vertexContext) { + Vertex v = new Vertex(); + v.setId(getNewVertexId()); + List labels = getLabels(vertexContext.header()); + v.setLabels(labels.isEmpty() ? + useDefaultVertexLabel ? Collections.singletonList(defaultVertexLabel) : Collections.emptyList() + : labels); + v.setProperties(getProperties(vertexContext.properties())); + + return v; } - else if (ctx.timeSelector()!=null){ - return buildTimeSelector(ctx.timeSelector()); + + /** + * Initializes a new edge from the given edge body context. + * + * @param edgeBodyContext edge body context + * @param isIncoming true, if it's an incoming edge, false for outgoing edge + * @return new edge + */ + private Edge initNewEdge(GDLParser.EdgeBodyContext edgeBodyContext, boolean isIncoming) { + boolean hasBody = edgeBodyContext != null; + Edge e = new Edge(); + e.setId(getNewEdgeId()); + e.setSourceVertexId(getSourceVertexId(isIncoming)); + e.setTargetVertexId(getTargetVertexId(isIncoming)); + + if (hasBody) { + List labels = getLabels(edgeBodyContext.header()); + e.setLabels(labels.isEmpty() ? + useDefaultEdgeLabel ? Collections.singletonList(defaultEdgeLabel) : Collections.emptyList() + : labels); + e.setProperties(getProperties(edgeBodyContext.properties())); + int[] range = parseEdgeLengthContext(edgeBodyContext.edgeLength()); + e.setLowerBound(range[0]); + e.setUpperBound(range[1]); + } else { + if (useDefaultEdgeLabel) { + e.setLabel(defaultEdgeLabel); + } else { + e.setLabel(null); + } + } + + return e; } - else if (ctx.complexTimePoint()!=null){ - return buildComplexTimePoint(ctx.complexTimePoint()); + + // -------------------------------------------------------------------------------------------- + // Update handlers + // -------------------------------------------------------------------------------------------- + + /** + * If the parser is currently inside a logical graph, the given element is added to that graph. + * + * @param graphElement graph element ({@link Vertex}, {@link Edge}) + */ + private void updateGraphElement(GraphElement graphElement) { + if (inGraph) { + graphElement.addToGraph(getNextGraphId()); + if (!graphElements.containsKey(getNextGraphId())) { + graphElements.put(getNextGraphId(), new ArrayList<>()); + } + graphElements.get(getNextGraphId()).add(graphElement); + } } - return null; - } - - /** - * Builds a TimeLiteral given a context. - * @param ctx context containing the literal - * @return TimeLiteral - */ - private TimeLiteral buildTimeLiteral(GDLParser.TimeLiteralContext ctx){ - return new TimeLiteral(ctx.getText().trim()); - } - - /** - * Builds a TimeSelector (variable.field, where field in {TX_FROM, TX_TO, VAL_FROM, VAL_TO}) - * @param ctx context containing the selector - * @return TimeSelector - */ - private TimeSelector buildTimeSelector(GDLParser.TimeSelectorContext ctx){ - // checks whether ID is even there (is a vertex or edge) and returns its variable - String var = ctx.Identifier()!=null ? - resolveIdentifier(ctx.Identifier().getText()) : TimeSelector.GLOBAL_SELECTOR; - String field = ctx.TimeProp().getText(); - return new TimeSelector(var, field); - } - - /** - * Builds a "complex" time point, i.e. a time point described by a {@code MAX(...)} or - * {@code MIN(...)} expression. - * @param ctx context containing the time point - * @return complex time point - */ - private TimePoint buildComplexTimePoint(GDLParser.ComplexTimePointContext ctx){ - - List argumentContexts = - ctx.complexTimePointArgument(); - TimePoint[] args = new TimePoint[argumentContexts.size()]; - - for(int i=0; i getLabels(GDLParser.HeaderContext header) { + if (header != null && header.label() != null) { + return header + .label() + .stream() + .map(RuleContext::getText) + .map(x -> x.substring(1)) + .collect(Collectors.toList()); + } + return null; } - else if(ctx.getText().startsWith("MIN(")){ - return new MinTimePoint(args); + + /** + * Returns the properties map from a given properties context. + * + * @param propertiesContext properties context + * @return properties map or {@code null} if context was null + */ + private Map getProperties(GDLParser.PropertiesContext propertiesContext) { + if (propertiesContext != null) { + Map properties = new HashMap<>(); + for (GDLParser.PropertyContext property : propertiesContext.property()) { + properties.put(property.Identifier().getText(), getPropertyValue(property.literal())); + } + return properties; + } + return Collections.emptyMap(); } - return null; - } - - @Override - public void enterAsOf(GDLParser.AsOfContext ctx){ - TimePoint tp = buildTimePoint(ctx.timePoint()); - String identifier = resolveIdentifier(ctx.Identifier().getText()); - currentPredicates.add(new And( - new Comparison( - new TimeSelector(identifier, TimeSelector.TimeField.TX_FROM), - LTE, - tp), - new Comparison( - new TimeSelector(identifier, TimeSelector.TimeField.TX_TO), - GTE, - tp) - ) - ); - } - - /** - * Creates the default asOf conditions, that ensure that every element's transaction time is - * as of now. This is only done if no other constraints on transaction times' ends - * are specified in the query. - * @return default asOf predicates - */ - private Predicate createDefaultAsOf(){ - Set vars = new HashSet<>(); - vars.addAll(userEdgeCache.keySet()); - vars.addAll(userVertexCache.keySet()); - vars.addAll(autoEdgeCache.keySet()); - vars.addAll(autoVertexCache.keySet()); - if(vars.isEmpty()){ + + /** + * Returns the corresponding value for a given literal. + * + * @param literalContext literal context + * @return parsed value + */ + private Object getPropertyValue(GDLParser.LiteralContext literalContext) { + String text; + if (literalContext.StringLiteral() != null) { + return parseString(literalContext.StringLiteral().getText()); + } else if (literalContext.BooleanLiteral() != null) { + return Boolean.parseBoolean(literalContext.BooleanLiteral().getText()); + } else if (literalContext.IntegerLiteral() != null) { + text = literalContext.IntegerLiteral().getText().toLowerCase(); + if (text.endsWith("l")) { + return Long.parseLong(text.substring(0, text.length() - 1)); + } + return Integer.parseInt(text); + } else if (literalContext.FloatingPointLiteral() != null) { + text = literalContext.FloatingPointLiteral().getText().toLowerCase(); + if (text.endsWith("f")) { + return Float.parseFloat(text.substring(0, text.length() - 1)); + } else if (text.endsWith("d")) { + return Double.parseDouble(text.substring(0, text.length() - 1)); + } + return Float.parseFloat(text); + } else if (literalContext.NaN() != null) { + return Double.NaN; + } return null; - } - else{ - TimeLiteral now = new TimeLiteral("now"); - ArrayList variables = new ArrayList<>(); - variables.addAll(vars); - Predicate asOfNow = new And( - new Comparison( - new TimeSelector(variables.get(0), TimeSelector.TimeField.TX_FROM), - Comparator.LTE, - now - ), - new Comparison( - new TimeSelector(variables.get(0), TimeSelector.TimeField.TX_TO), - GTE, - now - ) - ); - for(int i=1; i conjunctions) { - Predicate conjunctionReuse; - for (int i = conjunctions.size() - 1; i >= 0; i--) { - Predicate rhs = currentPredicates.removeLast(); - Predicate lhs = currentPredicates.removeLast(); - - switch (conjunctions.get(i).getText().toLowerCase()) { - case "and": - conjunctionReuse = new And(lhs, rhs); - break; - case "or": - conjunctionReuse = new Or(lhs, rhs); - break; - default: - conjunctionReuse = new Xor(lhs, rhs); - break; - } - currentPredicates.add(conjunctionReuse); + + /** + * Builds an property selector expression like alice.age + * + * @param ctx the property lookup context that will be parsed + * @return parsed property selector expression + */ + private PropertySelector buildPropertySelector(GDLParser.PropertyLookupContext ctx) { + String identifier = resolveIdentifier(ctx.Identifier(0).getText()); + String property = ctx.Identifier(1).getText(); + return new PropertySelector(identifier, property); + } + + String resolveIdentifier(String identifier) { + GraphElement element; + if (userVertexCache.containsKey(identifier)) { + element = userVertexCache.get(identifier); + } else if (userEdgeCache.containsKey(identifier)) { + element = userEdgeCache.get(identifier); + } else { + throw new InvalidReferenceException(identifier); + } + return element.getVariable(); } - } - - // -------------------------------------------------------------------------------------------- - // Init handlers - // -------------------------------------------------------------------------------------------- - - /** - * Initializes a new graph from a given graph context. - * - * @param graphContext graph context - * @return new graph - */ - private Graph initNewGraph(GDLParser.GraphContext graphContext) { - Graph g = new Graph(); - g.setId(getNewGraphId()); - List labels = getLabels(graphContext.header()); - g.setLabels(labels.isEmpty() ? - useDefaultGraphLabel ? Collections.singletonList(defaultGraphLabel) : Collections.emptyList() - : labels); - g.setProperties(getProperties(graphContext.properties())); - - return g; - } - - /** - * Initializes a new vertex from a given vertex context. - * - * @param vertexContext vertex context - * @return new vertex - */ - private Vertex initNewVertex(GDLParser.VertexContext vertexContext) { - Vertex v = new Vertex(); - v.setId(getNewVertexId()); - List labels = getLabels(vertexContext.header()); - v.setLabels(labels.isEmpty() ? - useDefaultVertexLabel ? Collections.singletonList(defaultVertexLabel) : Collections.emptyList() - : labels); - v.setProperties(getProperties(vertexContext.properties())); - - return v; - } - - /** - * Initializes a new edge from the given edge body context. - * - * @param edgeBodyContext edge body context - * @param isIncoming true, if it's an incoming edge, false for outgoing edge - * @return new edge - */ - private Edge initNewEdge(GDLParser.EdgeBodyContext edgeBodyContext, boolean isIncoming) { - boolean hasBody = edgeBodyContext != null; - Edge e = new Edge(); - e.setId(getNewEdgeId()); - e.setSourceVertexId(getSourceVertexId(isIncoming)); - e.setTargetVertexId(getTargetVertexId(isIncoming)); - - if (hasBody) { - List labels = getLabels(edgeBodyContext.header()); - e.setLabels(labels.isEmpty() ? - useDefaultEdgeLabel ? Collections.singletonList(defaultEdgeLabel) : Collections.emptyList() - : labels); - e.setProperties(getProperties(edgeBodyContext.properties())); - int[] range = parseEdgeLengthContext(edgeBodyContext.edgeLength()); - e.setLowerBound(range[0]); - e.setUpperBound(range[1]); - } else { - if (useDefaultEdgeLabel) { - e.setLabel(defaultEdgeLabel); - } else { - e.setLabel(null); - } + + // -------------------------------------------------------------------------------------------- + // Identifier management + // -------------------------------------------------------------------------------------------- + + /** + * Returns the current graph identifier. + * + * @return current graph identifier + */ + private Long getNextGraphId() { + return currentGraphId; } - return e; - } - - // -------------------------------------------------------------------------------------------- - // Update handlers - // -------------------------------------------------------------------------------------------- - - /** - * If the parser is currently inside a logical graph, the given element is added to that graph. - * - * @param graphElement graph element ({@link Vertex}, {@link Edge}) - */ - private void updateGraphElement(GraphElement graphElement) { - if (inGraph) { - graphElement.addToGraph(getNextGraphId()); - if(! graphElements.containsKey(getNextGraphId())){ - graphElements.put(getNextGraphId(), new ArrayList<>()); - } - graphElements.get(getNextGraphId()).add(graphElement); + /** + * Creates and returns an new graph identifier. + * + * @return new graph identifier + */ + private Long getNewGraphId() { + return nextGraphId++; } - } - - // -------------------------------------------------------------------------------------------- - // Payload handlers - // -------------------------------------------------------------------------------------------- - - /** - * Returns the element variable from a given header context. - * - * @param header header context - * @return element variable or {@code null} if context was null - */ - private String getVariable(GDLParser.HeaderContext header) { - if (header != null && header.Identifier() != null) { - return header.Identifier().getText(); + + /** + * Creates and returns a new vertex identifier. + * + * @return new vertex identifier + */ + private Long getNewVertexId() { + return nextVertexId++; } - return null; - } - - /** - * Returns the element labels from a given header context. - * - * @param header header context - * @return element labels or {@code null} if context was null - */ - private List getLabels(GDLParser.HeaderContext header) { - if (header != null && header.label() != null) { - return header - .label() - .stream() - .map(RuleContext::getText) - .map(x -> x.substring(1)) - .collect(Collectors.toList()); + + /** + * Creates and returns a new edge identifier. + * + * @return new edge identifier + */ + private Long getNewEdgeId() { + return nextEdgeId++; } - return null; - } - - /** - * Returns the properties map from a given properties context. - * - * @param propertiesContext properties context - * @return properties map or {@code null} if context was null - */ - private Map getProperties(GDLParser.PropertiesContext propertiesContext) { - if (propertiesContext != null) { - Map properties = new HashMap<>(); - for (GDLParser.PropertyContext property : propertiesContext.property()) { - properties.put(property.Identifier().getText(), getPropertyValue(property.literal())); - } - return properties; + + // -------------------------------------------------------------------------------------------- + // Helper + // -------------------------------------------------------------------------------------------- + + /** + * Creates a cache containing a mapping from variables to query elements. The cache is filled + * with elements from the user cache and/or the auto cache depending on the specified flags. + * + * @param userCache element user cache + * @param autoCache element auto cache + * @param includeUserDefined true, iff user cache elements shall be included + * @param includeAutoGenerated true, iff auto cache elements shall be included + * @param query element type + * @return immutable cache + */ + private Map getCache(Map userCache, Map autoCache, + boolean includeUserDefined, boolean includeAutoGenerated) { + Map cache = new HashMap<>(); + if (includeUserDefined) { + cache.putAll(userCache); + } + if (includeAutoGenerated) { + cache.putAll(autoCache); + } + return Collections.unmodifiableMap(cache); } - return Collections.emptyMap(); - } - - /** - * Returns the corresponding value for a given literal. - * - * @param literalContext literal context - * @return parsed value - */ - private Object getPropertyValue(GDLParser.LiteralContext literalContext) { - String text; - if (literalContext.StringLiteral() != null) { - return parseString(literalContext.StringLiteral().getText()); - } else if (literalContext.BooleanLiteral() != null) { - return Boolean.parseBoolean(literalContext.BooleanLiteral().getText()); - } else if (literalContext.IntegerLiteral() != null) { - text = literalContext.IntegerLiteral().getText().toLowerCase(); - if (text.endsWith("l")) { - return Long.parseLong(text.substring(0, text.length() - 1)); - } - return Integer.parseInt(text); - } else if (literalContext.FloatingPointLiteral() != null) { - text = literalContext.FloatingPointLiteral().getText().toLowerCase(); - if (text.endsWith("f")) { - return Float.parseFloat(text.substring(0, text.length() - 1)); - } else if (text.endsWith("d")) { - return Double.parseDouble(text.substring(0, text.length() - 1)); - } - return Float.parseFloat(text); - } else if (literalContext.NaN() != null) { - return Double.NaN; + + /** + * Adds a list of predicates to the current predicates using AND conjunctions + * + * @param newPredicates predicates to be added + */ + private void addPredicates(List newPredicates) { + for (Predicate newPredicate : newPredicates) { + if (this.predicates == null) { + this.predicates = newPredicate; + } else { + this.predicates = new And(this.predicates, newPredicate); + } + } } - return null; - } - - /** - * Parses an {@code EdgeLengthContext} and returns the indicated Range - * - * @param lengthCtx the edges length context - * @return int array representing lower and upper bound - */ - private int[] parseEdgeLengthContext(GDLParser.EdgeLengthContext lengthCtx) { - int lowerBound = 0; - int upperBound = 0; - - if(lengthCtx != null) { - int children = lengthCtx.getChildCount(); - - if (children == 4) { // [*1..2] - lowerBound = terminalNodeToInt(lengthCtx.IntegerLiteral(0)); - upperBound = terminalNodeToInt(lengthCtx.IntegerLiteral(1)); - } else if (children == 3) { // [*..2] - upperBound = terminalNodeToInt(lengthCtx.IntegerLiteral(0)); - - } else if (children == 2) { // [*1] - lowerBound = terminalNodeToInt(lengthCtx.IntegerLiteral(0)); - } else { // [*] - lowerBound = 0; - upperBound = 0; - } - } else { - // regular edge - lowerBound = 1; - upperBound = 1; + + /** + * Updates the source or target vertex identifier of the last seen edge. + * + * @param v current vertex + */ + private void updateLastSeenEdge(Vertex v) { + Edge lastSeenEdge = getLastSeenEdge(); + if (lastSeenEdge != null) { + if (lastSeenEdge.getSourceVertexId() == null) { + lastSeenEdge.setSourceVertexId(v.getId()); + } else if (lastSeenEdge.getTargetVertexId() == null) { + lastSeenEdge.setTargetVertexId(v.getId()); + } + } } - return new int[] { lowerBound, upperBound }; - } - - /** - * Builds a Comparison filter operator from comparison context - * - * @param ctx the comparison context that will be parsed - * @return parsed operator - */ - private Comparison buildComparison(GDLParser.ComparisonExpressionContext ctx) { - ComparableExpression lhs = extractComparableExpression(ctx.comparisonElement(0)); - ComparableExpression rhs = extractComparableExpression(ctx.comparisonElement(1)); - Comparator comp = Comparator.fromString(ctx .ComparisonOP().getText()); - - return new Comparison(lhs, comp, rhs); - } - - /** - * Extracts a ComparableExpression from comparissonElement - * - * @param element comparissonElement - * @return extracted comparable expression - */ - private ComparableExpression extractComparableExpression(GDLParser.ComparisonElementContext element) { - if(element.literal() != null) { - return new Literal(getPropertyValue(element.literal())); - } else if(element.propertyLookup() != null) { - return buildPropertySelector(element.propertyLookup()); + + /** + * Returns the vertex that was last seen by the parser. + * + * @return vertex seen last + */ + private Vertex getLastSeenVertex() { + return lastSeenVertex; } - else { - return new ElementSelector(element.Identifier().getText()); + + /** + * Sets the last seen vertex. + * + * @param v vertex + */ + private void setLastSeenVertex(Vertex v) { + lastSeenVertex = v; } - } - - /** - * Builds an property selector expression like alice.age - * - * @param ctx the property lookup context that will be parsed - * @return parsed property selector expression - */ - private PropertySelector buildPropertySelector(GDLParser.PropertyLookupContext ctx) { - String identifier = resolveIdentifier(ctx.Identifier(0).getText()); - String property = ctx.Identifier(1).getText(); - return new PropertySelector(identifier,property); - } - - private String resolveIdentifier(String identifier){ - GraphElement element; - if(userVertexCache.containsKey(identifier)) { - element = userVertexCache.get(identifier); + + /** + * Returns the edge that was last seen by the parser. + * + * @return edge seen last + */ + private Edge getLastSeenEdge() { + return lastSeenEdge; } - else if(userEdgeCache.containsKey(identifier)) { - element = userEdgeCache.get(identifier); + + /** + * Sets the last seen edge. + * + * @param e edge + */ + private void setLastSeenEdge(Edge e) { + lastSeenEdge = e; } - else { throw new InvalidReferenceException(identifier);} - return element.getVariable(); - } - - // -------------------------------------------------------------------------------------------- - // Identifier management - // -------------------------------------------------------------------------------------------- - - /** - * Returns the current graph identifier. - * - * @return current graph identifier - */ - private Long getNextGraphId() { - return currentGraphId; - } - - /** - * Creates and returns an new graph identifier. - * - * @return new graph identifier - */ - private Long getNewGraphId() { - return nextGraphId++; - } - - /** - * Creates and returns a new vertex identifier. - * - * @return new vertex identifier - */ - private Long getNewVertexId() { - return nextVertexId++; - } - - /** - * Creates and returns a new edge identifier. - * - * @return new edge identifier - */ - private Long getNewEdgeId() { - return nextEdgeId++; - } - - // -------------------------------------------------------------------------------------------- - // Helper - // -------------------------------------------------------------------------------------------- - - /** - * Creates a cache containing a mapping from variables to query elements. The cache is filled - * with elements from the user cache and/or the auto cache depending on the specified flags. - * - * @param userCache element user cache - * @param autoCache element auto cache - * @param includeUserDefined true, iff user cache elements shall be included - * @param includeAutoGenerated true, iff auto cache elements shall be included - * @param query element type - * @return immutable cache - */ - private Map getCache(Map userCache, Map autoCache, - boolean includeUserDefined, boolean includeAutoGenerated) { - Map cache = new HashMap<>(); - if (includeUserDefined) { - cache.putAll(userCache); + + /** + * Returns the source vertex identifier of an edge. + * + * @param isIncoming true, if edge is an incoming edge, false for outgoing edge + * @return the source vertex identifier or {@code null} if vertex has not been parsed yet + */ + private Long getSourceVertexId(boolean isIncoming) { + return isIncoming ? null : getLastSeenVertex().getId(); } - if (includeAutoGenerated) { - cache.putAll(autoCache); + + /** + * Returns the target vertex identifier of an edge. + * + * @param isIncoming true, if edge is an incoming edge, false for outgoing edge + * @return the target vertex identifier or {@code null} if vertex has not been parsed yet + */ + private Long getTargetVertexId(boolean isIncoming) { + return isIncoming ? getLastSeenVertex().getId() : null; } - return Collections.unmodifiableMap(cache); - } - - /** - * Adds a list of predicates to the current predicates using AND conjunctions - * - * @param newPredicates predicates to be added - */ - private void addPredicates(List newPredicates) { - for(Predicate newPredicate : newPredicates) { - if(this.predicates == null) { - this.predicates = newPredicate; - } else { - this.predicates = new And(this.predicates, newPredicate); - } + + /** + * Parses a terminal node to an integer. + * + * @param node the node which represents an integer + * @return the parsed integer + */ + private int terminalNodeToInt(TerminalNode node) { + return Integer.parseInt(node.getText()); } - } - - /** - * Updates the source or target vertex identifier of the last seen edge. - * - * @param v current vertex - */ - private void updateLastSeenEdge(Vertex v) { - Edge lastSeenEdge = getLastSeenEdge(); - if (lastSeenEdge != null) { - if (lastSeenEdge.getSourceVertexId() == null) { - lastSeenEdge.setSourceVertexId(v.getId()); - } else if (lastSeenEdge.getTargetVertexId() == null) { - lastSeenEdge.setTargetVertexId(v.getId()); - } + + /** + * Parses a String literal from the input string. Unescapes " and ' + * + * @param in the raw input string + * @return the parsed string + */ + private String parseString(String in) { + return in.replaceAll("^.|.$", "") + .replaceAll("\\\\\"", "\"") + .replaceAll("\\\\'", "'"); } - } - - /** - * Returns the vertex that was last seen by the parser. - * - * @return vertex seen last - */ - private Vertex getLastSeenVertex() { - return lastSeenVertex; - } - - /** - * Sets the last seen vertex. - * - * @param v vertex - */ - private void setLastSeenVertex(Vertex v) { - lastSeenVertex = v; - } - - /** - * Returns the edge that was last seen by the parser. - * - * @return edge seen last - */ - private Edge getLastSeenEdge() { - return lastSeenEdge; - } - - /** - * Sets the last seen edge. - * - * @param e edge - */ - private void setLastSeenEdge(Edge e) { - lastSeenEdge = e; - } - - /** - * Returns the source vertex identifier of an edge. - * - * @param isIncoming true, if edge is an incoming edge, false for outgoing edge - * @return the source vertex identifier or {@code null} if vertex has not been parsed yet - */ - private Long getSourceVertexId(boolean isIncoming) { - return isIncoming ? null : getLastSeenVertex().getId(); - } - - /** - * Returns the target vertex identifier of an edge. - * - * @param isIncoming true, if edge is an incoming edge, false for outgoing edge - * @return the target vertex identifier or {@code null} if vertex has not been parsed yet - */ - private Long getTargetVertexId(boolean isIncoming) { - return isIncoming ? getLastSeenVertex().getId() : null; - } - - /** - * Parses a terminal node to an integer. - * - * @param node the node which represents an integer - * @return the parsed integer - */ - private int terminalNodeToInt(TerminalNode node) { - return Integer.parseInt(node.getText()); - } - - /** - * Parses a String literal from the input string. Unescapes " and ' - * - * @param in the raw input string - * @return the parsed string - */ - private String parseString(String in) { - return in.replaceAll("^.|.$", "") - .replaceAll("\\\\\"","\"") - .replaceAll("\\\\\'","'"); - } } diff --git a/src/main/java/org/s1ck/gdl/GDLLoaderTemporal.java b/src/main/java/org/s1ck/gdl/GDLLoaderTemporal.java new file mode 100644 index 0000000..fda97bd --- /dev/null +++ b/src/main/java/org/s1ck/gdl/GDLLoaderTemporal.java @@ -0,0 +1,655 @@ +package org.s1ck.gdl; + +import org.s1ck.gdl.model.comparables.ComparableExpression; +import org.s1ck.gdl.model.comparables.time.*; +import org.s1ck.gdl.model.predicates.Predicate; +import org.s1ck.gdl.model.predicates.booleans.And; +import org.s1ck.gdl.model.predicates.expressions.Comparison; +import org.s1ck.gdl.utils.Comparator; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.List; + +import static org.s1ck.gdl.utils.Comparator.*; + +public class GDLLoaderTemporal { + + /** + * Holds predicates that might be created during processing of other predicates + */ + private final Deque predicateStack; + + /** + * GDLLoader that processes the whole query + */ + private final GDLLoader loader; + + /** + * Creates a new instance + * + * @param loader loader that processes the whole query + */ + public GDLLoaderTemporal(GDLLoader loader) { + this.predicateStack = new ArrayDeque<>(); + this.loader = loader; + } + + /** + * Builds a Comparison filter operator from comparison context + * + * @param ctx the comparison context that will be parsed + * @return parsed operator + */ + Comparison buildTemporalComparison(GDLParser.TemporalComparisonContext ctx) { + ComparableExpression lhs = buildTimePoint(ctx.timePoint(0)); + ComparableExpression rhs = buildTimePoint(ctx.timePoint(1)); + Comparator comp = Comparator.fromString(ctx.ComparisonOP().getText()); + + return new Comparison(lhs, comp, rhs); + } + + /** + * Builds a {@code TimePoint} (can be {@code TimeLiteral}, {@code TimeSelector}, {@code MIN},...) given its context + * + * @param ctx time point context + * @return the {@code TimePoint} described by the context + */ + private TimePoint buildTimePoint(GDLParser.TimePointContext ctx) { + if (ctx.timeLiteral() != null) { + return buildTimeLiteral(ctx.timeLiteral()); + } else if (ctx.timeSelector() != null) { + return buildTimeSelector(ctx.timeSelector()); + } else if (ctx.complexTimePoint() != null) { + return buildComplexTimePoint(ctx.complexTimePoint()); + } + return null; + } + + /** + * Builds a TimeLiteral given a context. + * + * @param ctx context containing the literal + * @return TimeLiteral + */ + private TimeLiteral buildTimeLiteral(GDLParser.TimeLiteralContext ctx) { + return new TimeLiteral(ctx.getText().trim()); + } + + /** + * Builds a TimeSelector (variable.field, where field in {TX_FROM, TX_TO, VAL_FROM, VAL_TO}) + * + * @param ctx context containing the selector + * @return TimeSelector + */ + private TimeSelector buildTimeSelector(GDLParser.TimeSelectorContext ctx) { + // checks whether ID is even there (is a vertex or edge) and returns its variable + String var = ctx.Identifier() != null ? + loader.resolveIdentifier(ctx.Identifier().getText()) : TimeSelector.GLOBAL_SELECTOR; + String field = ctx.TimeProp().getText(); + return new TimeSelector(var, field); + } + + /** + * Builds a "complex" time point, i.e. a time point described by a {@code MAX(...)} or + * {@code MIN(...)} expression. + * + * @param ctx context containing the time point + * @return complex time point + */ + private TimePoint buildComplexTimePoint(GDLParser.ComplexTimePointContext ctx) { + + List argumentContexts = + ctx.complexTimePointArgument(); + TimePoint[] args = new TimePoint[argumentContexts.size()]; + + for (int i = 0; i < argumentContexts.size(); i++) { + GDLParser.ComplexTimePointArgumentContext argumentContext = argumentContexts.get(i); + if (argumentContext.timeLiteral() != null) { + args[i] = buildTimeLiteral(argumentContext.timeLiteral()); + } else if (argumentContext.timeSelector() != null) { + args[i] = buildTimeSelector(argumentContext.timeSelector()); + } + } + // available complex time points: min and max + if (ctx.getText().startsWith("MAX(")) { + return new MaxTimePoint(args); + } else if (ctx.getText().startsWith("MIN(")) { + return new MinTimePoint(args); + } + return null; + } + + /** + * Converts an interval function into a (complex) predicate + * For example, i.between(x,y) would be translated to a predicate ((i.from<= y) AND (i.to>x)) + * + * @param ctx interval function context + * @return complex predicate that encodes the interval function. Atoms are time stamp comparisons + */ + Predicate buildIntervalFunction(GDLParser.IntvFContext ctx) { + int predicateSizeBefore = predicateStack.size(); + TimePoint[] intv = buildIntervall(ctx.interval()); + TimePoint from = intv[0]; + TimePoint to = intv[1]; + Predicate predicate = createIntervalPredicates(from, to, ctx.intervalFunc()); + // additional constraints? + int countConstraints = predicateStack.size() - predicateSizeBefore; + for (int i = 0; i < countConstraints; i++) { + predicate = new And(predicate, predicateStack.removeFirst()); + } + return predicate; + } + + /** + * Creates a new predicate about an interval. There are different types of intervall predicates/ + * functions: precedes, fromTo,... + * + * @param from represents the start time (from value) of the intervall + * @param to represents the end time (to value) of the intervall + * @param intervalFunc contains the context information needed to create the correct predicate + * @return new predicate (according to {@code intervalFunc}) about the intervall represented by + * {@code from} and {@code to}. + */ + private Predicate createIntervalPredicates(TimePoint from, TimePoint to, GDLParser.IntervalFuncContext intervalFunc) { + if (intervalFunc.overlapsIntervallOperator() != null) { + return createOverlapsPredicates(from, to, intervalFunc.overlapsIntervallOperator()); + } else if (intervalFunc.fromToOperator() != null) { + return createFromToPredicates(from, to, intervalFunc.fromToOperator()); + } else if (intervalFunc.betweenOperator() != null) { + return createBetweenPredicates(from, to, intervalFunc.betweenOperator()); + } else if (intervalFunc.precedesOperator() != null) { + return createPrecedesPredicates(to, intervalFunc.precedesOperator()); + } else if (intervalFunc.succeedsOperator() != null) { + return createSucceedsPredicates(from, intervalFunc.succeedsOperator()); + } else if (intervalFunc.containsOperator() != null) { + return createContainsPredicates(from, to, intervalFunc.containsOperator()); + } else if (intervalFunc.immediatelyPrecedesOperator() != null) { + return createImmediatelyPrecedesPredicates(to, intervalFunc.immediatelyPrecedesOperator()); + } else if (intervalFunc.immediatelySucceedsOperator() != null) { + return createImmediatelySucceedsPredicates(from, intervalFunc.immediatelySucceedsOperator()); + } else if (intervalFunc.equalsOperator() != null) { + return createEqualsPredicates(from, to, intervalFunc.equalsOperator()); + } else if (intervalFunc.longerThanOperator() != null) { + return createLongerThanPredicates(from, to, intervalFunc.longerThanOperator()); + } else if (intervalFunc.shorterThanOperator() != null) { + return createShorterThanPredicates(from, to, intervalFunc.shorterThanOperator()); + } else if (intervalFunc.lengthAtLeastOperator() != null) { + return createLengthAtLeastPredicates(from, to, intervalFunc.lengthAtLeastOperator()); + } else if (intervalFunc.lengthAtMostOperator() != null) { + return createLengthAtMostPredicates(from, to, intervalFunc.lengthAtMostOperator()); + } + return null; + } + + /** + * Creates a predicate a.overlaps(b)=max(a.from,b.from)x + * + * @param from from value of the calling interval + * @param to to value of the calling interval + * @param ctx context of the call, containing x and y + * @return fromTo predicate + */ + private Predicate createFromToPredicates(TimePoint from, TimePoint to, GDLParser.FromToOperatorContext ctx) { + TimePoint x = buildTimePoint(ctx.timePoint(0)); + TimePoint y = buildTimePoint(ctx.timePoint(1)); + return new And( + new Comparison(from, Comparator.LT, y), + new Comparison(to, Comparator.GT, x) + ); + } + + /** + * Creates a predicate a.between(x,y) = a.from<=y AND a.to>x + * + * @param from from value of the calling interval + * @param to to value of the calling interval + * @param ctx context of the call, containing x and y + * @return between predicate + */ + private Predicate createBetweenPredicates(TimePoint from, TimePoint to, GDLParser.BetweenOperatorContext ctx) { + TimePoint x = buildTimePoint(ctx.timePoint(0)); + TimePoint y = buildTimePoint(ctx.timePoint(1)); + return new And( + new Comparison(from, LTE, y), + new Comparison(to, Comparator.GT, x) + ); + } + + /** + * Creates a predicate a.precedes(b) = a.to <= b.from. + * Function is used for interval and timestamp function {@code precedes}, as they both + * only compare two time stamps + * + * @param to the time stamp of the caller to compare + * @param ctx the context containing the value to be compared + * @return precedes predicate + */ + private Predicate createPrecedesPredicates(TimePoint to, GDLParser.PrecedesOperatorContext ctx) { + TimePoint[] arg = buildIntervall(ctx.interval()); + TimePoint arg_from = arg[0]; + return new Comparison(to, LTE, arg_from); + } + + /** + * Creates a predicate a.immediatelyPrecedes(b) = (a.to == b.from). + * + * @param to the time stamp of the caller to compare + * @param ctx the context containing the from value to be compared + * @return immediatelyPrecedes predicate + */ + private Predicate createImmediatelyPrecedesPredicates(TimePoint to, GDLParser.ImmediatelyPrecedesOperatorContext ctx) { + TimePoint[] arg = buildIntervall(ctx.interval()); + TimePoint arg_from = arg[0]; + return new Comparison(to, EQ, arg_from); + } + + /** + * Creates a predicate a.succeeds(b) = a >= b. + * Function is used for interval and timestamp function {@code precedes}, as they both + * only compare two time stamps + * + * @param point the time stamp of the caller to compare + * @param ctx the context containing the value to be compared + * @return succeeds predicate + */ + private Predicate createSucceedsPredicates(TimePoint point, GDLParser.SucceedsOperatorContext ctx) { + TimePoint[] arg = buildIntervall(ctx.interval()); + TimePoint arg_to = arg[1]; + return new Comparison(point, GTE, arg_to); + } + + /** + * Creates a predicate a.immediatelySucceeds(b) = (a.from == b.to). + * Function is used for interval and timestamp function {@code precedes}, as they both + * only compare two time stamps + * + * @param from the from value of the caller interval + * @param ctx the context containing the to value of the interval to be compared + * @return immediatelySucceeds predicate + */ + private Predicate createImmediatelySucceedsPredicates(TimePoint from, + GDLParser.ImmediatelySucceedsOperatorContext ctx) { + TimePoint[] arg = buildIntervall(ctx.interval()); + TimePoint arg_to = arg[1]; + return new Comparison(from, EQ, arg_to); + } + + /** + * Creates a predicate a.contains(b) = a.from<=b.from AND a.to>=b.to + * + * @param from from value of the calling interval + * @param to to value of the calling interval + * @param ctx context of the call, containing b + * @return contains predicate + */ + private Predicate createContainsPredicates(TimePoint from, TimePoint to, GDLParser.ContainsOperatorContext ctx) { + if (ctx.interval() != null) { + TimePoint[] arg = buildIntervall(ctx.interval()); + TimePoint arg_from = arg[0]; + TimePoint arg_to = arg[1]; + return new And( + new Comparison(from, LTE, arg_from), + new Comparison(to, GTE, arg_to) + ); + } + // argument is only a timestamp + else { + TimePoint arg = buildTimePoint(ctx.timePoint()); + return new And( + new Comparison(from, LTE, arg), new Comparison(to, GTE, arg) + ); + } + } + + /** + * Creates a predicate a.equals(b) = (a.from = b.from AND a.to = b.to). + * + * @param from from value of the calling interval + * @param to to value of the calling interval + * @param ctx context containing the callee interval + * @return equals predicate + */ + private Predicate createEqualsPredicates(TimePoint from, TimePoint to, GDLParser.EqualsOperatorContext ctx) { + TimePoint[] arg = buildIntervall(ctx.interval()); + TimePoint arg_from = arg[0]; + TimePoint arg_to = arg[1]; + return new And( + new Comparison(from, EQ, arg_from), + new Comparison(to, EQ, arg_to) + ); + } + + /** + * Creates a predicate a.longerThan(b) = (length(a) > length(b)) + * Implicitly adds constraints that ensure that durations are always positive + * + * @param from from value of the calling interval + * @param to to value of the calling interval + * @param ctx context containing the callee interval + * @return longerThan predicate + */ + private Predicate createLongerThanPredicates(TimePoint from, TimePoint to, GDLParser.LongerThanOperatorContext ctx) { + Predicate durationPredicate; + Duration rhs = new Duration(from, to); + durationPredicate = new Comparison(from, LTE, to); + if (ctx.timeConstant() != null) { + TimeConstant constant = buildTimeConstant(ctx.timeConstant()); + durationPredicate = new And(durationPredicate, + new Comparison(rhs, GT, constant)); + } else if (ctx.interval() != null) { + TimePoint[] interval = buildIntervall(ctx.interval()); + Duration lhs = new Duration(interval[0], interval[1]); + durationPredicate = new And(durationPredicate, + new Comparison(interval[0], LTE, interval[1])); + durationPredicate = new And(durationPredicate, + new Comparison(rhs, GT, lhs)); + } + return durationPredicate; + } + + + /** + * Creates a predicate a.shorterThan(b) = (length(a) < length(b)) + * Implicitly adds constraints that ensure that durations are always positive + * + * @param from from value of the calling interval + * @param to to value of the calling interval + * @param ctx context containing the callee interval + * @return shorterThan predicate + */ + private Predicate createShorterThanPredicates(TimePoint from, TimePoint to, GDLParser.ShorterThanOperatorContext ctx) { + Predicate durationPredicate; + Duration rhs = new Duration(from, to); + durationPredicate = new Comparison(from, LTE, to); + if (ctx.timeConstant() != null) { + TimeConstant constant = buildTimeConstant(ctx.timeConstant()); + durationPredicate = new And(durationPredicate, + new Comparison(rhs, LT, constant)); + } else if (ctx.interval() != null) { + TimePoint[] interval = buildIntervall(ctx.interval()); + Duration lhs = new Duration(interval[0], interval[1]); + durationPredicate = new And(durationPredicate, + new Comparison(interval[0], LTE, interval[1])); + durationPredicate = new And(durationPredicate, + new Comparison(rhs, LT, lhs)); + } + return durationPredicate; + } + + /** + * Creates a predicate a.lengthAtLeast(b) = (length(a) >= length(b)) + * Implicitly adds constraints that ensure that durations are always positive + * + * @param from from value of the calling interval + * @param to to value of the calling interval + * @param ctx context containing the callee interval + * @return lengthAtLeast predicate + */ + private Predicate createLengthAtLeastPredicates(TimePoint from, TimePoint to, + GDLParser.LengthAtLeastOperatorContext ctx) { + Predicate durationPredicate; + Duration rhs = new Duration(from, to); + durationPredicate = new Comparison(from, LTE, to); + if (ctx.timeConstant() != null) { + TimeConstant constant = buildTimeConstant(ctx.timeConstant()); + durationPredicate = new And(durationPredicate, + new Comparison(rhs, GTE, constant)); + } else if (ctx.interval() != null) { + TimePoint[] interval = buildIntervall(ctx.interval()); + Duration lhs = new Duration(interval[0], interval[1]); + durationPredicate = new And(durationPredicate, + new Comparison(interval[0], LTE, interval[1])); + durationPredicate = new And(durationPredicate, + new Comparison(rhs, GTE, lhs)); + } + return durationPredicate; + } + + /** + * Creates a predicate a.lengthAtMost(b) = (length(a) <= length(b)) + * Implicitly adds constraints that ensure that durations are always positive + * + * @param from from value of the calling interval + * @param to to value of the calling interval + * @param ctx context containing the callee interval + * @return lengthAtMost predicate + */ + private Predicate createLengthAtMostPredicates(TimePoint from, TimePoint to, + GDLParser.LengthAtMostOperatorContext ctx) { + Predicate durationPredicate; + Duration rhs = new Duration(from, to); + durationPredicate = new Comparison(from, LTE, to); + if (ctx.timeConstant() != null) { + TimeConstant constant = buildTimeConstant(ctx.timeConstant()); + durationPredicate = new And(durationPredicate, + new Comparison(rhs, LTE, constant)); + } else if (ctx.interval() != null) { + TimePoint[] interval = buildIntervall(ctx.interval()); + Duration lhs = new Duration(interval[0], interval[1]); + durationPredicate = new And(durationPredicate, + new Comparison(interval[0], LTE, interval[1])); + durationPredicate = new And(durationPredicate, + new Comparison(rhs, LTE, lhs)); + } + return durationPredicate; + } + + /** + * Creates a TimeConstant given a suitable context. Constants can be a constant number + * of days ({@code Days(n)}), hours ({@code Hours(n)}), minutes ({@code Minutes(n)}), + * seconds ({@code Seconds(n)}) or milliseconds ({@code Millis(n)}). + * + * @param ctx the context containing the constant. + * @return time constant + */ + private TimeConstant buildTimeConstant(GDLParser.TimeConstantContext ctx) { + int value = Integer.parseInt(ctx.IntegerLiteral().getText()); + if (ctx.getText().startsWith("Days(")) { + return new TimeConstant(value, 0, 0, 0, 0); + } else if (ctx.getText().startsWith("Hours(")) { + return new TimeConstant(0, value, 0, 0, 0); + } else if (ctx.getText().startsWith("Minutes(")) { + return new TimeConstant(0, 0, value, 0, 0); + } else if (ctx.getText().startsWith("Seconds(")) { + return new TimeConstant(0, 0, 0, value, 0); + } else if (ctx.getText().startsWith("Millis(")) { + return new TimeConstant(0, 0, 0, 0, value); + } + return null; + } + + /** + * Creates an array {@code {from, to}} representing an interval. + * + * @param ctx context from which to derive {@code from} and {@code to} + * @return {@code {from, to}} representing an interval + */ + private TimePoint[] buildIntervall(GDLParser.IntervalContext ctx) { + if (ctx.intervalSelector() != null) { + GDLParser.IntervalSelectorContext selector = ctx.intervalSelector(); + // throws exception, if variable invalid + return buildIntervalFromSelector(selector); + } else if (ctx.intervalFromStamps() != null) { + GDLParser.IntervalFromStampsContext fs = ctx.intervalFromStamps(); + return buildIntervalFromStamps(fs); + } else if (ctx.complexInterval() != null) { + GDLParser.ComplexIntervalArgumentContext arg1 = ctx.complexInterval() + .complexIntervalArgument(0); + GDLParser.ComplexIntervalArgumentContext arg2 = ctx.complexInterval() + .complexIntervalArgument(1); + boolean join = ctx.getText().contains(".join("); + return buildIntervalFromComplex(arg1, arg2, join); + } + return null; + } + + /** + * Creates an interval as an array {@code {from, to}} from a selector context. + * I.e., a intervall like {@code a.val} would result in {@code {a.val_from, a.val_to}}. + * What is more, {@code val} results in {@code GLOBAL_SELECTOR.val_from, GLOBAL_SELECTOR.val_to} + * + * @param ctx context from which to derive the interval + * @return {@code {from, to}} representing the interval + */ + private TimePoint[] buildIntervalFromSelector(GDLParser.IntervalSelectorContext ctx) { + String var = ctx.Identifier() != null ? + loader.resolveIdentifier(ctx.Identifier().getText()) : TimeSelector.GLOBAL_SELECTOR; + String intId = ctx.IntervalConst().getText(); + TimePoint from = new TimeSelector(var, intId + "_from"); + TimePoint to = new TimeSelector(var, intId + "_to"); + return new TimePoint[]{from, to}; + } + + /** + * Creates an interval as an array {@code {from, to}} from a interval constant context. + * I.e., a intervall like {@code Interval(1970-01-01, 2020-01-01)} would result in + * {@code {1970-01-01, 2020-01-01}}. + * + * @param ctx context from which to derive the interval + * @return {@code {from, to}} representing the interval + */ + private TimePoint[] buildIntervalFromStamps(GDLParser.IntervalFromStampsContext ctx) { + TimePoint from = buildTimePoint(ctx.timePoint(0)); + TimePoint to = buildTimePoint(ctx.timePoint(1)); + return new TimePoint[]{from, to}; + } + + /** + * Creates an interval as an array {@code {from, to}} from a complex interval context, i.e. + * {@code merge} and {@code join} expressions. + * An interval like {@code a.merge(b)} would result in {@code {max(a.from, b.from), min(a.to, b.to}} + * while {@code a.join(b)} results in {@code {min(a.from, b.from), max(a.to, b.to)}}. + * Furthermore, a constraint {max(a.from, b.from)<= min(a.to, b.to)} is added (intervals must overlap, + * in at least one ms) + * + * @param arg1 context from which to derive the calling interval + * @param arg2 context from which to derive the callee interval + * @param join true iff join should be performed, false iff merge is desired + * @return {@code {from, to}} representing the interval + */ + private TimePoint[] buildIntervalFromComplex(GDLParser.ComplexIntervalArgumentContext arg1, + GDLParser.ComplexIntervalArgumentContext arg2, + boolean join) { + TimePoint[] i1; + TimePoint[] i2; + if (arg1.intervalFromStamps() != null) { + i1 = buildIntervalFromStamps(arg1.intervalFromStamps()); + } else { + i1 = buildIntervalFromSelector(arg1.intervalSelector()); + } + if (arg2.intervalFromStamps() != null) { + i2 = buildIntervalFromStamps(arg2.intervalFromStamps()); + } else { + i2 = buildIntervalFromSelector(arg2.intervalSelector()); + } + // constraint: merge and join only when overlapping or meeting + Comparison constraint = new Comparison( + new MaxTimePoint(i1[0], i2[0]), LTE, new MinTimePoint(i1[1], i2[1]) + ); + predicateStack.addFirst(constraint); + // now build complex intervall from i1, i2 + if (join) { + TimePoint start = new MinTimePoint(i1[0], i2[0]); + TimePoint end = new MaxTimePoint(i1[1], i2[1]); + return new TimePoint[]{start, end}; + } + // merge + else { + TimePoint start = new MaxTimePoint(i1[0], i2[0]); + TimePoint end = new MinTimePoint(i1[1], i2[1]); + return new TimePoint[]{start, end}; + } + } + + /** + * Converts a time stamp function into a (potentially complex) {@code Predicate} + * For example, i.before(x) would be translated to a {@code Predicate} ix + */ + private Predicate createAfterPredicates(TimePoint from, GDLParser.AfterPointOperatorContext ctx) { + TimePoint x = buildTimePoint(ctx.timePoint()); + return new Comparison(from, Comparator.GT, x); + } + + Predicate createAsOf(GDLParser.AsOfContext ctx) { + TimePoint tp = buildTimePoint(ctx.timePoint()); + String identifier = loader.resolveIdentifier(ctx.Identifier().getText()); + return new And( + new Comparison( + new TimeSelector(identifier, TimeSelector.TimeField.TX_FROM), + LTE, + tp), + new Comparison( + new TimeSelector(identifier, TimeSelector.TimeField.TX_TO), + GTE, + tp) + + ); + } +} diff --git a/src/main/java/org/s1ck/gdl/model/Edge.java b/src/main/java/org/s1ck/gdl/model/Edge.java index d845c8c..ffe82ba 100644 --- a/src/main/java/org/s1ck/gdl/model/Edge.java +++ b/src/main/java/org/s1ck/gdl/model/Edge.java @@ -16,8 +16,6 @@ package org.s1ck.gdl.model; -import java.util.List; - public class Edge extends GraphElement { private Long sourceVertexId; diff --git a/src/main/java/org/s1ck/gdl/model/GraphElement.java b/src/main/java/org/s1ck/gdl/model/GraphElement.java index ed2c43b..3a522eb 100644 --- a/src/main/java/org/s1ck/gdl/model/GraphElement.java +++ b/src/main/java/org/s1ck/gdl/model/GraphElement.java @@ -21,7 +21,7 @@ public class GraphElement extends Element { - private Set graphs; + private final Set graphs; public GraphElement() { graphs = new HashSet<>(); diff --git a/src/main/java/org/s1ck/gdl/model/comparables/ComparableExpression.java b/src/main/java/org/s1ck/gdl/model/comparables/ComparableExpression.java index 60fbde4..2755399 100644 --- a/src/main/java/org/s1ck/gdl/model/comparables/ComparableExpression.java +++ b/src/main/java/org/s1ck/gdl/model/comparables/ComparableExpression.java @@ -17,7 +17,6 @@ package org.s1ck.gdl.model.comparables; import org.s1ck.gdl.model.comparables.time.TimeSelector; -import org.s1ck.gdl.model.predicates.Predicate; import java.io.Serializable; import java.util.List; @@ -28,14 +27,14 @@ public interface ComparableExpression extends Serializable{ * Returns the variables of the expression * @return variable */ - public Set getVariables(); + Set getVariables(); /** * Returns the variable of the expression * Same functionality is given by {@code getVariables}, kept for downward compatibility * @return variable */ - public String getVariable(); + String getVariable(); /** * Checks whether a certain type of selector (val_from, val_to, tx_from, tx_to) is contained diff --git a/src/main/java/org/s1ck/gdl/model/comparables/ElementSelector.java b/src/main/java/org/s1ck/gdl/model/comparables/ElementSelector.java index e37ef4b..4500620 100644 --- a/src/main/java/org/s1ck/gdl/model/comparables/ElementSelector.java +++ b/src/main/java/org/s1ck/gdl/model/comparables/ElementSelector.java @@ -18,7 +18,6 @@ import org.s1ck.gdl.model.comparables.time.TimeSelector; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -31,7 +30,7 @@ public class ElementSelector implements ComparableExpression { /** * Variable which identifies the element */ - private String variable; + private final String variable; /** * Creates a new element selector diff --git a/src/main/java/org/s1ck/gdl/model/comparables/Literal.java b/src/main/java/org/s1ck/gdl/model/comparables/Literal.java index dd72999..0dd1551 100644 --- a/src/main/java/org/s1ck/gdl/model/comparables/Literal.java +++ b/src/main/java/org/s1ck/gdl/model/comparables/Literal.java @@ -18,7 +18,6 @@ import org.s1ck.gdl.model.comparables.time.TimeSelector; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -31,7 +30,7 @@ public class Literal implements ComparableExpression { /** * literal value */ - private Object value; + private final Object value; /** * Creates a new Literal @@ -49,7 +48,7 @@ public Object getValue() { @Override public Set getVariables() { - return new HashSet(); + return new HashSet<>(); } @Override diff --git a/src/main/java/org/s1ck/gdl/model/comparables/PropertySelector.java b/src/main/java/org/s1ck/gdl/model/comparables/PropertySelector.java index 658c80c..0c97174 100644 --- a/src/main/java/org/s1ck/gdl/model/comparables/PropertySelector.java +++ b/src/main/java/org/s1ck/gdl/model/comparables/PropertySelector.java @@ -18,7 +18,6 @@ import org.s1ck.gdl.model.comparables.time.TimeSelector; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -31,12 +30,12 @@ public class PropertySelector implements ComparableExpression { /** * Elements variable */ - private String variable; + private final String variable; /** * Elements property name */ - private String propertyName; + private final String propertyName; public PropertySelector(String variable, String propertyName) { this.variable = variable; diff --git a/src/main/java/org/s1ck/gdl/model/comparables/time/Duration.java b/src/main/java/org/s1ck/gdl/model/comparables/time/Duration.java index e8156b8..8640440 100644 --- a/src/main/java/org/s1ck/gdl/model/comparables/time/Duration.java +++ b/src/main/java/org/s1ck/gdl/model/comparables/time/Duration.java @@ -2,7 +2,6 @@ import org.s1ck.gdl.model.comparables.ComparableExpression; import org.s1ck.gdl.model.predicates.Predicate; -import org.s1ck.gdl.model.predicates.expressions.Comparison; import java.util.List; import java.util.Optional; @@ -16,12 +15,12 @@ public class Duration extends TimePoint { /** * The from value of the interval */ - private TimePoint from; + private final TimePoint from; /** * The to value of the interval */ - private TimePoint to; + private final TimePoint to; /** * Creates duration of an interval represented by {@code from} and {@code to} @@ -89,7 +88,7 @@ public Optional evaluate() { } } - @Override + /*@Override public long getLowerBound() { long toLowerBound = to.getLowerBound(); long fromUpperBound = from.getUpperBound(); @@ -107,7 +106,7 @@ public long getUpperBound() { return Long.MAX_VALUE; } return toUpperBound - fromLowerBound; - } + }*/ @Override protected Predicate unfoldEQ(TimePoint arg) { diff --git a/src/main/java/org/s1ck/gdl/model/comparables/time/MaxTimePoint.java b/src/main/java/org/s1ck/gdl/model/comparables/time/MaxTimePoint.java index 34332ea..54a710a 100644 --- a/src/main/java/org/s1ck/gdl/model/comparables/time/MaxTimePoint.java +++ b/src/main/java/org/s1ck/gdl/model/comparables/time/MaxTimePoint.java @@ -3,7 +3,6 @@ import org.s1ck.gdl.model.comparables.ComparableExpression; import org.s1ck.gdl.model.predicates.Predicate; import org.s1ck.gdl.model.predicates.booleans.And; -import org.s1ck.gdl.model.predicates.booleans.Not; import org.s1ck.gdl.model.predicates.booleans.Or; import org.s1ck.gdl.model.predicates.expressions.Comparison; import org.s1ck.gdl.utils.Comparator; @@ -44,7 +43,7 @@ public Optional evaluate(){ return Optional.of(mx); } - @Override + /*@Override public long getLowerBound(){ // lower bound of a max term is the maximal lower bound of all its arguments long res = Long.MIN_VALUE; @@ -55,9 +54,9 @@ public long getLowerBound(){ } } return res; - } + }*/ - @Override + /*@Override public long getUpperBound(){ // upper bound of a max term is the maximal upper bound of all its arguments long res = Long.MIN_VALUE; @@ -71,7 +70,7 @@ public long getUpperBound(){ } } return res; - } + }*/ @Override public String getVariable() { diff --git a/src/main/java/org/s1ck/gdl/model/comparables/time/MinTimePoint.java b/src/main/java/org/s1ck/gdl/model/comparables/time/MinTimePoint.java index 3a3a294..472cd1b 100644 --- a/src/main/java/org/s1ck/gdl/model/comparables/time/MinTimePoint.java +++ b/src/main/java/org/s1ck/gdl/model/comparables/time/MinTimePoint.java @@ -3,7 +3,6 @@ import org.s1ck.gdl.model.comparables.ComparableExpression; import org.s1ck.gdl.model.predicates.Predicate; import org.s1ck.gdl.model.predicates.booleans.And; -import org.s1ck.gdl.model.predicates.booleans.Not; import org.s1ck.gdl.model.predicates.booleans.Or; import org.s1ck.gdl.model.predicates.expressions.Comparison; import org.s1ck.gdl.utils.Comparator; @@ -41,7 +40,7 @@ public Optional evaluate(){ return Optional.of(mn); } - @Override + /*@Override public long getLowerBound(){ // lower bound of a min term is the minimum lower bound of all its arguments long res = Long.MAX_VALUE; @@ -68,7 +67,7 @@ public long getUpperBound(){ } } return res; - } + }*/ @Override public String getVariable() { diff --git a/src/main/java/org/s1ck/gdl/model/comparables/time/TimeConstant.java b/src/main/java/org/s1ck/gdl/model/comparables/time/TimeConstant.java index a4cf8a1..a3e0c29 100644 --- a/src/main/java/org/s1ck/gdl/model/comparables/time/TimeConstant.java +++ b/src/main/java/org/s1ck/gdl/model/comparables/time/TimeConstant.java @@ -2,7 +2,6 @@ import org.s1ck.gdl.model.comparables.ComparableExpression; import org.s1ck.gdl.model.predicates.Predicate; -import org.s1ck.gdl.model.predicates.expressions.Comparison; import java.util.HashSet; import java.util.List; @@ -18,7 +17,7 @@ public class TimeConstant extends TimePoint { /** * The number of milliseconds wrapped by this class */ - private Long millis; + private final Long millis; /** * Create a constant of size days+hours+minutes+seconds+millis (in millis) @@ -29,7 +28,7 @@ public class TimeConstant extends TimePoint { * @param millis number of millis [0-999] */ public TimeConstant(int days, int hours, int minutes, int seconds, int millis){ - long sum = (long)millis; + long sum = millis; sum +=1000L*(long)seconds; sum +=1000L*60L*(long)minutes; sum +=1000L*60L*60L*(long)hours; @@ -72,7 +71,7 @@ public Optional evaluate() { return Optional.of(getMillis()); } - @Override + /*@Override public long getLowerBound() { return getMillis(); } @@ -80,7 +79,7 @@ public long getLowerBound() { @Override public long getUpperBound() { return getMillis(); - } + }*/ @Override protected Predicate unfoldEQ(TimePoint arg) { diff --git a/src/main/java/org/s1ck/gdl/model/comparables/time/TimeLiteral.java b/src/main/java/org/s1ck/gdl/model/comparables/time/TimeLiteral.java index 803f7c9..a6e9e1c 100644 --- a/src/main/java/org/s1ck/gdl/model/comparables/time/TimeLiteral.java +++ b/src/main/java/org/s1ck/gdl/model/comparables/time/TimeLiteral.java @@ -17,19 +17,14 @@ public class TimeLiteral extends TimeAtom { /** * The wrapped LocalDateTime */ - private LocalDateTime time; + private final LocalDateTime time; /** * Construct a Literal from UNIX epoch milliseconds * @param millis milliseconds since 1970-01-01T00:00 */ public TimeLiteral(long millis){ - if (millis>=0){ - this.time = LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.of("Z")); - } - else{ - throw new IllegalArgumentException("millis must be positive"); - } + this.time = LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.of("Z")); } /** @@ -137,7 +132,7 @@ public Optional evaluate(){ return Optional.of(getMilliseconds()); } - @Override + /*@Override public long getLowerBound(){ return getMilliseconds(); } @@ -145,7 +140,7 @@ public long getLowerBound(){ @Override public long getUpperBound(){ return getMilliseconds(); - } + }*/ @Override public boolean containsSelectorType(TimeSelector.TimeField type){ @@ -159,7 +154,7 @@ public boolean equals(Object o) { TimeLiteral that = (TimeLiteral) o; - return evaluate()==that.evaluate(); + return getMilliseconds()==that.getMilliseconds(); } diff --git a/src/main/java/org/s1ck/gdl/model/comparables/time/TimePoint.java b/src/main/java/org/s1ck/gdl/model/comparables/time/TimePoint.java index 6d58724..7675761 100644 --- a/src/main/java/org/s1ck/gdl/model/comparables/time/TimePoint.java +++ b/src/main/java/org/s1ck/gdl/model/comparables/time/TimePoint.java @@ -4,7 +4,6 @@ import org.s1ck.gdl.model.predicates.Predicate; import org.s1ck.gdl.utils.Comparator; -import java.util.ArrayList; import java.util.Optional; /** @@ -25,17 +24,6 @@ public abstract class TimePoint implements ComparableExpression { */ public abstract Optional evaluate(); - /** - * calculates a lower bound for the timestamp (UNIX epoch long) - * @return lower bound as UNIX epoch long - */ - public abstract long getLowerBound(); - - /** - * calculates a upper bound for the timestamp (UNIX epoch long) - * @return upper bound as UNIX epoch long - */ - public abstract long getUpperBound(); /** * Translates a term "this comparator arg" into a Predicate over comparisons. diff --git a/src/main/java/org/s1ck/gdl/model/comparables/time/TimeSelector.java b/src/main/java/org/s1ck/gdl/model/comparables/time/TimeSelector.java index e3eeca5..32d7d9a 100644 --- a/src/main/java/org/s1ck/gdl/model/comparables/time/TimeSelector.java +++ b/src/main/java/org/s1ck/gdl/model/comparables/time/TimeSelector.java @@ -19,12 +19,12 @@ public class TimeSelector extends TimeAtom{ /** * The variable name */ - private String variable; + private final String variable; /** * The time property selected (VAL_FROM, VAL_TO, TX_FROM, TX_TO) */ - private TimeField timeProp; + private final TimeField timeProp; /** * Variable name that indicates a global time selector, referring to the whole pattern @@ -107,7 +107,7 @@ public Optional evaluate(){ return Optional.empty(); } - @Override + /*@Override public long getLowerBound(){ return Long.MIN_VALUE; } @@ -115,7 +115,7 @@ public long getLowerBound(){ @Override public long getUpperBound(){ return Long.MAX_VALUE; - } + }*/ @Override public boolean containsSelectorType(TimeSelector.TimeField type){ @@ -295,7 +295,7 @@ private Predicate forAllVariables(Comparator comp, ComparableExpression rhs, Lis return forall; } - @Override + /*@Override protected Predicate unfoldEQ(TimePoint arg){ return new Comparison(this, EQ, arg); } @@ -323,7 +323,7 @@ protected Predicate unfoldLT(TimePoint arg){ @Override protected Predicate unfoldLTE(TimePoint arg){ return new Comparison(this, Comparator.LTE, arg); - } + }*/ @Override public boolean isGlobal(){ diff --git a/src/main/java/org/s1ck/gdl/model/comparables/time/TimeTerm.java b/src/main/java/org/s1ck/gdl/model/comparables/time/TimeTerm.java index a1cf805..fa14612 100644 --- a/src/main/java/org/s1ck/gdl/model/comparables/time/TimeTerm.java +++ b/src/main/java/org/s1ck/gdl/model/comparables/time/TimeTerm.java @@ -1,9 +1,5 @@ package org.s1ck.gdl.model.comparables.time; -import org.s1ck.gdl.model.comparables.ComparableExpression; -import org.s1ck.gdl.model.predicates.Predicate; -import org.s1ck.gdl.utils.Comparator; - import java.util.*; /** diff --git a/src/main/java/org/s1ck/gdl/model/predicates/Predicate.java b/src/main/java/org/s1ck/gdl/model/predicates/Predicate.java index 1dfeffa..ed13dff 100644 --- a/src/main/java/org/s1ck/gdl/model/predicates/Predicate.java +++ b/src/main/java/org/s1ck/gdl/model/predicates/Predicate.java @@ -70,54 +70,6 @@ static List fromGraphElement(GraphElement element, String defaultLabe return predicates; } - /** - * Unfolds a predicate, i.e. reduces complex temporal predicates to simple comparisons - * This is needed for predicates containing complex temporal elements like e.g. MIN, MAX. - * These elements can be reduced to simple comparisons, thus yielding a predicate only - * consisting of comparisons between literals. - * e.g. [(MAX(a,b)> t1) AND (t2t1) OR (b>t1)) AND ((t2(b)}, the global predicate {@code tx_to >= 2020-04-28)} would be - * reduced to {@code a.tx_to>=2020-04-28 AND b.tx_to>=2020-04-28} - * while {@code tx_to <= 2020-04-28)} is reduced to - * {@code @code a.tx_to<=2020-04-28 OR b.tx_to<=2020-04-28} - * @param predicate the predicate whose global time predicates should be translated - * @param unfoldedComparisons indicates whether complex time predicates were already reduced to - * simple comparisons. If so, this flag should be set to {@code true} - * to avoid unnecessary work. - * @return equivalent predicate consisting only of primitive local time value comparisons - */ - static Predicate translateGlobalPredicates(Predicate predicate, ArrayList vars, boolean unfoldedComparisons){ - if(!unfoldedComparisons){ - predicate = Predicate.unfoldTemporalComparisons(predicate); - } - predicate = predicate.unfoldGlobalLeft(vars); - predicate = predicate.switchSides(); - return predicate.unfoldGlobalLeft(vars); - } - /** * Returns the predicates arguments * @@ -132,15 +84,6 @@ static Predicate translateGlobalPredicates(Predicate predicate, ArrayList getVariables(); - - - /** - * Unfolds a predicate, but only the left hand side of each temporal comparison. - * e.g. [(MAX(a,b)> t1) AND (t2t1) OR (b>t1)) AND ((t2 getVariables() { return expression.getVariables(); } - @Override + /*@Override public Predicate unfoldTemporalComparisonsLeft(){ return new Not(expression.unfoldTemporalComparisonsLeft()); } - +*/ @Override public Predicate switchSides(){ return new Not(expression.switchSides()); diff --git a/src/main/java/org/s1ck/gdl/model/predicates/booleans/Or.java b/src/main/java/org/s1ck/gdl/model/predicates/booleans/Or.java index 40142f5..a75e4da 100644 --- a/src/main/java/org/s1ck/gdl/model/predicates/booleans/Or.java +++ b/src/main/java/org/s1ck/gdl/model/predicates/booleans/Or.java @@ -25,10 +25,10 @@ public class Or implements Predicate { // left hand side - private Predicate lhs; + private final Predicate lhs; // right hand side - private Predicate rhs; + private final Predicate rhs; public Or(Predicate lhs, Predicate rhs) { this.lhs = lhs; @@ -52,10 +52,10 @@ public Set getVariables() { return variables; } - @Override + /*@Override public Predicate unfoldTemporalComparisonsLeft(){ return new Or(lhs.unfoldTemporalComparisonsLeft(), rhs.unfoldTemporalComparisonsLeft()); - } + }*/ @Override public Predicate switchSides(){ diff --git a/src/main/java/org/s1ck/gdl/model/predicates/booleans/Xor.java b/src/main/java/org/s1ck/gdl/model/predicates/booleans/Xor.java index e1f1c77..4ca32f9 100644 --- a/src/main/java/org/s1ck/gdl/model/predicates/booleans/Xor.java +++ b/src/main/java/org/s1ck/gdl/model/predicates/booleans/Xor.java @@ -25,10 +25,10 @@ public class Xor implements Predicate { // left hand side - private Predicate lhs; + private final Predicate lhs; // right hand side - private Predicate rhs; + private final Predicate rhs; public Xor(Predicate lhs, Predicate rhs) { this.lhs = lhs; @@ -40,10 +40,10 @@ public Predicate[] getArguments() { return new Predicate[] { lhs, rhs }; } - @Override + /*@Override public Predicate unfoldTemporalComparisonsLeft(){ return new Xor(lhs.unfoldTemporalComparisonsLeft(), rhs.unfoldTemporalComparisonsLeft()); - } + }*/ @Override public Predicate switchSides(){ diff --git a/src/main/java/org/s1ck/gdl/model/predicates/expressions/Comparison.java b/src/main/java/org/s1ck/gdl/model/predicates/expressions/Comparison.java index 1a89eb3..685cfec 100644 --- a/src/main/java/org/s1ck/gdl/model/predicates/expressions/Comparison.java +++ b/src/main/java/org/s1ck/gdl/model/predicates/expressions/Comparison.java @@ -34,15 +34,15 @@ public class Comparison implements Predicate { /** * Left hand side value */ - private ComparableExpression lhs; + private final ComparableExpression lhs; /** * Right hand side value */ - private ComparableExpression rhs; + private final ComparableExpression rhs; /** * The comparator used to compare a the values */ - private Comparator comparator; + private final Comparator comparator; /** * Creates a new comparison operator @@ -58,8 +58,7 @@ public Comparison(ComparableExpression lhs, Comparator comparator, ComparableExp @Override public Predicate[] getArguments() { - Predicate[] arguments = {}; - return arguments; + return new Predicate[]{}; } /** @@ -75,8 +74,7 @@ public Comparator getComparator() { * @return lhs and rhs values */ public ComparableExpression[] getComparableExpressions() { - ComparableExpression[] list = {lhs, rhs}; - return list; + return new ComparableExpression[]{lhs, rhs}; } @Override @@ -103,20 +101,20 @@ public Predicate replaceGlobalByLocal(List variables) { rhs.replaceGlobalByLocal(variables)); } - @Override + /*@Override public Predicate unfoldTemporalComparisonsLeft(){ if (!isTemporal()){ return this; } return ((TimePoint)lhs).unfoldComparison(comparator, (TimePoint)rhs); - } + }*/ @Override public Comparison switchSides(){ if(!isTemporal()){ return this; } - Comparator newComp = null; + Comparator newComp; if(comparator == Comparator.EQ){ newComp = Comparator.EQ; } diff --git a/src/test/java/org/s1ck/gdl/GDLLoaderTemporalTest.java b/src/test/java/org/s1ck/gdl/GDLLoaderTemporalTest.java index f418767..2feec32 100644 --- a/src/test/java/org/s1ck/gdl/GDLLoaderTemporalTest.java +++ b/src/test/java/org/s1ck/gdl/GDLLoaderTemporalTest.java @@ -3,75 +3,25 @@ import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.junit.Test; -import org.s1ck.gdl.model.comparables.Literal; -import org.s1ck.gdl.model.comparables.PropertySelector; import org.s1ck.gdl.model.comparables.time.*; -import org.s1ck.gdl.model.comparables.time.TimeConstant; import org.s1ck.gdl.model.predicates.Predicate; import org.s1ck.gdl.model.predicates.booleans.And; -import org.s1ck.gdl.model.predicates.booleans.Or; import org.s1ck.gdl.model.predicates.expressions.Comparison; import org.s1ck.gdl.utils.Comparator; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.s1ck.gdl.model.comparables.time.TimeSelector.TimeField.*; import static org.s1ck.gdl.utils.Comparator.*; public class GDLLoaderTemporalTest { - @Test - public void simpleTimestampFunctionsTest(){ -// GDLLoader loader = getLoaderFromGDLString( -// "MATCH (alice)-[e1:knows {since : 2014}]->(bob) (alice)-[e2:knows {since : 2013}]->(eve) " + -// "WHERE (e1.val_from.before(2017-01-01) AND e2.tx_to.after(2018-12-23T15:55:23)) OR e1.knows>2010"); -// assertTrue(predicateContainedIn( -// new Comparison(new TimeSelector("e1", "val_from"), Comparator.LT, new TimeLiteral("2017-01-01")), -// loader.getPredicates().get().switchSides())); -// assertTrue(predicateContainedIn( -// new Comparison(new TimeSelector("e2", "tx_to"), Comparator.GT, new TimeLiteral("2018-12-23T15:55:23")), -// loader.getPredicates().get().switchSides())); -// assertTrue(predicateContainedIn( -// new Comparison(new PropertySelector("e1", "knows"), Comparator.GT, new Literal(2010)), -// loader.getPredicates().get().switchSides())); - } @Test public void periodLiteralTest(){ - GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-->(b) " + + GDLLoader loader = getLoaderFromGDLString("MATCH (a)-->(b) " + "WHERE a.tx.overlaps(Interval(1970-01-01,1970-01-02))"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-->(b) " + - "WHERE a.tx.overlaps(Interval(1970-01-01,1970-01-02))", false); - assertPredicateEquals(loaderDoProcess.getPredicates().get(), - new And( - new And( - new Comparison( - new TimeSelector("a", "tx_to"), - Comparator.GT, - new TimeSelector("a", "tx_from") - ), - new Comparison( - new TimeLiteral("1970-01-02"), - Comparator.GT, - new TimeSelector("a", "tx_from") - ) - ), - new And( - new Comparison( - new TimeSelector("a", "tx_to"), - Comparator.GT, - new TimeLiteral("1970-01-01") - ), - new Comparison( - new TimeLiteral("1970-01-02"), - Comparator.GT, - new TimeLiteral("1970-01-01") - ) - ) - ) - ); - assertPredicateEquals(loaderRaw.getPredicates().get(), + assertPredicateEquals(loader.getPredicates().get(), new Comparison( new MaxTimePoint(new TimeSelector("a", TX_FROM), new TimeLiteral("1970-01-01")), @@ -83,12 +33,8 @@ public void periodLiteralTest(){ @Test public void afterTest(){ - GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-->(b) " + + GDLLoader loader = getLoaderFromGDLString("MATCH (a)-->(b) " + "WHERE a.val_from.after(1970-01-01T00:00:01) AND a.tx_to.after(1970-01-01T00:00:01)"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-->(b) " + - "WHERE a.val_from.after(1970-01-01T00:00:01) AND a.tx_to.after(1970-01-01T00:00:01)", - false); - Predicate result = loaderDoProcess.getPredicates().get(); Predicate expected = new And( new Comparison( @@ -101,17 +47,13 @@ public void afterTest(){ new TimeSelector("a", "tx_to")) ); - assertPredicateEquals(result, expected); - assertPredicateEquals(loaderRaw.getPredicates().get(), expected); + assertPredicateEquals(loader.getPredicates().get(), expected); } @Test public void fromToTest(){ - GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-->(b) " + + GDLLoader loader = getLoaderFromGDLString("MATCH (a)-->(b) " + "WHERE a.tx.fromTo(1970-01-01, b.tx_to)"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-->(b) " + - "WHERE a.tx.fromTo(1970-01-01, b.tx_to)", false); - Predicate result = loaderDoProcess.getPredicates().get(); Predicate expected = new And( new Comparison( new TimeSelector("b", "tx_to"), @@ -124,18 +66,13 @@ public void fromToTest(){ new TimeSelector("a", "tx_to") ) ); - System.out.println(result); - assertPredicateEquals(result, expected); - assertPredicateEquals(loaderRaw.getPredicates().get(), expected); + assertPredicateEquals(loader.getPredicates().get(), expected); } @Test public void betweenTest(){ - GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-->(b) " + + GDLLoader loader = getLoaderFromGDLString("MATCH (a)-->(b) " + "WHERE a.tx.between(b.tx_from, 2020-04-28T10:39:15)"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-->(b) " + - "WHERE a.tx.between(b.tx_from, 2020-04-28T10:39:15)", false); - Predicate result = loaderDoProcess.getPredicates().get(); Predicate expected = new And( new Comparison( new TimeSelector("a", TX_FROM), @@ -148,77 +85,57 @@ public void betweenTest(){ new TimeSelector("b", TX_FROM) ) ); - assertPredicateEquals(result, expected); - assertPredicateEquals(loaderRaw.getPredicates().get(), expected); + assertPredicateEquals(loader.getPredicates().get(), expected); } @Test public void precedesTest(){ - GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-->(b) " + + GDLLoader loader = getLoaderFromGDLString("MATCH (a)-->(b) " + "WHERE a.tx.precedes(b.val)"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-->(b) " + - "WHERE a.tx.precedes(b.val)", false); - Predicate result = loaderDoProcess.getPredicates().get(); Predicate expected = new Comparison( new TimeSelector("a", TX_TO), LTE, new TimeSelector("b", TimeSelector.TimeField.VAL_FROM) ); - assertPredicateEquals(result, expected); - assertPredicateEquals(loaderRaw.getPredicates().get(), expected); + assertPredicateEquals(loader.getPredicates().get(), expected); // timestamp as caller - loaderDoProcess = getLoaderFromGDLString("MATCH (a)-->(b) " + + loader = getLoaderFromGDLString("MATCH (a)-->(b) " + "WHERE a.tx_to.precedes(b.val)"); - loaderRaw = getLoaderFromGDLString("MATCH (a)-->(b) " + - "WHERE a.tx_to.precedes(b.val)", false); - result = loaderDoProcess.getPredicates().get(); expected = new Comparison( new TimeSelector("a", TX_TO), LTE, new TimeSelector("b", TimeSelector.TimeField.VAL_FROM) ); - assertPredicateEquals(result, expected); - assertPredicateEquals(loaderRaw.getPredicates().get(), expected); + assertPredicateEquals(loader.getPredicates().get(), expected); } @Test public void succeedsTest(){ - GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-->(b) " + + GDLLoader loader = getLoaderFromGDLString("MATCH (a)-->(b) " + "WHERE a.val.succeeds(b.tx)"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-->(b) " + - "WHERE a.val.succeeds(b.tx)", false); - Predicate result = loaderDoProcess.getPredicates().get(); Predicate expected = new Comparison( new TimeSelector("a", TimeSelector.TimeField.VAL_FROM), GTE, new TimeSelector("b", TX_TO) ); - assertPredicateEquals(result, expected); - assertPredicateEquals(loaderRaw.getPredicates().get(), expected); + assertPredicateEquals(loader.getPredicates().get(), expected); // timestamp as caller - loaderDoProcess = getLoaderFromGDLString("MATCH (a)-->(b) " + + loader = getLoaderFromGDLString("MATCH (a)-->(b) " + "WHERE a.tx_to.succeeds(b.val)"); - loaderRaw = getLoaderFromGDLString("MATCH (a)-->(b) " + - "WHERE a.tx_to.succeeds(b.val)", false); - result = loaderDoProcess.getPredicates().get(); expected = new Comparison( new TimeSelector("a", TX_TO), GTE, new TimeSelector("b", VAL_TO) ); - assertPredicateEquals(result, expected); - assertPredicateEquals(loaderRaw.getPredicates().get(), expected); + assertPredicateEquals(loader.getPredicates().get(), expected); } @Test public void asOfTest(){ - GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + GDLLoader loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE e.asOf(1970-01-01)"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE e.asOf(1970-01-01)", false); - Predicate result = loaderDoProcess.getPredicates().get(); Predicate expected = new And( new Comparison( new TimeSelector("e", TX_FROM), @@ -231,8 +148,7 @@ public void asOfTest(){ new TimeLiteral("1970-01-01") ) ); - assertPredicateEquals(result, expected); - assertPredicateEquals(loaderRaw.getPredicates().get(), expected); + assertPredicateEquals(loader.getPredicates().get(), expected); } @Test @@ -253,214 +169,72 @@ public void globalPredicateTest(){ MinTimePoint globalTo = new MinTimePoint( eTo, aTo, bTo ); + // only lhs global - GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + GDLLoader loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE tx.between(1970-01-01, 2020-05-01)"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE tx.between(1970-01-01, 2020-05-01)", false); - Predicate result1 = loaderDoProcess.getPredicates().get(); - Predicate expectedProcessed1 = new And( - // all froms <= l2 - new And( - new And( - new Comparison(eFrom, LTE, l2), - new Comparison(aFrom, LTE, l2) - ), - new Comparison(bFrom, LTE, l2) - ), - new And( - new And( - new Comparison(eTo, Comparator.GT, l1), - new Comparison(aTo, Comparator.GT, l1) - ), - new Comparison(bTo, Comparator.GT, l1) - ) - ); - Predicate expectedRaw1 = new And( + Predicate expected1 = new And( new Comparison(globalFrom, LTE, l2), new Comparison(globalTo, GT, l1) ); - assertPredicateEquals(expectedProcessed1, result1); - - assertPredicateEquals(expectedRaw1, loaderRaw.getPredicates().get()); + assertPredicateEquals(expected1, loader.getPredicates().get()); //only rhs global - loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE 1970-01-01.precedes(tx)"); - loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE 1970-01-01.precedes(tx)", false); - Predicate resultProcessed2 = loaderDoProcess.getPredicates().get(); - Or expectedProcessed2 = new Or( - new Or( - new Comparison(l1, LTE, eFrom), - new Comparison(l1, LTE, aFrom) - ), - new Comparison(l1, LTE, bFrom) - ); - Comparison expectedRaw2 = new Comparison(l1, LTE, globalFrom); - assertPredicateEquals(expectedProcessed2, resultProcessed2); - assertPredicateEquals(expectedRaw2, loaderRaw.getPredicates().get()); + Comparison expected2 = new Comparison(l1, LTE, globalFrom); + assertPredicateEquals(expected2, loader.getPredicates().get()); //both sides global - - loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE val_to.after(tx_from)"); - loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE val_to.after(tx_from)", false); TimeSelector aValTo = new TimeSelector("a", VAL_TO); TimeSelector bValTo = new TimeSelector("b", VAL_TO); TimeSelector eValTo = new TimeSelector("e", VAL_TO); MinTimePoint globalValTo = new MinTimePoint( eValTo, bValTo, eValTo ); - Predicate resultProcessed3 = loaderDoProcess.getPredicates().get(); - Predicate expectedProcessed3 = new And( - new And( - new And( - new And( - new Comparison(eValTo, Comparator.GT, eFrom), - new Comparison(aValTo, Comparator.GT, eFrom) - ), - new Comparison(bValTo, Comparator.GT, eFrom) - ), - new And( - new And( - new Comparison(eValTo, Comparator.GT, aFrom), - new Comparison(aValTo, Comparator.GT, aFrom) - ), - new Comparison(bValTo, Comparator.GT, aFrom) - ) - ), - new And( - new And( - new Comparison(eValTo, Comparator.GT, bFrom), - new Comparison(aValTo, Comparator.GT, bFrom) - ), - new Comparison(bValTo, Comparator.GT, bFrom) - ) - ); - Predicate expectedRaw3 = new Comparison(globalValTo, GT, globalFrom); - assertPredicateEquals(expectedProcessed3, resultProcessed3); - assertPredicateEquals(expectedRaw3, loaderRaw.getPredicates().get()); + Predicate expected3 = new Comparison(globalValTo, GT, globalFrom); + //assertPredicateEquals(expectedProcessed3, resultProcessed3); + assertPredicateEquals(expected3, loader.getPredicates().get()); } @Test - public void intervallMergeAndJoinTest(){ - GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + public void intervalMergeAndJoinTest(){ + GDLLoader loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE a.tx.merge(b.tx).succeeds(Interval(1970-01-01, 2020-05-01))"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.tx.merge(b.tx).succeeds(Interval(1970-01-01, 2020-05-01))", false); TimeSelector aTxFrom = new TimeSelector("a", TX_FROM); TimeSelector aTxTo = new TimeSelector("a", TX_TO); TimeSelector bTxFrom = new TimeSelector("b", TX_FROM); TimeSelector bTxTo = new TimeSelector("b",TX_TO); TimeLiteral tl1 = new TimeLiteral("1970-01-01"); TimeLiteral tl2 = new TimeLiteral("2020-05-01"); - Predicate expectedProcessed = new And( - //succeeds - new Or( - new Comparison(aTxFrom, GTE, tl2), - new Comparison(bTxFrom, GTE, tl2) - ), - //overlaps/meets - new And( - new And( - new Comparison(aTxFrom, LTE, aTxTo), - new Comparison(aTxFrom, LTE, bTxTo) - ), - new And( - new Comparison(bTxFrom, LTE, aTxTo), - new Comparison(bTxFrom, LTE, bTxTo) - ) - ) - ); - Predicate expectedRaw = new And( + + Predicate expected = new And( new Comparison(new MaxTimePoint(aTxFrom, bTxFrom), GTE, tl2), new Comparison(new MaxTimePoint(aTxFrom, bTxFrom), LTE, new MinTimePoint(aTxTo, bTxTo)) ); - Predicate result = loaderDoProcess.getPredicates().get(); - assertPredicateEquals(expectedProcessed, result); - assertPredicateEquals(expectedRaw, loaderRaw.getPredicates().get()); + assertPredicateEquals(expected, loader.getPredicates().get()); /* * Join */ - loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE a.tx.join(b.tx).succeeds(Interval(1970-01-01, 2020-05-01))"); - loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.tx.join(b.tx).succeeds(Interval(1970-01-01, 2020-05-01))", false); - expectedProcessed = new And( - //succeeds - new And( - new Comparison(aTxFrom, GTE, tl2), - new Comparison(bTxFrom, GTE, tl2) - ), - //overlaps/meets - new And( - new And( - new Comparison(aTxFrom, LTE, aTxTo), - new Comparison(aTxFrom, LTE, bTxTo) - ), - new And( - new Comparison(bTxFrom, LTE, aTxTo), - new Comparison(bTxFrom, LTE, bTxTo) - ) - ) - ); - expectedRaw = new And( + expected = new And( new Comparison(new MinTimePoint(aTxFrom, bTxFrom), GTE, tl2), new Comparison(new MaxTimePoint(aTxFrom, bTxFrom), LTE, new MinTimePoint(aTxTo, bTxTo)) ); - result = loaderDoProcess.getPredicates().get(); - assertPredicateEquals(expectedProcessed, result); - assertPredicateEquals(expectedRaw, loaderRaw.getPredicates().get()); + assertPredicateEquals(expected, loader.getPredicates().get()); + /* * Combine Merge And Join */ - loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE a.tx.join(b.tx).precedes(a.tx.merge(b.tx))"); - loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.tx.join(b.tx).precedes(a.tx.merge(b.tx))", false); - expectedProcessed = new And( - new And( - // actual precedes predicate - new And( - new Or( - new Comparison(aTxTo, LTE, aTxFrom), - new Comparison(aTxTo, LTE, bTxFrom) - ), - new Or( - new Comparison(bTxTo, LTE, aTxFrom), - new Comparison(bTxTo, LTE, bTxFrom) - ) - ), - //first overlap/meet - new And( - new And( - new Comparison(aTxFrom, LTE, aTxTo), - new Comparison(aTxFrom, LTE, bTxTo) - ), - new And( - new Comparison(bTxFrom, LTE, aTxTo), - new Comparison(bTxFrom, LTE, bTxTo) - ) - ) - ), - //second overlap/meet - new And( - new And( - new Comparison(aTxFrom, LTE, aTxTo), - new Comparison(aTxFrom, LTE, bTxTo) - ), - new And( - new Comparison(bTxFrom, LTE, aTxTo), - new Comparison(bTxFrom, LTE, bTxTo) - ) - ) - ); - expectedRaw = new And( + expected = new And( new And( new Comparison(new MaxTimePoint(aTxTo, bTxTo), LTE, new MaxTimePoint(aTxFrom, bTxFrom)), @@ -470,52 +244,11 @@ public void intervallMergeAndJoinTest(){ new Comparison(new MaxTimePoint(aTxFrom, bTxFrom), LTE, new MinTimePoint(aTxTo, bTxTo)) ); - result = loaderDoProcess.getPredicates().get(); - assertPredicateEquals(expectedProcessed, result); - assertPredicateEquals(expectedRaw, loaderRaw.getPredicates().get()); + assertPredicateEquals(expected, loader.getPredicates().get()); - loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE a.tx.merge(b.tx).precedes(a.tx.join(b.tx))"); - loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.tx.merge(b.tx).precedes(a.tx.join(b.tx))", false); - expectedProcessed = new And( - new And( - // actual preceeds predicate - new Or( - new And( - new Comparison(aTxTo, LTE, aTxFrom), - new Comparison(aTxTo, LTE, bTxFrom) - ), - new And( - new Comparison(bTxTo, LTE, aTxFrom), - new Comparison(bTxTo, LTE, bTxFrom) - ) - ), - //first overlap/meet - new And( - new And( - new Comparison(aTxFrom, LTE, aTxTo), - new Comparison(aTxFrom, LTE, bTxTo) - ), - new And( - new Comparison(bTxFrom, LTE, aTxTo), - new Comparison(bTxFrom, LTE, bTxTo) - ) - ) - ), - //second overlap/meet - new And( - new And( - new Comparison(aTxFrom, LTE, aTxTo), - new Comparison(aTxFrom, LTE, bTxTo) - ), - new And( - new Comparison(bTxFrom, LTE, aTxTo), - new Comparison(bTxFrom, LTE, bTxTo) - ) - ) - ); - expectedRaw = new And( + expected = new And( new And( new Comparison(new MinTimePoint(aTxTo, bTxTo), LTE, new MinTimePoint(aTxFrom, bTxFrom)), @@ -525,22 +258,17 @@ public void intervallMergeAndJoinTest(){ new Comparison(new MaxTimePoint(aTxFrom, bTxFrom), LTE, new MinTimePoint(aTxTo, bTxTo)) ); - result = loaderDoProcess.getPredicates().get(); - assertPredicateEquals(result, expectedProcessed); - assertPredicateEquals(loaderRaw.getPredicates().get(), expectedRaw); + assertPredicateEquals(loader.getPredicates().get(), expected); } @Test public void containsTest(){ GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE a.tx.contains(b.val)"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.tx.contains(b.val)", false); Predicate expected = new And( new Comparison(new TimeSelector("a", TX_FROM), LTE, new TimeSelector("b", VAL_FROM)), new Comparison(new TimeSelector("a", TX_TO), GTE, new TimeSelector("b", VAL_TO)) ); - assertPredicateEquals(expected, loaderRaw.getPredicates().get()); assertPredicateEquals(expected, loaderDoProcess.getPredicates().get()); } @@ -548,8 +276,6 @@ public void containsTest(){ public void comparisonTest(){ GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE a.tx_from > b.val_from AND 2013-06-01 <= a.val_to"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.tx_from > b.val_from AND 2013-06-01 <= a.val_to", false); Predicate expected = new And( new Comparison(new TimeSelector("a", TX_FROM), GT, new TimeSelector("b", VAL_FROM)), @@ -557,9 +283,6 @@ public void comparisonTest(){ new TimeSelector("a", VAL_TO) ) ); - System.out.println(loaderRaw.getPredicates().get()); - System.out.println(loaderDoProcess.getPredicates().get()); - assertPredicateEquals(loaderRaw.getPredicates().get(), expected); assertPredicateEquals(loaderDoProcess.getPredicates().get(), expected); } @@ -567,12 +290,9 @@ public void comparisonTest(){ public void immediatelyPrecedesTest(){ GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE a.tx.immediatelyPrecedes(e.val)"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.tx.immediatelyPrecedes(e.val)", false); Predicate expected = new Comparison( new TimeSelector("a", TX_TO), EQ, new TimeSelector("e", VAL_FROM) ); - assertPredicateEquals(loaderRaw.getPredicates().get(), expected); assertPredicateEquals(loaderDoProcess.getPredicates().get(), expected); } @@ -580,12 +300,9 @@ public void immediatelyPrecedesTest(){ public void immediatelySucceedsTest(){ GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE a.tx.immediatelySucceeds(e.val)"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.tx.immediatelySucceeds(e.val)", false); Predicate expected = new Comparison( new TimeSelector("a", TX_FROM), EQ, new TimeSelector("e", VAL_TO) ); - assertPredicateEquals(loaderRaw.getPredicates().get(), expected); assertPredicateEquals(loaderDoProcess.getPredicates().get(), expected); } @@ -593,13 +310,10 @@ public void immediatelySucceedsTest(){ public void equalsTest(){ GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE a.tx.equals(e.val)"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.tx.equals(e.val)", false); Predicate expected = new And( new Comparison(new TimeSelector("a", TX_FROM), EQ, new TimeSelector("e", VAL_FROM)), new Comparison(new TimeSelector("a", TX_TO), EQ, new TimeSelector("e", VAL_TO)) ); - assertPredicateEquals(loaderRaw.getPredicates().get(), expected); assertPredicateEquals(loaderDoProcess.getPredicates().get(), expected); } @@ -612,106 +326,46 @@ public void minMaxTest(){ TimeSelector bValTo = new TimeSelector("b", VAL_TO); TimeSelector eValTo = new TimeSelector("e", VAL_TO); TimeLiteral literal1 = new TimeLiteral("2020-05-05"); - GDLLoader loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + + GDLLoader loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE MIN(a.tx_from, b.tx_from, e.tx_from).before(2020-05-05)"); - GDLLoader loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE MIN(a.tx_from, b.tx_from, e.tx_from).before(2020-05-05)", false); - Predicate expected = new Or( - new Or( - new Comparison(aTxFrom, LT, literal1), - new Comparison(bTxFrom, LT, literal1) - ), - new Comparison(eTxFrom, LT, literal1) - ); - Predicate expectedRaw = new Comparison( + + Predicate expected = new Comparison( new MinTimePoint(aTxFrom, bTxFrom, eTxFrom), LT, literal1 ); - assertPredicateEquals(loaderDoProcess.getPredicates().get(), expected); - assertPredicateEquals(loaderRaw.getPredicates().get(), expectedRaw); + assertPredicateEquals(loader.getPredicates().get(), expected); + - loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE MAX(a.tx_from, b.tx_from, e.tx_from).before(2020-05-05)"); - loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE MAX(a.tx_from, b.tx_from, e.tx_from).before(2020-05-05)", false); - expected = new And( - new And( - new Comparison(aTxFrom, LT, literal1), - new Comparison(bTxFrom, LT, literal1) - ), - new Comparison(eTxFrom, LT, literal1) - ); - expectedRaw = new Comparison( + + expected = new Comparison( new MaxTimePoint(aTxFrom, bTxFrom, eTxFrom), LT, literal1 ); - assertPredicateEquals(loaderDoProcess.getPredicates().get(), expected); - assertPredicateEquals(loaderRaw.getPredicates().get(), expectedRaw); + assertPredicateEquals(loader.getPredicates().get(), expected); - loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE MAX(a.tx_from, b.tx_from, e.tx_from).after(" + "MIN(a.val_to, b.val_to, e.val_to))"); - loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE MAX(a.tx_from, b.tx_from, e.tx_from).after(" + - "MIN(a.val_to, b.val_to, e.val_to))", false); - expected = new Or( - //a, b - new Or( - // a - new Or(new Or( - new Comparison(aTxFrom, GT, aValTo), - new Comparison(aTxFrom, GT, bValTo) - ), - new Comparison(aTxFrom, GT, eValTo) - ), - // b - new Or( - new Or( - new Comparison(bTxFrom, GT, aValTo), - new Comparison(bTxFrom, GT, bValTo) - ), - new Comparison(bTxFrom, GT, eValTo) - ) - ), - //e - new Or( - new Or( - new Comparison(eTxFrom, GT, aValTo), - new Comparison(eTxFrom, GT, bValTo) - ), - new Comparison(eTxFrom, GT, eValTo) - ) - ); - expectedRaw = new Comparison( + expected = new Comparison( new MaxTimePoint(aTxFrom, bTxFrom, eTxFrom), GT, new MinTimePoint(aValTo, bValTo, eValTo) ); - assertPredicateEquals(loaderDoProcess.getPredicates().get(), expected); - assertPredicateEquals(loaderRaw.getPredicates().get(), expectedRaw); + assertPredicateEquals(loader.getPredicates().get(), expected); + - loaderDoProcess = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + "WHERE MIN(a.tx_from, b.tx_from, e.tx_from).before(2020-05-05) AND" + " a.tx.succeeds(b.tx)"); - loaderRaw = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE MIN(a.tx_from, b.tx_from, e.tx_from).before(2020-05-05) AND" + - " a.tx.succeeds(b.tx)", false); expected = new And( - new Or( - new Or( - new Comparison(aTxFrom, LT, literal1), - new Comparison(bTxFrom, LT, literal1) - ), - new Comparison(eTxFrom, LT, literal1) - ), - new Comparison(aTxFrom, GTE, new TimeSelector("b", TX_TO)) - ); - expectedRaw = new And( new Comparison( new MinTimePoint(aTxFrom, bTxFrom, eTxFrom), LT, literal1 ), new Comparison(aTxFrom, GTE, new TimeSelector("b", TX_TO)) ); - assertPredicateEquals(loaderDoProcess.getPredicates().get(), expected); - assertPredicateEquals(loaderRaw.getPredicates().get(), expectedRaw); + //assertPredicateEquals(loaderDoProcess.getPredicates().get(), expected); + assertPredicateEquals(loader.getPredicates().get(), expected); } @@ -737,7 +391,7 @@ public void lengthAtMostTest(){ private void lengthComparisonTest(String operator, Comparator comparator){ GDLLoader loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.val."+operator+"(Days(80))", false); + "WHERE a.val."+operator+"(Days(80))"); TimeSelector aValFrom = new TimeSelector("a", VAL_FROM); TimeSelector aValTo = new TimeSelector("a", VAL_TO); @@ -748,70 +402,92 @@ private void lengthComparisonTest(String operator, Comparator comparator){ TimeConstant eightyDays = new TimeConstant(80,0,0,0,0); Duration valDuration = new Duration(aValFrom, aValTo); + Comparison valDurationPred = new Comparison(aValFrom, LTE, aValTo); - Predicate expected = new Comparison(valDuration, comparator, eightyDays); + Predicate expected = new And(valDurationPred, + new Comparison(valDuration, comparator, eightyDays)); assertPredicateEquals(loader.getPredicates().get(), expected); loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.val."+operator+"(Hours(12))", false); + "WHERE a.val."+operator+"(Hours(12))"); TimeConstant twelveHours = new TimeConstant(0,12,0,0,0); - expected = new Comparison(valDuration, comparator, twelveHours); + expected = new And(valDurationPred, + new Comparison(valDuration, comparator, twelveHours)); assertPredicateEquals(loader.getPredicates().get(), expected); loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE val."+operator+"(Minutes(5))", false); + "WHERE val."+operator+"(Minutes(5))"); TimeConstant fiveMinutes = new TimeConstant(0,0,5,0,0); MaxTimePoint globalValFrom = new MaxTimePoint(eValFrom, aValFrom, bValFrom); MinTimePoint globalValTo = new MinTimePoint(eValTo, aValTo, bValTo); Duration globalValDuration = new Duration(globalValFrom, globalValTo); - expected = new Comparison(globalValDuration, comparator, fiveMinutes); + Comparison globalValPred = new Comparison(globalValFrom, LTE, globalValTo); + expected = new And(globalValPred, + new Comparison(globalValDuration, comparator, fiveMinutes)); assertPredicateEquals(loader.getPredicates().get(), expected); loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.val.merge(b.val)."+operator+"(Hours(20))", false); + "WHERE a.val.merge(b.val)."+operator+"(Hours(20))"); TimeConstant twentyHours = new TimeConstant(0,20,0,0,0); MaxTimePoint mergeFrom = new MaxTimePoint(aValFrom, bValFrom); MinTimePoint mergeTo = new MinTimePoint(aValTo, bValTo); Duration mergeDuration = new Duration(mergeFrom, mergeTo); + Comparison mergeDurationPred = new Comparison(mergeFrom, LTE, mergeTo); expected = new And( - new Comparison(mergeDuration, comparator, twentyHours), + new And( + mergeDurationPred, + new Comparison(mergeDuration, comparator, twentyHours)), new Comparison(mergeFrom, LTE, mergeTo) ); assertPredicateEquals(loader.getPredicates().get(), expected); loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.val.merge(b.val)."+operator+"(e.val.join(b.val))", false); + "WHERE a.val.merge(b.val)."+operator+"(e.val.join(b.val))"); MinTimePoint joinFrom = new MinTimePoint(eValFrom, bValFrom); MaxTimePoint joinTo = new MaxTimePoint(eValTo, bValTo); Duration joinDuration = new Duration(joinFrom, joinTo); + Comparison joinDurationPred = new Comparison(joinFrom, LTE, joinTo); + mergeDurationPred = new Comparison(mergeFrom, LTE, mergeTo); Comparison ebOverlap = new Comparison(new MaxTimePoint(eValFrom, bValFrom), LTE, new MinTimePoint(eValTo, bValTo)); expected = new And( new And( - new Comparison(mergeDuration, comparator, joinDuration), + new And( + new And( + mergeDurationPred, + joinDurationPred), + new Comparison(mergeDuration, comparator, joinDuration)), ebOverlap), new Comparison(mergeFrom, LTE, mergeTo) ); - System.out.println(loader.getPredicates().get()); - System.out.println(expected); + assertPredicateEquals(loader.getPredicates().get(), expected); loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE Interval(a.val_from, b.val_to)."+operator+"(Days(4))", false); + "WHERE Interval(a.val_from, b.val_to)."+operator+"(Days(4))"); TimeConstant fourDays = new TimeConstant(4,0,0,0,0); Duration intervalDuration = new Duration(aValFrom, bValTo); - expected = new Comparison(intervalDuration, comparator, fourDays); + Comparison intervalDurationPred = new Comparison(aValFrom, LTE, bValTo); + expected = new And( + intervalDurationPred, + new Comparison(intervalDuration, comparator, fourDays)); assertPredicateEquals(loader.getPredicates().get(), expected); loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE a.val."+operator+"(b.val)", false); + "WHERE a.val."+operator+"(b.val)"); Duration aVal = new Duration(aValFrom, aValTo); Duration bVal = new Duration(bValFrom, bValTo); - expected = new Comparison(aVal, comparator, bVal); + Comparison aValPred = new Comparison(aValFrom, LTE, aValTo); + Comparison bValPred = new Comparison(bValFrom, LTE, bValTo); + expected = new And( + new And( + aValPred, bValPred + ), + new Comparison(aVal, comparator, bVal)); assertPredicateEquals(loader.getPredicates().get(), expected); loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE val."+operator+"(tx)", false); + "WHERE val."+operator+"(tx)"); TimeSelector eTxFrom = new TimeSelector("e", TX_FROM); TimeSelector aTxFrom = new TimeSelector("a", TX_FROM); TimeSelector bTxFrom = new TimeSelector("b", TX_FROM); @@ -821,16 +497,23 @@ private void lengthComparisonTest(String operator, Comparator comparator){ MaxTimePoint globalTxFrom = new MaxTimePoint(eTxFrom, aTxFrom, bTxFrom); MinTimePoint globalTxTo = new MinTimePoint(eTxTo, aTxTo, bTxTo); Duration globalTxDuration = new Duration(globalTxFrom, globalTxTo); - expected = new Comparison(globalValDuration, comparator, globalTxDuration); + Comparison globalTxPred = new Comparison(globalTxFrom, LTE, globalTxTo); + expected = new And( + new And( + globalValPred, globalTxPred + ), + new Comparison(globalValDuration, comparator, globalTxDuration)); assertPredicateEquals(loader.getPredicates().get(), expected); loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + - "WHERE val."+operator+"(Interval(2020-05-01, 2020-05-05))", false); + "WHERE val."+operator+"(Interval(2020-05-01, 2020-05-05))"); TimeLiteral l1 = new TimeLiteral("2020-05-01"); TimeLiteral l2 = new TimeLiteral("2020-05-05"); Duration constantInterval = new Duration(l1, l2); - expected = new Comparison(globalValDuration, comparator, constantInterval); - System.out.println(loader.getPredicates().get()); + Comparison constantPred = new Comparison(l1, LTE, l2); + expected = new And( + new And(globalValPred, constantPred), + new Comparison(globalValDuration, comparator, constantInterval)); assertPredicateEquals(loader.getPredicates().get(), expected); } @@ -846,58 +529,16 @@ private void assertPredicateEquals(Predicate result, Predicate expected){ } - - // checks if pred 1 is contained in pred 2 - private boolean predicateContainedIn(Predicate p1, Predicate p2){ - if(p1 instanceof Comparison){ - if(p2 instanceof Comparison){ - // TODO better equals method? - return p1.equals(p2) || p1.switchSides().equals(p2); - } - else{ - Predicate lhs = p2.getArguments()[0]; - Predicate rhs = p2.getArguments()[1]; - return (predicateContainedIn(p1,lhs) || predicateContainedIn(p1,rhs)); - } - } - else{ - if(p2 instanceof Comparison){ - return false; - } - if(p1.toString().length() < p2.toString().length()){ - return false; - } - else if(p1.toString().length() == p2.toString().length()){ - return p1.equals(p2) || p1.switchSides().equals(p2); - } - else{ - Predicate lhs = p2.getArguments()[0]; - Predicate rhs = p2.getArguments()[1]; - return (predicateContainedIn(p1,lhs) || predicateContainedIn(p1,rhs)); - } - } - } - - - - - - private static final String DEFAULT_GRAPH_LABEL = "DefaultGraph"; private static final String DEFAULT_VERTEX_LABEL = "DefaultVertex"; private static final String DEFAULT_EDGE_LABEL = "DefaultEdge"; - private GDLLoader getLoaderFromGDLString(String gdlString) { - return getLoaderFromGDLString(gdlString, true); - } - - private GDLLoader getLoaderFromGDLString(String gdlString, boolean processPredicates){ + private GDLLoader getLoaderFromGDLString(String gdlString){ GDLLexer lexer = new GDLLexer(new ANTLRInputStream(gdlString)); GDLParser parser = new GDLParser(new CommonTokenStream(lexer)); ParseTreeWalker walker = new ParseTreeWalker(); - GDLLoader loader = new GDLLoader(DEFAULT_GRAPH_LABEL, DEFAULT_VERTEX_LABEL, DEFAULT_EDGE_LABEL, - processPredicates); + GDLLoader loader = new GDLLoader(DEFAULT_GRAPH_LABEL, DEFAULT_VERTEX_LABEL, DEFAULT_EDGE_LABEL); walker.walk(loader, parser.database()); return loader; } diff --git a/src/test/java/org/s1ck/gdl/GDLLoaderTest.java b/src/test/java/org/s1ck/gdl/GDLLoaderTest.java index 2f92ebb..e9ff82b 100644 --- a/src/test/java/org/s1ck/gdl/GDLLoaderTest.java +++ b/src/test/java/org/s1ck/gdl/GDLLoaderTest.java @@ -180,7 +180,7 @@ public void readIncomingEdgeWithVariablesTest() { } @Test - public void readEdgeWithNoLabelTest() throws Exception { + public void readEdgeWithNoLabelTest() { GDLLoader loader = getLoaderFromGDLString("()-[e]->()"); Edge e = loader.getEdgeCache().get("e"); assertEquals("edge has wrong label", loader.getDefaultEdgeLabel(), e.getLabel()); @@ -436,7 +436,7 @@ public void testWithCreateStatement() { // -------------------------------------------------------------------------------------------- @Test - public void testNonPredicateMatch() throws Exception { + public void testNonPredicateMatch() { String query = "MATCH (n)-[e]->(m)"; GDLLoader loader = getLoaderFromGDLString(query); @@ -691,7 +691,7 @@ private GDLLoader getLoaderFromFile(String fileName) throws IOException { } // string representation of all valid properties - private static String PROPERTIES_STRING; + private static final String PROPERTIES_STRING; // contains all valid properties private static final List> PROPERTIES_LIST = new ArrayList<>(); @@ -702,9 +702,9 @@ private GDLLoader getLoaderFromFile(String fileName) throws IOException { * @param */ private static class PropertyTriple { - private String key; - private String value; - private T expected; + private final String key; + private final String value; + private final T expected; public PropertyTriple(String key, String value, T expected) { this.key = key; diff --git a/src/test/java/org/s1ck/gdl/comparables/time/ComparisonTest.java b/src/test/java/org/s1ck/gdl/comparables/time/ComparisonTest.java index 45c7191..976d5a9 100644 --- a/src/test/java/org/s1ck/gdl/comparables/time/ComparisonTest.java +++ b/src/test/java/org/s1ck/gdl/comparables/time/ComparisonTest.java @@ -1,6 +1,5 @@ package org.s1ck.gdl.comparables.time; import org.junit.Test; -import org.junit.experimental.theories.FromDataPoints; import org.s1ck.gdl.model.comparables.PropertySelector; import org.s1ck.gdl.model.comparables.time.MaxTimePoint; import org.s1ck.gdl.model.comparables.time.MinTimePoint; diff --git a/src/test/java/org/s1ck/gdl/comparables/time/DurationTest.java b/src/test/java/org/s1ck/gdl/comparables/time/DurationTest.java index ed947ed..29c2227 100644 --- a/src/test/java/org/s1ck/gdl/comparables/time/DurationTest.java +++ b/src/test/java/org/s1ck/gdl/comparables/time/DurationTest.java @@ -17,8 +17,6 @@ public void simpleDurationTest(){ TimeLiteral l2 = new TimeLiteral("1970-01-01T00:00:01"); Duration duration = new Duration(l1, l2); assertEquals((long) duration.evaluate().get(), 1000L); - assertEquals(duration.getLowerBound(), 1000); - assertEquals(duration.getUpperBound(), 1000); } @Test @@ -27,8 +25,6 @@ public void selectorDurationTest(){ TimeSelector s1 = new TimeSelector("a", TX_TO); Duration duration = new Duration(l1, s1); assertFalse(duration.evaluate().isPresent()); - assertEquals(duration.getLowerBound(), 0L); - assertEquals(duration.getUpperBound(), Long.MAX_VALUE); assertEquals(duration.getVariables().size(), 1); assertEquals(duration.getVariables().toArray()[0], "a"); assertFalse(duration.isGlobal()); diff --git a/src/test/java/org/s1ck/gdl/comparables/time/MaxTimeTest.java b/src/test/java/org/s1ck/gdl/comparables/time/MaxTimeTest.java index 83e6f62..8b3d935 100644 --- a/src/test/java/org/s1ck/gdl/comparables/time/MaxTimeTest.java +++ b/src/test/java/org/s1ck/gdl/comparables/time/MaxTimeTest.java @@ -23,8 +23,8 @@ public void simpleMaxTimeTest(){ TimeLiteral l5 = new TimeLiteral("2019-04-05T01:02:31"); MaxTimePoint mx = new MaxTimePoint(l1,l2,l3,l4,l5); assertEquals(mx.evaluate().get(), l5.evaluate().get()); - assertEquals(mx.getLowerBound(), mx.getUpperBound()); - assertEquals(mx.getUpperBound(), (long)mx.evaluate().get()); +/* assertEquals(mx.getLowerBound(), mx.getUpperBound()); + assertEquals(mx.getUpperBound(), (long)mx.evaluate().get());*/ } @Test @@ -35,15 +35,15 @@ public void mixedMaxTimeTest(){ TimeSelector l4 = new TimeSelector("v", TimeSelector.TimeField.VAL_TO); MaxTimePoint mx = new MaxTimePoint(l1,l2,l3,l4); assertFalse(mx.evaluate().isPresent()); - assertEquals(mx.getLowerBound(), (long)l2.evaluate().get()); - assertEquals(mx.getUpperBound(), Long.MAX_VALUE); +/* assertEquals(mx.getLowerBound(), (long)l2.evaluate().get()); + assertEquals(mx.getUpperBound(), Long.MAX_VALUE);*/ // only selectors TimeSelector l5 = new TimeSelector("x",TimeSelector.TimeField.VAL_FROM); mx = new MaxTimePoint(l4,l5); assertFalse(mx.evaluate().isPresent()); - assertEquals(mx.getLowerBound(), Long.MIN_VALUE); - assertEquals(mx.getUpperBound(), Long.MAX_VALUE); +/* assertEquals(mx.getLowerBound(), Long.MIN_VALUE); + assertEquals(mx.getUpperBound(), Long.MAX_VALUE);*/ } @Test @@ -58,8 +58,8 @@ public void complexMaxTest(){ MaxTimePoint mx3 = new MaxTimePoint(mx1, mx2); assertFalse(mx3.evaluate().isPresent()); - assertEquals(mx3.getLowerBound(), mx1.getLowerBound()); - assertEquals(mx3.getUpperBound(), Long.MAX_VALUE); +/* assertEquals(mx3.getLowerBound(), mx1.getLowerBound()); + assertEquals(mx3.getUpperBound(), Long.MAX_VALUE);*/ } @@ -101,8 +101,6 @@ public void maxMinTest3(){ MinTimePoint mn2 = new MinTimePoint(l3,l4,s2); MaxTimePoint mx = new MaxTimePoint(mn1,mn2); assertFalse(mx.evaluate().isPresent()); - assertEquals(mx.getLowerBound(), Long.MIN_VALUE); - assertEquals(mx.getUpperBound(), (long)l1.evaluate().get()); } @Test @@ -118,8 +116,6 @@ public void maxMinTest4(){ MaxTimePoint mx1 = new MaxTimePoint(l3,l4,l5,s2); MaxTimePoint mx = new MaxTimePoint(mn1,mx1); assertFalse(mx.evaluate().isPresent()); - assertEquals(mx.getUpperBound(), Long.MAX_VALUE); - assertEquals(mx.getLowerBound(), (long)l5.evaluate().get()); } @Test @@ -158,7 +154,6 @@ public void unfoldEQTest(){ ); Predicate unfolded = mn.unfoldComparison(Comparator.EQ, arg); - System.out.println(unfolded); assertEquals(expected, unfolded); } @@ -198,7 +193,6 @@ public void unfoldNEQTest(){ ); Predicate unfolded = mn.unfoldComparison(Comparator.NEQ, arg); - System.out.println(unfolded); assertEquals(expected, unfolded); } @@ -220,7 +214,6 @@ public void unfoldGTTest(){ ); Predicate unfolded = mn.unfoldComparison(Comparator.GT, arg); - System.out.println(unfolded); assertEquals(expected, unfolded); } @@ -242,7 +235,6 @@ public void unfoldGTETest(){ ); Predicate unfolded = mn.unfoldComparison(Comparator.GTE, arg); - System.out.println(unfolded); assertEquals(expected, unfolded); } @@ -264,7 +256,6 @@ public void unfoldLTTest(){ ); Predicate unfolded = mn.unfoldComparison(Comparator.LT, arg); - System.out.println(unfolded); assertEquals(expected, unfolded); } @@ -286,7 +277,6 @@ public void unfoldLTETest(){ ); Predicate unfolded = mn.unfoldComparison(Comparator.LTE, arg); - System.out.println(unfolded); assertEquals(expected, unfolded); } diff --git a/src/test/java/org/s1ck/gdl/comparables/time/MinTimeTest.java b/src/test/java/org/s1ck/gdl/comparables/time/MinTimeTest.java index c723c9d..77f10ea 100644 --- a/src/test/java/org/s1ck/gdl/comparables/time/MinTimeTest.java +++ b/src/test/java/org/s1ck/gdl/comparables/time/MinTimeTest.java @@ -7,7 +7,6 @@ import org.s1ck.gdl.model.comparables.time.TimeSelector; import org.s1ck.gdl.model.predicates.Predicate; import org.s1ck.gdl.model.predicates.booleans.And; -import org.s1ck.gdl.model.predicates.booleans.Not; import org.s1ck.gdl.model.predicates.booleans.Or; import org.s1ck.gdl.model.predicates.expressions.Comparison; import org.s1ck.gdl.utils.Comparator; @@ -28,8 +27,6 @@ public void simpleMinTimeTest(){ TimeLiteral l5 = new TimeLiteral("2019-04-05T01:02:31"); MinTimePoint mn = new MinTimePoint(l1,l2,l3,l4,l5); assertEquals(mn.evaluate().get(), l3.evaluate().get()); - assertEquals(mn.getLowerBound(), mn.getUpperBound()); - assertEquals(mn.getUpperBound(), (long)mn.evaluate().get()); } @Test @@ -40,15 +37,11 @@ public void mixedMinTimeTest(){ TimeSelector l4 = new TimeSelector("v", TimeSelector.TimeField.VAL_TO); MinTimePoint mn = new MinTimePoint(l1,l2,l3,l4); assertFalse(mn.evaluate().isPresent()); - assertEquals(mn.getLowerBound(), Long.MIN_VALUE); - assertEquals(mn.getUpperBound(), (long)l3.evaluate().get()); // only selectors TimeSelector l5 = new TimeSelector("x",TimeSelector.TimeField.VAL_FROM); mn = new MinTimePoint(l4,l5); assertFalse(mn.evaluate().isPresent()); - assertEquals(mn.getLowerBound(), Long.MIN_VALUE); - assertEquals(mn.getUpperBound(), Long.MAX_VALUE); } @Test @@ -63,8 +56,6 @@ public void complexMinTest(){ MinTimePoint mn3 = new MinTimePoint(mn1, mn2); assertFalse(mn3.evaluate().isPresent()); - assertEquals(mn3.getLowerBound(), Long.MIN_VALUE); - assertEquals(mn3.getUpperBound(), (long)l2.evaluate().get()); assertEquals(mn3.getVariables().size(),2); assertTrue(mn3.getVariables().contains("q")); @@ -109,8 +100,6 @@ public void minMaxTest3(){ MaxTimePoint mx2 = new MaxTimePoint(l3,l4,s2); MinTimePoint mn = new MinTimePoint(mx1,mx2); assertFalse(mn.evaluate().isPresent()); - assertEquals(mn.getLowerBound(), (long)l2.evaluate().get()); - assertEquals(mn.getUpperBound(), Long.MAX_VALUE); } @Test @@ -126,8 +115,6 @@ public void minMaxTest4(){ MaxTimePoint mx1 = new MaxTimePoint(l3,l4,l5,s2); MinTimePoint mn = new MinTimePoint(mn1,mx1); assertFalse(mn.evaluate().isPresent()); - assertEquals(mn.getUpperBound(), (long)l1.evaluate().get()); - assertEquals(mn.getLowerBound(), Long.MIN_VALUE); } @Test @@ -166,7 +153,6 @@ public void unfoldEQTest(){ ); Predicate unfolded = mn.unfoldComparison(Comparator.EQ, arg); - System.out.println(unfolded); assertEquals(expected, unfolded); } @@ -206,7 +192,6 @@ public void unfoldNEQTest(){ ); Predicate unfolded = mn.unfoldComparison(Comparator.NEQ, arg); - System.out.println(unfolded); assertEquals(expected, unfolded); } @@ -228,7 +213,6 @@ public void unfoldGTTest(){ ); Predicate unfolded = mn.unfoldComparison(Comparator.GT, arg); - System.out.println(unfolded); assertEquals(expected, unfolded); } @@ -250,7 +234,6 @@ public void unfoldGTETest(){ ); Predicate unfolded = mn.unfoldComparison(Comparator.GTE, arg); - System.out.println(unfolded); assertEquals(expected, unfolded); } @@ -272,7 +255,6 @@ public void unfoldLTTest(){ ); Predicate unfolded = mn.unfoldComparison(Comparator.LT, arg); - System.out.println(unfolded); assertEquals(expected, unfolded); } @@ -294,7 +276,6 @@ public void unfoldLTETest(){ ); Predicate unfolded = mn.unfoldComparison(Comparator.LTE, arg); - System.out.println(unfolded); assertEquals(expected, unfolded); } diff --git a/src/test/java/org/s1ck/gdl/comparables/time/PlusTimeTest.java b/src/test/java/org/s1ck/gdl/comparables/time/PlusTimeTest.java deleted file mode 100644 index 275c5a3..0000000 --- a/src/test/java/org/s1ck/gdl/comparables/time/PlusTimeTest.java +++ /dev/null @@ -1,146 +0,0 @@ -//package org.s1ck.gdl.comparables.time; -// -//import org.junit.Test; -//import org.s1ck.gdl.model.comparables.time.*; -//import org.s1ck.gdl.model.comparables.time.TimeConstant; -//import org.s1ck.gdl.model.predicates.expressions.Comparison; -//import org.s1ck.gdl.utils.Comparator; -// -//import java.util.ArrayList; -//import java.util.Arrays; -// -//import static org.junit.Assert.*; -// -//public class PlusTimeTest { -// -// @Test -// public void simplePlusTest(){ -// TimeLiteral l1 = new TimeLiteral("2017-01-12T08:00"); -// TimeConstant c = new TimeConstant(1000); -// -// PlusTimePoint p = new PlusTimePoint(l1,c); -// long sum = l1.getMilliseconds() + c.getMillis(); -// assertEquals(p.evaluate(), sum); -// assertEquals(p.getLowerBound(), p.evaluate()); -// assertEquals(p.getUpperBound(), p.evaluate()); -// -// assertEquals(p.getVariables().size(),0); -// } -// -// @Test -// public void selectorPlusTest(){ -// TimeSelector s = new TimeSelector("p", TimeSelector.TimeField.VAL_FROM); -// TimeConstant c = new TimeConstant(1234); -// PlusTimePoint p = new PlusTimePoint(s,c); -// -// assertEquals(p.evaluate(), TimePoint.UNDEFINED); -// assertEquals(p.getLowerBound(), 1234); -// assertEquals(p.getUpperBound(), Long.MAX_VALUE); -// -// assertEquals(p.getVariables().size(),1); -// assertEquals(new ArrayList(p.getVariables()).get(0), "p"); -// } -// -// @Test -// public void maxPlusTest(){ -// TimeLiteral l1 = new TimeLiteral("2017-01-12"); -// TimeLiteral l2 = new TimeLiteral("2017-01-12T08:00"); -// MaxTimePoint mx1 = new MaxTimePoint(l1,l2); -// TimeConstant c = new TimeConstant(1); -// -// PlusTimePoint p = new PlusTimePoint(mx1, c); -// assertEquals(p.evaluate(), l2.getMilliseconds()+1); -// assertEquals(p.evaluate(), p.getLowerBound()); -// assertEquals(p.evaluate(), p.getUpperBound()); -// -// // now with undetermined maximum -// TimeSelector s1 = new TimeSelector("x", "tx_to"); -// MaxTimePoint mx2 = new MaxTimePoint(l1, s1); -// PlusTimePoint p2 = new PlusTimePoint(mx2, c); -// assertEquals(p2.evaluate(), TimePoint.UNDEFINED); -// assertEquals(p2.getLowerBound(), l1.getMilliseconds()+c.getMillis()); -// assertEquals(p2.getUpperBound(), Long.MAX_VALUE); -// } -// -// @Test -// public void minPlusTest(){ -// TimeLiteral l1 = new TimeLiteral("2017-01-12"); -// TimeLiteral l2 = new TimeLiteral("2017-01-12T08:00"); -// MinTimePoint mn1 = new MinTimePoint(l1,l2); -// TimeConstant c = new TimeConstant(1); -// -// PlusTimePoint p = new PlusTimePoint(mn1, c); -// assertEquals(p.evaluate(), l1.getMilliseconds()+1); -// assertEquals(p.evaluate(), p.getLowerBound()); -// assertEquals(p.evaluate(), p.getUpperBound()); -// -// // now with undetermined minimum -// TimeSelector s1 = new TimeSelector("x", "tx_to"); -// MinTimePoint mn2 = new MinTimePoint(l1, s1); -// PlusTimePoint p2 = new PlusTimePoint(mn2, c); -// assertEquals(p2.evaluate(), TimePoint.UNDEFINED); -// assertEquals(p2.getLowerBound(), c.getMillis()); -// assertEquals(p2.getUpperBound(), l1.getMilliseconds()+c.getMillis()); -// } -// -// @Test -// public void unfoldPredicateTest(){ -// TimeLiteral lit = new TimeLiteral("2020-04-10T12:00:00"); -// TimeConstant c = new TimeConstant(1000); -// PlusTimePoint plus = new PlusTimePoint(lit, c); -// TimeSelector s = new TimeSelector("x", TimeSelector.TimeField.VAL_TO); -// //expected values -// Comparison cEq = new Comparison(plus, Comparator.EQ, s); -// Comparison cNeq = new Comparison(plus, Comparator.NEQ, s); -// Comparison cGt = new Comparison(plus, Comparator.GT, s); -// Comparison cGte = new Comparison(plus, Comparator.GTE, s); -// Comparison cLt = new Comparison(plus, Comparator.LT, s); -// Comparison cLte = new Comparison(plus, Comparator.LTE, s); -// -// assertEquals(plus.unfoldComparison(Comparator.EQ, s), cEq); -// assertEquals(plus.unfoldComparison(Comparator.NEQ, s), cNeq); -// assertEquals(plus.unfoldComparison(Comparator.GT, s), cGt); -// assertEquals(plus.unfoldComparison(Comparator.GTE, s), cGte); -// assertEquals(plus.unfoldComparison(Comparator.LT, s), cLt); -// assertEquals(plus.unfoldComparison(Comparator.LTE, s), cLte); -// -// } -// -// @Test -// public void containsTxToTest(){ -// TimeConstant c = new TimeConstant(1000); -// TimeSelector s1 = new TimeSelector("a", "val_from"); -// PlusTimePoint p1 = new PlusTimePoint(s1, c); -// assertFalse(p1.containsSelectorType(TimeSelector.TimeField.TX_TO)); -// -// TimeSelector s2 = new TimeSelector("a", "tx_to"); -// PlusTimePoint p2 = new PlusTimePoint(s2, c); -// assertTrue(p2.containsSelectorType(TimeSelector.TimeField.TX_TO));maxPlusTest(); -// } -// -// @Test -// public void globalTest(){ -// TimeConstant c = new TimeConstant(1000); -// TimeSelector s1 = new TimeSelector("a", "val_from"); -// TimeSelector global = new TimeSelector(TimeSelector.GLOBAL_SELECTOR, "val_to"); -// -// ArrayList variables = new ArrayList<>(Arrays.asList("a","b")); -// -// assertEquals(new PlusTimePoint(s1, c).replaceGlobalByLocal(variables), -// new PlusTimePoint(s1,c)); -// -// PlusTimePoint expectedGlobal = new PlusTimePoint( -// new MinTimePoint( -// new TimeSelector("a", TimeSelector.TimeField.VAL_TO), -// new TimeSelector("b", TimeSelector.TimeField.VAL_TO) -// ), -// c -// ); -// -// assertEquals(new PlusTimePoint(global, c).replaceGlobalByLocal(variables), -// expectedGlobal); -// -// assertFalse(new PlusTimePoint(s1,c).isGlobal()); -// assertTrue(new PlusTimePoint(global, c).isGlobal()); -// } -//} diff --git a/src/test/java/org/s1ck/gdl/comparables/time/TimeConstantTest.java b/src/test/java/org/s1ck/gdl/comparables/time/TimeConstantTest.java index 318c2a3..385c7ca 100644 --- a/src/test/java/org/s1ck/gdl/comparables/time/TimeConstantTest.java +++ b/src/test/java/org/s1ck/gdl/comparables/time/TimeConstantTest.java @@ -23,8 +23,5 @@ public void constantTest(){ assertEquals(expected_millis, c2.getMillis()); assertEquals(c2.getMillis(), (long)c2.evaluate().get()); - assertEquals(c2.getMillis(), c2.getUpperBound()); - assertEquals(c2.getMillis(), c2.getLowerBound()); - } } diff --git a/src/test/java/org/s1ck/gdl/comparables/time/TimeLiteralTest.java b/src/test/java/org/s1ck/gdl/comparables/time/TimeLiteralTest.java index 1224186..7290da9 100644 --- a/src/test/java/org/s1ck/gdl/comparables/time/TimeLiteralTest.java +++ b/src/test/java/org/s1ck/gdl/comparables/time/TimeLiteralTest.java @@ -5,12 +5,11 @@ import org.s1ck.gdl.model.predicates.expressions.Comparison; import org.s1ck.gdl.utils.Comparator; -import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Arrays; -import java.util.Date; +import java.util.Collections; import static org.junit.Assert.*; import static org.s1ck.gdl.utils.Comparator.NEQ; @@ -20,7 +19,6 @@ public class TimeLiteralTest { @Test public void millisInitTest(){ TimeLiteral tl1 = new TimeLiteral(0); - System.out.println(tl1.toString()); assertEquals(tl1.getMilliseconds(),0); assertEquals(tl1.getYear(), 1970); assertEquals(tl1.getMonth(),1 ); @@ -29,12 +27,19 @@ public void millisInitTest(){ assertEquals(tl1.getMinute(),0); assertEquals(tl1.getSecond(), 0); + TimeLiteral tl2 = new TimeLiteral(-1000); + assertEquals(tl2.getMilliseconds(),-1000); + assertEquals(tl2.getYear(), 1969); + assertEquals(tl2.getMonth(),12); + assertEquals(tl2.getDay(), 31); + assertEquals(tl2.getHour(),23); + assertEquals(tl2.getMinute(),59); + assertEquals(tl2.getSecond(), 59); } @Test public void stringInitTest(){ TimeLiteral tl1 = new TimeLiteral("2020-04-06T15:33:00"); - System.out.println(tl1.toString()); assertEquals(tl1.getYear(), 2020); assertEquals(tl1.getMonth(),4 ); assertEquals(tl1.getDay(), 6); @@ -42,8 +47,6 @@ public void stringInitTest(){ assertEquals(tl1.getMinute(),33); assertEquals(tl1.getSecond(), 0); - assertEquals(tl1.getLowerBound(), tl1.getUpperBound()); - assertEquals(tl1.getUpperBound(), (long)tl1.evaluate().get()); assertEquals((long)tl1.evaluate().get(), tl1.getMilliseconds()); TimeLiteral tl2 = new TimeLiteral("2020-04-05"); @@ -55,9 +58,8 @@ public void stringInitTest(){ assertEquals(tl2.getSecond(), 0); TimeLiteral tl3 = new TimeLiteral("now"); - System.out.println(tl3.getMilliseconds()); long millis = LocalDateTime.now().toInstant(ZoneOffset.ofTotalSeconds(0)).toEpochMilli(); - //should work... + assertTrue(millis - tl3.getMilliseconds() > 0); assertTrue(millis - tl3.getMilliseconds() < 5000); } @@ -89,20 +91,12 @@ public void containsTxToTest(){ assertFalse(literal.containsSelectorType(TimeSelector.TimeField.TX_TO)); } - @Test - public void unfoldGlobalTest(){ - TimeLiteral literal = new TimeLiteral(); - TimeSelector s = new TimeSelector("a", TimeSelector.TimeField.TX_TO); - Comparison c = new Comparison(literal, NEQ, s); - assertEquals(c.unfoldTemporalComparisonsLeft(), c); - } - @Test public void globalTest(){ TimeLiteral literal1 = new TimeLiteral(); TimeLiteral literal2 = new TimeLiteral("2020-05-06"); assertFalse(literal1.isGlobal() || literal2.isGlobal()); - assertEquals(literal1.replaceGlobalByLocal(new ArrayList<>(Arrays.asList("a"))), + assertEquals(literal1.replaceGlobalByLocal(new ArrayList<>(Collections.singletonList("a"))), literal1); } } diff --git a/src/test/java/org/s1ck/gdl/comparables/time/TimeSelectorTest.java b/src/test/java/org/s1ck/gdl/comparables/time/TimeSelectorTest.java index 9462695..6aab6a3 100644 --- a/src/test/java/org/s1ck/gdl/comparables/time/TimeSelectorTest.java +++ b/src/test/java/org/s1ck/gdl/comparables/time/TimeSelectorTest.java @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import static org.junit.Assert.*; import static org.s1ck.gdl.utils.Comparator.*; @@ -21,11 +22,9 @@ public class TimeSelectorTest { @Test public void selectorTest(){ TimeSelector selector = new TimeSelector("var", TimeSelector.TimeField.TX_FROM); - assertEquals(new ArrayList(selector.getVariables()).get(0), "var"); + assertEquals(new ArrayList<>(selector.getVariables()).get(0), "var"); assertEquals(selector.getVariables().size(), 1); - assertEquals(new ArrayList(selector.getVariables()).get(0), "var"); - assertEquals(selector.getLowerBound(), Long.MIN_VALUE); - assertEquals(selector.getUpperBound(), Long.MAX_VALUE); + assertEquals(new ArrayList<>(selector.getVariables()).get(0), "var"); assertFalse(selector.evaluate().isPresent()); assertEquals(selector.getTimeProp(), TimeSelector.TimeField.TX_FROM); } @@ -228,7 +227,7 @@ public void containsTxToTest(){ public void globalTest(){ TimeSelector valF = new TimeSelector("a", "val_from"); assertFalse(valF.isGlobal()); - assertEquals(valF.replaceGlobalByLocal(new ArrayList<>(Arrays.asList("a"))), + assertEquals(valF.replaceGlobalByLocal(new ArrayList<>(Collections.singletonList("a"))), valF); TimeSelector global = new TimeSelector(TimeSelector.GLOBAL_SELECTOR, "val_to"); ArrayList vars = new ArrayList<>(Arrays.asList("a", "b", "e")); @@ -247,7 +246,7 @@ public void globalTest(){ ); assertEquals(expected2, global2.replaceGlobalByLocal(vars)); // only one variable -> no max/min, but single selector - ArrayList singleVar = new ArrayList<>(Arrays.asList("a")); + ArrayList singleVar = new ArrayList<>(Collections.singletonList("a")); TimeSelector expectedSingle = new TimeSelector("a", "tx_from"); assertEquals(global2.replaceGlobalByLocal(singleVar), expectedSingle); assertTrue(global.isGlobal()); diff --git a/src/test/java/org/s1ck/gdl/predicates/PredicateTest.java b/src/test/java/org/s1ck/gdl/predicates/PredicateTest.java deleted file mode 100644 index a5eb7e0..0000000 --- a/src/test/java/org/s1ck/gdl/predicates/PredicateTest.java +++ /dev/null @@ -1,413 +0,0 @@ -package org.s1ck.gdl.predicates; - -import org.junit.Test; -import org.s1ck.gdl.model.comparables.ComparableExpression; -import org.s1ck.gdl.model.comparables.time.MaxTimePoint; -import org.s1ck.gdl.model.comparables.time.MinTimePoint; -import org.s1ck.gdl.model.comparables.time.TimeLiteral; -import org.s1ck.gdl.model.comparables.time.TimeSelector; -import org.s1ck.gdl.model.predicates.Predicate; -import org.s1ck.gdl.model.predicates.booleans.And; -import org.s1ck.gdl.model.predicates.booleans.Not; -import org.s1ck.gdl.model.predicates.booleans.Or; -import org.s1ck.gdl.model.predicates.booleans.Xor; -import org.s1ck.gdl.model.predicates.expressions.Comparison; -import org.s1ck.gdl.utils.Comparator; - -import java.util.ArrayList; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class PredicateTest { - - @Test - // only comparison, only one complex type of depth 1 - public void testSimpleUnfold(){ - //-------------------------------------------------- - // DATA - //------------------------------------------------ - TimeLiteral literal = new TimeLiteral("1970-01-01"); - TimeSelector m1 = new TimeSelector("p", TimeSelector.TimeField.VAL_FROM); - TimeLiteral m2 = new TimeLiteral("1972-01-01"); - MaxTimePoint mx1 = new MaxTimePoint(m1, m2); - - //--------------------------------------------------- - // EQ - //--------------------------------------------------- - Comparison c1 = new Comparison(literal, Comparator.EQ, mx1); - Comparison c2 = new Comparison(mx1, Comparator.EQ, literal); - Or expected1 = new Or( - new And( - new Comparison(m1, Comparator.EQ, literal), - new Comparison(m1, Comparator.GTE, m2) - ), - new And( - new Comparison(m2, Comparator.EQ, literal), - new Comparison(m2, Comparator.GTE, m1) - ) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c1), expected1); - // expected 1 with switched sides - Or expected2 = new Or( - new And( - new Comparison(literal, Comparator.EQ, m1), - new Comparison(m2, Comparator.LTE, m1) - ), - new And( - new Comparison(literal, Comparator.EQ, m2), - new Comparison(m1, Comparator.LTE, m2) - ) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c2), expected2); - - //-------------------------------------------------------------- - //NEQ - //------------------------------------------------------------- - Comparison c3 = new Comparison(literal, Comparator.NEQ, mx1); - Comparison c4 = new Comparison(mx1, Comparator.NEQ, literal); - - And expected3 = new And( - new Or( - new Comparison(m1, Comparator.NEQ, literal), - new Comparison(m1, Comparator.LT, m2) - ), - new Or( - new Comparison(m2, Comparator.NEQ, literal), - new Comparison(m2, Comparator.LT, m1) - ) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c3), expected3); - //expected3 with switched sides - And expected4 = new And( - new Or( - new Comparison(literal, Comparator.NEQ, m1), - new Comparison(m2, Comparator.GT, m1) - ), - new Or( - new Comparison(literal, Comparator.NEQ, m2), - new Comparison(m1, Comparator.GT, m2) - ) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c4), expected4); - - //-------------------------------------------------------------- - // GT - //------------------------------------------------------------- - Comparison c5 = new Comparison(literal, Comparator.GT, mx1); - Comparison c6 = new Comparison(mx1, Comparator.GT, literal); - - And expected5= new And( - new Comparison(m1, Comparator.LT, literal), - new Comparison(m2, Comparator.LT, literal) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c5), expected5); - - Or expected6 = new Or( - new Comparison(literal, Comparator.LT, m1), - new Comparison(literal, Comparator.LT, m2) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c6), expected6); - - //-------------------------------------------------------------- - // GTE - //------------------------------------------------------------- - Comparison c7 = new Comparison(literal, Comparator.GTE, mx1); - Comparison c8 = new Comparison(mx1, Comparator.GTE, literal); - - And expected7= new And( - new Comparison(m1, Comparator.LTE, literal), - new Comparison(m2, Comparator.LTE, literal) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c7), expected7); - - Or expected8 = new Or( - new Comparison(literal, Comparator.LTE, m1), - new Comparison(literal, Comparator.LTE, m2) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c8), expected8); - - //-------------------------------------------------------------- - // LT - //------------------------------------------------------------- - Comparison c9 = new Comparison(literal, Comparator.LT, mx1); - Comparison c10 = new Comparison(mx1, Comparator.LT, literal); - - Or expected9= new Or( - new Comparison(m1, Comparator.GT, literal), - new Comparison(m2, Comparator.GT, literal) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c9), expected9); - - And expected10 = new And( - new Comparison(literal, Comparator.GT, m1), - new Comparison(literal, Comparator.GT, m2) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c10), expected10); - - //-------------------------------------------------------------- - // LTE - //------------------------------------------------------------- - Comparison c11 = new Comparison(literal, Comparator.LTE, mx1); - Comparison c12 = new Comparison(mx1, Comparator.LTE, literal); - - Or expected11= new Or( - new Comparison(m1, Comparator.GTE, literal), - new Comparison(m2, Comparator.GTE, literal) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c7), expected7); - - And expected12 = new And( - new Comparison(literal, Comparator.GTE, m1), - new Comparison(literal, Comparator.GTE, m2) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c8), expected8); - - } - - @Test - public void testUnfoldWithTwoTempPredicates(){ - TimeSelector mx1 = new TimeSelector("mx1", TimeSelector.TimeField.VAL_FROM); - TimeSelector mx2 = new TimeSelector("mx2", TimeSelector.TimeField.VAL_TO); - MaxTimePoint mx = new MaxTimePoint(mx1, mx2); - - TimeSelector mn1 = new TimeSelector("mn1", TimeSelector.TimeField.TX_FROM); - TimeSelector mn2 = new TimeSelector("mn2", TimeSelector.TimeField.TX_TO); - MinTimePoint mn = new MinTimePoint(mn1, mn2); - - //----------------------------------------------- - // compare max to min - //------------------------------------------------- - Comparison c1 = new Comparison(mn, Comparator.GT, mx); - And expected1 = new And( - new And( - new Comparison(mx1, Comparator.LT, mn1), - new Comparison(mx2, Comparator.LT, mn1) - ), - new And( - new Comparison(mx1, Comparator.LT, mn2), - new Comparison(mx2, Comparator.LT, mn2) - ) - ); - assertEquals(expected1, Predicate.unfoldTemporalComparisons(c1)); - - Comparison c2 = new Comparison(mx, Comparator.GT, mn); - Or expected2 = new Or( - new Or( - new Comparison(mn1, Comparator.LT, mx1), - new Comparison(mn2, Comparator.LT, mx1) - ), - new Or( - new Comparison(mn1, Comparator.LT, mx2), - new Comparison(mn2, Comparator.LT, mx2) - ) - ); - assertEquals(expected2, Predicate.unfoldTemporalComparisons(c2)); - - //--------------------------------------------------------------- - // compare MAX to MAX - //-------------------------------------------------------------- - Comparison c3 = new Comparison(mx, Comparator.EQ, mx); - Or expected3 = new Or( - new And( - // mx == mx1 - new Or( - new And( - new Comparison(mx1, Comparator.EQ, mx1), - new Comparison(mx1, Comparator.GTE, mx2) - ), - new And( - new Comparison(mx2, Comparator.EQ, mx1), - new Comparison(mx2, Comparator.GTE, mx1) - ) - ), - // mx1 >= mx2 - new Comparison(mx2, Comparator.LTE, mx1) - ), - new And( - // mx == mx2 - new Or( - new And( - new Comparison(mx1, Comparator.EQ, mx2), - new Comparison(mx1, Comparator.GTE, mx2) - ), - new And( - new Comparison(mx2, Comparator.EQ, mx2), - new Comparison(mx2, Comparator.GTE, mx1) - ) - ), - new Comparison(mx1, Comparator.LTE, mx2) - ) - ); - assertEquals(expected3, Predicate.unfoldTemporalComparisons(c3)); - - //-------------------------------------------------- - // compare MIN to MIN - //-------------------------------------------------- - Comparison c4 = new Comparison(mn, Comparator.LTE, mn); - Or expected4 = new Or( - new And( - new Comparison(mn1, Comparator.GTE, mn1), - new Comparison(mn2, Comparator.GTE, mn1) - ), - new And( - new Comparison(mn1, Comparator.GTE, mn2), - new Comparison(mn2, Comparator.GTE, mn2) - ) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c4), expected4); - } - - @Test - public void testUnfoldWithBooleans(){ - TimeSelector mx1 = new TimeSelector("mx1", TimeSelector.TimeField.VAL_FROM); - TimeSelector mx2 = new TimeSelector("mx2", TimeSelector.TimeField.VAL_TO); - MaxTimePoint mx = new MaxTimePoint(mx1, mx2); - - TimeSelector mn1 = new TimeSelector("mn1", TimeSelector.TimeField.TX_FROM); - TimeSelector mn2 = new TimeSelector("mn2", TimeSelector.TimeField.TX_TO); - MinTimePoint mn = new MinTimePoint(mn1, mn2); - - Comparison c1 = new Comparison(mx, Comparator.NEQ, mn); - Comparison c2 = new Comparison(mn1, Comparator.LTE, mx2); - - Predicate expected1 = new And( - new Or( - // mn neq mx1 - new And( - new Or( - new Comparison(mn1, Comparator.NEQ, mx1), - new Comparison(mn1, Comparator.GT, mn2) - ), - new Or( - new Comparison(mn2, Comparator.NEQ, mx1), - new Comparison(mn2, Comparator.GT, mn1) - ) - ), - - new Comparison(mx2, Comparator.GT, mx1) - ), - new Or( - // mn neq mx2 - new And( - new Or( - new Comparison(mn1, Comparator.NEQ, mx2), - new Comparison(mn1, Comparator.GT, mn2) - ), - new Or( - new Comparison(mn2, Comparator.NEQ, mx2), - new Comparison(mn2, Comparator.GT, mn1) - ) - ), - new Comparison(mx1, Comparator.GT, mx2) - ) - ); - - Predicate expected2 = new Comparison(mx2, Comparator.GTE, mn1); - - //or - Or or = new Or(c1, c2); - assertEquals(Predicate.unfoldTemporalComparisons(or), new Or(expected1, expected2)); - - //and - And and = new And(c1, c2); - assertEquals(Predicate.unfoldTemporalComparisons(and), new And(expected1, expected2)); - - //xor - Xor xor = new Xor(c1, c2); - assertEquals(Predicate.unfoldTemporalComparisons(xor), new Xor(expected1, expected2)); - - //not - Not not = new Not(c1); - assertEquals(Predicate.unfoldTemporalComparisons(not), new Not(expected1)); - } - - @Test - public void testOneSideDeepUnfold(){ - TimeLiteral l1 = new TimeLiteral("1970-02-01"); - TimeLiteral l2 = new TimeLiteral("2005-04-13"); - TimeLiteral l3 = new TimeLiteral("1999-12-31T23:59:59"); - TimeLiteral l4 = new TimeLiteral("2021-04-11"); - MinTimePoint mn = new MinTimePoint(l1,l2); - MaxTimePoint mx = new MaxTimePoint(mn, l3); - Comparison c = new Comparison(mx, Comparator.GT, l4); - - Predicate expected = new Or( - // mn > l4 - new And( - new Comparison(l4, Comparator.LT, l1), - new Comparison(l4, Comparator.LT, l2) - ), - new Comparison(l4, Comparator.LT, l3) - ); - - assertEquals(Predicate.unfoldTemporalComparisons(c), expected); - } - - @Test - public void testBothSideDeepUnfold(){ - TimeLiteral l1 = new TimeLiteral("1970-02-01"); - TimeLiteral l2 = new TimeLiteral("2005-04-13"); - TimeLiteral l3 = new TimeLiteral("1999-12-31T23:59:59"); - TimeLiteral l4 = new TimeLiteral("2021-04-11"); - - TimeLiteral l5 = new TimeLiteral("1970-02-01"); - TimeLiteral l6 = new TimeLiteral("2005-04-13"); - TimeLiteral l7 = new TimeLiteral("1999-12-31T23:59:59"); - TimeLiteral l8 = new TimeLiteral("2021-04-11"); - - MaxTimePoint lhs = new MaxTimePoint(new MinTimePoint(l1,l2), new MaxTimePoint(l3,l4)); - MinTimePoint rhs = new MinTimePoint(new MaxTimePoint(l5, l6), new MinTimePoint(l7, l8)); - Comparison c = new Comparison(lhs, Comparator.LTE, rhs); - - Predicate expected = new And( - new Or( - new And( - new Or( - new Comparison(l5, Comparator.GTE, l1), - new Comparison(l6, Comparator.GTE, l1) - ), - new And( - new Comparison(l7, Comparator.GTE, l1), - new Comparison(l8, Comparator.GTE, l1) - ) - ), - new And( - new Or( - new Comparison(l5, Comparator.GTE, l2), - new Comparison(l6, Comparator.GTE, l2) - ), - new And( - new Comparison(l7, Comparator.GTE, l2), - new Comparison(l8, Comparator.GTE, l2) - ) - ) - ), - new And( - new And( - new Or( - new Comparison(l5, Comparator.GTE, l3), - new Comparison(l6, Comparator.GTE, l3) - ), - new And( - new Comparison(l7, Comparator.GTE, l3), - new Comparison(l8, Comparator.GTE, l3) - ) - ), - new And( - new Or( - new Comparison(l5, Comparator.GTE, l4), - new Comparison(l6, Comparator.GTE, l4) - ), - new And( - new Comparison(l7, Comparator.GTE, l4), - new Comparison(l8, Comparator.GTE, l4) - ) - ) - ) - ); - assertEquals(Predicate.unfoldTemporalComparisons(c), expected); - } - - -}