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:09 UTC
[09/11] DELTASPIKE-60 Data module initial import
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/CurrentUser.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/CurrentUser.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/CurrentUser.java
new file mode 100644
index 0000000..3e5f11d
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/CurrentUser.java
@@ -0,0 +1,42 @@
+/*
+ * 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.api.audit;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Identifies the current user responsible for entity creation or modification.
+ */
+@Qualifier
+@Target({ TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+public @interface CurrentUser
+{
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/ModifiedBy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/ModifiedBy.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/ModifiedBy.java
new file mode 100644
index 0000000..2b2a353
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/ModifiedBy.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.api.audit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a property which should keep track on the last changing user.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.FIELD, ElementType.METHOD })
+public @interface ModifiedBy
+{
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/ModifiedOn.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/ModifiedOn.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/ModifiedOn.java
new file mode 100644
index 0000000..edf3840
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/audit/ModifiedOn.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.apache.deltaspike.data.api.audit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a property which should be updated with a timestamp when the entity gets updated.
+ * By settings {@link #onCreate()} to {@code true}, the property gets also set when
+ * the entity is persisted.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.FIELD, ElementType.METHOD })
+public @interface ModifiedOn
+{
+ boolean onCreate() default false;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/Criteria.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/Criteria.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/Criteria.java
new file mode 100644
index 0000000..a2f1ca7
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/Criteria.java
@@ -0,0 +1,302 @@
+/*
+ * 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.api.criteria;
+
+import java.util.Collection;
+import java.util.List;
+
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.JoinType;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.metamodel.CollectionAttribute;
+import javax.persistence.metamodel.ListAttribute;
+import javax.persistence.metamodel.MapAttribute;
+import javax.persistence.metamodel.PluralAttribute;
+import javax.persistence.metamodel.SetAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+
+/**
+ * Criteria API utilities.
+ *
+ * @author thomashug
+ *
+ * @param <C> Entity type.
+ * @param <R> Result type.
+ */
+public interface Criteria<C, R>
+{
+
+ /**
+ * Executes the query and returns the result list.
+ * @return List of entities matching the query.
+ */
+ List<R> getResultList();
+
+ /**
+ * Executes the query which has a single result.
+ * @return Entity matching the search query.
+ */
+ R getSingleResult();
+
+ /**
+ * Creates a JPA query object to be executed.
+ * @return A {@link TypedQuery} object ready to return results.
+ */
+ TypedQuery<R> createQuery();
+
+ /**
+ * Boolean OR with another Criteria.
+ * @param criteria The right side of the boolean OR.
+ * @return Fluent API: Criteria instance.
+ */
+ Criteria<C, R> or(Criteria<C, R>... criteria);
+
+ /**
+ * Boolean OR with another Criteria.
+ * @param criteria The right side of the boolean OR.
+ * @return Fluent API: Criteria instance.
+ */
+ Criteria<C, R> or(Collection<Criteria<C, R>> criteria);
+
+ /**
+ * Join an attribute with another Criteria.
+ * @param att The attribute to join.
+ * @param criteria The join criteria.
+ * @return Fluent API: Criteria instance.
+ */
+ <P, E> Criteria<C, R> join(SingularAttribute<? super C, P> att, Criteria<P, P> criteria);
+
+ /**
+ * Join a collection attribute with another Criteria.
+ * @param att The attribute to join.
+ * @param criteria The join criteria.
+ * @return Fluent API: Criteria instance.
+ */
+ <P, E> Criteria<C, R> join(ListAttribute<? super C, P> att, Criteria<P, P> criteria);
+
+ /**
+ * Join a collection attribute with another Criteria.
+ * @param att The attribute to join.
+ * @param criteria The join criteria.
+ * @return Fluent API: Criteria instance.
+ */
+ <P, E> Criteria<C, R> join(CollectionAttribute<? super C, P> att, Criteria<P, P> criteria);
+
+ /**
+ * Join a collection attribute with another Criteria.
+ * @param att The attribute to join.
+ * @param criteria The join criteria.
+ * @return Fluent API: Criteria instance.
+ */
+ <P, E> Criteria<C, R> join(SetAttribute<? super C, P> att, Criteria<P, P> criteria);
+
+ /**
+ * Join a collection attribute with another Criteria.
+ * @param att The attribute to join.
+ * @param criteria The join criteria.
+ * @return Fluent API: Criteria instance.
+ */
+ <P, E> Criteria<C, R> join(MapAttribute<? super C, E, P> att, Criteria<P, P> criteria);
+
+
+ /**
+ * Fetch join an attribute.
+ * @param att The attribute to fetch.
+ * @return Fluent API: Criteria instance.
+ */
+ <P, E> Criteria<C, R> fetch(SingularAttribute<? super C, P> att);
+
+ /**
+ * Fetch join an attribute.
+ * @param att The attribute to fetch.
+ * @param joinType The JoinType to use.
+ * @return Fluent API: Criteria instance.
+ */
+ <P, E> Criteria<C, R> fetch(SingularAttribute<? super C, P> att, JoinType joinType);
+
+ /**
+ * Fetch join an attribute.
+ * @param att The attribute to fetch.
+ * @return Fluent API: Criteria instance.
+ */
+ <P, E> Criteria<C, R> fetch(PluralAttribute<? super C, P, E> att);
+
+ /**
+ * Fetch join an attribute.
+ * @param att The attribute to fetch.
+ * @param joinType The JoinType to use.
+ * @return Fluent API: Criteria instance.
+ */
+ <P, E> Criteria<C, R> fetch(PluralAttribute<? super C, P, E> att, JoinType joinType);
+
+ /**
+ * Apply sorting by an attribute, ascending direction.
+ * @param att The attribute to order for.
+ * @return Fluent API: Criteria instance.
+ */
+ <P> Criteria<C, R> orderAsc(SingularAttribute<? super C, P> att);
+
+ /**
+ * Apply sorting by an attribute, descending direction.
+ * @param att The attribute to order for.
+ * @return Fluent API: Criteria instance.
+ */
+ <P> Criteria<C, R> orderDesc(SingularAttribute<? super C, P> att);
+
+ /**
+ * Create a select query.
+ * @param resultClass The query result class.
+ * @param selection List of selects (attributes, scalars...)
+ * @return Fluent API: Criteria instance.
+ */
+ <N> Criteria<C, N> select(Class<N> resultClass, QuerySelection<? super C, ?>... selection);
+
+ /**
+ * Create a select query.
+ * @param selection List of selects (attributes, scalars...)
+ * @return Fluent API: Criteria instance.
+ */
+ Criteria<C, Object[]> select(QuerySelection<? super C, ?>... selection);
+
+ /**
+ * Apply a distinct on the query.
+ * @return Fluent API: Criteria instance.
+ */
+ Criteria<C, R> distinct();
+
+ /**
+ * Equals predicate.
+ * @param att The attribute to compare with.
+ * @param value The comparison value.
+ * @return Fluent API: Criteria instance.
+ */
+ <P> Criteria<C, R> eq(SingularAttribute<? super C, P> att, P value);
+
+ /**
+ * Not Equals predicate.
+ * @param att The attribute to compare with.
+ * @param value The comparison value.
+ * @return Fluent API: Criteria instance.
+ */
+ <P> Criteria<C, R> notEq(SingularAttribute<? super C, P> att, P value);
+
+ /**
+ * Like predicate.
+ * @param att The attribute to compare with.
+ * @param value The comparison value.
+ * @return Fluent API: Criteria instance.
+ */
+ <P> Criteria<C, R> like(SingularAttribute<? super C, String> att, String value);
+
+ /**
+ * Not like predicate.
+ * @param att The attribute to compare with.
+ * @param value The comparison value.
+ * @return Fluent API: Criteria instance.
+ */
+ <P> Criteria<C, R> notLike(SingularAttribute<? super C, String> att, String value);
+
+ /**
+ * Less than predicate.
+ * @param att The attribute to compare with.
+ * @param value The comparison value.
+ * @return Fluent API: Criteria instance.
+ */
+ <P extends Number> Criteria<C, R> lt(SingularAttribute<? super C, P> att, P value);
+
+ /**
+ * Less than or equals predicate.
+ * @param att The attribute to compare with.
+ * @param value The comparison value.
+ * @return Fluent API: Criteria instance.
+ */
+ <P extends Comparable<? super P>> Criteria<C, R> ltOrEq(SingularAttribute<? super C, P> att, P value);
+
+ /**
+ * Greater than predicate.
+ * @param att The attribute to compare with.
+ * @param value The comparison value.
+ * @return Fluent API: Criteria instance.
+ */
+ <P extends Number> Criteria<C, R> gt(SingularAttribute<? super C, P> att, P value);
+
+ /**
+ * Greater than or equals predicate.
+ * @param att The attribute to compare with.
+ * @param value The comparison value.
+ * @return Fluent API: Criteria instance.
+ */
+ <P extends Comparable<? super P>> Criteria<C, R> gtOrEq(SingularAttribute<? super C, P> att, P value);
+
+ /**
+ * Between predicate.
+ * @param att The attribute to compare with.
+ * @param lower The lower bound comparison value.
+ * @param upper The upper bound comparison value.
+ * @return Fluent API: Criteria instance.
+ */
+ <P extends Comparable<? super P>> Criteria<C, R> between(SingularAttribute<? super C, P> att, P lower, P upper);
+
+ /**
+ * IsNull predicate.
+ * @param att The null attribute.
+ * @return Fluent API: Criteria instance.
+ */
+ <P> Criteria<C, R> isNull(SingularAttribute<? super C, P> att);
+
+ /**
+ * NotNull predicate.
+ * @param att The non-null attribute.
+ * @return Fluent API: Criteria instance.
+ */
+ <P> Criteria<C, R> notNull(SingularAttribute<? super C, P> att);
+
+ /**
+ * Empty predicate.
+ * @param att The collection attribute to check for emptyness.
+ * @return Fluent API: Criteria instance.
+ */
+ <P extends Collection<?>> Criteria<C, R> empty(SingularAttribute<? super C, P> att);
+
+ /**
+ * Not empty predicate.
+ * @param att The collection attribute to check for non-emptyness.
+ * @return Fluent API: Criteria instance.
+ */
+ <P extends Collection<?>> Criteria<C, R> notEmpty(SingularAttribute<? super C, P> att);
+
+ /**
+ * In predicte.
+ * @param att The attribute to check for.
+ * @param values The values for the in predicate.
+ * @return
+ */
+ <P> Criteria<C, R> in(SingularAttribute<? super C, P> att, P... values);
+
+ /**
+ * Return the list of predicates applicable for this Criteria instance.
+ * @param builder A CriteriaBuilder used to instantiate the Predicates.
+ * @param path Current path.
+ * @return List of predicates applicable to this Criteria.
+ */
+ List<Predicate> predicates(CriteriaBuilder builder, Path<C> path);
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/CriteriaSupport.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/CriteriaSupport.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/CriteriaSupport.java
new file mode 100644
index 0000000..2904431
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/CriteriaSupport.java
@@ -0,0 +1,196 @@
+/*
+ * 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.api.criteria;
+
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+
+import javax.persistence.criteria.JoinType;
+import javax.persistence.metamodel.SingularAttribute;
+
+/**
+ * Interface to be added to a repository for criteria support.
+ * @author thomashug
+ * @param <E> Entity type.
+ */
+public interface CriteriaSupport<E>
+{
+
+ /**
+ * Create a {@link Criteria} instance.
+ * @return Criteria instance related to the Repository entity class.
+ */
+ Criteria<E, E> criteria();
+
+ /**
+ * Create a {@link Criteria} instance.
+ * @param <T> Type related to the current criteria class.
+ * @param clazz Class other than the current entity class.
+ * @return Criteria instance related to a join type of the current entity class.
+ */
+ <T> Criteria<T, T> where(Class<T> clazz);
+
+ /**
+ * Create a {@link Criteria} instance with a join type.
+ * @param <T> Type related to the current criteria class.
+ * @param clazz Class other than the current entity class.
+ * @param joinType Join type to apply.
+ * @return Criteria instance related to a join type of the current entity class.
+ */
+ <T> Criteria<T, T> where(Class<T> clazz, JoinType joinType);
+
+ /**
+ * Create a query selection for an Entity attribute.
+ * @param attribute Attribute to show up in the result selection
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ <X> QuerySelection<E, X> attribute(SingularAttribute<E, X> attribute);
+
+ /**
+ * Create a query selection for the
+ * {@link javax.persistence.criteria.CriteriaBuilder#abs(javax.persistence.criteria.Expression)}
+ * over an attribute.
+ * @param attribute Attribute to use in the aggregate.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ <N extends Number> QuerySelection<E, N> abs(SingularAttribute<E, N> attribute);
+
+ /**
+ * Create a query selection for the
+ * {@link javax.persistence.criteria.CriteriaBuilder#avg(javax.persistence.criteria.Expression)}
+ * over an attribute.
+ * @param attribute Attribute to use in the aggregate.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ <N extends Number> QuerySelection<E, N> avg(SingularAttribute<E, N> attribute);
+
+ /**
+ * Create a query selection for the
+ * {@link javax.persistence.criteria.CriteriaBuilder#count(javax.persistence.criteria.Expression)}
+ * over an attribute.
+ * @param attribute Attribute to use in the aggregate.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ <N extends Number> QuerySelection<E, N> count(SingularAttribute<E, N> attribute);
+
+ /**
+ * Create a query selection for the
+ * {@link javax.persistence.criteria.CriteriaBuilder#max(javax.persistence.criteria.Expression)}
+ * over an attribute.
+ * @param attribute Attribute to use in the aggregate.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ <N extends Number> QuerySelection<E, N> max(SingularAttribute<E, N> attribute);
+
+ /**
+ * Create a query selection for the
+ * {@link javax.persistence.criteria.CriteriaBuilder#min(javax.persistence.criteria.Expression)}
+ * over an attribute.
+ * @param attribute Attribute to use in the aggregate.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ <N extends Number> QuerySelection<E, N> min(SingularAttribute<E, N> attribute);
+
+ /**
+ * Create a query selection for the
+ * {@link javax.persistence.criteria.CriteriaBuilder#neg(javax.persistence.criteria.Expression)}
+ * over an attribute.
+ * @param attribute Attribute to use in the aggregate.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ <N extends Number> QuerySelection<E, N> neg(SingularAttribute<E, N> attribute);
+
+ /**
+ * Create a query selection for the
+ * {@link javax.persistence.criteria.CriteriaBuilder#sum(javax.persistence.criteria.Expression)}
+ * over an attribute.
+ * @param attribute Attribute to use in the aggregate.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ <N extends Number> QuerySelection<E, N> sum(SingularAttribute<E, N> attribute);
+
+ /**
+ * Create a query selection for the
+ * {@link javax.persistence.criteria.CriteriaBuilder#mod(javax.persistence.criteria.Expression, Integer)}
+ * for an attribute.
+ * @param attribute Attribute to use in the aggregate.
+ * @param modulo Modulo what.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ QuerySelection<E, Integer> modulo(SingularAttribute<E, Integer> attribute, Integer modulo);
+
+ /**
+ * Create a query selection for the
+ * {@link javax.persistence.criteria.CriteriaBuilder#upper(javax.persistence.criteria.Expression)}
+ * over a String attribute.
+ * @param attribute Attribute to uppercase.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ QuerySelection<E, String> upper(SingularAttribute<E, String> attribute);
+
+ /**
+ * Create a query selection for the
+ * {@link javax.persistence.criteria.CriteriaBuilder#lower(javax.persistence.criteria.Expression)}
+ * over a String attribute.
+ * @param attribute Attribute to lowercase.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ QuerySelection<E, String> lower(SingularAttribute<E, String> attribute);
+
+ /**
+ * Create a query selection for the
+ * {@link javax.persistence.criteria.CriteriaBuilder#substring(javax.persistence.criteria.Expression, int)}
+ * over a String attribute.
+ * @param attribute Attribute to create a substring from.
+ * @param from Substring start.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ QuerySelection<E, String> substring(SingularAttribute<E, String> attribute, int from);
+
+ /**
+ * Create a query selection for the
+ * {@link javax.persistence.criteria.CriteriaBuilder#substring(javax.persistence.criteria.Expression, int, int)}
+ * over a String attribute.
+ * @param attribute Attribute to create a substring from.
+ * @param from Substring start.
+ * @param length Substring length.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ QuerySelection<E, String> substring(SingularAttribute<E, String> attribute, int from, int length);
+
+ /**
+ * Create a query selection for the {@link javax.persistence.criteria.CriteriaBuilder#currentDate()}.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ QuerySelection<E, Date> currDate();
+
+ /**
+ * Create a query selection for the {@link javax.persistence.criteria.CriteriaBuilder#currentTime()}.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ QuerySelection<E, Time> currTime();
+
+ /**
+ * Create a query selection for the {@link javax.persistence.criteria.CriteriaBuilder#currentTimestamp()}.
+ * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call.
+ */
+ QuerySelection<E, Timestamp> currTStamp();
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/QuerySelection.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/QuerySelection.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/QuerySelection.java
new file mode 100644
index 0000000..3afb87c
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/criteria/QuerySelection.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.api.criteria;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Selection;
+
+/**
+ * Used for selection queries with the simplified Criteria API.
+ * @author thomashug
+ *
+ * @param <P> Entity type.
+ * @param <X> Result type.
+ */
+public interface QuerySelection<P, X>
+{
+
+ /**
+ * Convert the instance to a criteria selection.
+ * @param query The current criteria query.
+ * @param builder The query builder used to instantiate the selection.
+ * @param path Current path.
+ * @return Criteria API selection instance corresponding to the
+ * QuerySelection implementation.
+ */
+ <R> Selection<X> toSelection(CriteriaQuery<R> query, CriteriaBuilder builder, Path<? extends P> path);
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/DelegateQueryHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/DelegateQueryHandler.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/DelegateQueryHandler.java
new file mode 100644
index 0000000..781b3a1
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/DelegateQueryHandler.java
@@ -0,0 +1,48 @@
+/*
+ * 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.spi;
+
+/**
+ * A marker interface. Used for writing custom query methods:
+ *
+ * public interface RepositoryExtension<E> {
+ * E saveAndFlushAndRefresh(E entity);
+ * }
+ *
+ * public class DelegateRepositoryExtension<E> implements RepositoryExtension<E>, DelegateQueryHandler {
+ * @Inject
+ * private QueryInvocationContext context;
+ *
+ * @Override
+ * public E saveAndFlushAndRefresh(E entity) {
+ * ...
+ * }
+ * }
+ *
+ * The extension is now usable with:
+ *
+ * @Repository
+ * public interface MySimpleRepository
+ * extends RepositoryExtension<Simple>, EntityRepository<Simple, Long> {
+ * }
+ *
+ */
+public interface DelegateQueryHandler
+{
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/QueryInvocationContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/QueryInvocationContext.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/QueryInvocationContext.java
new file mode 100644
index 0000000..6ee4836
--- /dev/null
+++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/spi/QueryInvocationContext.java
@@ -0,0 +1,47 @@
+/*
+ * 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.spi;
+
+import javax.persistence.EntityManager;
+
+/**
+ * Expose the current query invocation to extensions.
+ */
+public interface QueryInvocationContext
+{
+
+ /**
+ * Entity Manager used for the query.
+ */
+ EntityManager getEntityManager();
+
+ /**
+ * The class of the Entity related to the invoked Repository.
+ */
+ Class<?> getEntityClass();
+
+ /**
+ * Given the object parameter is an entity, checks if the entity is
+ * persisted or not.
+ * @param entity Entity object, non nullable.
+ * @return true if the entity is not persisted, false otherwise and if no entity.
+ */
+ boolean isNew(Object entity);
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/pom.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/pom.xml b/deltaspike/modules/data/impl/pom.xml
new file mode 100755
index 0000000..95a677a
--- /dev/null
+++ b/deltaspike/modules/data/impl/pom.xml
@@ -0,0 +1,259 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.deltaspike.modules</groupId>
+ <artifactId>data-module-project</artifactId>
+ <version>0.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>deltaspike-data-module-impl</artifactId>
+ <packaging>bundle</packaging>
+
+ <name>Apache DeltaSpike Data-Module Impl</name>
+
+ <prerequisites>
+ <maven>3.0</maven>
+ </prerequisites>
+
+ <properties>
+ <deltaspike.osgi.export.pkg>
+ org.apache.deltaspike.data.impl.*
+ </deltaspike.osgi.export.pkg>
+ <deltaspike.osgi.import>
+ !org.apache.deltaspike.data.impl.*,
+ *
+ </deltaspike.osgi.import>
+ <cdi.osgi.beans-managed>META-INF/beans.xml</cdi.osgi.beans-managed>
+ </properties>
+
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ </testResource>
+ </testResources>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <argLine>-Xms128m -Xmx1024m -XX:MaxPermSize=256m</argLine>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.bsc.maven</groupId>
+ <artifactId>maven-processor-plugin</artifactId>
+ <version>2.0.7</version>
+ <executions>
+ <execution>
+ <id>process-test</id>
+ <goals>
+ <goal>process-test</goal>
+ </goals>
+ <phase>generate-test-sources</phase>
+ </execution>
+ </executions>
+ <configuration>
+ <processors>
+ <processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
+ </processors>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-jpamodelgen</artifactId>
+ <version>1.2.0.Final</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.spec.javax.ejb</groupId>
+ <artifactId>jboss-ejb-api_3.1_spec</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hibernate.javax.persistence</groupId>
+ <artifactId>hibernate-jpa-2.0-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.geronimo.components</groupId>
+ <artifactId>geronimo-transaction</artifactId>
+ <version>3.1.1</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.deltaspike.modules</groupId>
+ <artifactId>deltaspike-data-module-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.deltaspike.core</groupId>
+ <artifactId>deltaspike-core-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.deltaspike.core</groupId>
+ <artifactId>deltaspike-core-impl</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.deltaspike.modules</groupId>
+ <artifactId>deltaspike-partial-bean-module-api</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.deltaspike.modules</groupId>
+ <artifactId>deltaspike-partial-bean-module-impl</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+
+ <!-- Tests -->
+
+ <dependency>
+ <groupId>org.jboss.arquillian.junit</groupId>
+ <artifactId>arquillian-junit-container</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.protocol</groupId>
+ <artifactId>arquillian-protocol-servlet</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-impl-maven</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>jbossas-build-managed-7</id>
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ </testResource>
+ <testResource>
+ <directory>src/test/resources-jbossas7</directory>
+ </testResource>
+ </testResources>
+ </build>
+ </profile>
+ <profile>
+ <id>glassfish-remote-3.1</id>
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ </testResource>
+ <testResource>
+ <directory>src/test/resources-glassfish</directory>
+ </testResource>
+ </testResources>
+ </build>
+ </profile>
+ <profile>
+ <id>tomee-build-managed</id>
+ <build>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ </testResource>
+ <testResource>
+ <directory>src/test/resources-openejb</directory>
+ </testResource>
+ </testResources>
+ <plugins>
+ <plugin>
+ <groupId>org.bsc.maven</groupId>
+ <artifactId>maven-processor-plugin</artifactId>
+ <version>2.0.7</version>
+ <executions>
+ <execution>
+ <id>process-test</id>
+ <goals>
+ <goal>process-test</goal>
+ </goals>
+ <phase>generate-test-sources</phase>
+ </execution>
+ </executions>
+ <configuration combine.self="override">
+ <processors>
+ <processor>org.apache.openjpa.persistence.meta.AnnotationProcessor6</processor>
+ </processors>
+ <compilerArguments>-Aopenjpa.metamodel=true -Aopenjpa.log=TRACE</compilerArguments>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa-persistence</artifactId>
+ <version>2.2.2</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa-persistence</artifactId>
+ <version>2.2.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.2.5</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
+
+</project>
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/RepositoryDefinitionException.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/RepositoryDefinitionException.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/RepositoryDefinitionException.java
new file mode 100644
index 0000000..ffe5db8
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/RepositoryDefinitionException.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;
+
+import java.text.MessageFormat;
+
+public class RepositoryDefinitionException extends RuntimeException
+{
+
+ private static final long serialVersionUID = 1L;
+
+ private final Class<?> repositoryClass;
+
+ public RepositoryDefinitionException(Class<?> repositoryClass)
+ {
+ this(repositoryClass, null);
+ }
+
+ public RepositoryDefinitionException(Class<?> repositoryClass, Throwable t)
+ {
+ super(t);
+ this.repositoryClass = repositoryClass;
+ }
+
+ @Override
+ public String getMessage()
+ {
+ if (getCause() != null)
+ {
+ return MessageFormat.format("Repository creation for class {0} failed: {1}",
+ repositoryClass, super.getMessage());
+ }
+ else
+ {
+ return MessageFormat.format("Repository creation for class {0} failed. " +
+ "Is it associated with a valid Entity?", repositoryClass);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/RepositoryExtension.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/RepositoryExtension.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/RepositoryExtension.java
new file mode 100755
index 0000000..cd7579d
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/RepositoryExtension.java
@@ -0,0 +1,105 @@
+/*
+ * 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;
+
+import java.lang.reflect.InvocationHandler;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+
+import org.apache.deltaspike.data.api.Repository;
+import org.apache.deltaspike.data.impl.meta.RepositoryComponentsFactory;
+import org.apache.deltaspike.data.impl.meta.unit.PersistenceUnits;
+
+/**
+ * The main extension class for Repositories, based on PartialBeans. Handles following events:<br/>
+ * <br/>
+ * <b>{@code @Observes BeforeBeanDiscovery}</b>:
+ * Scans the classpath for <code>persistence.xml</code> and extracts relevant information out of it.
+ * This includes mainly entity definitions (type, primary keys) which are not declared with annotations.<br/>
+ * <br/>
+ * <b>{@code @Observes ProcessAnnotatedType<X>}</b>:
+ * Looks for types annotated with {@link Repository}. Repositories are validated and preprocessed -
+ * all the methods on the repository are checked and analyzed for better runtime performance.<br/>
+ * <br/>
+ * <b>{@code @Observes AfterBeanDiscovery<X>}</b>:
+ * Raises any definition errors discovered before.
+ *
+ * @author thomashug
+ */
+public class RepositoryExtension implements Extension
+{
+
+ private static final Logger log = Logger.getLogger(RepositoryExtension.class.getName());
+
+ private final List<RepositoryDefinitionException> definitionExceptions =
+ new LinkedList<RepositoryDefinitionException>();
+
+ void beforeBeanDiscovery(@Observes BeforeBeanDiscovery before)
+ {
+ PersistenceUnits.instance().init();
+ }
+
+ <X> void processAnnotatedType(@Observes ProcessAnnotatedType<X> event, BeanManager beanManager)
+ {
+ if (isRepository(event.getAnnotatedType()))
+ {
+ Class<X> repoClass = event.getAnnotatedType().getJavaClass();
+ try
+ {
+ log.log(Level.FINER, "getHandlerClass: Repository annotation detected on {0}",
+ event.getAnnotatedType());
+ RepositoryComponentsFactory.instance().add(repoClass);
+ }
+ catch (RepositoryDefinitionException e)
+ {
+ definitionExceptions.add(e);
+ }
+ catch (Exception e)
+ {
+ definitionExceptions.add(new RepositoryDefinitionException(repoClass, e));
+ }
+ }
+ }
+
+ <X> void addDefinitionErrors(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager)
+ {
+ for (RepositoryDefinitionException ex : definitionExceptions)
+ {
+ afterBeanDiscovery.addDefinitionError(ex);
+ }
+ }
+
+ private <X> boolean isRepository(AnnotatedType<X> annotatedType)
+ {
+ return (annotatedType.isAnnotationPresent(Repository.class) ||
+ annotatedType.getJavaClass().isAnnotationPresent(Repository.class)) &&
+ !InvocationHandler.class.isAssignableFrom(annotatedType.getJavaClass());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditEntityListener.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditEntityListener.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditEntityListener.java
new file mode 100644
index 0000000..1caf039
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditEntityListener.java
@@ -0,0 +1,59 @@
+/*
+ * 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.audit;
+
+import java.util.Set;
+
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+
+import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
+
+public class AuditEntityListener
+{
+
+ @PrePersist
+ public void persist(Object entity)
+ {
+ BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();
+ Set<Bean<?>> beans = beanManager.getBeans(PrePersistAuditListener.class);
+ for (Bean<?> bean : beans)
+ {
+ PrePersistAuditListener result = (PrePersistAuditListener) beanManager.getReference(
+ bean, PrePersistAuditListener.class, beanManager.createCreationalContext(bean));
+ result.prePersist(entity);
+ }
+ }
+
+ @PreUpdate
+ public void update(Object entity)
+ {
+ BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();
+ Set<Bean<?>> beans = beanManager.getBeans(PreUpdateAuditListener.class);
+ for (Bean<?> bean : beans)
+ {
+ PreUpdateAuditListener result = (PreUpdateAuditListener) beanManager.getReference(
+ bean, PreUpdateAuditListener.class, beanManager.createCreationalContext(bean));
+ result.preUpdate(entity);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditPropertyException.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditPropertyException.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditPropertyException.java
new file mode 100644
index 0000000..17ab03a
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditPropertyException.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.impl.audit;
+
+public class AuditPropertyException extends RuntimeException
+{
+
+ private static final long serialVersionUID = -8725707870578473975L;
+
+ public AuditPropertyException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditProvider.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditProvider.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditProvider.java
new file mode 100644
index 0000000..b549c9b
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/AuditProvider.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.apache.deltaspike.data.impl.audit;
+
+import java.util.logging.Logger;
+
+import org.apache.deltaspike.data.impl.property.Property;
+
+abstract class AuditProvider implements PrePersistAuditListener, PreUpdateAuditListener
+{
+
+ protected static final Logger log = Logger.getLogger(AuditProvider.class.getName());
+
+ String propertyName(Object entity, Property<Object> property)
+ {
+ return entity.getClass().getSimpleName() + "." + property.getName();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/PrePersistAuditListener.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/PrePersistAuditListener.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/PrePersistAuditListener.java
new file mode 100644
index 0000000..14d3f6e
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/PrePersistAuditListener.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.apache.deltaspike.data.impl.audit;
+
+public interface PrePersistAuditListener
+{
+
+ void prePersist(Object entity);
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/PreUpdateAuditListener.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/PreUpdateAuditListener.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/PreUpdateAuditListener.java
new file mode 100644
index 0000000..3710196
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/PreUpdateAuditListener.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.apache.deltaspike.data.impl.audit;
+
+public interface PreUpdateAuditListener
+{
+
+ void preUpdate(Object entity);
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/PrincipalProvider.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/PrincipalProvider.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/PrincipalProvider.java
new file mode 100644
index 0000000..6504e7c
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/PrincipalProvider.java
@@ -0,0 +1,94 @@
+/*
+ * 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.audit;
+
+import java.util.Set;
+import java.util.logging.Level;
+
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+
+import org.apache.deltaspike.core.util.metadata.AnnotationInstanceProvider;
+import org.apache.deltaspike.data.api.audit.CurrentUser;
+import org.apache.deltaspike.data.api.audit.ModifiedBy;
+import org.apache.deltaspike.data.impl.property.Property;
+import org.apache.deltaspike.data.impl.property.query.AnnotatedPropertyCriteria;
+import org.apache.deltaspike.data.impl.property.query.PropertyQueries;
+import org.apache.deltaspike.data.impl.property.query.PropertyQuery;
+
+class PrincipalProvider extends AuditProvider
+{
+
+ @Inject
+ private BeanManager manager;
+
+ @Override
+ public void prePersist(Object entity)
+ {
+ updatePrincipal(entity);
+ }
+
+ @Override
+ public void preUpdate(Object entity)
+ {
+ updatePrincipal(entity);
+ }
+
+ private void updatePrincipal(Object entity)
+ {
+ PropertyQuery<Object> query = PropertyQueries.<Object> createQuery(entity.getClass())
+ .addCriteria(new AnnotatedPropertyCriteria(ModifiedBy.class));
+ for (Property<Object> property : query.getWritableResultList())
+ {
+ setProperty(entity, property);
+ }
+ }
+
+ private void setProperty(Object entity, Property<Object> property)
+ {
+ try
+ {
+ Object value = resolvePrincipal(entity, property);
+ property.setValue(entity, value);
+ log.log(Level.FINER, "Updated {0} with {1}", new Object[] { propertyName(entity, property), value });
+ }
+ catch (Exception e)
+ {
+ throw new AuditPropertyException("Failed to write principal to " +
+ propertyName(entity, property), e);
+ }
+ }
+
+ private Object resolvePrincipal(Object entity, Property<Object> property)
+ {
+ CurrentUser principal = AnnotationInstanceProvider.of(CurrentUser.class);
+ Class<?> propertyClass = property.getJavaClass();
+ Set<Bean<?>> beans = manager.getBeans(propertyClass, principal);
+ if (!beans.isEmpty() && beans.size() == 1)
+ {
+ Bean<?> bean = beans.iterator().next();
+ Object result = manager.getReference(bean, propertyClass, manager.createCreationalContext(bean));
+ return result;
+ }
+ throw new IllegalArgumentException("Principal " + (beans.isEmpty() ? "not found" : "not unique") +
+ " for " + propertyName(entity, property));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/TimestampsProvider.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/TimestampsProvider.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/TimestampsProvider.java
new file mode 100644
index 0000000..aeb5104
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/audit/TimestampsProvider.java
@@ -0,0 +1,128 @@
+/*
+ * 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.audit;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+
+import org.apache.deltaspike.data.api.audit.CreatedOn;
+import org.apache.deltaspike.data.api.audit.ModifiedOn;
+import org.apache.deltaspike.data.impl.property.Property;
+import org.apache.deltaspike.data.impl.property.query.AnnotatedPropertyCriteria;
+import org.apache.deltaspike.data.impl.property.query.PropertyQueries;
+import org.apache.deltaspike.data.impl.property.query.PropertyQuery;
+
+/**
+ * Set timestamps on marked properties.
+ */
+class TimestampsProvider extends AuditProvider
+{
+
+ @Override
+ public void prePersist(Object entity)
+ {
+ updateTimestamps(entity, true);
+ }
+
+ @Override
+ public void preUpdate(Object entity)
+ {
+ updateTimestamps(entity, false);
+ }
+
+ private void updateTimestamps(Object entity, boolean create)
+ {
+ long systime = System.currentTimeMillis();
+ List<Property<Object>> properties = new LinkedList<Property<Object>>();
+ PropertyQuery<Object> query = PropertyQueries.<Object> createQuery(entity.getClass())
+ .addCriteria(new AnnotatedPropertyCriteria(ModifiedOn.class));
+ properties.addAll(query.getWritableResultList());
+ if (create)
+ {
+ query = PropertyQueries.<Object> createQuery(entity.getClass())
+ .addCriteria(new AnnotatedPropertyCriteria(CreatedOn.class));
+ properties.addAll(query.getWritableResultList());
+ }
+ for (Property<Object> property : properties)
+ {
+ setProperty(entity, property, systime, create);
+ }
+ }
+
+ private void setProperty(Object entity, Property<Object> property, long systime, boolean create)
+ {
+ try
+ {
+ if (!isCorrectContext(property, create))
+ {
+ return;
+ }
+ Object now = now(property.getJavaClass(), systime);
+ property.setValue(entity, now);
+ log.log(Level.FINER, "Updated property {0} with {1}", new Object[] { propertyName(entity, property), now });
+ }
+ catch (Exception e)
+ {
+ String message = "Failed to set property " + propertyName(entity, property) + ", is this a temporal type?";
+ throw new AuditPropertyException(message, e);
+ }
+ }
+
+ private boolean isCorrectContext(Property<Object> property, boolean create)
+ {
+ if (create && property.getAnnotatedElement().isAnnotationPresent(ModifiedOn.class))
+ {
+ ModifiedOn annotation = property.getAnnotatedElement().getAnnotation(ModifiedOn.class);
+ if (!annotation.onCreate())
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private Object now(Class<?> field, long systime) throws Exception
+ {
+ if (isCalendarClass(field))
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(systime);
+ return cal;
+ }
+ else if (isDateClass(field))
+ {
+ return field.getConstructor(Long.TYPE).newInstance(systime);
+ }
+ throw new IllegalArgumentException("Annotated field is not a date class: " + field);
+ }
+
+ private boolean isCalendarClass(Class<?> field)
+ {
+ return Calendar.class.isAssignableFrom(field);
+ }
+
+ private boolean isDateClass(Class<?> field)
+ {
+ return Date.class.isAssignableFrom(field);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/AnnotatedQueryBuilder.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/AnnotatedQueryBuilder.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/AnnotatedQueryBuilder.java
new file mode 100644
index 0000000..a13a56e
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/AnnotatedQueryBuilder.java
@@ -0,0 +1,87 @@
+/*
+ * 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 static org.apache.deltaspike.data.impl.util.QueryUtils.isNotEmpty;
+
+import java.lang.reflect.Method;
+
+import javax.persistence.EntityManager;
+
+import org.apache.deltaspike.data.api.Query;
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+import org.apache.deltaspike.data.impl.meta.MethodType;
+import org.apache.deltaspike.data.impl.meta.QueryInvocation;
+import org.apache.deltaspike.data.impl.param.Parameters;
+import org.apache.deltaspike.data.impl.util.jpa.QueryStringExtractorFactory;
+
+/**
+ * Create the query based on method annotations.
+ *
+ * @author thomashug
+ */
+@QueryInvocation(MethodType.ANNOTATED)
+public class AnnotatedQueryBuilder extends QueryBuilder
+{
+
+ private final QueryStringExtractorFactory factory = new QueryStringExtractorFactory();
+
+ @Override
+ public Object execute(CdiQueryInvocationContext context)
+ {
+ Method method = context.getMethod();
+ Query query = method.getAnnotation(Query.class);
+ javax.persistence.Query jpaQuery = createJpaQuery(query, context);
+ return context.executeQuery(jpaQuery);
+ }
+
+ private javax.persistence.Query createJpaQuery(Query query, CdiQueryInvocationContext context)
+ {
+ EntityManager entityManager = context.getEntityManager();
+ Parameters params = context.getParams();
+ javax.persistence.Query result = null;
+ if (isNotEmpty(query.named()))
+ {
+ if (!context.hasQueryStringPostProcessors())
+ {
+ result = params.applyTo(entityManager.createNamedQuery(query.named()));
+ }
+ else
+ {
+ javax.persistence.Query namedQuery = entityManager.createNamedQuery(query.named());
+ String named = factory.select(namedQuery).extractFrom(namedQuery);
+ String jpqlQuery = context.applyQueryStringPostProcessors(named);
+ result = params.applyTo(entityManager.createQuery(jpqlQuery));
+ }
+ }
+ else if (query.isNative())
+ {
+ String jpqlQuery = context.applyQueryStringPostProcessors(query.value());
+ result = params.applyTo(entityManager.createNativeQuery(jpqlQuery));
+ }
+ else
+ {
+ String jpqlQuery = context.applyQueryStringPostProcessors(query.value());
+ context.setQueryString(jpqlQuery);
+ result = params.applyTo(entityManager.createQuery(jpqlQuery));
+ }
+ return applyRestrictions(context, result);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java
new file mode 100644
index 0000000..65cbf05
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java
@@ -0,0 +1,113 @@
+/*
+ * 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.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+import org.apache.deltaspike.data.impl.handler.QueryInvocationException;
+import org.apache.deltaspike.data.impl.meta.MethodType;
+import org.apache.deltaspike.data.impl.meta.QueryInvocation;
+import org.apache.deltaspike.data.spi.DelegateQueryHandler;
+
+@QueryInvocation(MethodType.DELEGATE)
+public class DelegateQueryBuilder extends QueryBuilder
+{
+
+ @Inject
+ @Any
+ private Instance<DelegateQueryHandler> delegates;
+
+ @Override
+ public Object execute(CdiQueryInvocationContext context)
+ {
+ try
+ {
+ DelegateQueryHandler delegate = selectDelegate(context.getMethod());
+ if (delegate != null)
+ {
+ return invoke(delegate, context);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new QueryInvocationException(e, context);
+ }
+ throw new QueryInvocationException("No DelegateQueryHandler found", context);
+ }
+
+ private DelegateQueryHandler selectDelegate(Method method)
+ {
+ for (DelegateQueryHandler delegate : delegates)
+ {
+ if (contains(delegate, method))
+ {
+ return delegate;
+ }
+ }
+ return null;
+ }
+
+ private boolean contains(Object obj, Method method)
+ {
+ return extract(obj, method) != null;
+ }
+
+ private Method extract(Object obj, Method method)
+ {
+ try
+ {
+ String name = method.getName();
+ return obj != null ? obj.getClass().getMethod(name, method.getParameterTypes()) : null;
+ }
+ catch (NoSuchMethodException e)
+ {
+ return null;
+ }
+ }
+
+ private Object invoke(DelegateQueryHandler delegate, CdiQueryInvocationContext context)
+ {
+ try
+ {
+ return invoke(delegate, context.getMethod(), context.getMethodParameters());
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected Object invoke(Object target, Method method, Object[] args) throws InvocationTargetException,
+ IllegalAccessException
+ {
+ Method extract = extract(target, method);
+ return extract.invoke(target, args);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/MethodExpressionException.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/MethodExpressionException.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/MethodExpressionException.java
new file mode 100644
index 0000000..3a0320a
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/MethodExpressionException.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+public class MethodExpressionException extends RuntimeException
+{
+
+ private static final long serialVersionUID = 1L;
+ private final String property;
+ private final Class<?> repoClass;
+ private final String method;
+
+ public MethodExpressionException(Class<?> repoClass, String method)
+ {
+ this(null, repoClass, method);
+ }
+
+ public MethodExpressionException(String property, Class<?> repoClass, String method)
+ {
+ this.property = property;
+ this.repoClass = repoClass;
+ this.method = method;
+ }
+
+ @Override
+ public String getMessage()
+ {
+ if (property != null)
+ {
+ return "Invalid property '" + property + "' in method expression " + repoClass.getName() + "." + method;
+ }
+ return "Method '" + method + "'of Repository " + repoClass.getName() + " is not a method expression";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/MethodQueryBuilder.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/MethodQueryBuilder.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/MethodQueryBuilder.java
new file mode 100644
index 0000000..a6ebf09
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/MethodQueryBuilder.java
@@ -0,0 +1,53 @@
+/*
+ * 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 javax.persistence.Query;
+
+import org.apache.deltaspike.data.impl.builder.part.QueryRoot;
+import org.apache.deltaspike.data.impl.handler.CdiQueryInvocationContext;
+import org.apache.deltaspike.data.impl.meta.MethodType;
+import org.apache.deltaspike.data.impl.meta.QueryInvocation;
+import org.apache.deltaspike.data.impl.param.Parameters;
+
+/**
+ * @author thomashug
+ */
+@QueryInvocation(MethodType.PARSE)
+public class MethodQueryBuilder extends QueryBuilder
+{
+
+ @Override
+ public Object execute(CdiQueryInvocationContext context)
+ {
+ Query jpaQuery = createJpaQuery(context);
+ return context.executeQuery(jpaQuery);
+ }
+
+ private Query createJpaQuery(CdiQueryInvocationContext context)
+ {
+ Parameters params = context.getParams();
+ QueryRoot root = context.getRepositoryMethod().getQueryRoot();
+ String jpqlQuery = context.applyQueryStringPostProcessors(root.getJpqlQuery());
+ context.setQueryString(jpqlQuery);
+ Query result = params.applyTo(context.getEntityManager().createQuery(jpqlQuery));
+ return applyRestrictions(context, result);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/OrderDirection.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/OrderDirection.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/OrderDirection.java
new file mode 100644
index 0000000..c715483
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/OrderDirection.java
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+public enum OrderDirection
+{
+
+ ASC
+ {
+ @Override
+ public OrderDirection change()
+ {
+ return DESC;
+ }
+ },
+ DESC
+ {
+ @Override
+ public OrderDirection change()
+ {
+ return ASC;
+ }
+ };
+
+ public abstract OrderDirection change();
+}