You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by th...@apache.org on 2013/06/27 10:39:08 UTC
[08/11] DELTASPIKE-60 Data module initial import
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryBuilder.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryBuilder.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryBuilder.java
new file mode 100644
index 0000000..5743ca3
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryBuilder.java
@@ -0,0 +1,121 @@
+/*
+ * 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.deltaspike.data.impl.builder;
+
+import java.lang.reflect.Method;
+import java.text.MessageFormat;
+import java.util.List;
+
+import javax.persistence.LockModeType;
+import javax.persistence.Query;
+import javax.persistence.QueryHint;
+
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+import org.apache.deltaspike.data.impl.param.Parameters;
+
+/**
+ * Query builder factory. Delegates to concrete implementations.
+ *
+ * @author thomashug
+ */
+public abstract class QueryBuilder
+{
+
+ public static final String QUERY_SELECT = "select e from {0} e";
+ public static final String QUERY_COUNT = "select count(e) from {0} e";
+ public static final String ENTITY_NAME = "e";
+
+ public static String selectQuery(String entityName)
+ {
+ return MessageFormat.format(QUERY_SELECT, entityName);
+ }
+
+ public static String countQuery(String entityName)
+ {
+ return MessageFormat.format(QUERY_COUNT, entityName);
+ }
+
+ public abstract Object execute(CdiQueryInvocationContext ctx);
+
+ protected boolean returnsList(Method method)
+ {
+ return method.getReturnType().isAssignableFrom(List.class);
+ }
+
+ protected LockModeType extractLockMode(Method method)
+ {
+ Class<org.apache.deltaspike.data.api.Query> query = org.apache.deltaspike.data.api.Query.class;
+ if (method.isAnnotationPresent(query) &&
+ method.getAnnotation(query).lock() != LockModeType.NONE)
+ {
+ return method.getAnnotation(query).lock();
+ }
+ return null;
+ }
+
+ protected boolean hasLockMode(Method method)
+ {
+ return extractLockMode(method) != null;
+ }
+
+ protected QueryHint[] extractQueryHints(Method method)
+ {
+ Class<org.apache.deltaspike.data.api.Query> query = org.apache.deltaspike.data.api.Query.class;
+ if (method.isAnnotationPresent(query) &&
+ method.getAnnotation(query).hints().length > 0)
+ {
+ return method.getAnnotation(query).hints();
+ }
+ return null;
+ }
+
+ protected boolean hasQueryHints(Method method)
+ {
+ return extractQueryHints(method) != null;
+ }
+
+ protected Query applyRestrictions(CdiQueryInvocationContext context, Query query)
+ {
+ Parameters params = context.getParams();
+ Method method = context.getMethod();
+ if (params.hasSizeRestriction())
+ {
+ query.setMaxResults(params.getSizeRestriciton());
+ }
+ if (params.hasFirstResult())
+ {
+ query.setFirstResult(params.getFirstResult());
+ }
+ if (hasLockMode(method))
+ {
+ query.setLockMode(extractLockMode(method));
+ }
+ if (hasQueryHints(method))
+ {
+ QueryHint[] hints = extractQueryHints(method);
+ for (QueryHint hint : hints)
+ {
+ query.setHint(hint.name(), hint.value());
+ }
+ }
+ query = context.applyJpaQueryPostProcessors(query);
+ return query;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryBuilderContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryBuilderContext.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryBuilderContext.java
new file mode 100644
index 0000000..c4681a4
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryBuilderContext.java
@@ -0,0 +1,56 @@
+/*
+ * 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.deltaspike.data.impl.builder;
+
+/**
+ * @author thomashug
+ */
+public class QueryBuilderContext
+{
+
+ private final StringBuilder builder;
+ private int counter = 1;
+
+ public QueryBuilderContext()
+ {
+ this.builder = new StringBuilder();
+ }
+
+ public int increment()
+ {
+ return counter++;
+ }
+
+ public QueryBuilderContext append(String string)
+ {
+ builder.append(string);
+ return this;
+ }
+
+ public String resultString()
+ {
+ return builder.toString();
+ }
+
+ public int getCounter()
+ {
+ return counter;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryBuilderFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryBuilderFactory.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryBuilderFactory.java
new file mode 100644
index 0000000..b37c9b8
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryBuilderFactory.java
@@ -0,0 +1,50 @@
+/*
+ * 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.deltaspike.data.impl.builder;
+
+import java.io.Serializable;
+
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+
+import org.apache.deltaspike.data.api.QueryResult;
+import org.apache.deltaspike.data.impl.meta.RepositoryMethod;
+import org.apache.deltaspike.data.impl.meta.QueryInvocationLiteral;
+
+public class QueryBuilderFactory implements Serializable
+{
+
+ private static final long serialVersionUID = 1L;
+
+ @Inject
+ @Any
+ private Instance<QueryBuilder> queryBuilder;
+
+ public QueryBuilder build(RepositoryMethod method)
+ {
+ QueryBuilder builder = queryBuilder.select(new QueryInvocationLiteral(method.getMethodType())).get();
+ if (method.returns(QueryResult.class))
+ {
+ return new WrappedQueryBuilder(builder);
+ }
+ return builder;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryOperator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryOperator.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryOperator.java
new file mode 100644
index 0000000..b4b3595
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/QueryOperator.java
@@ -0,0 +1,71 @@
+/*
+ * 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.deltaspike.data.impl.builder;
+
+/**
+ * Comparison options for queries.
+ *
+ * @author thomashug
+ */
+public enum QueryOperator
+{
+
+ LessThan("LessThan", "{0} < {1}"),
+ LessThanEquals("LessThanEquals", "{0} <= {1}"),
+ GreaterThan("GreaterThan", "{0} > {1}"),
+ GreaterThanEquals("GreaterThanEquals", "{0} >= {1}"),
+ Like("Like", "{0} like {1}"),
+ NotEqual("NotEqual", "{0} <> {1}"),
+ Equal("Equal", "{0} = {1}"),
+ Between("Between", "{0} between {1} and {2}", 2),
+ IsNotNull("IsNotNull", "{0} IS NOT NULL", 0),
+ IsNull("IsNull", "{0} IS NULL", 0);
+
+ private final String expression;
+ private final String jpql;
+ private final int paramNum;
+
+ private QueryOperator(String expression, String jpql)
+ {
+ this(expression, jpql, 1);
+ }
+
+ private QueryOperator(String expression, String jpql, int paramNum)
+ {
+ this.expression = expression;
+ this.jpql = jpql;
+ this.paramNum = paramNum;
+ }
+
+ public String getExpression()
+ {
+ return expression;
+ }
+
+ public String getJpql()
+ {
+ return jpql;
+ }
+
+ public int getParamNum()
+ {
+ return paramNum;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/WrappedQueryBuilder.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/WrappedQueryBuilder.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/WrappedQueryBuilder.java
new file mode 100644
index 0000000..8cb4147
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/WrappedQueryBuilder.java
@@ -0,0 +1,41 @@
+/*
+ * 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.deltaspike.data.impl.builder;
+
+import org.apache.deltaspike.data.impl.builder.result.DefaultQueryResult;
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+
+public class WrappedQueryBuilder extends QueryBuilder
+{
+
+ private final QueryBuilder delegate;
+
+ public WrappedQueryBuilder(QueryBuilder delegate)
+ {
+ this.delegate = delegate;
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ public Object execute(CdiQueryInvocationContext ctx)
+ {
+ return new DefaultQueryResult(delegate, ctx);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/AndQueryPart.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/AndQueryPart.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/AndQueryPart.java
new file mode 100644
index 0000000..7dfcb97
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/AndQueryPart.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.deltaspike.data.impl.builder.part;
+
+import org.apache.deltaspike.data.impl.builder.QueryBuilderContext;
+import org.apache.deltaspike.data.impl.meta.RepositoryComponent;
+
+/**
+ *
+ * @author thomashug
+ */
+class AndQueryPart extends ConnectingQueryPart
+{
+
+ public AndQueryPart(boolean first)
+ {
+ super(first);
+ }
+
+ @Override
+ protected QueryPart build(String queryPart, String method, RepositoryComponent repo)
+ {
+ children.add(new PropertyQueryPart().build(queryPart, method, repo));
+ return this;
+ }
+
+ @Override
+ protected QueryPart buildQuery(QueryBuilderContext ctx)
+ {
+ if (!first)
+ {
+ ctx.append(" and ");
+ }
+ buildQueryForChildren(ctx);
+ return this;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/BasePropertyQueryPart.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/BasePropertyQueryPart.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/BasePropertyQueryPart.java
new file mode 100644
index 0000000..13d2ac1
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/BasePropertyQueryPart.java
@@ -0,0 +1,62 @@
+/*
+ * 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.deltaspike.data.impl.builder.part;
+
+import org.apache.deltaspike.data.impl.builder.MethodExpressionException;
+import org.apache.deltaspike.data.impl.meta.RepositoryComponent;
+import org.apache.deltaspike.data.impl.property.Property;
+import org.apache.deltaspike.data.impl.property.query.NamedPropertyCriteria;
+import org.apache.deltaspike.data.impl.property.query.PropertyQueries;
+import org.apache.deltaspike.data.impl.property.query.PropertyQuery;
+
+abstract class BasePropertyQueryPart extends QueryPart
+{
+
+ static final String SEPARATOR = "_";
+
+ void validate(String name, String method, RepositoryComponent repo)
+ {
+ Class<?> current = repo.getEntityClass();
+ if (name == null)
+ {
+ throw new MethodExpressionException(null, repo.getRepositoryClass(), method);
+ }
+ for (String property : name.split(SEPARATOR))
+ {
+ PropertyQuery<?> query = PropertyQueries.createQuery(current)
+ .addCriteria(new NamedPropertyCriteria(property));
+ Property<?> result = query.getFirstResult();
+ if (result == null)
+ {
+ throw new MethodExpressionException(property, repo.getRepositoryClass(), method);
+ }
+ current = result.getJavaClass();
+ }
+ }
+
+ String rewriteSeparator(String name)
+ {
+ if (name.contains("_"))
+ {
+ return name.replaceAll(SEPARATOR, ".");
+ }
+ return name;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/ConnectingQueryPart.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/ConnectingQueryPart.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/ConnectingQueryPart.java
new file mode 100644
index 0000000..6752bc5
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/ConnectingQueryPart.java
@@ -0,0 +1,40 @@
+/*
+ * 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.deltaspike.data.impl.builder.part;
+
+/**
+ *
+ * @author thomashug
+ */
+abstract class ConnectingQueryPart extends QueryPart
+{
+
+ protected final boolean first;
+
+ public ConnectingQueryPart(boolean first)
+ {
+ this.first = first;
+ }
+
+ public boolean isFirst()
+ {
+ return first;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/OrQueryPart.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/OrQueryPart.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/OrQueryPart.java
new file mode 100644
index 0000000..3873062
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/OrQueryPart.java
@@ -0,0 +1,62 @@
+/*
+ * 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.deltaspike.data.impl.builder.part;
+
+import static org.apache.deltaspike.data.impl.util.QueryUtils.splitByKeyword;
+
+import org.apache.deltaspike.data.impl.builder.QueryBuilderContext;
+import org.apache.deltaspike.data.impl.meta.RepositoryComponent;
+
+/**
+ * @author thomashug
+ */
+class OrQueryPart extends ConnectingQueryPart
+{
+
+ public OrQueryPart(boolean first)
+ {
+ super(first);
+ }
+
+ @Override
+ protected QueryPart build(String queryPart, String method, RepositoryComponent repo)
+ {
+ String[] andParts = splitByKeyword(queryPart, "And");
+ boolean first = true;
+ for (String and : andParts)
+ {
+ AndQueryPart andPart = new AndQueryPart(first);
+ first = false;
+ children.add(andPart.build(and, method, repo));
+ }
+ return this;
+ }
+
+ @Override
+ protected QueryPart buildQuery(QueryBuilderContext ctx)
+ {
+ if (!first)
+ {
+ ctx.append(" or ");
+ }
+ buildQueryForChildren(ctx);
+ return this;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/OrderByQueryPart.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/OrderByQueryPart.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/OrderByQueryPart.java
new file mode 100644
index 0000000..9e87b8f
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/OrderByQueryPart.java
@@ -0,0 +1,154 @@
+/*
+ * 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.deltaspike.data.impl.builder.part;
+
+import static org.apache.deltaspike.data.impl.util.QueryUtils.isNotEmpty;
+import static org.apache.deltaspike.data.impl.util.QueryUtils.splitByKeyword;
+import static org.apache.deltaspike.data.impl.util.QueryUtils.uncapitalize;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.deltaspike.data.impl.builder.QueryBuilder;
+import org.apache.deltaspike.data.impl.builder.QueryBuilderContext;
+import org.apache.deltaspike.data.impl.meta.RepositoryComponent;
+
+
+public class OrderByQueryPart extends BasePropertyQueryPart
+{
+
+ private static final String KEYWORD_ASC = "Asc";
+ private static final String KEYWORD_DESC = "Desc";
+
+ private final List<OrderByQueryAttribute> attributes = new LinkedList<OrderByQueryAttribute>();
+
+ @Override
+ protected QueryPart build(String queryPart, String method, RepositoryComponent repo)
+ {
+ Set<String> collect = new TreeSet<String>();
+ List<String> ascSplit = new LinkedList<String>();
+ split(queryPart, KEYWORD_ASC, ascSplit);
+ for (String ascPart : ascSplit)
+ {
+ split(ascPart, KEYWORD_DESC, collect);
+ }
+ for (String part : collect)
+ {
+ Direction direction = Direction.fromQueryPart(part);
+ String attribute = direction.attribute(part);
+ validate(attribute, method, repo);
+ attributes.add(new OrderByQueryAttribute(attribute, direction));
+ }
+ return this;
+ }
+
+ @Override
+ protected QueryPart buildQuery(QueryBuilderContext ctx)
+ {
+ ctx.append(" order by ");
+ for (Iterator<OrderByQueryAttribute> it = attributes.iterator(); it.hasNext();)
+ {
+ it.next().buildQuery(ctx);
+ if (it.hasNext())
+ {
+ ctx.append(", ");
+ }
+ }
+ return this;
+ }
+
+ private void split(String queryPart, String keyword, Collection<String> result)
+ {
+ for (String part : splitByKeyword(queryPart, keyword))
+ {
+ String attribute = !part.endsWith(KEYWORD_DESC) && !part.endsWith(KEYWORD_ASC) ? part + keyword : part;
+ result.add(attribute);
+ }
+ }
+
+ private class OrderByQueryAttribute
+ {
+
+ private final String attribute;
+ private final Direction direction;
+
+ public OrderByQueryAttribute(String attribute, Direction direction)
+ {
+ this.attribute = attribute;
+ this.direction = direction;
+ }
+
+ protected void buildQuery(QueryBuilderContext ctx)
+ {
+ String entityPrefix = QueryBuilder.ENTITY_NAME + ".";
+ ctx.append(entityPrefix).append(rewriteSeparator(attribute))
+ .append(direction.queryDirection());
+ }
+ }
+
+ private static enum Direction
+ {
+ ASC(KEYWORD_ASC),
+ DESC(KEYWORD_DESC),
+ DEFAULT("");
+
+ private final String postfix;
+
+ private Direction(String postfix)
+ {
+ this.postfix = postfix;
+ }
+
+ public boolean endsWith(String queryPart)
+ {
+ return isNotEmpty(postfix) ? queryPart.endsWith(postfix) : false;
+ }
+
+ public String attribute(String queryPart)
+ {
+ String attribute = isNotEmpty(postfix) ?
+ queryPart.substring(0, queryPart.indexOf(postfix)) :
+ queryPart;
+ return uncapitalize(attribute);
+ }
+
+ public String queryDirection()
+ {
+ return isNotEmpty(postfix) ? " " + postfix.toLowerCase() : "";
+ }
+
+ public static Direction fromQueryPart(String queryPart)
+ {
+ for (Direction dir : values())
+ {
+ if (dir.endsWith(queryPart))
+ {
+ return dir;
+ }
+ }
+ return DEFAULT;
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/PropertyQueryPart.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/PropertyQueryPart.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/PropertyQueryPart.java
new file mode 100644
index 0000000..b6aac30
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/PropertyQueryPart.java
@@ -0,0 +1,72 @@
+/*
+ * 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.deltaspike.data.impl.builder.part;
+
+import static org.apache.deltaspike.data.impl.util.QueryUtils.uncapitalize;
+
+import java.text.MessageFormat;
+
+import org.apache.deltaspike.data.impl.builder.QueryBuilder;
+import org.apache.deltaspike.data.impl.builder.QueryBuilderContext;
+import org.apache.deltaspike.data.impl.builder.QueryOperator;
+import org.apache.deltaspike.data.impl.meta.RepositoryComponent;
+
+/**
+ *
+ * @author thomashug
+ */
+class PropertyQueryPart extends BasePropertyQueryPart
+{
+
+ private String name;
+ private QueryOperator comparator;
+
+ @Override
+ protected QueryPart build(String queryPart, String method, RepositoryComponent repo)
+ {
+ comparator = QueryOperator.Equal;
+ name = uncapitalize(queryPart);
+ for (QueryOperator comp : QueryOperator.values())
+ {
+ if (queryPart.endsWith(comp.getExpression()))
+ {
+ comparator = comp;
+ name = uncapitalize(queryPart.substring(0, queryPart.indexOf(comp.getExpression())));
+ break;
+ }
+ }
+ validate(name, method, repo);
+ name = rewriteSeparator(name);
+ return this;
+ }
+
+ @Override
+ protected QueryPart buildQuery(QueryBuilderContext ctx)
+ {
+ String[] args = new String[comparator.getParamNum() + 1];
+ args[0] = QueryBuilder.ENTITY_NAME + "." + name;
+ for (int i = 1; i < args.length; i++)
+ {
+ args[i] = "?" + ctx.increment();
+ }
+ ctx.append(MessageFormat.format(comparator.getJpql(), (Object[]) args));
+ return this;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryPart.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryPart.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryPart.java
new file mode 100644
index 0000000..d51ec50
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryPart.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.apache.deltaspike.data.impl.builder.part;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.deltaspike.data.impl.builder.QueryBuilderContext;
+import org.apache.deltaspike.data.impl.meta.RepositoryComponent;
+
+/**
+ * @author thomashug
+ */
+public abstract class QueryPart
+{
+
+ protected List<QueryPart> children = new LinkedList<QueryPart>();
+
+ protected abstract QueryPart build(String queryPart, String method, RepositoryComponent repo);
+
+ protected abstract QueryPart buildQuery(QueryBuilderContext ctx);
+
+ protected void buildQueryForChildren(QueryBuilderContext ctx)
+ {
+ for (QueryPart child : children)
+ {
+ child.buildQuery(ctx);
+ }
+ }
+
+ protected boolean hasChildren(Set<Class<? extends QueryPart>> excluded)
+ {
+ if (children == null || children.isEmpty())
+ {
+ return false;
+ }
+ for (QueryPart part : children)
+ {
+ if (!excluded.contains(part.getClass()))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryRoot.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryRoot.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryRoot.java
new file mode 100644
index 0000000..5adb0ad
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/part/QueryRoot.java
@@ -0,0 +1,138 @@
+/*
+ * 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.deltaspike.data.impl.builder.part;
+
+import static org.apache.deltaspike.data.impl.util.QueryUtils.splitByKeyword;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.deltaspike.data.impl.builder.MethodExpressionException;
+import org.apache.deltaspike.data.impl.builder.QueryBuilder;
+import org.apache.deltaspike.data.impl.builder.QueryBuilderContext;
+import org.apache.deltaspike.data.impl.meta.RepositoryComponent;
+
+/**
+ * Root of the query tree. Also the only exposed class in the package.
+ *
+ * @author thomashug
+ */
+public class QueryRoot extends QueryPart
+{
+
+ public static final QueryRoot UNKNOWN_ROOT = new QueryRoot("null-object", "");
+
+ private static final Logger log = Logger.getLogger(QueryRoot.class.getName());
+
+ private final String entityName;
+ private final String queryPrefix;
+
+ private String jpqlQuery;
+
+ protected QueryRoot(String entityName, String queryPrefix)
+ {
+ this.entityName = entityName;
+ this.queryPrefix = queryPrefix;
+ }
+
+ public static QueryRoot create(String method, RepositoryComponent repo)
+ {
+ QueryRoot root = new QueryRoot(repo.getEntityName(), repo.getMethodPrefix());
+ root.build(method, method, repo);
+ root.createJpql();
+ return root;
+ }
+
+ public String getJpqlQuery()
+ {
+ return jpqlQuery;
+ }
+
+ @Override
+ protected QueryPart build(String queryPart, String method, RepositoryComponent repo)
+ {
+ String[] orderByParts = splitByKeyword(queryPart, "OrderBy");
+ if (hasQueryConditions(orderByParts))
+ {
+ String[] orParts = splitByKeyword(removePrefix(orderByParts[0]), "Or");
+ boolean first = true;
+ for (String or : orParts)
+ {
+ OrQueryPart orPart = new OrQueryPart(first);
+ first = false;
+ children.add(orPart.build(or, method, repo));
+ }
+ }
+ if (orderByParts.length > 1)
+ {
+ OrderByQueryPart orderByPart = new OrderByQueryPart();
+ children.add(orderByPart.build(orderByParts[1], method, repo));
+ }
+ if (children.isEmpty())
+ {
+ throw new MethodExpressionException(repo.getRepositoryClass(), method);
+ }
+ return this;
+ }
+
+ @Override
+ protected QueryPart buildQuery(QueryBuilderContext ctx)
+ {
+ ctx.append(QueryBuilder.selectQuery(entityName));
+ if (hasChildren(excludedForWhereCheck()))
+ {
+ ctx.append(" where ");
+ }
+ buildQueryForChildren(ctx);
+ return this;
+ }
+
+ protected String createJpql()
+ {
+ QueryBuilderContext ctx = new QueryBuilderContext();
+ buildQuery(ctx);
+ jpqlQuery = ctx.resultString();
+ log.log(Level.FINER, "createJpql: Query is {0}", jpqlQuery);
+ return jpqlQuery;
+ }
+
+ private Set<Class<? extends QueryPart>> excludedForWhereCheck()
+ {
+ Set<Class<? extends QueryPart>> excluded = new HashSet<Class<? extends QueryPart>>();
+ excluded.add(OrderByQueryPart.class);
+ return excluded;
+ }
+
+ private boolean hasQueryConditions(String[] orderByParts)
+ {
+ return !queryPrefix.equals(orderByParts[0]);
+ }
+
+ private String removePrefix(String queryPart)
+ {
+ if (queryPart.startsWith(queryPrefix))
+ {
+ return queryPart.substring(queryPrefix.length());
+ }
+ return queryPart;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/CountQueryPostProcessor.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/CountQueryPostProcessor.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/CountQueryPostProcessor.java
new file mode 100644
index 0000000..6659776
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/CountQueryPostProcessor.java
@@ -0,0 +1,124 @@
+/*
+ * 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.deltaspike.data.impl.builder.postprocessor;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.persistence.Query;
+
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+import org.apache.deltaspike.data.impl.handler.JpaQueryPostProcessor;
+import org.apache.deltaspike.data.impl.param.Parameters;
+import org.apache.deltaspike.data.impl.util.QueryUtils;
+import org.apache.deltaspike.data.impl.util.jpa.QueryStringExtractorFactory;
+
+public class CountQueryPostProcessor implements JpaQueryPostProcessor
+{
+
+ private static final Logger log = Logger.getLogger(CountQueryPostProcessor.class.getName());
+
+ private final QueryStringExtractorFactory factory = new QueryStringExtractorFactory();
+
+ @Override
+ public Query postProcess(CdiQueryInvocationContext context, Query query)
+ {
+ String queryString = getQueryString(context, query);
+ QueryExtraction extract = new QueryExtraction(queryString);
+ String count = extract.rewriteToCount();
+ log.log(Level.FINER, "Rewrote query {0} to {1}", new Object[] { queryString, count });
+ Query result = context.getEntityManager().createQuery(count);
+ Parameters params = context.getParams();
+ params.applyTo(result);
+ return result;
+ }
+
+ private String getQueryString(CdiQueryInvocationContext context, Query query)
+ {
+ if (QueryUtils.isNotEmpty(context.getQueryString()))
+ {
+ return context.getQueryString();
+ }
+ return factory.select(query).extractFrom(query);
+ }
+
+ private static class QueryExtraction
+ {
+
+ private String select;
+ private String from;
+ private String where;
+
+ private String entityName;
+ private final String query;
+
+ public QueryExtraction(String query)
+ {
+ this.query = query;
+ }
+
+ public String rewriteToCount()
+ {
+ splitQuery();
+ extractEntityName();
+ return rewrite();
+ }
+
+ private String rewrite()
+ {
+ return "select count(" + (select != null ? select : entityName) + ") " + from + where;
+ }
+
+ private void extractEntityName()
+ {
+ String[] split = from.split(" ");
+ if (split.length > 1)
+ {
+ entityName = split[split.length - 1];
+ }
+ else
+ {
+ entityName = "*";
+ }
+ }
+
+ private void splitQuery()
+ {
+ String lower = query.toLowerCase();
+ int selectIndex = lower.indexOf("select");
+ int fromIndex = lower.indexOf("from");
+ int whereIndex = lower.indexOf("where");
+ if (selectIndex >= 0)
+ {
+ select = query.substring("select".length(), fromIndex);
+ }
+ if (whereIndex >= 0)
+ {
+ from = query.substring(fromIndex, whereIndex);
+ where = query.substring(whereIndex);
+ }
+ else
+ {
+ from = query.substring(fromIndex);
+ }
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/FirstResultPostProcessor.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/FirstResultPostProcessor.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/FirstResultPostProcessor.java
new file mode 100644
index 0000000..3733a57
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/FirstResultPostProcessor.java
@@ -0,0 +1,43 @@
+/*
+ * 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.deltaspike.data.impl.builder.postprocessor;
+
+import javax.persistence.Query;
+
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+import org.apache.deltaspike.data.impl.handler.JpaQueryPostProcessor;
+
+public class FirstResultPostProcessor implements JpaQueryPostProcessor
+{
+
+ private final int startPosition;
+
+ public FirstResultPostProcessor(int startPosition)
+ {
+ this.startPosition = startPosition;
+ }
+
+ @Override
+ public Query postProcess(CdiQueryInvocationContext context, Query query)
+ {
+ query.setFirstResult(startPosition);
+ return query;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/FlushModePostProcessor.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/FlushModePostProcessor.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/FlushModePostProcessor.java
new file mode 100644
index 0000000..a97e8b4
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/FlushModePostProcessor.java
@@ -0,0 +1,44 @@
+/*
+ * 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.deltaspike.data.impl.builder.postprocessor;
+
+import javax.persistence.FlushModeType;
+import javax.persistence.Query;
+
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+import org.apache.deltaspike.data.impl.handler.JpaQueryPostProcessor;
+
+public class FlushModePostProcessor implements JpaQueryPostProcessor
+{
+
+ private final FlushModeType flushMode;
+
+ public FlushModePostProcessor(FlushModeType flushMode)
+ {
+ this.flushMode = flushMode;
+ }
+
+ @Override
+ public Query postProcess(CdiQueryInvocationContext context, Query query)
+ {
+ query.setFlushMode(flushMode);
+ return query;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/HintPostProcessor.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/HintPostProcessor.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/HintPostProcessor.java
new file mode 100644
index 0000000..beb7722
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/HintPostProcessor.java
@@ -0,0 +1,45 @@
+/*
+ * 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.deltaspike.data.impl.builder.postprocessor;
+
+import javax.persistence.Query;
+
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+import org.apache.deltaspike.data.impl.handler.JpaQueryPostProcessor;
+
+public class HintPostProcessor implements JpaQueryPostProcessor
+{
+
+ private final String hintName;
+ private final Object hintValue;
+
+ public HintPostProcessor(String hintName, Object hintValue)
+ {
+ this.hintName = hintName;
+ this.hintValue = hintValue;
+ }
+
+ @Override
+ public Query postProcess(CdiQueryInvocationContext context, Query query)
+ {
+ query.setHint(hintName, hintValue);
+ return query;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/LockModePostProcessor.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/LockModePostProcessor.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/LockModePostProcessor.java
new file mode 100644
index 0000000..6c21f8c
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/LockModePostProcessor.java
@@ -0,0 +1,44 @@
+/*
+ * 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.deltaspike.data.impl.builder.postprocessor;
+
+import javax.persistence.LockModeType;
+import javax.persistence.Query;
+
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+import org.apache.deltaspike.data.impl.handler.JpaQueryPostProcessor;
+
+public class LockModePostProcessor implements JpaQueryPostProcessor
+{
+
+ private final LockModeType lockMode;
+
+ public LockModePostProcessor(LockModeType lockMode)
+ {
+ this.lockMode = lockMode;
+ }
+
+ @Override
+ public Query postProcess(CdiQueryInvocationContext context, Query query)
+ {
+ query.setLockMode(lockMode);
+ return query;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/MaxResultPostProcessor.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/MaxResultPostProcessor.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/MaxResultPostProcessor.java
new file mode 100644
index 0000000..d97f618
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/MaxResultPostProcessor.java
@@ -0,0 +1,43 @@
+/*
+ * 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.deltaspike.data.impl.builder.postprocessor;
+
+import javax.persistence.Query;
+
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+import org.apache.deltaspike.data.impl.handler.JpaQueryPostProcessor;
+
+public class MaxResultPostProcessor implements JpaQueryPostProcessor
+{
+
+ private final int max;
+
+ public MaxResultPostProcessor(int max)
+ {
+ this.max = max;
+ }
+
+ @Override
+ public Query postProcess(CdiQueryInvocationContext context, Query query)
+ {
+ query.setMaxResults(max);
+ return query;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/OrderByQueryStringPostProcessor.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/OrderByQueryStringPostProcessor.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/OrderByQueryStringPostProcessor.java
new file mode 100644
index 0000000..cb9f046
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/postprocessor/OrderByQueryStringPostProcessor.java
@@ -0,0 +1,80 @@
+/*
+ * 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.deltaspike.data.impl.builder.postprocessor;
+
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.apache.deltaspike.data.impl.builder.OrderDirection;
+import org.apache.deltaspike.data.impl.builder.QueryBuilder;
+import org.apache.deltaspike.data.impl.handler.QueryStringPostProcessor;
+
+public class OrderByQueryStringPostProcessor implements QueryStringPostProcessor
+{
+
+ private static final String ORDER_BY = " order by ";
+
+ private final String attribute;
+ private OrderDirection direction;
+
+ public OrderByQueryStringPostProcessor(SingularAttribute<?, ?> attribute, OrderDirection direction)
+ {
+ this.attribute = attribute.getName();
+ this.direction = direction;
+ }
+
+ public OrderByQueryStringPostProcessor(String attribute, OrderDirection direction)
+ {
+ this.attribute = attribute;
+ this.direction = direction;
+ }
+
+ @Override
+ public String postProcess(String queryString)
+ {
+ StringBuilder builder = new StringBuilder(queryString);
+ if (queryString.contains(ORDER_BY))
+ {
+ builder.append(",");
+ }
+ else
+ {
+ builder.append(ORDER_BY);
+ }
+ return builder.append(QueryBuilder.ENTITY_NAME)
+ .append(".").append(attribute)
+ .append(" ").append(direction)
+ .toString();
+ }
+
+ public boolean matches(SingularAttribute<?, ?> attribute)
+ {
+ return matches(attribute.getName());
+ }
+
+ public boolean matches(String attribute)
+ {
+ return this.attribute.equals(attribute);
+ }
+
+ public void changeDirection()
+ {
+ direction = direction.change();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/DefaultQueryResult.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/DefaultQueryResult.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/DefaultQueryResult.java
new file mode 100644
index 0000000..c6b7c72
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/DefaultQueryResult.java
@@ -0,0 +1,284 @@
+/*
+ * 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.deltaspike.data.impl.builder.result;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javax.persistence.FlushModeType;
+import javax.persistence.LockModeType;
+import javax.persistence.Query;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.apache.deltaspike.data.api.QueryResult;
+import org.apache.deltaspike.data.impl.builder.OrderDirection;
+import org.apache.deltaspike.data.impl.builder.QueryBuilder;
+import org.apache.deltaspike.data.impl.builder.postprocessor.CountQueryPostProcessor;
+import org.apache.deltaspike.data.impl.builder.postprocessor.FirstResultPostProcessor;
+import org.apache.deltaspike.data.impl.builder.postprocessor.FlushModePostProcessor;
+import org.apache.deltaspike.data.impl.builder.postprocessor.HintPostProcessor;
+import org.apache.deltaspike.data.impl.builder.postprocessor.LockModePostProcessor;
+import org.apache.deltaspike.data.impl.builder.postprocessor.MaxResultPostProcessor;
+import org.apache.deltaspike.data.impl.builder.postprocessor.OrderByQueryStringPostProcessor;
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+import org.apache.deltaspike.data.impl.handler.QueryStringPostProcessor;
+
+public class DefaultQueryResult<T> implements QueryResult<T>
+{
+
+ private final QueryBuilder builder;
+ private final CdiQueryInvocationContext context;
+
+ private int page = 0;
+ private int pageSize = 10;
+
+ public DefaultQueryResult(QueryBuilder builder, CdiQueryInvocationContext context)
+ {
+ this.builder = builder;
+ this.context = context;
+ }
+
+ @Override
+ public <X> QueryResult<T> orderAsc(SingularAttribute<T, X> attribute)
+ {
+ context.addQueryStringPostProcessor(new OrderByQueryStringPostProcessor(attribute, OrderDirection.ASC));
+ return this;
+ }
+
+ @Override
+ public QueryResult<T> orderAsc(String attribute)
+ {
+ context.addQueryStringPostProcessor(new OrderByQueryStringPostProcessor(attribute, OrderDirection.ASC));
+ return this;
+ }
+
+ @Override
+ public <X> QueryResult<T> orderDesc(SingularAttribute<T, X> attribute)
+ {
+ context.addQueryStringPostProcessor(new OrderByQueryStringPostProcessor(attribute, OrderDirection.DESC));
+ return this;
+ }
+
+ @Override
+ public QueryResult<T> orderDesc(String attribute)
+ {
+ context.addQueryStringPostProcessor(new OrderByQueryStringPostProcessor(attribute, OrderDirection.DESC));
+ return this;
+ }
+
+ @Override
+ public <X> QueryResult<T> changeOrder(final SingularAttribute<T, X> attribute)
+ {
+ changeOrder(new ChangeOrder()
+ {
+ @Override
+ public boolean matches(OrderByQueryStringPostProcessor orderBy)
+ {
+ return orderBy.matches(attribute);
+ }
+
+ @Override
+ public void addDefault()
+ {
+ orderAsc(attribute);
+ }
+ });
+ return this;
+ }
+
+ @Override
+ public QueryResult<T> changeOrder(final String attribute)
+ {
+ changeOrder(new ChangeOrder()
+ {
+ @Override
+ public boolean matches(OrderByQueryStringPostProcessor orderBy)
+ {
+ return orderBy.matches(attribute);
+ }
+
+ @Override
+ public void addDefault()
+ {
+ orderAsc(attribute);
+ }
+ });
+ return this;
+ }
+
+ @Override
+ public QueryResult<T> clearOrder()
+ {
+ for (Iterator<QueryStringPostProcessor> it = context.getQueryStringPostProcessors().iterator(); it.hasNext();)
+ {
+ if (it.next() instanceof OrderByQueryStringPostProcessor)
+ {
+ it.remove();
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public QueryResult<T> maxResults(int max)
+ {
+ context.addJpaQueryPostProcessor(new MaxResultPostProcessor(max));
+ pageSize = max;
+ return this;
+ }
+
+ @Override
+ public QueryResult<T> firstResult(int first)
+ {
+ context.addJpaQueryPostProcessor(new FirstResultPostProcessor(first));
+ return this;
+ }
+
+ @Override
+ public QueryResult<T> lockMode(LockModeType lockMode)
+ {
+ context.addJpaQueryPostProcessor(new LockModePostProcessor(lockMode));
+ return this;
+ }
+
+ @Override
+ public QueryResult<T> flushMode(FlushModeType flushMode)
+ {
+ context.addJpaQueryPostProcessor(new FlushModePostProcessor(flushMode));
+ return this;
+ }
+
+ @Override
+ public QueryResult<T> hint(String hint, Object value)
+ {
+ context.addJpaQueryPostProcessor(new HintPostProcessor(hint, value));
+ return this;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public List<T> getResultList()
+ {
+ return ((Query) builder.execute(context)).getResultList();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public T getSingleResult()
+ {
+ return (T) ((Query) builder.execute(context)).getSingleResult();
+ }
+
+ @Override
+ public long count()
+ {
+ CountQueryPostProcessor counter = new CountQueryPostProcessor();
+ context.addJpaQueryPostProcessor(counter);
+ try
+ {
+ Long result = (Long) ((Query) builder.execute(context)).getSingleResult();
+ return result.intValue();
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ finally
+ {
+ context.removeJpaQueryPostProcessor(counter);
+ }
+ }
+
+ @Override
+ public QueryResult<T> withPageSize(int pageSize)
+ {
+ return maxResults(pageSize);
+ }
+
+ @Override
+ public QueryResult<T> toPage(int page)
+ {
+ this.page = page;
+ return firstResult(pageSize * page);
+ }
+
+ @Override
+ public QueryResult<T> nextPage()
+ {
+ page = page + 1;
+ return firstResult(pageSize * page);
+ }
+
+ @Override
+ public QueryResult<T> previousPage()
+ {
+ page = page > 0 ? page - 1 : page;
+ return firstResult(pageSize * page);
+ }
+
+ @Override
+ public int countPages()
+ {
+ return (int) Math.ceil((double) count() / pageSize);
+ }
+
+ @Override
+ public int currentPage()
+ {
+ return page;
+ }
+
+ @Override
+ public int pageSize()
+ {
+ return pageSize;
+ }
+
+ private <X> QueryResult<T> changeOrder(ChangeOrder changeOrder)
+ {
+ for (QueryStringPostProcessor processor : context.getQueryStringPostProcessors())
+ {
+ if (processor instanceof OrderByQueryStringPostProcessor)
+ {
+ OrderByQueryStringPostProcessor orderBy = (OrderByQueryStringPostProcessor) processor;
+ if (changeOrder.matches(orderBy))
+ {
+ orderBy.changeDirection();
+ return this;
+ }
+ }
+ }
+ changeOrder.addDefault();
+ return this;
+ }
+
+ private abstract static class ChangeOrder
+ {
+
+ public abstract boolean matches(OrderByQueryStringPostProcessor orderBy);
+
+ public abstract void addDefault();
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessor.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessor.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessor.java
new file mode 100644
index 0000000..b39b9ee
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessor.java
@@ -0,0 +1,28 @@
+/*
+ * 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.deltaspike.data.impl.builder.result;
+
+import javax.persistence.Query;
+
+public interface QueryProcessor
+{
+
+ Object executeQuery(Query query);
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java
new file mode 100644
index 0000000..4b14616
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java
@@ -0,0 +1,122 @@
+/*
+ * 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.deltaspike.data.impl.builder.result;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import javax.persistence.Query;
+
+import org.apache.deltaspike.data.api.Modifying;
+import org.apache.deltaspike.data.api.QueryResult;
+
+public final class QueryProcessorFactory
+{
+
+ private final Method method;
+
+ private QueryProcessorFactory(Method method)
+ {
+ this.method = method;
+ }
+
+ public static QueryProcessorFactory newInstance(Method method)
+ {
+ return new QueryProcessorFactory(method);
+ }
+
+ public QueryProcessor build()
+ {
+ if (returns(QueryResult.class))
+ {
+ return new NoOpQueryProcessor();
+ }
+ if (returns(List.class))
+ {
+ return new ListQueryProcessor();
+ }
+ if (isModifying())
+ {
+ return new ExecuteUpdateQueryProcessor(returns(Void.TYPE));
+ }
+ return new SingleResultQueryProcessor();
+ }
+
+ private boolean isModifying()
+ {
+ boolean matchesType = Void.TYPE.equals(method.getReturnType()) ||
+ int.class.equals(method.getReturnType()) ||
+ Integer.class.equals(method.getReturnType());
+ return method.isAnnotationPresent(Modifying.class) && matchesType;
+ }
+
+ private boolean returns(Class<?> clazz)
+ {
+ return method.getReturnType().isAssignableFrom(clazz);
+ }
+
+ private static final class ListQueryProcessor implements QueryProcessor
+ {
+ @Override
+ public Object executeQuery(Query query)
+ {
+ return query.getResultList();
+ }
+ }
+
+ private static final class NoOpQueryProcessor implements QueryProcessor
+ {
+ @Override
+ public Object executeQuery(Query query)
+ {
+ return query;
+ }
+ }
+
+ private static final class SingleResultQueryProcessor implements QueryProcessor
+ {
+ @Override
+ public Object executeQuery(Query query)
+ {
+ return query.getSingleResult();
+ }
+ }
+
+ private static final class ExecuteUpdateQueryProcessor implements QueryProcessor
+ {
+
+ private final boolean returnsVoid;
+
+ private ExecuteUpdateQueryProcessor(boolean returnsVoid)
+ {
+ this.returnsVoid = returnsVoid;
+ }
+
+ @Override
+ public Object executeQuery(Query query)
+ {
+ int result = query.executeUpdate();
+ if (!returnsVoid)
+ {
+ return result;
+ }
+ return null;
+ }
+ }
+}