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:06 UTC

[06/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/criteria/selection/numeric/Sum.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/numeric/Sum.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/numeric/Sum.java
new file mode 100644
index 0000000..4048cc1
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/numeric/Sum.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.criteria.selection.numeric;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Selection;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.apache.deltaspike.data.impl.criteria.selection.SingularAttributeSelection;
+
+public class Sum<P, X extends Number> extends SingularAttributeSelection<P, X>
+{
+
+    public Sum(SingularAttribute<P, X> attribute)
+    {
+        super(attribute);
+    }
+
+    @Override
+    public <R> Selection<X> toSelection(CriteriaQuery<R> query, CriteriaBuilder builder, Path<? extends P> path)
+    {
+        return builder.sum(path.get(attribute));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/Lower.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/Lower.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/Lower.java
new file mode 100644
index 0000000..aec917a
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/Lower.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.criteria.selection.strings;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Selection;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.apache.deltaspike.data.impl.criteria.selection.SingularAttributeSelection;
+
+public class Lower<P> extends SingularAttributeSelection<P, String>
+{
+
+    public Lower(SingularAttribute<P, String> attribute)
+    {
+        super(attribute);
+    }
+
+    @Override
+    public <R> Selection<String> toSelection(CriteriaQuery<R> query, CriteriaBuilder builder, Path<? extends P> path)
+    {
+        return builder.lower(path.get(getAttribute()));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/SubstringFrom.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/SubstringFrom.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/SubstringFrom.java
new file mode 100644
index 0000000..906ac30
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/SubstringFrom.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.criteria.selection.strings;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Selection;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.apache.deltaspike.data.impl.criteria.selection.SingularAttributeSelection;
+
+public class SubstringFrom<P> extends SingularAttributeSelection<P, String>
+{
+
+    private final int from;
+
+    public SubstringFrom(SingularAttribute<P, String> attribute, int from)
+    {
+        super(attribute);
+        this.from = from;
+    }
+
+    @Override
+    public <R> Selection<String> toSelection(CriteriaQuery<R> query, CriteriaBuilder builder, Path<? extends P> path)
+    {
+        return builder.substring(path.get(getAttribute()), from);
+    }
+
+    int getFrom()
+    {
+        return from;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/SubstringFromTo.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/SubstringFromTo.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/SubstringFromTo.java
new file mode 100644
index 0000000..5fcecad
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/SubstringFromTo.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.criteria.selection.strings;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Selection;
+import javax.persistence.metamodel.SingularAttribute;
+
+public class SubstringFromTo<P> extends SubstringFrom<P>
+{
+
+    private final int length;
+
+    public SubstringFromTo(SingularAttribute<P, String> attribute, int from, int length)
+    {
+        super(attribute, from);
+        this.length = length;
+    }
+
+    @Override
+    public <R> Selection<String> toSelection(CriteriaQuery<R> query, CriteriaBuilder builder, Path<? extends P> path)
+    {
+        return builder.substring(path.get(getAttribute()), getFrom(), length);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/Upper.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/Upper.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/Upper.java
new file mode 100644
index 0000000..a7e9166
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/strings/Upper.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.criteria.selection.strings;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Selection;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.apache.deltaspike.data.impl.criteria.selection.SingularAttributeSelection;
+
+public class Upper<P> extends SingularAttributeSelection<P, String>
+{
+
+    public Upper(SingularAttribute<P, String> attribute)
+    {
+        super(attribute);
+    }
+
+    @Override
+    public <R> Selection<String> toSelection(CriteriaQuery<R> query, CriteriaBuilder builder, Path<? extends P> path)
+    {
+        return builder.upper(path.get(getAttribute()));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/temporal/CurrentDate.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/temporal/CurrentDate.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/temporal/CurrentDate.java
new file mode 100644
index 0000000..afc9355
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/temporal/CurrentDate.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.impl.criteria.selection.temporal;
+
+import java.sql.Date;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Selection;
+
+import org.apache.deltaspike.data.api.criteria.QuerySelection;
+
+public class CurrentDate<P> implements QuerySelection<P, Date>
+{
+
+    @Override
+    public <R> Selection<Date> toSelection(CriteriaQuery<R> query, CriteriaBuilder builder, Path<? extends P> path)
+    {
+        return builder.currentDate();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/temporal/CurrentTime.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/temporal/CurrentTime.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/temporal/CurrentTime.java
new file mode 100644
index 0000000..b75d4fd
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/temporal/CurrentTime.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.impl.criteria.selection.temporal;
+
+import java.sql.Time;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Selection;
+
+import org.apache.deltaspike.data.api.criteria.QuerySelection;
+
+public class CurrentTime<P> implements QuerySelection<P, Time>
+{
+
+    @Override
+    public <R> Selection<Time> toSelection(CriteriaQuery<R> query, CriteriaBuilder builder, Path<? extends P> path)
+    {
+        return builder.currentTime();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/temporal/CurrentTimestamp.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/temporal/CurrentTimestamp.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/temporal/CurrentTimestamp.java
new file mode 100644
index 0000000..f079621
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/criteria/selection/temporal/CurrentTimestamp.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.data.impl.criteria.selection.temporal;
+
+import java.sql.Timestamp;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Selection;
+
+import org.apache.deltaspike.data.api.criteria.QuerySelection;
+
+public class CurrentTimestamp<P> implements QuerySelection<P, Timestamp>
+{
+
+    @Override
+    public <R> Selection<Timestamp> toSelection(CriteriaQuery<R> query, CriteriaBuilder builder, Path<? extends P> path)
+    {
+        return builder.currentTimestamp();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/AbstractDelegateQueryHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/AbstractDelegateQueryHandler.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/AbstractDelegateQueryHandler.java
new file mode 100644
index 0000000..488196c
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/AbstractDelegateQueryHandler.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.handler;
+
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+
+import org.apache.deltaspike.data.spi.DelegateQueryHandler;
+
+public abstract class AbstractDelegateQueryHandler<E> implements DelegateQueryHandler
+{
+
+    @Inject
+    protected CdiQueryInvocationContext context;
+
+    @SuppressWarnings("unchecked")
+    protected Class<E> getEntityClass()
+    {
+        return (Class<E>) context.getEntityClass();
+    }
+
+    protected EntityManager getEntityManager()
+    {
+        return context.getEntityManager();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryContextHolder.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryContextHolder.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryContextHolder.java
new file mode 100644
index 0000000..c17e4f9
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryContextHolder.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.impl.handler;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Produces;
+
+@ApplicationScoped
+public class CdiQueryContextHolder
+{
+
+    private final ThreadLocal<CdiQueryInvocationContext> context = new ThreadLocal<CdiQueryInvocationContext>();
+
+    public void set(CdiQueryInvocationContext context)
+    {
+        this.context.set(context);
+    }
+
+    @Produces
+    public CdiQueryInvocationContext get()
+    {
+        return context.get();
+    }
+
+    public void dispose()
+    {
+        context.remove();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
new file mode 100644
index 0000000..ac1bdf0
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
@@ -0,0 +1,172 @@
+/*
+ * 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.handler;
+
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.apache.deltaspike.data.impl.meta.RepositoryMethod;
+import org.apache.deltaspike.data.impl.param.Parameters;
+import org.apache.deltaspike.data.spi.QueryInvocationContext;
+
+public class CdiQueryInvocationContext implements QueryInvocationContext
+{
+
+    private final EntityManager entityManager;
+    private final Parameters params;
+    private final Class<?> entityClass;
+    private final Object proxy;
+    private final Method method;
+    private final Object[] args;
+    private final RepositoryMethod repoMethod;
+    private final List<QueryStringPostProcessor> queryPostProcessors;
+    private final List<JpaQueryPostProcessor> jpaPostProcessors;
+
+    private String queryString;
+
+    public CdiQueryInvocationContext(Object proxy, Method method, Object[] args, RepositoryMethod repoMethod,
+            EntityManager entityManager)
+    {
+        this.entityManager = entityManager;
+        this.args = args == null ? new Object[] {} : args;
+        this.params = Parameters.create(method, this.args);
+        this.proxy = proxy;
+        this.method = method;
+        this.repoMethod = repoMethod;
+        this.entityClass = repoMethod.getRepository().getEntityClass();
+        this.queryPostProcessors = new LinkedList<QueryStringPostProcessor>();
+        this.jpaPostProcessors = new LinkedList<JpaQueryPostProcessor>();
+    }
+
+    @Override
+    public EntityManager getEntityManager()
+    {
+        return entityManager;
+    }
+
+    @Override
+    public boolean isNew(Object entity)
+    {
+        try
+        {
+            return entityManager.getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier(entity) == null;
+        }
+        catch (IllegalArgumentException e)
+        {
+            // Not an entity
+            return false;
+        }
+    }
+
+    @Override
+    public Class<?> getEntityClass()
+    {
+        return entityClass;
+    }
+
+    public Object proceed() throws Exception
+    {
+        return method.invoke(proxy, args);
+    }
+
+    public Method getMethod()
+    {
+        return method;
+    }
+
+    public Object[] getMethodParameters()
+    {
+        return args;
+    }
+
+    public void addQueryStringPostProcessor(QueryStringPostProcessor postProcessor)
+    {
+        queryPostProcessors.add(postProcessor);
+    }
+
+    public void addJpaQueryPostProcessor(JpaQueryPostProcessor postProcessor)
+    {
+        jpaPostProcessors.add(postProcessor);
+    }
+
+    public void removeJpaQueryPostProcessor(JpaQueryPostProcessor postProcessor)
+    {
+        jpaPostProcessors.remove(postProcessor);
+    }
+
+    public boolean hasQueryStringPostProcessors()
+    {
+        return !queryPostProcessors.isEmpty();
+    }
+
+    public String applyQueryStringPostProcessors(String queryString)
+    {
+        String result = queryString;
+        for (QueryStringPostProcessor processor : queryPostProcessors)
+        {
+            result = processor.postProcess(result);
+        }
+        return result;
+    }
+
+    public Query applyJpaQueryPostProcessors(Query query)
+    {
+        Query result = query;
+        for (JpaQueryPostProcessor processor : jpaPostProcessors)
+        {
+            result = processor.postProcess(this, result);
+        }
+        return result;
+    }
+
+    public Object executeQuery(Query jpaQuery)
+    {
+        return repoMethod.getQueryProcessor().executeQuery(jpaQuery);
+    }
+
+    public Parameters getParams()
+    {
+        return params;
+    }
+
+    public RepositoryMethod getRepositoryMethod()
+    {
+        return repoMethod;
+    }
+
+    public String getQueryString()
+    {
+        return queryString;
+    }
+
+    public void setQueryString(String queryString)
+    {
+        this.queryString = queryString;
+    }
+
+    public List<QueryStringPostProcessor> getQueryStringPostProcessors()
+    {
+        return queryPostProcessors;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CriteriaSupportHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CriteriaSupportHandler.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CriteriaSupportHandler.java
new file mode 100644
index 0000000..cac105f
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CriteriaSupportHandler.java
@@ -0,0 +1,179 @@
+/*
+ * 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.handler;
+
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+
+import javax.enterprise.context.Dependent;
+import javax.persistence.criteria.JoinType;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.apache.deltaspike.data.api.criteria.Criteria;
+import org.apache.deltaspike.data.api.criteria.CriteriaSupport;
+import org.apache.deltaspike.data.api.criteria.QuerySelection;
+import org.apache.deltaspike.data.impl.criteria.QueryCriteria;
+import org.apache.deltaspike.data.impl.criteria.selection.AttributeQuerySelection;
+import org.apache.deltaspike.data.impl.criteria.selection.numeric.Abs;
+import org.apache.deltaspike.data.impl.criteria.selection.numeric.Avg;
+import org.apache.deltaspike.data.impl.criteria.selection.numeric.Count;
+import org.apache.deltaspike.data.impl.criteria.selection.numeric.Max;
+import org.apache.deltaspike.data.impl.criteria.selection.numeric.Min;
+import org.apache.deltaspike.data.impl.criteria.selection.numeric.Modulo;
+import org.apache.deltaspike.data.impl.criteria.selection.numeric.Neg;
+import org.apache.deltaspike.data.impl.criteria.selection.numeric.Sum;
+import org.apache.deltaspike.data.impl.criteria.selection.strings.Lower;
+import org.apache.deltaspike.data.impl.criteria.selection.strings.SubstringFrom;
+import org.apache.deltaspike.data.impl.criteria.selection.strings.SubstringFromTo;
+import org.apache.deltaspike.data.impl.criteria.selection.strings.Upper;
+import org.apache.deltaspike.data.impl.criteria.selection.temporal.CurrentDate;
+import org.apache.deltaspike.data.impl.criteria.selection.temporal.CurrentTime;
+import org.apache.deltaspike.data.impl.criteria.selection.temporal.CurrentTimestamp;
+
+@Dependent
+public class CriteriaSupportHandler<E> extends AbstractDelegateQueryHandler<E> implements CriteriaSupport<E>
+{
+
+    @Override
+    public Criteria<E, E> criteria()
+    {
+        return new QueryCriteria<E, E>(getEntityClass(), getEntityClass(), getEntityManager());
+    }
+
+    @Override
+    public <T> Criteria<T, T> where(Class<T> clazz)
+    {
+        return new QueryCriteria<T, T>(clazz, clazz, getEntityManager());
+    }
+
+    @Override
+    public <T> Criteria<T, T> where(Class<T> clazz, JoinType joinType)
+    {
+        return new QueryCriteria<T, T>(clazz, clazz, getEntityManager(), joinType);
+    }
+
+    @Override
+    public <X> QuerySelection<E, X> attribute(SingularAttribute<E, X> attribute)
+    {
+        return new AttributeQuerySelection<E, X>(attribute);
+    }
+
+    // ----------------------------------------------------------------------------
+    // NUMERIC QUERY SELECTION
+    // ----------------------------------------------------------------------------
+
+    @Override
+    public <N extends Number> QuerySelection<E, N> abs(SingularAttribute<E, N> attribute)
+    {
+        return new Abs<E, N>(attribute);
+    }
+
+    @Override
+    public <N extends Number> QuerySelection<E, N> avg(SingularAttribute<E, N> attribute)
+    {
+        return new Avg<E, N>(attribute);
+    }
+
+    @Override
+    public <N extends Number> QuerySelection<E, N> count(SingularAttribute<E, N> attribute)
+    {
+        return new Count<E, N>(attribute);
+    }
+
+    @Override
+    public <N extends Number> QuerySelection<E, N> max(SingularAttribute<E, N> attribute)
+    {
+        return new Max<E, N>(attribute);
+    }
+
+    @Override
+    public <N extends Number> QuerySelection<E, N> min(SingularAttribute<E, N> attribute)
+    {
+        return new Min<E, N>(attribute);
+    }
+
+    @Override
+    public <N extends Number> QuerySelection<E, N> neg(SingularAttribute<E, N> attribute)
+    {
+        return new Neg<E, N>(attribute);
+    }
+
+    @Override
+    public <N extends Number> QuerySelection<E, N> sum(SingularAttribute<E, N> attribute)
+    {
+        return new Sum<E, N>(attribute);
+    }
+
+    @Override
+    public QuerySelection<E, Integer> modulo(SingularAttribute<E, Integer> attribute, Integer modulo)
+    {
+        return new Modulo<E>(attribute, modulo);
+    }
+
+    // ----------------------------------------------------------------------------
+    // STRING QUERY SELECTION
+    // ----------------------------------------------------------------------------
+
+    @Override
+    public QuerySelection<E, String> upper(SingularAttribute<E, String> attribute)
+    {
+        return new Upper<E>(attribute);
+    }
+
+    @Override
+    public QuerySelection<E, String> lower(SingularAttribute<E, String> attribute)
+    {
+        return new Lower<E>(attribute);
+    }
+
+    @Override
+    public QuerySelection<E, String> substring(SingularAttribute<E, String> attribute, int from)
+    {
+        return new SubstringFrom<E>(attribute, from);
+    }
+
+    @Override
+    public QuerySelection<E, String> substring(SingularAttribute<E, String> attribute, int from, int length)
+    {
+        return new SubstringFromTo<E>(attribute, from, length);
+    }
+
+    // ----------------------------------------------------------------------------
+    // TEMPORAL QUERY SELECTION
+    // ----------------------------------------------------------------------------
+
+    @Override
+    public QuerySelection<E, Date> currDate()
+    {
+        return new CurrentDate<E>();
+    }
+
+    @Override
+    public QuerySelection<E, Time> currTime()
+    {
+        return new CurrentTime<E>();
+    }
+
+    @Override
+    public QuerySelection<E, Timestamp> currTStamp()
+    {
+        return new CurrentTimestamp<E>();
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerLookup.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerLookup.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerLookup.java
new file mode 100644
index 0000000..6d866ca
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityManagerLookup.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.handler;
+
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+
+import org.apache.deltaspike.data.api.EntityManagerResolver;
+import org.apache.deltaspike.data.impl.meta.RepositoryComponent;
+
+public class EntityManagerLookup
+{
+
+    @Inject
+    @Any
+    private Instance<EntityManager> entityManager;
+
+    @Inject
+    @Any
+    private Instance<EntityManagerResolver> entityManagerResolver;
+
+    public EntityManager lookupFor(RepositoryComponent repository)
+    {
+        if (repository.hasEntityManagerResolver())
+        {
+            EntityManagerResolver resolver = lookupResolver(repository.getEntityManagerResolverClass());
+            EntityManager result = resolver.resolveEntityManager();
+            if (repository.getEntityManagerFlushMode() != null)
+            {
+                result.setFlushMode(repository.getEntityManagerFlushMode());
+            }
+        }
+        return entityManager.get();
+    }
+
+    private EntityManagerResolver lookupResolver(
+            Class<? extends EntityManagerResolver> resolverClass)
+    {
+        return entityManagerResolver.select(resolverClass).get();
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandler.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandler.java
new file mode 100755
index 0000000..7497031
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandler.java
@@ -0,0 +1,328 @@
+/*
+ * 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.handler;
+
+import static org.apache.deltaspike.data.impl.util.EntityUtils.entityName;
+import static org.apache.deltaspike.data.impl.util.QueryUtils.isEmpty;
+import static org.apache.deltaspike.data.impl.util.QueryUtils.isString;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.apache.deltaspike.data.api.EntityRepository;
+import org.apache.deltaspike.data.impl.builder.QueryBuilder;
+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.spi.DelegateQueryHandler;
+import org.apache.deltaspike.data.spi.QueryInvocationContext;
+
+/**
+ * Implement basic functionality from the {@link EntityRepository}.
+ *
+ * @author thomashug
+ *
+ * @param <E>   Entity type.
+ * @param <PK>  Primary key type, must be a serializable.
+ */
+public class EntityRepositoryHandler<E, PK extends Serializable>
+        implements EntityRepository<E, PK>, DelegateQueryHandler
+{
+
+    private static final Logger log = Logger.getLogger(EntityRepositoryHandler.class.getName());
+
+    @Inject
+    private QueryInvocationContext context;
+
+    @Override
+    public E save(E entity)
+    {
+        if (context.isNew(entity))
+        {
+            entityManager().persist(entity);
+            return entity;
+        }
+        return entityManager().merge(entity);
+    }
+
+    @Override
+    public E saveAndFlush(E entity)
+    {
+        E result = save(entity);
+        flush();
+        return result;
+    }
+
+    @Override
+    public E saveAndFlushAndRefresh(E entity)
+    {
+        E result = saveAndFlush(entity);
+        entityManager().refresh(result);
+        return result;
+    }
+
+    @Override
+    public void refresh(E entity)
+    {
+        entityManager().refresh(entity);
+    }
+
+    @Override
+    public E findBy(PK primaryKey)
+    {
+        return entityManager().find(entityClass(), primaryKey);
+    }
+
+    @Override
+    public List<E> findBy(E example, SingularAttribute<E, ?>... attributes)
+    {
+        return findBy(example, -1, -1, attributes);
+    }
+
+    @Override
+    public List<E> findBy(E example, int start, int max, SingularAttribute<E, ?>... attributes)
+    {
+        return executeExampleQuery(example, start, max, false, attributes);
+    }
+
+    @Override
+    public List<E> findByLike(E example, SingularAttribute<E, ?>... attributes)
+    {
+        return findByLike(example, -1, -1, attributes);
+    }
+
+    @Override
+    public List<E> findByLike(E example, int start, int max, SingularAttribute<E, ?>... attributes)
+    {
+        return executeExampleQuery(example, start, max, true, attributes);
+    }
+
+    @Override
+    public List<E> findAll()
+    {
+        return entityManager().createQuery(allQuery(), entityClass()).getResultList();
+    }
+
+    @Override
+    public List<E> findAll(int start, int max)
+    {
+        TypedQuery<E> query = entityManager().createQuery(allQuery(), entityClass());
+        if (start > 0)
+        {
+            query.setFirstResult(start);
+        }
+        if (max > 0)
+        {
+            query.setMaxResults(max);
+        }
+        return query.getResultList();
+    }
+
+    @Override
+    public Long count()
+    {
+        return entityManager().createQuery(countQuery(), Long.class).getSingleResult();
+    }
+
+    @Override
+    public Long count(E example, SingularAttribute<E, ?>... attributes)
+    {
+        return executeCountQuery(example, false, attributes);
+    }
+
+    @Override
+    public Long countLike(E example, SingularAttribute<E, ?>... attributes)
+    {
+        return executeCountQuery(example, true, attributes);
+    }
+
+    @Override
+    public void remove(E entity)
+    {
+        entityManager().remove(entity);
+    }
+
+    @Override
+    public void removeAndFlush(E entity)
+    {
+        entityManager().remove(entity);
+        flush();
+    }
+
+    @Override
+    public void flush()
+    {
+        entityManager().flush();
+    }
+
+    public EntityManager entityManager()
+    {
+        return context.getEntityManager();
+    }
+
+    public CriteriaQuery<E> criteriaQuery()
+    {
+        return entityManager().getCriteriaBuilder().createQuery(entityClass());
+    }
+
+    @SuppressWarnings("unchecked")
+    public Class<E> entityClass()
+    {
+        return (Class<E>) context.getEntityClass();
+    }
+
+    // ----------------------------------------------------------------------------
+    // PRIVATE
+    // ----------------------------------------------------------------------------
+
+    private String allQuery()
+    {
+        return QueryBuilder.selectQuery(entityName(entityClass()));
+    }
+
+    private String countQuery()
+    {
+        return QueryBuilder.countQuery(entityName(entityClass()));
+    }
+
+    private String exampleQuery(String queryBase, List<Property<Object>> properties, boolean useLikeOperator)
+    {
+        StringBuilder jpqlQuery = new StringBuilder(queryBase).append(" where ");
+        jpqlQuery.append(prepareWhere(properties, useLikeOperator));
+        return jpqlQuery.toString();
+    }
+
+    private void addParameters(TypedQuery<?> query, E example, List<Property<Object>> properties,
+            boolean useLikeOperator)
+    {
+        for (Property<Object> property : properties)
+        {
+            property.setAccessible();
+            query.setParameter(property.getName(), transform(property.getValue(example), useLikeOperator));
+        }
+    }
+
+    private Object transform(Object value, final boolean useLikeOperator)
+    {
+        if (value != null && useLikeOperator && isString(value))
+        {
+            // seems to be an OpenJPA bug:
+            // parameters in querys fail validation, e.g. UPPER(e.name) like UPPER(:name)
+            String result = ((String) value).toUpperCase();
+            return "%" + result + "%";
+        }
+        return value;
+    }
+
+    private String prepareWhere(List<Property<Object>> properties, boolean useLikeOperator)
+    {
+        Iterator<Property<Object>> iterator = properties.iterator();
+        StringBuilder result = new StringBuilder();
+        while (iterator.hasNext())
+        {
+            Property<Object> property = iterator.next();
+            String name = property.getName();
+            if (useLikeOperator && property.getJavaClass().getName().equals(String.class.getName()))
+            {
+                result.append("UPPER(e.").append(name).append(") like :").append(name)
+                        .append(iterator.hasNext() ? " and " : "");
+            }
+            else
+            {
+                result.append("e.").append(name).append(" = :").append(name).append(iterator.hasNext() ? " and " : "");
+            }
+        }
+        return result.toString();
+    }
+
+    private List<String> extractPropertyNames(SingularAttribute<E, ?>... attributes)
+    {
+        List<String> result = new ArrayList<String>(attributes.length);
+        for (SingularAttribute<E, ?> attribute : attributes)
+        {
+            result.add(attribute.getName());
+        }
+        return result;
+    }
+
+    private List<Property<Object>> extractProperties(SingularAttribute<E, ?>... attributes)
+    {
+        List<String> names = extractPropertyNames(attributes);
+        List<Property<Object>> properties = PropertyQueries.createQuery(entityClass())
+                .addCriteria(new NamedPropertyCriteria(names.toArray(new String[] {}))).getResultList();
+        return properties;
+    }
+
+    private List<E> executeExampleQuery(E example, int start, int max, boolean useLikeOperator,
+            SingularAttribute<E, ?>... attributes)
+    {
+        // Not sure if this should be the intended behaviour
+        // when we don't get any attributes maybe we should
+        // return a empty list instead of all results
+        if (isEmpty(attributes))
+        {
+            return findAll(start, max);
+        }
+
+        List<Property<Object>> properties = extractProperties(attributes);
+        String jpqlQuery = exampleQuery(allQuery(), properties, useLikeOperator);
+        log.log(Level.FINER, "findBy|findByLike: Created query {0}", jpqlQuery);
+        TypedQuery<E> query = entityManager().createQuery(jpqlQuery, entityClass());
+
+        // set starting position
+        if (start > 0)
+        {
+            query.setFirstResult(start);
+        }
+
+        // set maximum results
+        if (max > 0)
+        {
+            query.setMaxResults(max);
+        }
+
+        addParameters(query, example, properties, useLikeOperator);
+        return query.getResultList();
+    }
+
+    private Long executeCountQuery(E example, boolean useLikeOperator, SingularAttribute<E, ?>... attributes)
+    {
+        if (isEmpty(attributes))
+        {
+            return count();
+        }
+        List<Property<Object>> properties = extractProperties(attributes);
+        String jpqlQuery = exampleQuery(countQuery(), properties, useLikeOperator);
+        log.log(Level.FINER, "count: Created query {0}", jpqlQuery);
+        TypedQuery<Long> query = entityManager().createQuery(jpqlQuery, Long.class);
+        addParameters(query, example, properties, useLikeOperator);
+        return query.getSingleResult();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/JpaQueryPostProcessor.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/JpaQueryPostProcessor.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/JpaQueryPostProcessor.java
new file mode 100644
index 0000000..cb8213a
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/JpaQueryPostProcessor.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.handler;
+
+import javax.persistence.Query;
+
+public interface JpaQueryPostProcessor
+{
+
+    Query postProcess(CdiQueryInvocationContext context, 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/handler/QueryHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java
new file mode 100755
index 0000000..5645ff3
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java
@@ -0,0 +1,129 @@
+/*
+ * 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.handler;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.apache.deltaspike.data.api.Repository;
+import org.apache.deltaspike.data.impl.builder.QueryBuilder;
+import org.apache.deltaspike.data.impl.builder.QueryBuilderFactory;
+import org.apache.deltaspike.data.impl.meta.Initialized;
+import org.apache.deltaspike.data.impl.meta.RepositoryComponent;
+import org.apache.deltaspike.data.impl.meta.RepositoryComponents;
+import org.apache.deltaspike.data.impl.meta.RepositoryMethod;
+
+/**
+ * Entry point for query processing.
+ *
+ * @author thomashug
+ */
+@Repository
+@ApplicationScoped
+public class QueryHandler implements Serializable, InvocationHandler
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private static final Logger log = Logger.getLogger(QueryHandler.class.getName());
+
+    @Inject
+    private QueryBuilderFactory queryBuilder;
+
+    @Inject
+    @Initialized
+    private RepositoryComponents components;
+
+    @Inject
+    private CdiQueryContextHolder context;
+
+    @Inject
+    private EntityManagerLookup entityManagerLookup;
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+    {
+        CdiQueryInvocationContext queryContext = null;
+        try
+        {
+            List<Class<?>> candidates = extractFromProxy(proxy.getClass());
+            RepositoryComponent repo = components.lookupComponent(candidates);
+            RepositoryMethod repoMethod = components.lookupMethod(repo.getRepositoryClass(), method);
+            queryContext = createContext(proxy, method, args, repo, repoMethod);
+            QueryBuilder builder = queryBuilder.build(repoMethod);
+            Object result = builder.execute(queryContext);
+            return result;
+        }
+        catch (Exception e)
+        {
+            log.log(Level.SEVERE, "Query execution error", e);
+            if (queryContext != null)
+            {
+                throw new QueryInvocationException(e, queryContext);
+            }
+            throw new QueryInvocationException(e, proxy.getClass(), method);
+        }
+        finally
+        {
+            context.dispose();
+        }
+    }
+
+    private CdiQueryInvocationContext createContext(Object proxy, Method method,
+            Object[] args, RepositoryComponent repo, RepositoryMethod repoMethod)
+    {
+        CdiQueryInvocationContext queryContext = new CdiQueryInvocationContext(proxy, method, args, repoMethod,
+                entityManagerLookup.lookupFor(repo));
+        context.set(queryContext);
+        return queryContext;
+    }
+
+    protected List<Class<?>> extractFromProxy(Class<?> proxyClass)
+    {
+        List<Class<?>> result = new LinkedList<Class<?>>();
+        result.add(proxyClass);
+        if (isInterfaceProxy(proxyClass))
+        {
+            result.addAll(Arrays.asList(proxyClass.getInterfaces()));
+        }
+        else
+        {
+            result.add(proxyClass.getSuperclass());
+        }
+        return result;
+    }
+
+    private boolean isInterfaceProxy(Class<?> proxyClass)
+    {
+        Class<?>[] interfaces = proxyClass.getInterfaces();
+        return Proxy.class.equals(proxyClass.getSuperclass()) &&
+                interfaces != null && interfaces.length > 0;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryInvocationException.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryInvocationException.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryInvocationException.java
new file mode 100644
index 0000000..2b8c216
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryInvocationException.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.handler;
+
+import java.lang.reflect.Method;
+
+public class QueryInvocationException extends RuntimeException
+{
+
+    private static final long serialVersionUID = 1L;
+
+    public QueryInvocationException(Throwable t, CdiQueryInvocationContext context)
+    {
+        super(createMessage(context, t), t);
+    }
+
+    public QueryInvocationException(String message, CdiQueryInvocationContext context)
+    {
+        super(createMessage(context));
+    }
+
+    public QueryInvocationException(Throwable t, Class<?> proxy, Method method)
+    {
+        super(createMessage(proxy, method, t), t);
+    }
+
+    private static String createMessage(CdiQueryInvocationContext context)
+    {
+        StringBuilder builder = new StringBuilder();
+        builder.append("Failed calling Repository: [");
+        builder.append("Repository=").append(context.getRepositoryMethod()
+                .getRepository().getRepositoryClass().getName()).append(",");
+        builder.append("entity=").append(context.getEntityClass().getName()).append(",");
+        builder.append("method=").append(context.getMethod().getName()).append(",");
+        builder.append("query=").append(context.getQueryString()).append("],");
+        return builder.toString();
+    }
+
+    private static String createMessage(CdiQueryInvocationContext context, Throwable t)
+    {
+        StringBuilder builder = new StringBuilder(createMessage(context));
+        builder.append("exception=").append(t.getClass()).append(",message=").append(t.getMessage());
+        return builder.toString();
+    }
+
+    private static String createMessage(Class<?> proxy, Method method, Throwable t)
+    {
+        StringBuilder builder = new StringBuilder();
+        builder.append("Exception calling Repository: [");
+        builder.append("Repository=").append(proxy).append(",");
+        builder.append("method=").append(method.getName()).append("],");
+        builder.append("exception=").append(t.getClass()).append(",message=").append(t.getMessage());
+        return builder.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryStringPostProcessor.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryStringPostProcessor.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryStringPostProcessor.java
new file mode 100644
index 0000000..3bf580f
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryStringPostProcessor.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.handler;
+
+public interface QueryStringPostProcessor
+{
+
+    String postProcess(String queryString);
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/Initialized.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/Initialized.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/Initialized.java
new file mode 100644
index 0000000..bbfe2ff
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/Initialized.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.meta;
+
+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;
+
+/**
+ * CDI qualifier. Mainly used for producers which create an initialized instance.
+ *
+ * @author thomashug
+ */
+@Qualifier
+@Target({ TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+public @interface Initialized
+{
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/MethodType.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/MethodType.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/MethodType.java
new file mode 100644
index 0000000..3b9d72c
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/MethodType.java
@@ -0,0 +1,38 @@
+/*
+ * 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.meta;
+
+
+/**
+ * Repository method type. Stands for
+ * <ul>
+ * <li>Delegated methods - the Repository has a concrete implementation for this or the method is implemented in the
+ * {@link org.apache.deltaspike.data.impl.handler.EntityRepositoryHandler}.</li>
+ * <li>Annotated method - the query is defined via a Query annotation.</li>
+ * <li>The method defines a query expression by its name.</li>
+ * </ul>
+ *
+ * @author thomashug
+ */
+public enum MethodType
+{
+
+    DELEGATE, ANNOTATED, PARSE
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/NonEntityException.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/NonEntityException.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/NonEntityException.java
new file mode 100644
index 0000000..bdcfdaa
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/NonEntityException.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.impl.meta;
+
+public class NonEntityException extends RuntimeException
+{
+
+    private static final long serialVersionUID = 1L;
+
+    public NonEntityException()
+    {
+        super();
+    }
+
+    public NonEntityException(String message)
+    {
+        super(message);
+    }
+
+    public NonEntityException(Throwable cause)
+    {
+        super(cause);
+    }
+
+    public NonEntityException(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/meta/QueryInvocation.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/QueryInvocation.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/QueryInvocation.java
new file mode 100644
index 0000000..817a365
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/QueryInvocation.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.impl.meta;
+
+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;
+
+/**
+ * CDI qualifier - defines the kind of query invocation. Mainly used to resolve the correct query builder by method
+ * type.
+ *
+ * @author thomashug
+ */
+@Qualifier
+@Target({ TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+public @interface QueryInvocation
+{
+
+    MethodType value();
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/QueryInvocationLiteral.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/QueryInvocationLiteral.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/QueryInvocationLiteral.java
new file mode 100644
index 0000000..a57e02d
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/QueryInvocationLiteral.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.impl.meta;
+
+import javax.enterprise.util.AnnotationLiteral;
+
+/**
+ * Utility class to construct a qualifier and resolve a dependency programmatically.
+ *
+ * @author thomashug
+ */
+@SuppressWarnings("all")
+public class QueryInvocationLiteral extends AnnotationLiteral<QueryInvocation>
+        implements QueryInvocation
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private final MethodType methodType;
+
+    public QueryInvocationLiteral(MethodType methodType)
+    {
+        this.methodType = methodType;
+    }
+
+    @Override
+    public MethodType value()
+    {
+        return methodType;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponent.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponent.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponent.java
new file mode 100644
index 0000000..ff3aac9
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponent.java
@@ -0,0 +1,213 @@
+/*
+ * 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.meta;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.persistence.FlushModeType;
+
+import org.apache.deltaspike.data.api.EntityManagerConfig;
+import org.apache.deltaspike.data.api.EntityManagerResolver;
+import org.apache.deltaspike.data.api.Repository;
+import org.apache.deltaspike.data.impl.util.EntityUtils;
+
+/**
+ * Stores information about a specific Repository. Extracts information about:
+ * <ul>
+ * <li>The Repository class</li>
+ * <li>The target entity the Repository is for</li>
+ * <li>The primary key class</li>
+ * <li>All methods of the Repository.</li>
+ * </ul>
+ *
+ * @author thomashug
+ */
+public class RepositoryComponent
+{
+
+    private static final Logger log = Logger.getLogger(RepositoryComponent.class.getName());
+
+    private final Class<?> repoClass;
+    private final RepositoryEntity entityClass;
+    private final Class<? extends EntityManagerResolver> entityManagerResolver;
+    private final FlushModeType entityManagerFlushMode;
+
+    private final Map<Method, RepositoryMethod> methods = new HashMap<Method, RepositoryMethod>();
+
+    public RepositoryComponent(Class<?> repoClass, RepositoryEntity entityClass)
+    {
+        if (entityClass == null)
+        {
+            throw new IllegalArgumentException("Entity class cannot be null");
+        }
+        this.repoClass = repoClass;
+        this.entityClass = entityClass;
+        this.entityManagerResolver = extractEntityManagerResolver(repoClass);
+        this.entityManagerFlushMode = extractEntityManagerFlushMode(repoClass);
+        initialize();
+    }
+
+    public String getEntityName()
+    {
+        return EntityUtils.entityName(entityClass.getEntityClass());
+    }
+
+    /**
+     * Looks up method meta data by a Method object.
+     *
+     * @param method    The Repository method.
+     * @return Method meta data.
+     */
+    public RepositoryMethod lookupMethod(Method method)
+    {
+        return methods.get(method);
+    }
+
+    /**
+     * Looks up the method type by a Method object.
+     *
+     * @param method    The Repository method.
+     * @return Method meta data.
+     */
+    public MethodType lookupMethodType(Method method)
+    {
+        return lookupMethod(method).getMethodType();
+    }
+
+    /**
+     * Gets the entity class related the Repository.
+     *
+     * @return The class of the entity related to the Repository.
+     */
+    public Class<?> getEntityClass()
+    {
+        return entityClass.getEntityClass();
+    }
+
+    /**
+     * Gets the entity primary key class related the Repository.
+     *
+     * @return The class of the entity primary key related to the Repository.
+     */
+    public Class<? extends Serializable> getPrimaryKey()
+    {
+        return entityClass.getPrimaryClass();
+    }
+
+    /**
+     * Returns the original Repository class this meta data is related to.
+     *
+     * @return The class of the Repository.
+     */
+    public Class<?> getRepositoryClass()
+    {
+        return repoClass;
+    }
+
+    public String getMethodPrefix()
+    {
+        return repoClass.getAnnotation(Repository.class).methodPrefix();
+    }
+
+    public boolean hasEntityManagerResolver()
+    {
+        return getEntityManagerResolverClass() != null;
+    }
+
+    public Class<? extends EntityManagerResolver> getEntityManagerResolverClass()
+    {
+        return entityManagerResolver;
+    }
+
+    public FlushModeType getEntityManagerFlushMode()
+    {
+        return entityManagerFlushMode;
+    }
+
+    private void initialize()
+    {
+        Collection<Class<?>> allImplemented = collectClasses();
+        for (Class<?> implemented : allImplemented)
+        {
+            Method[] repoClassMethods = implemented.getDeclaredMethods();
+            for (Method repoClassMethod : repoClassMethods)
+            {
+                RepositoryMethod repoMethod = new RepositoryMethod(repoClassMethod, this);
+                methods.put(repoClassMethod, repoMethod);
+            }
+        }
+    }
+
+    private Set<Class<?>> collectClasses()
+    {
+        Set<Class<?>> result = new HashSet<Class<?>>();
+        Class<?> current = repoClass;
+        while (!Object.class.equals(current) && current != null)
+        {
+            result.add(current);
+            Class<?>[] interfaces = current.getInterfaces();
+            if (interfaces != null)
+            {
+                result.addAll(Arrays.asList(interfaces));
+            }
+            current = current.getSuperclass();
+        }
+        log.log(Level.FINER, "collectClasses(): Found {0} for {1}", new Object[] { result, repoClass });
+        return result;
+    }
+
+    private Class<? extends EntityManagerResolver> extractEntityManagerResolver(Class<?> clazz)
+    {
+        EntityManagerConfig config = extractEntityManagerConfig(clazz);
+        if (config != null && !EntityManagerResolver.class.equals(config.entityManagerResolver()))
+        {
+            return config.entityManagerResolver();
+        }
+        return null;
+    }
+
+    private FlushModeType extractEntityManagerFlushMode(Class<?> clazz)
+    {
+        EntityManagerConfig config = extractEntityManagerConfig(clazz);
+        if (config != null)
+        {
+            return config.flushMode();
+        }
+        return null;
+    }
+
+    private EntityManagerConfig extractEntityManagerConfig(Class<?> clazz)
+    {
+        if (clazz.isAnnotationPresent(EntityManagerConfig.class))
+        {
+            return clazz.getAnnotation(EntityManagerConfig.class);
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponents.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponents.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponents.java
new file mode 100644
index 0000000..f8ee622
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponents.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.meta;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.deltaspike.data.impl.RepositoryDefinitionException;
+import org.apache.deltaspike.data.impl.meta.extractor.AnnotationMetadataExtractor;
+import org.apache.deltaspike.data.impl.meta.extractor.MetadataExtractor;
+import org.apache.deltaspike.data.impl.meta.extractor.TypeMetadataExtractor;
+
+/**
+ * Convenience class to access Repository and Repository method meta data.
+ * Acts as repository for Repository related meta data.
+ *
+ * @author thomashug
+ */
+public class RepositoryComponents implements Serializable
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private final Map<Class<?>, RepositoryComponent> repos = new HashMap<Class<?>, RepositoryComponent>();
+
+    private final List<MetadataExtractor> extractors = Arrays.asList(new AnnotationMetadataExtractor(),
+            new TypeMetadataExtractor());
+
+    /**
+     * Add a Repository class to the meta data repository.
+     *
+     * @param repoClass  The repo class.
+     * @return {@code true} if Repository class has been added, {@code false} otherwise.
+     */
+    public void add(Class<?> repoClass)
+    {
+        RepositoryEntity entityClass = extractEntityMetaData(repoClass);
+        RepositoryComponent repo = new RepositoryComponent(repoClass, entityClass);
+        repos.put(repoClass, repo);
+    }
+
+    /**
+     * Repository access - lookup the Repository component meta data from a list of candidate classes.
+     * Depending on the implementation, proxy objects might have been modified so the actual class
+     * does not match the original Repository class.
+     *
+     * @param candidateClasses  List of candidates to check.
+     * @return A {@link RepositoryComponent} corresponding to the repoClass parameter.
+     */
+    public RepositoryComponent lookupComponent(List<Class<?>> candidateClasses)
+    {
+        for (Class<?> repoClass : candidateClasses)
+        {
+            if (repos.containsKey(repoClass))
+            {
+                return repos.get(repoClass);
+            }
+        }
+        throw new RuntimeException("Unknown Repository classes " + candidateClasses);
+    }
+
+    /**
+     * Repository access - lookup the Repository component meta data for a specific Repository class.
+     *
+     * @param repoClass  The Repository class to lookup the method for
+     * @return A {@link RepositoryComponent} corresponding to the repoClass parameter.
+     */
+    public RepositoryComponent lookupComponent(Class<?> repoClass)
+    {
+        if (repos.containsKey(repoClass))
+        {
+            return repos.get(repoClass);
+        }
+        throw new RuntimeException("Unknown Repository class " + repoClass.getName());
+    }
+
+    /**
+     * Repository access - lookup method information for a specific Repository class.
+     *
+     * @param repoClass The Repository class to lookup the method for
+     * @param method    The Method object to get Repository meta data for.
+     * @return A {@link RepositoryMethod} corresponding to the method parameter.
+     */
+    public RepositoryMethod lookupMethod(Class<?> repoClass, Method method)
+    {
+        return lookupComponent(repoClass).lookupMethod(method);
+    }
+
+    private RepositoryEntity extractEntityMetaData(Class<?> repoClass)
+    {
+        for (MetadataExtractor extractor : extractors)
+        {
+            RepositoryEntity entity = extractor.extract(repoClass);
+            if (entity != null)
+            {
+                return entity;
+            }
+        }
+        throw new RepositoryDefinitionException(repoClass);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ae1a7147/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponentsFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponentsFactory.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponentsFactory.java
new file mode 100644
index 0000000..4368135
--- /dev/null
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryComponentsFactory.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.impl.meta;
+
+import javax.enterprise.inject.Produces;
+
+/**
+ * Repository components producer. Exposes a singleton both programmatically as well
+ * as over a CDI producer.
+ *
+ * @author thomashug
+ */
+public class RepositoryComponentsFactory
+{
+
+    private static RepositoryComponents components = new RepositoryComponents();
+
+    public static RepositoryComponents instance()
+    {
+        return components;
+    }
+
+    @Produces
+    @Initialized
+    public RepositoryComponents producer()
+    {
+        return instance();
+    }
+
+}