diff --git a/spring-data-commons-core/pom.xml b/spring-data-commons-core/pom.xml
index df116c007..9c2a32b67 100644
--- a/spring-data-commons-core/pom.xml
+++ b/spring-data-commons-core/pom.xml
@@ -10,6 +10,11 @@
spring-data-commons-core
jar
Spring Data Commons Core
+
+
+ 2.1.1
+
+
@@ -69,6 +74,26 @@
1.6
true
+
+
+ com.mysema.querydsl
+ querydsl-mongodb
+ ${querydsl.version}
+ true
+
+
+ com.google.code.morphia
+ morphia
+
+
+
+
+
+ com.mysema.querydsl
+ querydsl-apt
+ ${querydsl.version}
+ provided
+
@@ -77,6 +102,23 @@
com.springsource.bundlor
com.springsource.bundlor.maven
+
+ com.mysema.maven
+ maven-apt-plugin
+ 1.0
+
+
+ generate-test-sources
+
+ test-process
+
+
+ target/generated-sources/test-annotations
+ com.mysema.query.apt.QuerydslAnnotationProcessor
+
+
+
+
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/querydsl/EntityPathResolver.java b/spring-data-commons-core/src/main/java/org/springframework/data/querydsl/EntityPathResolver.java
new file mode 100644
index 000000000..389a9aefb
--- /dev/null
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/querydsl/EntityPathResolver.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed 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.springframework.data.querydsl;
+
+import com.mysema.query.types.EntityPath;
+
+/**
+ * Strategy interface to abstract the ways to translate an plain domain class into a {@link EntityPath}.
+ *
+ * @author Oliver Gierke
+ */
+public interface EntityPathResolver {
+
+ EntityPath createPath(Class domainClass);
+}
\ No newline at end of file
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/querydsl/QueryDslUtils.java b/spring-data-commons-core/src/main/java/org/springframework/data/querydsl/QueryDslUtils.java
new file mode 100644
index 000000000..d9a4ca37a
--- /dev/null
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/querydsl/QueryDslUtils.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed 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.springframework.data.querydsl;
+
+
+/**
+ *
+ * @author Oliver Gierke
+ */
+public class QueryDslUtils {
+
+ public static final boolean QUERY_DSL_PRESENT = org.springframework.util.ClassUtils.isPresent(
+ "com.mysema.query.types.Predicate", QueryDslUtils.class.getClassLoader());
+}
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/querydsl/SimpleEntityPathResolver.java b/spring-data-commons-core/src/main/java/org/springframework/data/querydsl/SimpleEntityPathResolver.java
new file mode 100644
index 000000000..6d360001e
--- /dev/null
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/querydsl/SimpleEntityPathResolver.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed 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.springframework.data.querydsl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import org.springframework.util.ClassUtils;
+import org.springframework.util.ReflectionUtils;
+
+import com.mysema.query.types.EntityPath;
+
+/**
+ * Simple implementation of {@link EntityPathResolver} to lookup a query
+ * class by reflection and using the static field of the same type.
+ *
+ * @author Oliver Gierke
+ */
+public enum SimpleEntityPathResolver implements EntityPathResolver {
+
+ INSTANCE;
+
+ private static final String NO_CLASS_FOUND_TEMPLATE =
+ "Did not find a query class %s for domain class %s!";
+ private static final String NO_FIELD_FOUND_TEMPLATE =
+ "Did not find a static field of the same type in %s!";
+
+
+ /**
+ * Creates an {@link EntityPath} instance for the given domain class.
+ * Tries to lookup a class matching the naming convention (prepend Q to
+ * the simple name of the class, same package) and find a static field
+ * of the same type in it.
+ *
+ * @param domainClass
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public EntityPath createPath(Class domainClass) {
+
+ String pathClassName = getQueryClassName(domainClass);
+
+ try {
+ Class> pathClass =
+ ClassUtils.forName(pathClassName,
+ SimpleEntityPathResolver.class.getClassLoader());
+ Field field = getStaticFieldOfType(pathClass);
+
+ if (field == null) {
+ throw new IllegalStateException(String.format(
+ NO_FIELD_FOUND_TEMPLATE, pathClass));
+ } else {
+ return (EntityPath) ReflectionUtils
+ .getField(field, null);
+ }
+
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(String.format(
+ NO_CLASS_FOUND_TEMPLATE, pathClassName,
+ domainClass.getName()), e);
+ }
+ }
+
+
+ /**
+ * Returns the first static field of the given type inside the given
+ * type.
+ *
+ * @param type
+ * @return
+ */
+ private Field getStaticFieldOfType(Class> type) {
+
+ for (Field field : type.getDeclaredFields()) {
+
+ boolean isStatic = Modifier.isStatic(field.getModifiers());
+ boolean hasSameType = type.equals(field.getType());
+
+ if (isStatic && hasSameType) {
+ return field;
+ }
+ }
+
+ Class> superclass = type.getSuperclass();
+ return Object.class.equals(superclass) ? null
+ : getStaticFieldOfType(superclass);
+ }
+
+
+ /**
+ * Returns the name of the query class for the given domain class.
+ *
+ * @param domainClass
+ * @return
+ */
+ private String getQueryClassName(Class> domainClass) {
+
+ String simpleClassName = ClassUtils.getShortName(domainClass);
+ return String.format("%s.Q%s%s",
+ domainClass.getPackage().getName(),
+ getClassBase(simpleClassName), domainClass.getSimpleName());
+ }
+
+
+ /**
+ * Analyzes the short class name and potentially returns the outer
+ * class.
+ *
+ * @param shortName
+ * @return
+ */
+ private String getClassBase(String shortName) {
+
+ String[] parts = shortName.split("\\.");
+
+ if (parts.length < 2) {
+ return "";
+ }
+
+ return parts[0] + "_";
+ }
+}
\ No newline at end of file
diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/querydsl/SimpleEntityPathResolverUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/querydsl/SimpleEntityPathResolverUnitTests.java
new file mode 100644
index 000000000..146f25a8a
--- /dev/null
+++ b/spring-data-commons-core/src/test/java/org/springframework/data/querydsl/SimpleEntityPathResolverUnitTests.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed 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.springframework.data.querydsl;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.springframework.data.querydsl.EntityPathResolver;
+import org.springframework.data.querydsl.SimpleEntityPathResolver;
+import org.springframework.data.querydsl.QSimpleEntityPathResolverUnitTests_NamedUser;
+import org.springframework.data.querydsl.QSimpleEntityPathResolverUnitTests_Sample;
+import org.springframework.data.querydsl.QUser;
+
+import com.mysema.query.annotations.QueryEntity;
+
+
+/**
+ * Unit test for {@link SimpleEntityPathResolver}.
+ *
+ * @author Oliver Gierke
+ */
+public class SimpleEntityPathResolverUnitTests {
+
+ EntityPathResolver resolver = SimpleEntityPathResolver.INSTANCE;
+
+
+ @Test
+ public void createsRepositoryFromDomainClassCorrectly() throws Exception {
+
+ assertThat(resolver.createPath(User.class), is(QUser.class));
+ }
+
+
+ @Test
+ public void resolvesEntityPathForInnerClassCorrectly() throws Exception {
+
+ assertThat(resolver.createPath(NamedUser.class),
+ is(QSimpleEntityPathResolverUnitTests_NamedUser.class));
+ }
+
+
+ @Test(expected = IllegalArgumentException.class)
+ public void rejectsClassWithoutQueryClassConfrmingToTheNamingScheme()
+ throws Exception {
+
+ resolver.createPath(QSimpleEntityPathResolverUnitTests_Sample.class);
+ }
+
+ @QueryEntity
+ static class Sample {
+
+ }
+
+ @QueryEntity
+ static class NamedUser {
+
+ }
+}
diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/querydsl/User.java b/spring-data-commons-core/src/test/java/org/springframework/data/querydsl/User.java
new file mode 100644
index 000000000..1547360fe
--- /dev/null
+++ b/spring-data-commons-core/src/test/java/org/springframework/data/querydsl/User.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed 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.springframework.data.querydsl;
+
+import com.mysema.query.annotations.QueryEntity;
+
+/**
+ * @author Oliver Gierke
+ */
+@QueryEntity
+public class User {
+
+}
diff --git a/spring-data-commons-core/template.mf b/spring-data-commons-core/template.mf
index f55c1819d..dac7166fa 100644
--- a/spring-data-commons-core/template.mf
+++ b/spring-data-commons-core/template.mf
@@ -5,6 +5,7 @@ Bundle-ManifestVersion: 2
Import-Package:
sun.reflect;version="0";resolution:=optional
Import-Template:
+ com.mysema.query.*;version="${querydsl.version:[=.=.=,+1.0.0)}";resolution:=optional,
org.springframework.aop.*;version="${org.springframework.version:[=.=.=,+1.0.0)}",
org.springframework.beans.*;version="${org.springframework.version:[=.=.=,+1.0.0)}",
org.springframework.core.*;version="${org.springframework.version:[=.=.=,+1.0.0)}",
diff --git a/spring-data-commons-parent/pom.xml b/spring-data-commons-parent/pom.xml
index cea7c716e..96145b9d2 100644
--- a/spring-data-commons-parent/pom.xml
+++ b/spring-data-commons-parent/pom.xml
@@ -361,6 +361,14 @@
Spring Framework Maven Snapshot Repository
http://maven.springframework.org/snapshot
+
+ querydsl
+ Mysema QueryDsl
+ http://source.mysema.com/maven2/releases
+
+ false
+
+
diff --git a/src/main/resources/changelog.txt b/src/main/resources/changelog.txt
index 5db709af9..1c35db42f 100644
--- a/src/main/resources/changelog.txt
+++ b/src/main/resources/changelog.txt
@@ -5,6 +5,7 @@ Changes in version 1.0.1
----------------------------------------
General
+* Extracted Querydsl support code from JPA and Mongo modules (DATACMNS-32)
* Implementations of Page, Pageable and Sort are now serializable (DATACMNS-30)
Changes in version 1.0.0 (2011-04-18)