You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2020/10/05 12:48:06 UTC
[groovy] branch GROOVY-8258 updated: GROOVY-8258: build AST for
ginq and generate target method calls
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY-8258
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY-8258 by this push:
new a6d4c4e GROOVY-8258: build AST for ginq and generate target method calls
a6d4c4e is described below
commit a6d4c4e4106ced92f15af893992e5843ecfa66ba
Author: Daniel Sun <su...@apache.org>
AuthorDate: Mon Oct 5 20:47:43 2020 +0800
GROOVY-8258: build AST for ginq and generate target method calls
---
.../apache/groovy/linq/LinqGroovyMethods.groovy | 116 ++------------------
.../org/apache/groovy/linq/dsl/GinqAstBuilder.java | 67 ++++++++++++
.../org/apache/groovy/linq/dsl/GinqBuilder.groovy | 118 +++++++++++++++++++++
.../org/apache/groovy/linq/dsl/GinqVisitor.java | 33 ++++++
.../dsl/expression/AbstractGinqExpression.java | 20 ++++
.../linq/dsl/expression/FilterableExpression.java | 31 ++++++
.../groovy/linq/dsl/expression/FromExpression.java | 54 ++++++++++
.../groovy/linq/dsl/expression/GinqExpression.java | 25 +++++
.../groovy/linq/dsl/expression/RootExpression.java | 58 ++++++++++
.../linq/dsl/expression/SelectExpression.java | 46 ++++++++
.../linq/dsl/expression/WhereExpression.java | 39 +++++++
11 files changed, 501 insertions(+), 106 deletions(-)
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/LinqGroovyMethods.groovy b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/LinqGroovyMethods.groovy
index 70a9596..4d9af35 100644
--- a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/LinqGroovyMethods.groovy
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/LinqGroovyMethods.groovy
@@ -18,126 +18,30 @@
*/
package org.apache.groovy.linq
-import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
-import groovy.transform.ToString
-import org.codehaus.groovy.ast.ClassHelper
-import org.codehaus.groovy.ast.expr.ArgumentListExpression
+import org.apache.groovy.linq.dsl.GinqAstBuilder
+import org.apache.groovy.linq.dsl.GinqBuilder
+import org.apache.groovy.linq.dsl.expression.RootExpression
import org.codehaus.groovy.ast.expr.ClosureExpression
import org.codehaus.groovy.ast.expr.Expression
import org.codehaus.groovy.ast.expr.MethodCallExpression
-import org.codehaus.groovy.ast.expr.VariableExpression
-import org.codehaus.groovy.ast.stmt.BlockStatement
-import org.codehaus.groovy.ast.stmt.ExpressionStatement
import org.codehaus.groovy.ast.stmt.Statement
import org.codehaus.groovy.macro.runtime.Macro
import org.codehaus.groovy.macro.runtime.MacroContext
-import static org.codehaus.groovy.ast.tools.GeneralUtils.callX
-import static org.codehaus.groovy.ast.tools.GeneralUtils.lambdaX
-import static org.codehaus.groovy.ast.tools.GeneralUtils.param
-import static org.codehaus.groovy.ast.tools.GeneralUtils.params
-import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt
-
@CompileStatic
class LinqGroovyMethods {
@Macro
static Expression GINQ(MacroContext ctx, final ClosureExpression closureExpression) {
- BlockStatement code = (BlockStatement) closureExpression.getCode()
- List<Statement> statementList = code.getStatements()
-
- LinqContext linqContext = new LinqContext()
- for (Statement statement : statementList) {
- ExpressionStatement expressionStatement = (ExpressionStatement) statement
- MethodCallExpression methodCallExpression = (MethodCallExpression) expressionStatement.getExpression()
-
- String methodName = methodCallExpression.getMethodAsString()
- switch (methodName) {
- case 'from': {
- break
- }
- case 'of': {
- MethodCallExpression fromMethodCallExpression = (MethodCallExpression) methodCallExpression.getObjectExpression()
- VariableExpression aliasVariable = (VariableExpression) ((ArgumentListExpression) fromMethodCallExpression.getArguments()).getExpression(0)
- Expression dataSourceExpression = ((ArgumentListExpression) methodCallExpression.getArguments()).getExpression(0)
- linqContext.addFrom(aliasVariable, dataSourceExpression)
- break
- }
- case 'where': {
- Expression conditionExpression = ((ArgumentListExpression) methodCallExpression.getArguments()).getExpression(0)
- linqContext.addWhere(conditionExpression)
- break
- }
- case 'select': {
- Expression selectExpression = ((ArgumentListExpression) methodCallExpression.getArguments()).getExpression(0)
- linqContext.addSelect(selectExpression)
- break
- }
- default: {
- break
- }
- }
- }
-
- constructLinqMethodCalls(linqContext)
- }
+ Statement code = closureExpression.getCode()
- private static Expression constructLinqMethodCalls(LinqContext linqContext) {
- Map.Entry<VariableExpression, Expression> fromEntry = linqContext.fromMap.entrySet().toList().get(0)
- VariableExpression aliasVariable = fromEntry.key
+ GinqAstBuilder ginqAstBuilder = new GinqAstBuilder()
+ code.visit(ginqAstBuilder)
+ RootExpression rootExpression = ginqAstBuilder.getRootExpression()
- Expression selectMethodReceiver = null
+ GinqBuilder ginqBuilder = new GinqBuilder()
+ MethodCallExpression selectMethodCallExpression = ginqBuilder.visitRootExpression(rootExpression)
- MethodCallExpression from = constructFromMethodCall(fromEntry)
-
- selectMethodReceiver = from
-
- if (linqContext.whereList.size() > 0) {
- MethodCallExpression where = callXWithLambda(from, "where", aliasVariable.name, linqContext.whereList[0])
- selectMethodReceiver = where
- }
-
- MethodCallExpression select = callXWithLambda(selectMethodReceiver, "select", aliasVariable.name, linqContext.selectList[0])
-
- return select
- }
-
- @CompileDynamic
- private static MethodCallExpression constructFromMethodCall(fromEntry) {
- macro {
- org.apache.groovy.linq.provider.QueryableCollection
- .from($v { fromEntry.value })
- }
- }
-
- private static MethodCallExpression callXWithLambda(Expression receiver, String methodName, String lambdaParamName, Expression lambdaCode) {
- callX(
- receiver,
- methodName,
- lambdaX(
- params(param(ClassHelper.DYNAMIC_TYPE, lambdaParamName)),
- stmt(lambdaCode)
- )
- )
- }
-
- @ToString(includeNames=true)
- static class LinqContext {
- Map<VariableExpression, Expression> fromMap = new LinkedHashMap<>()
- List<Expression> whereList = new ArrayList<>()
- List<Expression> selectList = new ArrayList<>()
-
- void addFrom(VariableExpression aliasVariable, Expression dataSourceExpression) {
- fromMap.put(aliasVariable, dataSourceExpression)
- }
-
- void addWhere(Expression... conditionExpressions) {
- whereList.addAll(conditionExpressions)
- }
-
- void addSelect(Expression... selectExpressions) {
- selectList.addAll(selectExpressions)
- }
+ return selectMethodCallExpression
}
}
-
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/GinqAstBuilder.java b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/GinqAstBuilder.java
new file mode 100644
index 0000000..e2bec3f
--- /dev/null
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/GinqAstBuilder.java
@@ -0,0 +1,67 @@
+package org.apache.groovy.linq.dsl;
+
+import org.apache.groovy.linq.dsl.expression.FilterableExpression;
+import org.apache.groovy.linq.dsl.expression.FromExpression;
+import org.apache.groovy.linq.dsl.expression.GinqExpression;
+import org.apache.groovy.linq.dsl.expression.RootExpression;
+import org.apache.groovy.linq.dsl.expression.SelectExpression;
+import org.apache.groovy.linq.dsl.expression.WhereExpression;
+import org.codehaus.groovy.GroovyBugError;
+import org.codehaus.groovy.ast.CodeVisitorSupport;
+import org.codehaus.groovy.ast.expr.ArgumentListExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
+
+public class GinqAstBuilder extends CodeVisitorSupport {
+ private RootExpression rootExpression = new RootExpression(); // store the result
+ private GinqExpression ginqExpression; // store the return value
+
+ public RootExpression getRootExpression() {
+ return rootExpression;
+ }
+
+ @Override
+ public void visitMethodCallExpression(MethodCallExpression call) {
+ super.visitMethodCallExpression(call);
+ final String methodName = call.getMethodAsString();
+ System.out.println(methodName + " : " + call);
+
+ if ("from".equals(methodName)) {
+ return;
+ }
+
+ if ("of".equals(methodName)) {
+ MethodCallExpression fromMethodCallExpression = (MethodCallExpression) call.getObjectExpression();
+ Expression aliasExpr = ((ArgumentListExpression) fromMethodCallExpression.getArguments()).getExpression(0);
+ Expression dataSourceExpr = ((ArgumentListExpression) call.getArguments()).getExpression(0);
+
+ FromExpression fromExpression = new FromExpression(aliasExpr, dataSourceExpr);
+ rootExpression.addFromExpression(fromExpression);
+
+ ginqExpression = fromExpression;
+ return;
+ }
+
+ if ("where".equals(methodName)) {
+ Expression filterExpr = ((ArgumentListExpression) call.getArguments()).getExpression(0);
+ WhereExpression whereExpression = new WhereExpression(filterExpr);
+
+ if (ginqExpression instanceof FilterableExpression) {
+ ((FilterableExpression) ginqExpression).setWhereExpression(whereExpression);
+ } else {
+ throw new GroovyBugError("The preceding expression is not a FilterableExpression: " + ginqExpression);
+ }
+
+ return;
+ }
+
+ if ("select".equals(methodName)) {
+ SelectExpression selectExpression = new SelectExpression(call.getArguments());
+ rootExpression.setSelectExpression(selectExpression);
+
+ ginqExpression = selectExpression;
+
+ return;
+ }
+ }
+}
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/GinqBuilder.groovy b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/GinqBuilder.groovy
new file mode 100644
index 0000000..8cbb86b
--- /dev/null
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/GinqBuilder.groovy
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.groovy.linq.dsl
+
+import groovy.transform.CompileDynamic
+import groovy.transform.CompileStatic
+import org.apache.groovy.linq.dsl.expression.FromExpression
+import org.apache.groovy.linq.dsl.expression.GinqExpression
+import org.apache.groovy.linq.dsl.expression.RootExpression
+import org.apache.groovy.linq.dsl.expression.SelectExpression
+import org.apache.groovy.linq.dsl.expression.WhereExpression
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.expr.ArgumentListExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.lambdaX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt
+
+@CompileStatic
+class GinqBuilder implements GinqVisitor<Object> {
+ @Override
+ MethodCallExpression visitRootExpression(RootExpression rootExpression) {
+ List<MethodCallExpression> fromMethodCallExpressionList = new LinkedList<>()
+ List<FromExpression> fromExpressionList = rootExpression.getFromExpressionList()
+ for (FromExpression fromExpression : (fromExpressionList)) {
+ MethodCallExpression methodCallExpression = this.visitFromExpression(fromExpression)
+ fromMethodCallExpressionList.add(methodCallExpression)
+ }
+
+ MethodCallExpression selectMethodReceiver = fromMethodCallExpressionList.getLast()
+
+ SelectExpression selectExpression = rootExpression.getSelectExpression()
+ selectExpression.putNodeMetaData(__SELECT_METHOD_RECEIVER, selectMethodReceiver)
+ selectExpression.putNodeMetaData(__ALIAS_EXPR, fromExpressionList.get(fromExpressionList.size() - 1).aliasExpr)
+ MethodCallExpression selectMethodCallExpression = this.visitSelectExpression(selectExpression)
+
+
+ return selectMethodCallExpression
+ }
+
+ @Override
+ MethodCallExpression visitFromExpression(FromExpression fromExpression) {
+ MethodCallExpression fromMethodCallExpression = constructFromMethodCallExpression(fromExpression)
+
+ WhereExpression whereExpression = fromExpression.getWhereExpression()
+ if (whereExpression) {
+ whereExpression.putNodeMetaData(__FROM_EXPRESSION, fromExpression)
+ whereExpression.putNodeMetaData(__FROM_METHOD_CALL_EXPRESSION, fromMethodCallExpression)
+
+ return visitWhereExpression(whereExpression)
+ }
+
+ return fromMethodCallExpression
+ }
+
+ @CompileDynamic
+ private MethodCallExpression constructFromMethodCallExpression(FromExpression fromExpression) {
+ macro {
+ org.apache.groovy.linq.provider.QueryableCollection
+ .from($v { fromExpression.dataSourceExpr })
+ }
+ }
+
+ @Override
+ MethodCallExpression visitWhereExpression(WhereExpression whereExpression) {
+ FromExpression fromExpression = whereExpression.getNodeMetaData(__FROM_EXPRESSION)
+ Expression fromMethodCallExpression = whereExpression.getNodeMetaData(__FROM_METHOD_CALL_EXPRESSION)
+ return callXWithLambda(fromMethodCallExpression, "where", fromExpression.aliasExpr.text, whereExpression.getFilterExpr())
+ }
+
+ @Override
+ MethodCallExpression visitSelectExpression(SelectExpression selectExpression) {
+ Expression selectMethodReceiver = selectExpression.getNodeMetaData(__SELECT_METHOD_RECEIVER)
+ Expression aliasExpr = selectExpression.getNodeMetaData(__ALIAS_EXPR)
+ return callXWithLambda(selectMethodReceiver, "select", aliasExpr.text, ((ArgumentListExpression) selectExpression.getProjectionExpr()).getExpression(0))
+ }
+
+ @Override
+ Object visit(GinqExpression expression) {
+ return expression.accept(this)
+ }
+
+ private static MethodCallExpression callXWithLambda(Expression receiver, String methodName, String lambdaParamName, Expression lambdaCode) {
+ callX(
+ receiver,
+ methodName,
+ lambdaX(
+ params(param(ClassHelper.DYNAMIC_TYPE, lambdaParamName)),
+ stmt(lambdaCode)
+ )
+ )
+ }
+
+ private static final String __FROM_EXPRESSION = "__fromExpression"
+ private static final String __FROM_METHOD_CALL_EXPRESSION = "__fromMethodCallExpression"
+ private static final String __SELECT_METHOD_RECEIVER = "__selectMethodReceiver"
+ private static final String __ALIAS_EXPR = "__aliasExpr"
+}
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/GinqVisitor.java b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/GinqVisitor.java
new file mode 100644
index 0000000..4e7c242
--- /dev/null
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/GinqVisitor.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.groovy.linq.dsl;
+
+import org.apache.groovy.linq.dsl.expression.FromExpression;
+import org.apache.groovy.linq.dsl.expression.GinqExpression;
+import org.apache.groovy.linq.dsl.expression.RootExpression;
+import org.apache.groovy.linq.dsl.expression.SelectExpression;
+import org.apache.groovy.linq.dsl.expression.WhereExpression;
+
+public interface GinqVisitor<R> {
+ R visitRootExpression(RootExpression rootExpression);
+ R visitFromExpression(FromExpression fromExpression);
+ R visitWhereExpression(WhereExpression whereExpression);
+ R visitSelectExpression(SelectExpression selectExpression);
+ R visit(GinqExpression expression);
+}
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/AbstractGinqExpression.java b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/AbstractGinqExpression.java
new file mode 100644
index 0000000..25e4e84
--- /dev/null
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/AbstractGinqExpression.java
@@ -0,0 +1,20 @@
+package org.apache.groovy.linq.dsl.expression;
+
+import org.codehaus.groovy.ast.NodeMetaDataHandler;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public abstract class AbstractGinqExpression implements GinqExpression, NodeMetaDataHandler {
+ private Map<?, ?> metaDataMap = new LinkedHashMap<>();
+
+ @Override
+ public Map<?, ?> getMetaDataMap() {
+ return metaDataMap;
+ }
+
+ @Override
+ public void setMetaDataMap(Map<?, ?> metaDataMap) {
+ this.metaDataMap = metaDataMap;
+ }
+}
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/FilterableExpression.java b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/FilterableExpression.java
new file mode 100644
index 0000000..d739e21
--- /dev/null
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/FilterableExpression.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.groovy.linq.dsl.expression;
+
+public abstract class FilterableExpression extends AbstractGinqExpression {
+ protected WhereExpression whereExpression;
+
+ public WhereExpression getWhereExpression() {
+ return whereExpression;
+ }
+
+ public void setWhereExpression(WhereExpression whereExpression) {
+ this.whereExpression = whereExpression;
+ }
+}
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/FromExpression.java b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/FromExpression.java
new file mode 100644
index 0000000..4c212e4
--- /dev/null
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/FromExpression.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.groovy.linq.dsl.expression;
+
+import org.apache.groovy.linq.dsl.GinqVisitor;
+import org.codehaus.groovy.ast.expr.Expression;
+
+public class FromExpression extends FilterableExpression {
+ private final Expression aliasExpr;
+ private final Expression dataSourceExpr;
+
+ public FromExpression(Expression aliasExpr, Expression dataSourceExpr) {
+ this.aliasExpr = aliasExpr;
+ this.dataSourceExpr = dataSourceExpr;
+ }
+
+ @Override
+ public <R> R accept(GinqVisitor<R> visitor) {
+ return visitor.visitFromExpression(this);
+ }
+
+ public Expression getAliasExpr() {
+ return aliasExpr;
+ }
+
+ public Expression getDataSourceExpr() {
+ return dataSourceExpr;
+ }
+
+ @Override
+ public String toString() {
+ return "FromExpression{" +
+ "aliasExpr=" + aliasExpr +
+ ", dataSourceExpr=" + dataSourceExpr +
+ ", whereExpression=" + whereExpression +
+ '}';
+ }
+}
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/GinqExpression.java b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/GinqExpression.java
new file mode 100644
index 0000000..22ef3ff
--- /dev/null
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/GinqExpression.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.groovy.linq.dsl.expression;
+
+import org.apache.groovy.linq.dsl.GinqVisitor;
+
+public interface GinqExpression {
+ <R> R accept(GinqVisitor<R> visitor);
+}
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/RootExpression.java b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/RootExpression.java
new file mode 100644
index 0000000..d4ddf0c
--- /dev/null
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/RootExpression.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.groovy.linq.dsl.expression;
+
+import org.apache.groovy.linq.dsl.GinqVisitor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RootExpression extends AbstractGinqExpression {
+ private List<FromExpression> fromExpressionList = new ArrayList<>();
+ private SelectExpression selectExpression;
+
+ @Override
+ public <R> R accept(GinqVisitor<R> visitor) {
+ return visitor.visitRootExpression(this);
+ }
+
+ public List<FromExpression> getFromExpressionList() {
+ return fromExpressionList;
+ }
+
+ public void addFromExpression(FromExpression fromExpression) {
+ this.fromExpressionList.add(fromExpression);
+ }
+
+ public SelectExpression getSelectExpression() {
+ return selectExpression;
+ }
+
+ public void setSelectExpression(SelectExpression selectExpression) {
+ this.selectExpression = selectExpression;
+ }
+
+ @Override
+ public String toString() {
+ return "RootExpression{" +
+ "fromExpressionList=" + fromExpressionList +
+ ", selectExpression=" + selectExpression +
+ '}';
+ }
+}
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/SelectExpression.java b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/SelectExpression.java
new file mode 100644
index 0000000..0cd3429
--- /dev/null
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/SelectExpression.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.groovy.linq.dsl.expression;
+
+import org.apache.groovy.linq.dsl.GinqVisitor;
+import org.codehaus.groovy.ast.expr.Expression;
+
+public class SelectExpression extends AbstractGinqExpression {
+ private final Expression projectionExpr;
+
+ public SelectExpression(Expression projectionExpr) {
+ this.projectionExpr = projectionExpr;
+ }
+
+ @Override
+ public <R> R accept(GinqVisitor<R> visitor) {
+ return visitor.visitSelectExpression(this);
+ }
+
+ public Expression getProjectionExpr() {
+ return projectionExpr;
+ }
+
+ @Override
+ public String toString() {
+ return "SelectExpression{" +
+ "projectionExpr=" + projectionExpr +
+ '}';
+ }
+}
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/WhereExpression.java b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/WhereExpression.java
new file mode 100644
index 0000000..b23ba94
--- /dev/null
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/dsl/expression/WhereExpression.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.groovy.linq.dsl.expression;
+
+import org.apache.groovy.linq.dsl.GinqVisitor;
+import org.codehaus.groovy.ast.expr.Expression;
+
+public class WhereExpression extends AbstractGinqExpression {
+ private final Expression filterExpr;
+
+ public WhereExpression(Expression filterExpr) {
+ this.filterExpr = filterExpr;
+ }
+
+ @Override
+ public <R> R accept(GinqVisitor<R> visitor) {
+ return visitor.visitWhereExpression(this);
+ }
+
+ public Expression getFilterExpr() {
+ return filterExpr;
+ }
+}