You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metamodel.apache.org by ka...@apache.org on 2013/07/22 10:10:56 UTC
[43/64] [partial] Hard rename of all 'org/eobjects' folders to
'org/apache'.
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/InitFromBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/InitFromBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/InitFromBuilder.java
new file mode 100644
index 0000000..fcbdbcf
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/InitFromBuilder.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.eobjects.metamodel.query.builder;
+
+import org.eobjects.metamodel.schema.Schema;
+import org.eobjects.metamodel.schema.Table;
+
+/**
+ * The initial interface used when building a query. A query starts by stating
+ * the FROM clause.
+ *
+ * @author Kasper Sørensen
+ */
+public interface InitFromBuilder {
+
+ public TableFromBuilder from(Table table);
+
+ public TableFromBuilder from(Schema schema, String tableName);
+
+ public TableFromBuilder from(String schemaName, String tableName);
+
+ public TableFromBuilder from(String tableName);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/InitFromBuilderImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/InitFromBuilderImpl.java b/core/src/main/java/org/apache/metamodel/query/builder/InitFromBuilderImpl.java
new file mode 100644
index 0000000..3d523a8
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/InitFromBuilderImpl.java
@@ -0,0 +1,89 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eobjects.metamodel.DataContext;
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.schema.Schema;
+import org.eobjects.metamodel.schema.Table;
+import org.eobjects.metamodel.util.BaseObject;
+
+public final class InitFromBuilderImpl extends BaseObject implements InitFromBuilder {
+
+ private DataContext dataContext;
+ private Query query;
+
+ public InitFromBuilderImpl(DataContext dataContext) {
+ this.dataContext = dataContext;
+ this.query = new Query();
+ }
+
+ @Override
+ public TableFromBuilder from(Table table) {
+ if (table == null) {
+ throw new IllegalArgumentException("table cannot be null");
+ }
+ return new TableFromBuilderImpl(table, query, dataContext);
+ }
+
+ @Override
+ public TableFromBuilder from(String schemaName, String tableName) {
+ if (schemaName == null) {
+ throw new IllegalArgumentException("schemaName cannot be null");
+ }
+ if (tableName == null) {
+ throw new IllegalArgumentException("tableName cannot be null");
+ }
+ Schema schema = dataContext.getSchemaByName(schemaName);
+ if (schema == null) {
+ schema = dataContext.getDefaultSchema();
+ }
+ return from(schema, tableName);
+ }
+
+ @Override
+ public TableFromBuilder from(Schema schema, String tableName) {
+ Table table = schema.getTableByName(tableName);
+ if (table == null) {
+ throw new IllegalArgumentException("Nu such table '" + tableName + "' found in schema: " + schema
+ + ". Available tables are: " + Arrays.toString(schema.getTableNames()));
+ }
+ return from(table);
+ }
+
+ @Override
+ public TableFromBuilder from(String tableName) {
+ if (tableName == null) {
+ throw new IllegalArgumentException("tableName cannot be null");
+ }
+ Table table = dataContext.getTableByQualifiedLabel(tableName);
+ if (table == null) {
+ throw new IllegalArgumentException("No such table: " + tableName);
+ }
+ return from(table);
+ }
+
+ @Override
+ protected void decorateIdentity(List<Object> identifiers) {
+ identifiers.add(query);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/JoinFromBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/JoinFromBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/JoinFromBuilder.java
new file mode 100644
index 0000000..1cad5fc
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/JoinFromBuilder.java
@@ -0,0 +1,26 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import org.eobjects.metamodel.schema.Column;
+
+public interface JoinFromBuilder extends SatisfiedFromBuilder {
+
+ public SatisfiedFromBuilder on(Column left, Column right);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/JoinFromBuilderImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/JoinFromBuilderImpl.java b/core/src/main/java/org/apache/metamodel/query/builder/JoinFromBuilderImpl.java
new file mode 100644
index 0000000..6e9520c
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/JoinFromBuilderImpl.java
@@ -0,0 +1,73 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import java.util.List;
+
+import org.eobjects.metamodel.DataContext;
+import org.eobjects.metamodel.query.FromItem;
+import org.eobjects.metamodel.query.JoinType;
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.query.SelectItem;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.Table;
+
+final class JoinFromBuilderImpl extends SatisfiedFromBuilderCallback implements
+ JoinFromBuilder {
+
+ private JoinType joinType;
+ private FromItem leftItem;
+ private FromItem rightItem;
+
+ public JoinFromBuilderImpl(Query query, FromItem leftItem,
+ Table rightTable, JoinType joinType, DataContext dataContext) {
+ super(query, dataContext);
+ this.joinType = joinType;
+ this.leftItem = leftItem;
+ this.rightItem = new FromItem(rightTable);
+ }
+
+ @Override
+ public SatisfiedFromBuilder on(Column left, Column right) {
+ if (left == null) {
+ throw new IllegalArgumentException("left cannot be null");
+ }
+ if (right == null) {
+ throw new IllegalArgumentException("right cannot be null");
+ }
+ getQuery().getFromClause().removeItem(leftItem);
+
+ SelectItem[] leftOn = new SelectItem[] { new SelectItem(left) };
+ SelectItem[] rightOn = new SelectItem[] { new SelectItem(right) };
+ FromItem fromItem = new FromItem(joinType, leftItem, rightItem, leftOn,
+ rightOn);
+
+ getQuery().from(fromItem);
+
+ return this;
+ }
+
+ @Override
+ protected void decorateIdentity(List<Object> identifiers) {
+ super.decorateIdentity(identifiers);
+ identifiers.add(joinType);
+ identifiers.add(leftItem);
+ identifiers.add(rightItem);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedFromBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedFromBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedFromBuilder.java
new file mode 100644
index 0000000..6cc2611
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedFromBuilder.java
@@ -0,0 +1,52 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import org.eobjects.metamodel.query.FunctionType;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.Table;
+
+/**
+ * Represents a builder where the FROM part is satisfied, ie. a SELECT clause is
+ * now buildable.
+ *
+ * @author Kasper Sørensen
+ */
+public interface SatisfiedFromBuilder {
+
+ public TableFromBuilder and(Table table);
+
+ public TableFromBuilder and(String schemaName, String tableName);
+
+ public TableFromBuilder and(String tableName);
+
+ public ColumnSelectBuilder<?> select(Column column);
+
+ public FunctionSelectBuilder<?> select(FunctionType functionType, Column column);
+
+ public CountSelectBuilder<?> selectCount();
+
+ public SatisfiedSelectBuilder<?> select(Column... columns);
+
+ public SatisfiedSelectBuilder<?> selectAll();
+
+ public ColumnSelectBuilder<?> select(String columnName);
+
+ public SatisfiedSelectBuilder<?> select(String... columnNames);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedFromBuilderCallback.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedFromBuilderCallback.java b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedFromBuilderCallback.java
new file mode 100644
index 0000000..d6798c2
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedFromBuilderCallback.java
@@ -0,0 +1,161 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import java.util.List;
+
+import org.eobjects.metamodel.DataContext;
+import org.eobjects.metamodel.query.FunctionType;
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.Schema;
+import org.eobjects.metamodel.schema.Table;
+import org.eobjects.metamodel.util.BaseObject;
+
+abstract class SatisfiedFromBuilderCallback extends BaseObject implements SatisfiedFromBuilder {
+
+ private Query query;
+ private DataContext dataContext;
+
+ public SatisfiedFromBuilderCallback(Query query, DataContext dataContext) {
+ this.query = query;
+ this.dataContext = dataContext;
+ }
+
+ protected Query getQuery() {
+ return query;
+ }
+
+ protected DataContext getDataContext() {
+ return dataContext;
+ }
+
+ @Override
+ public TableFromBuilder and(Table table) {
+ if (table == null) {
+ throw new IllegalArgumentException("table cannot be null");
+ }
+
+ return new TableFromBuilderImpl(table, query, dataContext);
+ }
+
+ @Override
+ public ColumnSelectBuilder<?> select(Column column) {
+ if (column == null) {
+ throw new IllegalArgumentException("column cannot be null");
+ }
+
+ GroupedQueryBuilder queryBuilder = new GroupedQueryBuilderImpl(dataContext, query);
+ return new ColumnSelectBuilderImpl(column, query, queryBuilder);
+ }
+
+ @Override
+ public SatisfiedSelectBuilder<?> selectAll() {
+ getQuery().selectAll();
+ GroupedQueryBuilder queryBuilder = new GroupedQueryBuilderImpl(dataContext, query);
+ return new SatisfiedSelectBuilderImpl(queryBuilder);
+ }
+
+ @Override
+ public FunctionSelectBuilder<?> select(FunctionType functionType, Column column) {
+ if (functionType == null) {
+ throw new IllegalArgumentException("functionType cannot be null");
+ }
+ if (column == null) {
+ throw new IllegalArgumentException("column cannot be null");
+ }
+
+ GroupedQueryBuilder queryBuilder = new GroupedQueryBuilderImpl(dataContext, query);
+ return new FunctionSelectBuilderImpl(functionType, column, query, queryBuilder);
+ }
+
+ @Override
+ public CountSelectBuilder<?> selectCount() {
+ GroupedQueryBuilder queryBuilder = new GroupedQueryBuilderImpl(dataContext, query);
+ return new CountSelectBuilderImpl(query, queryBuilder);
+ }
+
+ @Override
+ public TableFromBuilder and(String schemaName, String tableName) {
+ if (schemaName == null) {
+ throw new IllegalArgumentException("schemaName cannot be null");
+ }
+ if (tableName == null) {
+ throw new IllegalArgumentException("tableName cannot be null");
+ }
+
+ Schema schema = dataContext.getSchemaByName(schemaName);
+ if (schema == null) {
+ schema = dataContext.getDefaultSchema();
+ }
+ return and(schema, tableName);
+ }
+
+ private TableFromBuilder and(Schema schema, String tableName) {
+ Table table = schema.getTableByName(tableName);
+ return and(table);
+ }
+
+ @Override
+ public TableFromBuilder and(String tableName) {
+ if (tableName == null) {
+ throw new IllegalArgumentException("tableName cannot be null");
+ }
+ return and(dataContext.getDefaultSchema(), tableName);
+ }
+
+ @Override
+ public SatisfiedSelectBuilder<?> select(Column... columns) {
+ if (columns == null) {
+ throw new IllegalArgumentException("columns cannot be null");
+ }
+ query.select(columns);
+ GroupedQueryBuilder queryBuilder = new GroupedQueryBuilderImpl(dataContext, query);
+ return new SatisfiedSelectBuilderImpl(queryBuilder);
+ }
+
+ @Override
+ public SatisfiedSelectBuilder<?> select(String... columnNames) {
+ if (columnNames == null) {
+ throw new IllegalArgumentException("columnNames cannot be null");
+ }
+ for (String columnName : columnNames) {
+ select(columnName);
+ }
+ GroupedQueryBuilder queryBuilder = new GroupedQueryBuilderImpl(dataContext, query);
+ return new SatisfiedSelectBuilderImpl(queryBuilder);
+ }
+
+ @Override
+ public ColumnSelectBuilder<?> select(String columnName) {
+ if (columnName == null) {
+ throw new IllegalArgumentException("columnName cannot be null");
+ }
+
+ GroupedQueryBuilderImpl queryBuilder = new GroupedQueryBuilderImpl(dataContext, query);
+ Column column = queryBuilder.findColumn(columnName);
+ return select(column);
+ }
+
+ @Override
+ protected void decorateIdentity(List<Object> identifiers) {
+ identifiers.add(query);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedHavingBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedHavingBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedHavingBuilder.java
new file mode 100644
index 0000000..b5c6efe
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedHavingBuilder.java
@@ -0,0 +1,29 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import org.eobjects.metamodel.query.FunctionType;
+import org.eobjects.metamodel.schema.Column;
+
+public interface SatisfiedHavingBuilder extends GroupedQueryBuilder {
+
+ public HavingBuilder or(FunctionType functionType, Column column);
+
+ public HavingBuilder and(FunctionType functionType, Column column);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedOrderByBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedOrderByBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedOrderByBuilder.java
new file mode 100644
index 0000000..a7023cf
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedOrderByBuilder.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.eobjects.metamodel.query.builder;
+
+import org.eobjects.metamodel.schema.Column;
+
+public interface SatisfiedOrderByBuilder<B extends SatisfiedQueryBuilder<?>>
+ extends SatisfiedQueryBuilder<B> {
+
+ public B asc();
+
+ public B desc();
+
+ public SatisfiedOrderByBuilder<B> and(Column column);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedOrderByBuilderImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedOrderByBuilderImpl.java b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedOrderByBuilderImpl.java
new file mode 100644
index 0000000..5ebe755
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedOrderByBuilderImpl.java
@@ -0,0 +1,64 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import org.eobjects.metamodel.query.FunctionType;
+import org.eobjects.metamodel.query.OrderByItem;
+import org.eobjects.metamodel.query.OrderByItem.Direction;
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.query.SelectItem;
+import org.eobjects.metamodel.schema.Column;
+
+final class SatisfiedOrderByBuilderImpl extends GroupedQueryBuilderCallback
+ implements SatisfiedOrderByBuilder<GroupedQueryBuilder> {
+
+ private OrderByItem orderByitem;
+
+ public SatisfiedOrderByBuilderImpl(Column column, Query query,
+ GroupedQueryBuilder queryBuilder) {
+ super(queryBuilder);
+ orderByitem = new OrderByItem(new SelectItem(column));
+ query.orderBy(orderByitem);
+ }
+
+ public SatisfiedOrderByBuilderImpl(FunctionType function, Column column,
+ Query query, GroupedQueryBuilder queryBuilder) {
+ super(queryBuilder);
+ orderByitem = new OrderByItem(new SelectItem(function, column));
+ query.orderBy(orderByitem);
+ }
+
+ @Override
+ public GroupedQueryBuilder asc() {
+ orderByitem.setDirection(Direction.ASC);
+ return getQueryBuilder();
+ }
+
+ @Override
+ public GroupedQueryBuilder desc() {
+ orderByitem.setDirection(Direction.DESC);
+ return getQueryBuilder();
+ }
+
+ @Override
+ public SatisfiedOrderByBuilder<GroupedQueryBuilder> and(Column column) {
+ return getQueryBuilder().orderBy(column);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java
new file mode 100644
index 0000000..dd98935
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedQueryBuilder.java
@@ -0,0 +1,133 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import org.eobjects.metamodel.DataContext;
+import org.eobjects.metamodel.data.DataSet;
+import org.eobjects.metamodel.query.CompiledQuery;
+import org.eobjects.metamodel.query.FilterItem;
+import org.eobjects.metamodel.query.FunctionType;
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.schema.Column;
+
+/**
+ * Represents a built query that is satisfied and ready for querying or further
+ * building.
+ *
+ * @author Kasper Sørensen
+ *
+ * @param <B>
+ */
+public interface SatisfiedQueryBuilder<B extends SatisfiedQueryBuilder<?>> {
+
+ public ColumnSelectBuilder<B> select(Column column);
+
+ public SatisfiedSelectBuilder<B> select(Column... columns);
+
+ /**
+ * Sets the offset (number of rows to skip) of the query that is being
+ * built.
+ *
+ * Note that this number is a 0-based variant of invoking
+ * {@link #firstRow(int)}.
+ *
+ * @param offset
+ * the number of rows to skip
+ * @return
+ */
+ public SatisfiedQueryBuilder<B> offset(int offset);
+
+ /**
+ * Sets the first row of the query that is being built.
+ *
+ * Note that this is a 1-based variant of invoking {@link #limit(int)}.
+ *
+ * @param firstRow
+ * @return
+ */
+ public SatisfiedQueryBuilder<B> firstRow(int firstRow);
+
+ /**
+ * Sets the limit (aka. max rows) of the query that is being built.
+ *
+ * @param maxRows
+ * @return
+ */
+ public SatisfiedQueryBuilder<B> limit(int limit);
+
+ /**
+ * Sets the max rows (aka. limit) of the query that is being built.
+ *
+ * @param maxRows
+ * @return
+ */
+ public SatisfiedQueryBuilder<B> maxRows(int maxRows);
+
+ public FunctionSelectBuilder<B> select(FunctionType functionType, Column column);
+
+ public CountSelectBuilder<B> selectCount();
+
+ public ColumnSelectBuilder<B> select(String columnName);
+
+ public WhereBuilder<B> where(Column column);
+
+ public WhereBuilder<B> where(String columnName);
+
+ public SatisfiedQueryBuilder<B> where(FilterItem... filters);
+
+ public SatisfiedQueryBuilder<B> where(Iterable<FilterItem> filters);
+
+ public SatisfiedOrderByBuilder<B> orderBy(String columnName);
+
+ public SatisfiedOrderByBuilder<B> orderBy(Column column);
+
+ public GroupedQueryBuilder groupBy(String columnName);
+
+ public GroupedQueryBuilder groupBy(Column column);
+
+ public B groupBy(Column... columns);
+
+ /**
+ * Gets the built query as a {@link Query} object. Typically the returned
+ * query will be a clone of the built query to prevent conflicting
+ * mutations.
+ *
+ * @return a {@link Query} object representing the built query.
+ */
+ public Query toQuery();
+
+ public CompiledQuery compile();
+
+ /**
+ * Executes the built query. This call is similar to calling
+ * {@link #toQuery()} and then {@link DataContext#executeQuery(Query)}.
+ *
+ * @return the {@link DataSet} that is returned by executing the query.
+ */
+ public DataSet execute();
+
+ /**
+ * Finds a column by name within the already defined FROM items
+ *
+ * @param columnName
+ * @return
+ * @throws IllegalArgumentException
+ */
+ public Column findColumn(String columnName) throws IllegalArgumentException;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedSelectBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedSelectBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedSelectBuilder.java
new file mode 100644
index 0000000..886b763
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedSelectBuilder.java
@@ -0,0 +1,35 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import org.eobjects.metamodel.query.FunctionType;
+import org.eobjects.metamodel.schema.Column;
+
+public interface SatisfiedSelectBuilder<B extends SatisfiedQueryBuilder<?>>
+ extends SatisfiedQueryBuilder<B> {
+
+ public ColumnSelectBuilder<B> and(Column column);
+
+ public SatisfiedSelectBuilder<B> and(Column ... columns);
+
+ public FunctionSelectBuilder<B> and(FunctionType function,
+ Column column);
+
+ public SatisfiedSelectBuilder<B> and(String columnName);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedSelectBuilderImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedSelectBuilderImpl.java b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedSelectBuilderImpl.java
new file mode 100644
index 0000000..2fe66ce
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedSelectBuilderImpl.java
@@ -0,0 +1,67 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import org.eobjects.metamodel.query.FunctionType;
+import org.eobjects.metamodel.schema.Column;
+
+class SatisfiedSelectBuilderImpl extends GroupedQueryBuilderCallback implements
+ SatisfiedSelectBuilder<GroupedQueryBuilder> {
+
+ public SatisfiedSelectBuilderImpl(GroupedQueryBuilder queryBuilder) {
+ super(queryBuilder);
+ }
+
+ @Override
+ public ColumnSelectBuilder<GroupedQueryBuilder> and(Column column) {
+ if (column == null) {
+ throw new IllegalArgumentException("column cannot be null");
+ }
+ return getQueryBuilder().select(column);
+ }
+
+ @Override
+ public SatisfiedSelectBuilder<GroupedQueryBuilder> and(Column... columns) {
+ if (columns == null) {
+ throw new IllegalArgumentException("columns cannot be null");
+ }
+ return getQueryBuilder().select(columns);
+ }
+
+ @Override
+ public FunctionSelectBuilder<GroupedQueryBuilder> and(
+ FunctionType functionType, Column column) {
+ if (functionType == null) {
+ throw new IllegalArgumentException("functionType cannot be null");
+ }
+ if (column == null) {
+ throw new IllegalArgumentException("column cannot be null");
+ }
+ return getQueryBuilder().select(functionType, column);
+ }
+
+ @Override
+ public SatisfiedSelectBuilder<GroupedQueryBuilder> and(String columnName) {
+ if (columnName == null) {
+ throw new IllegalArgumentException("columnName cannot be null");
+ }
+ return getQueryBuilder().select(columnName);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedWhereBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedWhereBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedWhereBuilder.java
new file mode 100644
index 0000000..d236ed2
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/SatisfiedWhereBuilder.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.eobjects.metamodel.query.builder;
+
+import org.eobjects.metamodel.schema.Column;
+
+public interface SatisfiedWhereBuilder<B extends SatisfiedQueryBuilder<?>>
+ extends SatisfiedQueryBuilder<B> {
+
+ public WhereBuilder<B> or(String columnName);
+
+ public WhereBuilder<B> or(Column column);
+
+ public WhereBuilder<B> and(String columnName);
+
+ public WhereBuilder<B> and(Column column);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/TableFromBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/TableFromBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/TableFromBuilder.java
new file mode 100644
index 0000000..d030653
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/TableFromBuilder.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.eobjects.metamodel.query.builder;
+
+import org.eobjects.metamodel.schema.Table;
+
+public interface TableFromBuilder extends
+ SatisfiedFromBuilder {
+
+ public JoinFromBuilder innerJoin(Table table);
+
+ public JoinFromBuilder leftJoin(Table table);
+
+ public JoinFromBuilder rightJoin(Table table);
+
+ public TableFromBuilder as(String alias);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/TableFromBuilderImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/TableFromBuilderImpl.java b/core/src/main/java/org/apache/metamodel/query/builder/TableFromBuilderImpl.java
new file mode 100644
index 0000000..4460d8e
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/TableFromBuilderImpl.java
@@ -0,0 +1,83 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import java.util.List;
+
+import org.eobjects.metamodel.DataContext;
+import org.eobjects.metamodel.query.FromItem;
+import org.eobjects.metamodel.query.JoinType;
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.schema.Table;
+
+final class TableFromBuilderImpl extends SatisfiedFromBuilderCallback implements
+ TableFromBuilder {
+
+ private FromItem fromItem;
+
+ public TableFromBuilderImpl(Table table, Query query,
+ DataContext dataContext) {
+ super(query, dataContext);
+
+ fromItem = new FromItem(table);
+ query.from(fromItem);
+ }
+
+ @Override
+ public JoinFromBuilder innerJoin(Table table) {
+ if (table == null) {
+ throw new IllegalArgumentException("table cannot be null");
+ }
+ return new JoinFromBuilderImpl(getQuery(), fromItem, table,
+ JoinType.INNER, getDataContext());
+ }
+
+ @Override
+ public JoinFromBuilder leftJoin(Table table) {
+ if (table == null) {
+ throw new IllegalArgumentException("table cannot be null");
+ }
+ return new JoinFromBuilderImpl(getQuery(), fromItem, table,
+ JoinType.LEFT, getDataContext());
+ }
+
+ @Override
+ public JoinFromBuilder rightJoin(Table table) {
+ if (table == null) {
+ throw new IllegalArgumentException("table cannot be null");
+ }
+ return new JoinFromBuilderImpl(getQuery(), fromItem, table,
+ JoinType.RIGHT, getDataContext());
+ }
+
+ @Override
+ public TableFromBuilder as(String alias) {
+ if (alias == null) {
+ throw new IllegalArgumentException("alias cannot be null");
+ }
+ fromItem.setAlias(alias);
+ return this;
+ }
+
+ @Override
+ protected void decorateIdentity(List<Object> identifiers) {
+ super.decorateIdentity(identifiers);
+ identifiers.add(fromItem);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/WhereBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/WhereBuilder.java b/core/src/main/java/org/apache/metamodel/query/builder/WhereBuilder.java
new file mode 100644
index 0000000..3055214
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/WhereBuilder.java
@@ -0,0 +1,86 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import org.eobjects.metamodel.query.CompiledQuery;
+import org.eobjects.metamodel.query.QueryParameter;
+
+/**
+ * Builder interface for WHERE items.
+ *
+ * In addition to the {@link FilterBuilder}, the WHERE builder allows using
+ * {@link QueryParameter}s as operands in the generated filters.
+ *
+ * @param <B>
+ */
+public interface WhereBuilder<B extends SatisfiedQueryBuilder<?>> extends FilterBuilder<SatisfiedWhereBuilder<B>> {
+
+ /**
+ * Equals to a query parameter. Can be used with {@link CompiledQuery}
+ * objects.
+ */
+ public SatisfiedWhereBuilder<B> eq(QueryParameter queryParameter);
+
+ /**
+ * Equals to a query parameter. Can be used with {@link CompiledQuery}
+ * objects.
+ */
+ public SatisfiedWhereBuilder<B> isEquals(QueryParameter queryParameter);
+
+ /**
+ * Not equals to a query parameter. Can be used with {@link CompiledQuery}
+ * objects.
+ */
+ public SatisfiedWhereBuilder<B> differentFrom(QueryParameter queryParameter);
+
+ /**
+ * Not equals to a query parameter. Can be used with {@link CompiledQuery}
+ * objects.
+ */
+ public SatisfiedWhereBuilder<B> ne(QueryParameter queryParameter);
+
+ /**
+ * Greater than a query parameter. Can be used with {@link CompiledQuery}
+ * objects.
+ */
+ public SatisfiedWhereBuilder<B> greaterThan(QueryParameter queryParameter);
+
+ /**
+ * Greater than a query parameter. Can be used with {@link CompiledQuery}
+ * objects.
+ */
+ public SatisfiedWhereBuilder<B> gt(QueryParameter queryParameter);
+
+ /**
+ * Less than a query parameter. Can be used with {@link CompiledQuery}
+ * objects.
+ */
+ public SatisfiedWhereBuilder<B> lessThan(QueryParameter queryParameter);
+
+ /**
+ * Less than a query parameter. Can be used with {@link CompiledQuery}
+ * objects.
+ */
+ public SatisfiedWhereBuilder<B> lt(QueryParameter queryParameter);
+
+ /**
+ * Like a query parameter. Can be used with {@link CompiledQuery} objects.
+ */
+ public SatisfiedWhereBuilder<B> like(QueryParameter queryParameter);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/WhereBuilderImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/WhereBuilderImpl.java b/core/src/main/java/org/apache/metamodel/query/builder/WhereBuilderImpl.java
new file mode 100644
index 0000000..7e1db14
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/WhereBuilderImpl.java
@@ -0,0 +1,151 @@
+/**
+ * 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.eobjects.metamodel.query.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eobjects.metamodel.query.FilterItem;
+import org.eobjects.metamodel.query.OperatorType;
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.query.QueryParameter;
+import org.eobjects.metamodel.query.SelectItem;
+import org.eobjects.metamodel.schema.Column;
+
+final class WhereBuilderImpl extends AbstractQueryFilterBuilder<SatisfiedWhereBuilder<GroupedQueryBuilder>> implements
+ WhereBuilder<GroupedQueryBuilder>, SatisfiedWhereBuilder<GroupedQueryBuilder> {
+
+ private final Query _query;
+ private final List<FilterItem> _orFilters;
+ private FilterItem _parentOrFilter;
+
+ public WhereBuilderImpl(Column column, Query query, GroupedQueryBuilder queryBuilder) {
+ super(new SelectItem(column), queryBuilder);
+ _query = query;
+ _orFilters = new ArrayList<FilterItem>();
+ }
+
+ public WhereBuilderImpl(Column column, Query query, FilterItem parentOrFilter, List<FilterItem> orFilters,
+ GroupedQueryBuilder queryBuilder) {
+ super(new SelectItem(column), queryBuilder);
+ _query = query;
+ _parentOrFilter = parentOrFilter;
+ _orFilters = orFilters;
+ }
+
+ @Override
+ protected SatisfiedWhereBuilder<GroupedQueryBuilder> applyFilter(FilterItem filter) {
+ if (_parentOrFilter == null) {
+ _query.where(filter);
+ } else {
+ if (_parentOrFilter.getChildItemCount() == 1) {
+ _query.getWhereClause().removeItem(_orFilters.get(0));
+ _query.getWhereClause().addItem(_parentOrFilter);
+ }
+ }
+ _orFilters.add(filter);
+ return this;
+ }
+
+ @Override
+ public WhereBuilder<GroupedQueryBuilder> or(String columnName) {
+ Column column = findColumn(columnName);
+ return or(column);
+ }
+
+ @Override
+ public WhereBuilder<GroupedQueryBuilder> or(Column column) {
+ if (_parentOrFilter == null) {
+ _parentOrFilter = new FilterItem(_orFilters);
+ }
+ return new WhereBuilderImpl(column, _query, _parentOrFilter, _orFilters, getQueryBuilder());
+ }
+
+ @Override
+ public WhereBuilder<GroupedQueryBuilder> and(String columnName) {
+ Column column = findColumn(columnName);
+ return and(column);
+ }
+
+ @Override
+ public WhereBuilder<GroupedQueryBuilder> and(Column column) {
+ return getQueryBuilder().where(column);
+ }
+
+ @Override
+ public SatisfiedWhereBuilder<GroupedQueryBuilder> eq(QueryParameter queryParameter) {
+ return isEquals(queryParameter);
+ }
+
+ @Override
+ public SatisfiedWhereBuilder<GroupedQueryBuilder> isEquals(QueryParameter queryParameter) {
+ if (queryParameter == null) {
+ throw new IllegalArgumentException("query parameter cannot be null");
+ }
+ return _filterBuilder.applyFilter(OperatorType.EQUALS_TO, queryParameter);
+ }
+
+ @Override
+ public SatisfiedWhereBuilder<GroupedQueryBuilder> differentFrom(QueryParameter queryParameter) {
+ return ne(queryParameter);
+ }
+
+ @Override
+ public SatisfiedWhereBuilder<GroupedQueryBuilder> ne(QueryParameter queryParameter) {
+ if (queryParameter == null) {
+ throw new IllegalArgumentException("query parameter cannot be null");
+ }
+ return _filterBuilder.applyFilter(OperatorType.DIFFERENT_FROM, queryParameter);
+ }
+
+ @Override
+ public SatisfiedWhereBuilder<GroupedQueryBuilder> greaterThan(QueryParameter queryParameter) {
+ return gt(queryParameter);
+ }
+
+ @Override
+ public SatisfiedWhereBuilder<GroupedQueryBuilder> gt(QueryParameter queryParameter) {
+ if (queryParameter == null) {
+ throw new IllegalArgumentException("query parameter cannot be null");
+ }
+ return _filterBuilder.applyFilter(OperatorType.GREATER_THAN, queryParameter);
+ }
+
+ @Override
+ public SatisfiedWhereBuilder<GroupedQueryBuilder> lessThan(QueryParameter queryParameter) {
+ return lt(queryParameter);
+ }
+
+ @Override
+ public SatisfiedWhereBuilder<GroupedQueryBuilder> lt(QueryParameter queryParameter) {
+ if (queryParameter == null) {
+ throw new IllegalArgumentException("query parameter cannot be null");
+ }
+ return _filterBuilder.applyFilter(OperatorType.LESS_THAN, queryParameter);
+ }
+
+ @Override
+ public SatisfiedWhereBuilder<GroupedQueryBuilder> like(QueryParameter queryParameter) {
+ if (queryParameter == null) {
+ throw new IllegalArgumentException("query parameter cannot be null");
+ }
+ return _filterBuilder.applyFilter(OperatorType.LIKE, queryParameter);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/builder/package-info.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/builder/package-info.java b/core/src/main/java/org/apache/metamodel/query/builder/package-info.java
new file mode 100644
index 0000000..87e58db
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/builder/package-info.java
@@ -0,0 +1,23 @@
+/**
+ * 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.
+ */
+/**
+ * API for query building
+ */
+package org.eobjects.metamodel.query.builder;
+
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/package-info.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/package-info.java b/core/src/main/java/org/apache/metamodel/query/package-info.java
new file mode 100644
index 0000000..f71ce82
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/package-info.java
@@ -0,0 +1,23 @@
+/**
+ * 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.
+ */
+/**
+ * API for querying
+ */
+package org.eobjects.metamodel.query;
+
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/parser/FromItemParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/parser/FromItemParser.java b/core/src/main/java/org/apache/metamodel/query/parser/FromItemParser.java
new file mode 100644
index 0000000..78fff2e
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/parser/FromItemParser.java
@@ -0,0 +1,173 @@
+/**
+ * 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.eobjects.metamodel.query.parser;
+
+import org.eobjects.metamodel.DataContext;
+import org.eobjects.metamodel.query.FromItem;
+import org.eobjects.metamodel.query.JoinType;
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.query.SelectItem;
+import org.eobjects.metamodel.schema.Table;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class FromItemParser implements QueryPartProcessor {
+
+ private static final Logger logger = LoggerFactory.getLogger(FromItemParser.class);
+
+ private final Query _query;
+ private final DataContext _dataContext;
+
+ public FromItemParser(DataContext dataContext, Query query) {
+ _dataContext = dataContext;
+ _query = query;
+ }
+
+ @Override
+ public void parse(String delim, String itemToken) {
+ final FromItem fromItem;
+
+ final int parenthesisStart = itemToken.indexOf('(');
+ if (parenthesisStart != -1) {
+ if (parenthesisStart != 0) {
+ throw new QueryParserException("Not capable of parsing FROM token: " + itemToken
+ + ". Expected parenthesis to start at first character.");
+ }
+ final int parenthesisEnd = itemToken.indexOf(')', parenthesisStart);
+ if (parenthesisEnd == -1) {
+ throw new QueryParserException("Not capable of parsing FROM token: " + itemToken
+ + ". Expected end parenthesis.");
+ }
+
+ final String subQueryString = itemToken.substring(parenthesisStart + 1, parenthesisEnd);
+ logger.debug("Parsing sub-query: {}", subQueryString);
+
+ final Query subQuery = new QueryParser(_dataContext, subQueryString).parse();
+ fromItem = new FromItem(subQuery);
+
+ final String alias = itemToken.substring(parenthesisEnd + 1).trim();
+ if (!alias.isEmpty()) {
+ fromItem.setAlias(alias);
+ }
+ } else if (itemToken.toUpperCase().indexOf(" JOIN ") != -1) {
+ fromItem = parseJoinItem(itemToken);
+ } else {
+ fromItem = parseTableItem(itemToken);
+ }
+
+ _query.from(fromItem);
+ }
+
+ private FromItem parseTableItem(String itemToken) {
+ final String[] tokens = itemToken.split(" ");
+ final String alias;
+ if (tokens.length == 2) {
+ alias = tokens[1];
+ } else if (tokens.length == 1) {
+ alias = null;
+ } else {
+ throw new QueryParserException("Not capable of parsing FROM token: " + itemToken);
+ }
+
+ final Table table = _dataContext.getTableByQualifiedLabel(tokens[0]);
+ if (table == null) {
+ throw new QueryParserException("Not capable of parsing FROM token: " + itemToken);
+ }
+
+ final FromItem result = new FromItem(table);
+ result.setAlias(alias);
+ result.setQuery(_query);
+ return result;
+ }
+
+ // this method will be documented based on this example itemToken: FOO f
+ // INNER JOIN BAR b ON f.id = b.id
+ private FromItem parseJoinItem(final String itemToken) {
+ final int indexOfJoin = itemToken.toUpperCase().indexOf(" JOIN ");
+
+ // firstPart = "FOO f INNER"
+ final String firstPart = itemToken.substring(0, indexOfJoin).trim();
+
+ // secondPart = "BAR b ON f.id = b.id"
+ final String secondPart = itemToken.substring(indexOfJoin + " JOIN ".length()).trim();
+
+ final int indexOfJoinType = firstPart.lastIndexOf(" ");
+
+ // joinTypeString = "INNER"
+ final String joinTypeString = firstPart.substring(indexOfJoinType).trim().toUpperCase();
+ final JoinType joinType = JoinType.valueOf(joinTypeString);
+
+ // firstTableToken = "FOO f"
+ final String firstTableToken = firstPart.substring(0, indexOfJoinType).trim();
+
+ final int indexOfOn = secondPart.toUpperCase().indexOf(" ON ");
+
+ // secondTableToken = "BAR b"
+ final String secondTableToken = secondPart.substring(0, indexOfOn).trim();
+
+ final FromItem leftSide = parseTableItem(firstTableToken);
+ final FromItem rightSide = parseTableItem(secondTableToken);
+
+ // onClausess = ["f.id = b.id"]
+ final String[] onClauses = secondPart.substring(indexOfOn + " ON ".length()).split(" AND ");
+ final SelectItem[] leftOn = new SelectItem[onClauses.length];
+ final SelectItem[] rightOn = new SelectItem[onClauses.length];
+ for (int i = 0; i < onClauses.length; i++) {
+ final String onClause = onClauses[i];
+ final int indexOfEquals = onClause.indexOf("=");
+ // leftPart = "f.id"
+ final String leftPart = onClause.substring(0, indexOfEquals).trim();
+ // rightPart = "b.id"
+ final String rightPart = onClause.substring(indexOfEquals + 1).trim();
+
+ leftOn[i] = findSelectItem(leftPart, leftSide, rightSide);
+ rightOn[i] = findSelectItem(rightPart, leftSide, rightSide);
+ }
+
+ final FromItem result = new FromItem(joinType, leftSide, rightSide, leftOn, rightOn);
+ result.setQuery(_query);
+ return result;
+ }
+
+ private SelectItem findSelectItem(String token, FromItem leftSide, FromItem rightSide) {
+ // first look in the original query
+ SelectItemParser selectItemParser = new SelectItemParser(_query, false);
+ SelectItem result = selectItemParser.findSelectItem(token);
+
+ if (result == null) {
+ // fail over and try with the from items available in the join that
+ // is being built.
+ final Query temporaryQuery = new Query().from(leftSide, rightSide);
+ selectItemParser = new SelectItemParser(temporaryQuery, false);
+ result = selectItemParser.findSelectItem(token);
+
+ if (result == null) {
+ throw new QueryParserException("Not capable of parsing ON token: " + token);
+ }
+
+ // set the query on the involved query parts (since they have been
+ // temporarily moved to the searched query).
+ leftSide.setQuery(_query);
+ rightSide.setQuery(_query);
+ result.setQuery(_query);
+ }
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/parser/GroupByItemParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/parser/GroupByItemParser.java b/core/src/main/java/org/apache/metamodel/query/parser/GroupByItemParser.java
new file mode 100644
index 0000000..fc7e776
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/parser/GroupByItemParser.java
@@ -0,0 +1,36 @@
+/**
+ * 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.eobjects.metamodel.query.parser;
+
+import org.eobjects.metamodel.query.Query;
+
+final class GroupByItemParser implements QueryPartProcessor {
+
+ private final Query _query;
+
+ public GroupByItemParser(Query query) {
+ _query = query;
+ }
+
+ @Override
+ public void parse(String delim, String itemToken) {
+ _query.groupBy(itemToken);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/parser/HavingItemParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/parser/HavingItemParser.java b/core/src/main/java/org/apache/metamodel/query/parser/HavingItemParser.java
new file mode 100644
index 0000000..5f4a559
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/parser/HavingItemParser.java
@@ -0,0 +1,36 @@
+/**
+ * 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.eobjects.metamodel.query.parser;
+
+import org.eobjects.metamodel.query.Query;
+
+final class HavingItemParser implements QueryPartProcessor {
+
+ private final Query _query;
+
+ public HavingItemParser(Query query) {
+ _query = query;
+ }
+
+ @Override
+ public void parse(String delim, String itemToken) {
+ _query.having(itemToken);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/parser/OrderByItemParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/parser/OrderByItemParser.java b/core/src/main/java/org/apache/metamodel/query/parser/OrderByItemParser.java
new file mode 100644
index 0000000..8c3ebf0
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/parser/OrderByItemParser.java
@@ -0,0 +1,36 @@
+/**
+ * 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.eobjects.metamodel.query.parser;
+
+import org.eobjects.metamodel.query.Query;
+
+final class OrderByItemParser implements QueryPartProcessor {
+
+ private final Query _query;
+
+ public OrderByItemParser(Query query) {
+ _query = query;
+ }
+
+ @Override
+ public void parse(String delim, String itemToken) {
+ _query.orderBy(itemToken);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/parser/QueryParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/parser/QueryParser.java b/core/src/main/java/org/apache/metamodel/query/parser/QueryParser.java
new file mode 100644
index 0000000..a5f0e03
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/parser/QueryParser.java
@@ -0,0 +1,264 @@
+/**
+ * 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.eobjects.metamodel.query.parser;
+
+import org.eobjects.metamodel.DataContext;
+import org.eobjects.metamodel.query.Query;
+
+/**
+ * A parser class of for full SQL-like queries.
+ */
+public class QueryParser {
+
+ private final DataContext _dataContext;
+ private final String _queryString;
+ private final String _queryStringUpperCase;
+
+ public QueryParser(DataContext dataContext, String queryString) {
+ if (dataContext == null) {
+ throw new IllegalArgumentException("DataContext cannot be null");
+ }
+ if (queryString == null) {
+ throw new IllegalArgumentException("Query string cannot be null");
+ }
+ _dataContext = dataContext;
+ _queryString = prepareQuery(queryString);
+ _queryStringUpperCase = _queryString.toUpperCase();
+ }
+
+ /**
+ * Performs any preparations (not changing any semantics) to the query
+ * string
+ *
+ * @param queryString
+ * @return
+ */
+ private String prepareQuery(String queryString) {
+ queryString = queryString.replaceAll("[\n\r\t]", " ");
+ queryString = queryString.replaceAll(" ", " ");
+ queryString = queryString.trim();
+ return queryString;
+ }
+
+ public Query parse() throws QueryParserException {
+ final Query query = new Query();
+
+ // collect focal point query clauses
+ int[] selectIndices = indexesOf("SELECT ", null);
+ int[] fromIndices = indexesOf(" FROM ", selectIndices);
+ int[] whereIndices = indexesOf(" WHERE ", fromIndices);
+ int[] groupByIndices = indexesOf(" GROUP BY ", whereIndices);
+ int[] havingIndices = indexesOf(" HAVING ", groupByIndices);
+ int[] orderByIndices = indexesOf(" ORDER BY", havingIndices);
+ int[] limitIndices = indexesOf(" LIMIT ", orderByIndices);
+ int[] offsetIndices = indexesOf(" OFFSET ", limitIndices);
+
+ // a few validations, minimum requirements
+ if (selectIndices == null) {
+ throw new QueryParserException("SELECT not found in query: " + _queryString);
+ }
+ if (fromIndices == null) {
+ throw new QueryParserException("FROM not found in query: " + _queryString);
+ }
+
+ // parse FROM
+ {
+ final String fromClause = getSubstring(
+ getLastEndIndex(fromIndices),
+ getNextStartIndex(whereIndices, groupByIndices, havingIndices, orderByIndices, limitIndices,
+ offsetIndices));
+ parseFromClause(query, fromClause);
+ }
+
+ {
+ String selectClause = getSubstring(getLastEndIndex(selectIndices), fromIndices[0]);
+ if (selectClause.startsWith("DISTINCT ")) {
+ query.selectDistinct();
+ selectClause = selectClause.substring("DISTINCT ".length());
+ }
+ parseSelectClause(query, selectClause);
+ }
+
+ if (whereIndices != null) {
+ final String whereClause = getSubstring(getLastEndIndex(whereIndices),
+ getNextStartIndex(groupByIndices, havingIndices, orderByIndices, limitIndices, offsetIndices));
+ if (whereClause != null) {
+ parseWhereClause(query, whereClause);
+ }
+ }
+
+ if (groupByIndices != null) {
+ final String groupByClause = getSubstring(getLastEndIndex(groupByIndices, whereIndices),
+ getNextStartIndex(havingIndices, orderByIndices, limitIndices, offsetIndices));
+ if (groupByClause != null) {
+ parseGroupByClause(query, groupByClause);
+ }
+ }
+
+ if (havingIndices != null) {
+ final String havingClause = getSubstring(
+ getLastEndIndex(havingIndices, groupByIndices, whereIndices, fromIndices, selectIndices),
+ getNextStartIndex(orderByIndices, limitIndices, offsetIndices));
+ if (havingClause != null) {
+ parseHavingClause(query, havingClause);
+ }
+ }
+
+ if (orderByIndices != null) {
+ final String orderByClause = getSubstring(
+ getLastEndIndex(orderByIndices, havingIndices, groupByIndices, whereIndices, fromIndices,
+ selectIndices), getNextStartIndex(limitIndices, offsetIndices));
+ if (orderByClause != null) {
+ parseOrderByClause(query, orderByClause);
+ }
+ }
+
+ if (limitIndices != null) {
+ final String limitClause = getSubstring(
+ getLastEndIndex(limitIndices, orderByIndices, havingIndices, groupByIndices, whereIndices,
+ fromIndices, selectIndices), getNextStartIndex(offsetIndices));
+ if (limitClause != null) {
+ parseLimitClause(query, limitClause);
+ }
+ }
+
+ if (offsetIndices != null) {
+ final String offsetClause = getSubstring(
+ getLastEndIndex(offsetIndices, limitIndices, orderByIndices, havingIndices, groupByIndices,
+ whereIndices, fromIndices, selectIndices), getNextStartIndex());
+ if (offsetClause != null) {
+ parseOffsetClause(query, offsetClause);
+ }
+ }
+
+ return query;
+ }
+
+ private void parseFromClause(Query query, String fromClause) {
+ QueryPartParser clauseParser = new QueryPartParser(new FromItemParser(_dataContext, query), fromClause, ",");
+ clauseParser.parse();
+ }
+
+ private void parseSelectClause(Query query, String selectClause) {
+ QueryPartParser clauseParser = new QueryPartParser(new SelectItemParser(query, false), selectClause, ",");
+ clauseParser.parse();
+ }
+
+ private void parseWhereClause(Query query, String whereClause) {
+ // only parse "AND" delimitors, since "OR" will be taken care of as
+ // compound filter items at 2nd level parsing
+ QueryPartParser clauseParser = new QueryPartParser(new WhereItemParser(query), whereClause, " AND ");
+ clauseParser.parse();
+ }
+
+ private void parseGroupByClause(Query query, String groupByClause) {
+ QueryPartParser clauseParser = new QueryPartParser(new GroupByItemParser(query), groupByClause, ",");
+ clauseParser.parse();
+ }
+
+ private void parseHavingClause(Query query, String havingClause) {
+ // only parse "AND" delimitors, since "OR" will be taken care of as
+ // compound filter items at 2nd level parsing
+ QueryPartParser clauseParser = new QueryPartParser(new HavingItemParser(query), havingClause, " AND ");
+ clauseParser.parse();
+ }
+
+ private void parseOrderByClause(Query query, String orderByClause) {
+ QueryPartParser clauseParser = new QueryPartParser(new OrderByItemParser(query), orderByClause, ",");
+ clauseParser.parse();
+ }
+
+ private void parseLimitClause(Query query, String limitClause) {
+ limitClause = limitClause.trim();
+ if (!limitClause.isEmpty()) {
+ try {
+ int limit = Integer.parseInt(limitClause);
+ query.setMaxRows(limit);
+ } catch (NumberFormatException e) {
+ throw new QueryParserException("Could not parse LIMIT value: " + limitClause);
+ }
+ }
+ }
+
+ private void parseOffsetClause(Query query, String offsetClause) {
+ offsetClause = offsetClause.trim();
+ if (!offsetClause.isEmpty()) {
+ try {
+ final int offset = Integer.parseInt(offsetClause);
+ // ofset is 0-based, but first-row is 1-based
+ final int firstRow = offset + 1;
+ query.setFirstRow(firstRow);
+ } catch (NumberFormatException e) {
+ throw new QueryParserException("Could not parse OFFSET value: " + offsetClause);
+ }
+ }
+ }
+
+ private String getSubstring(Integer from, int to) {
+ if (from == null) {
+ return null;
+ }
+ if (from.intValue() == to) {
+ return null;
+ }
+ return _queryString.substring(from, to);
+ }
+
+ private int getNextStartIndex(int[]... indicesArray) {
+ for (int[] indices : indicesArray) {
+ if (indices != null) {
+ return indices[0];
+ }
+ }
+ return _queryString.length();
+ }
+
+ private Integer getLastEndIndex(int[]... indicesArray) {
+ for (int[] indices : indicesArray) {
+ if (indices != null) {
+ return indices[1];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Finds the start and end indexes of a string in the query. The string
+ * parameter of this method is expected to be in upper case, while the query
+ * itself is tolerant of case differences.
+ *
+ * @param string
+ * @param previousIndices
+ * @return
+ */
+ protected int[] indexesOf(String string, int[] previousIndices) {
+ final int startIndex;
+ if (previousIndices == null) {
+ startIndex = _queryStringUpperCase.indexOf(string);
+ } else {
+ startIndex = _queryStringUpperCase.indexOf(string, previousIndices[1]);
+ }
+ if (startIndex == -1) {
+ return null;
+ }
+ int endIndex = startIndex + string.length();
+ return new int[] { startIndex, endIndex };
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/parser/QueryParserException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/parser/QueryParserException.java b/core/src/main/java/org/apache/metamodel/query/parser/QueryParserException.java
new file mode 100644
index 0000000..ad3f42c
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/parser/QueryParserException.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.eobjects.metamodel.query.parser;
+
+import org.eobjects.metamodel.MetaModelException;
+
+/**
+ * Subtype of {@link MetaModelException} which indicate a problem in parsing a
+ * query passed to the {@link QueryParser}.
+ */
+public class QueryParserException extends MetaModelException {
+
+ private static final long serialVersionUID = 1L;
+
+ public QueryParserException() {
+ super();
+ }
+
+ public QueryParserException(Exception cause) {
+ super(cause);
+ }
+
+ public QueryParserException(String message, Exception cause) {
+ super(message, cause);
+ }
+
+ public QueryParserException(String message) {
+ super(message);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/parser/QueryPartCollectionProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/parser/QueryPartCollectionProcessor.java b/core/src/main/java/org/apache/metamodel/query/parser/QueryPartCollectionProcessor.java
new file mode 100644
index 0000000..ac45a49
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/parser/QueryPartCollectionProcessor.java
@@ -0,0 +1,52 @@
+/**
+ * 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.eobjects.metamodel.query.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Simple implementation of {@link QueryPartProcessor} which simply adds all
+ * elements to a collection. Use {@link #getTokens()} to retrieve the 'processed'
+ * tokens and {@link #getDelims()} for the corresponding delimitors.
+ */
+public class QueryPartCollectionProcessor implements QueryPartProcessor {
+
+ private final List<String> _delims;
+ private final List<String> _tokens;
+
+ public QueryPartCollectionProcessor() {
+ _tokens = new ArrayList<String>();
+ _delims = new ArrayList<String>();
+ }
+
+ @Override
+ public void parse(String delim, String token) {
+ _delims.add(delim);
+ _tokens.add(token);
+ }
+
+ public List<String> getDelims() {
+ return _delims;
+ }
+
+ public List<String> getTokens() {
+ return _tokens;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/core/src/main/java/org/apache/metamodel/query/parser/QueryPartParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/metamodel/query/parser/QueryPartParser.java b/core/src/main/java/org/apache/metamodel/query/parser/QueryPartParser.java
new file mode 100644
index 0000000..15050ea
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/query/parser/QueryPartParser.java
@@ -0,0 +1,126 @@
+/**
+ * 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.eobjects.metamodel.query.parser;
+
+/**
+ * Parser of query parts. This parser is aware of parenthesis symbols '(' and
+ * ')' and only yields tokens that have balanced parentheses. Delimitors are
+ * configurable.
+ */
+public final class QueryPartParser {
+
+ private final QueryPartProcessor _processor;
+ private final String _clause;
+ private final String[] _ItemDelims;
+
+ public QueryPartParser(QueryPartProcessor processor, String clause, String... itemDelims) {
+ if (clause == null) {
+ throw new IllegalArgumentException("Clause cannot be null");
+ }
+ if (itemDelims == null || itemDelims.length == 0) {
+ throw new IllegalArgumentException("Item delimitors cannot be null or empty");
+ }
+ _processor = processor;
+ _clause = clause;
+ _ItemDelims = itemDelims;
+ }
+
+ public void parse() {
+ if (_clause.isEmpty()) {
+ return;
+ }
+
+ int parenthesisCount = 0;
+ int offset = 0;
+ boolean singleOuterParenthesis = _clause.charAt(0) == '(' && _clause.charAt(_clause.length() - 1) == ')';
+
+ String previousDelim = null;
+ DelimOccurrence nextDelimOccurrence = getNextDelim(0);
+ if (nextDelimOccurrence != null) {
+ for (int i = 0; i < _clause.length(); i++) {
+ char c = _clause.charAt(i);
+ if (c == '(') {
+ parenthesisCount++;
+ } else if (c == ')') {
+ parenthesisCount--;
+ if (singleOuterParenthesis && parenthesisCount == 0 && i != _clause.length() - 1) {
+ singleOuterParenthesis = false;
+ }
+ }
+ if (i == nextDelimOccurrence.index) {
+ if (parenthesisCount == 0) {
+ // token bounds has been identified
+ String itemToken = _clause.substring(offset, i);
+ parseItem(previousDelim, itemToken);
+ offset = i + nextDelimOccurrence.delim.length();
+ previousDelim = nextDelimOccurrence.delim;
+ }
+ nextDelimOccurrence = getNextDelim(nextDelimOccurrence.index + 1);
+ if (nextDelimOccurrence == null) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (singleOuterParenthesis) {
+ String newClause = _clause.substring(1, _clause.length() - 1);
+ // re-run based on new clause
+ QueryPartParser newParser = new QueryPartParser(_processor, newClause, _ItemDelims);
+ newParser.parse();
+ return;
+ }
+
+ // last token will occur outside loop
+ if (offset != _clause.length()) {
+ final String token = _clause.substring(offset);
+ parseItem(previousDelim, token);
+ }
+ }
+
+ private static class DelimOccurrence {
+ public int index;
+ public String delim;
+ }
+
+ private DelimOccurrence getNextDelim(int offset) {
+ DelimOccurrence result = null;
+ for (int i = 0; i < _ItemDelims.length; i++) {
+ String delim = _ItemDelims[i];
+ int index = _clause.indexOf(delim, offset);
+ if (index != -1) {
+ if (result == null || index == Math.min(result.index, index)) {
+ result = new DelimOccurrence();
+ result.index = index;
+ result.delim = delim;
+ }
+ }
+ }
+ return result;
+ }
+
+ private void parseItem(String delim, String token) {
+ if (token != null) {
+ token = token.trim();
+ if (!token.isEmpty()) {
+ _processor.parse(delim, token);
+ }
+ }
+ }
+}