diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 78f88b85f..c958525a3 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -21,12 +21,22 @@
org.springframework
spring-tx
+
+ org.springframework
+ spring-test
+ test
+
org.springframework.data
spring-data-document-core
+
+ org.springframework.data
+ spring-data-commons-core
+ ${project.version}
+
@@ -78,12 +88,20 @@
mockito-all
test
+
+
+ org.hamcrest
+ hamcrest-all
+ 1.1
+ test
+
junit
junit
+
org.mongodb
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoExceptionTranslator.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoExceptionTranslator.java
new file mode 100644
index 000000000..013876701
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoExceptionTranslator.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 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.document.mongodb;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.support.PersistenceExceptionTranslator;
+
+
+/**
+ * Simple {@link PersistenceExceptionTranslator} for Mongo.
+ *
+ * @author Oliver Gierke
+ */
+public class MongoExceptionTranslator implements PersistenceExceptionTranslator {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.dao.support.PersistenceExceptionTranslator#
+ * translateExceptionIfPossible(java.lang.RuntimeException)
+ */
+ public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
+
+ return MongoDbUtils.translateMongoExceptionIfPossible(ex);
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoEntityInformation.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoEntityInformation.java
new file mode 100644
index 000000000..1d62c6d50
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoEntityInformation.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2010 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.document.mongodb.repository;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.List;
+
+import org.springframework.data.repository.support.IdAware;
+import org.springframework.data.repository.support.IsNewAware;
+import org.springframework.util.ReflectionUtils;
+
+
+/**
+ * Expects the domain class to contain a field with a name out of the following
+ * {@value #FIELD_NAMES}.
+ *
+ * @author Oliver Gierke
+ */
+class MongoEntityInformation implements IsNewAware, IdAware {
+
+ private final List FIELD_NAMES = Arrays.asList("ID", "id", "_id");
+ private Field field;
+
+
+ /**
+ * Creates a new {@link MongoEntityInformation}.
+ *
+ * @param domainClass
+ */
+ public MongoEntityInformation(Class> domainClass) {
+
+ for (String name : FIELD_NAMES) {
+
+ Field field = ReflectionUtils.findField(domainClass, name);
+
+ if (field != null) {
+ ReflectionUtils.makeAccessible(field);
+ this.field = field;
+ break;
+ }
+ }
+
+ if (this.field == null) {
+ throw new IllegalArgumentException(String.format(
+ "Given domain class %s does not contain an id property!",
+ domainClass.getName()));
+ }
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.repository.support.IsNewAware#isNew(java.lang
+ * .Object)
+ */
+ public boolean isNew(Object entity) {
+
+ return null == ReflectionUtils.getField(field, entity);
+ }
+
+
+ /**
+ * Returns the actual field name containing the id.
+ *
+ * @return
+ */
+ public String getFieldName() {
+
+ return field.getName();
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.repository.support.IdAware#getId(java.lang.Object
+ * )
+ */
+ public Object getId(Object entity) {
+
+ return ReflectionUtils.getField(field, entity);
+ }
+}
\ No newline at end of file
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java
new file mode 100644
index 000000000..c06ba3b3d
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2002-2010 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.document.mongodb.repository;
+
+import java.util.List;
+
+import org.springframework.data.document.mongodb.MongoTemplate;
+import org.springframework.data.repository.query.QueryMethod;
+import org.springframework.data.repository.query.RepositoryQuery;
+import org.springframework.data.repository.query.SimpleParameterAccessor;
+import org.springframework.data.repository.query.parser.PartTree;
+import org.springframework.util.Assert;
+
+import com.mongodb.DBObject;
+
+
+/**
+ * {@link RepositoryQuery} implementation for Mongo.
+ *
+ * @author Oliver Gierke
+ */
+public class MongoQuery implements RepositoryQuery {
+
+ private final QueryMethod method;
+ private final MongoTemplate template;
+ private final PartTree tree;
+
+
+ /**
+ * Creates a new {@link MongoQuery} from the given {@link QueryMethod} and
+ * {@link MongoTemplate}.
+ *
+ * @param method
+ * @param template
+ */
+ public MongoQuery(QueryMethod method, MongoTemplate template) {
+
+ Assert.notNull(template);
+ Assert.notNull(method);
+ Assert.isTrue(!method.isPageQuery(),
+ "Pagination queries not supported!");
+
+ this.method = method;
+ this.template = template;
+ this.tree = new PartTree(method.getName(), method.getDomainClass());
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.repository.query.RepositoryQuery#execute(java
+ * .lang.Object[])
+ */
+ public Object execute(Object[] parameters) {
+
+ SimpleParameterAccessor accessor =
+ new SimpleParameterAccessor(method.getParameters(), parameters);
+ MongoQueryCreator creator = new MongoQueryCreator(tree, accessor);
+ DBObject query = creator.createQuery();
+
+ List> result =
+ template.query(template.getDefaultCollectionName(), query,
+ method.getDomainClass());
+
+ if (method.isCollectionQuery()) {
+ return result;
+ } else {
+ return result.isEmpty() ? null : result.get(0);
+ }
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java
new file mode 100644
index 000000000..1b97ee0d9
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2002-2010 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.document.mongodb.repository;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.repository.query.SimpleParameterAccessor;
+import org.springframework.data.repository.query.SimpleParameterAccessor.BindableParameterIterator;
+import org.springframework.data.repository.query.parser.AbstractQueryCreator;
+import org.springframework.data.repository.query.parser.Part;
+import org.springframework.data.repository.query.parser.Part.Type;
+import org.springframework.data.repository.query.parser.PartTree;
+
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+
+
+/**
+ * Custom query creator to create Mongo criterias.
+ *
+ * @author Oliver Gierke
+ */
+class MongoQueryCreator extends AbstractQueryCreator {
+
+ /**
+ * Creates a new {@link MongoQueryCreator} from the given {@link PartTree}
+ * and {@link SimpleParameterAccessor}.
+ *
+ * @param tree
+ * @param accessor
+ */
+ public MongoQueryCreator(PartTree tree, SimpleParameterAccessor accessor) {
+
+ super(tree, accessor);
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.document.mongodb.repository.AbstractQueryCreator
+ * #create(org.springframework.data.repository.query.parser.Part,
+ * org.springframework
+ * .data.repository.query.SimpleParameterAccessor.BindableParameterIterator)
+ */
+ @Override
+ protected QueryBuilder create(Part part, BindableParameterIterator iterator) {
+
+ return from(part.getType(), QueryBuilder.start(part.getProperty()),
+ iterator);
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.document.mongodb.repository.AbstractQueryCreator
+ * #handlePart(org.springframework.data.repository.query.parser.Part,
+ * org.springframework
+ * .data.repository.query.SimpleParameterAccessor.BindableParameterIterator)
+ */
+ @Override
+ protected QueryBuilder and(Part part, QueryBuilder base,
+ BindableParameterIterator iterator) {
+
+ return from(part.getType(), base.and(part.getProperty()), iterator);
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.document.mongodb.repository.AbstractQueryCreator
+ * #reduceCriterias(java.lang.Object, java.lang.Object)
+ */
+ @Override
+ protected QueryBuilder or(QueryBuilder base, QueryBuilder criteria) {
+
+ base.or(criteria.get());
+ return base;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.document.mongodb.repository.AbstractQueryCreator
+ * #finalize(java.lang.Object)
+ */
+ @Override
+ protected DBObject finalize(QueryBuilder criteria, Sort sort) {
+
+ // TODO: apply sorting
+ return criteria.get();
+ }
+
+
+ /**
+ * Populates the given {@link Criteria} depending on the {@link Type} given.
+ *
+ * @param type
+ * @param criteria
+ * @param parameters
+ * @return
+ */
+ private QueryBuilder from(Type type, QueryBuilder criteria,
+ BindableParameterIterator parameters) {
+
+ switch (type) {
+ case GREATER_THAN:
+ return criteria.greaterThan(parameters.next());
+ case LESS_THAN:
+ return criteria.lessThan(parameters.next());
+ case IS_NOT_NULL:
+ return criteria.notEquals(null);
+ case IS_NULL:
+ return criteria.is(null);
+ case SIMPLE_PROPERTY:
+ return criteria.is(parameters.next());
+ case NEGATING_SIMPLE_PROPERTY:
+ return criteria.notEquals(parameters.next());
+ }
+
+ throw new IllegalArgumentException("Unsupported keyword!");
+ }
+}
\ No newline at end of file
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepository.java
new file mode 100644
index 000000000..7d9b53856
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepository.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2002-2010 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.document.mongodb.repository;
+
+import java.io.Serializable;
+
+import org.springframework.data.repository.Repository;
+
+
+/**
+ * Mongo specific {@link Repository} interface.
+ *
+ * @author Oliver Gierke
+ */
+public interface MongoRepository extends
+ Repository {
+
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBean.java
new file mode 100644
index 000000000..71bc673f4
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBean.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2002-2010 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.document.mongodb.repository;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.data.document.mongodb.MongoTemplate;
+import org.springframework.data.repository.Repository;
+import org.springframework.data.repository.query.QueryLookupStrategy;
+import org.springframework.data.repository.query.QueryLookupStrategy.Key;
+import org.springframework.data.repository.query.QueryMethod;
+import org.springframework.data.repository.query.RepositoryQuery;
+import org.springframework.data.repository.support.RepositoryFactoryBeanSupport;
+import org.springframework.data.repository.support.RepositoryFactorySupport;
+import org.springframework.data.repository.support.RepositorySupport;
+import org.springframework.util.Assert;
+
+
+/**
+ * {@link FactoryBean} to create {@link MongoRepository} instances.
+ *
+ * @author Oliver Gierke
+ */
+public class MongoRepositoryFactoryBean extends
+ RepositoryFactoryBeanSupport> {
+
+ private MongoTemplate template;
+
+
+ /**
+ * Configures the {@link MongoTemplate} to be used.
+ *
+ * @param template the template to set
+ */
+ public void setTemplate(MongoTemplate template) {
+
+ this.template = template;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.repository.support.RepositoryFactoryBeanSupport
+ * #createRepositoryFactory()
+ */
+ @Override
+ protected RepositoryFactorySupport createRepositoryFactory() {
+
+ return new MongoRepositoryFactory();
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.repository.support.RepositoryFactoryBeanSupport
+ * #afterPropertiesSet()
+ */
+ @Override
+ public void afterPropertiesSet() {
+
+ super.afterPropertiesSet();
+ Assert.notNull(template, "MongoTemplate must not be null!");
+ }
+
+ /**
+ * Repository to create {@link MongoRepository} instances.
+ *
+ * @author Oliver Gierke
+ */
+ private class MongoRepositoryFactory extends RepositoryFactorySupport {
+
+ @Override
+ protected RepositorySupport getTargetRepository(
+ Class domainClass) {
+
+ return new SimpleMongoRepository(domainClass, template);
+ }
+
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected Class extends RepositorySupport> getRepositoryClass() {
+
+ return SimpleMongoRepository.class;
+ }
+
+
+ @Override
+ protected QueryLookupStrategy getQueryLookupStrategy(Key key) {
+
+ return new MongoQueryLookupStrategy();
+ }
+
+ /**
+ * {@link QueryLookupStrategy} to create {@link MongoQuery} instances.
+ *
+ * @author Oliver Gierke
+ */
+ private class MongoQueryLookupStrategy implements QueryLookupStrategy {
+
+ public RepositoryQuery resolveQuery(Method method) {
+
+ return new MongoQuery(new QueryMethod(method), template);
+ }
+ }
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java
new file mode 100644
index 000000000..7ba978c3b
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2002-2010 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.document.mongodb.repository;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.data.document.mongodb.MongoTemplate;
+import org.springframework.data.repository.support.IsNewAware;
+import org.springframework.data.repository.support.RepositorySupport;
+import org.springframework.util.Assert;
+
+import com.mongodb.QueryBuilder;
+
+
+/**
+ * Repository base implementation for Mongo.
+ *
+ * @author Oliver Gierke
+ */
+public class SimpleMongoRepository extends
+ RepositorySupport {
+
+ private final MongoTemplate template;
+ private MongoEntityInformation entityInformation;
+
+
+ /**
+ * @param domainClass
+ * @param template
+ */
+ public SimpleMongoRepository(Class domainClass, MongoTemplate template) {
+
+ super(domainClass);
+
+ Assert.notNull(template);
+ this.template = template;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.repository.Repository#save(java.lang.Object)
+ */
+ public T save(T entity) {
+
+ template.save(entity);
+ return entity;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.repository.Repository#save(java.lang.Iterable)
+ */
+ public List save(Iterable extends T> entities) {
+
+ List result = new ArrayList();
+
+ for (T entity : entities) {
+ template.save(entity);
+ result.add(entity);
+ }
+
+ return result;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.repository.Repository#findById(java.io.Serializable
+ * )
+ */
+ public T findById(ID id) {
+
+ List result =
+ template.query(template.getDefaultCollectionName(),
+ QueryBuilder.start("_id").get(), getDomainClass());
+
+ return result.isEmpty() ? null : result.get(0);
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.repository.Repository#exists(java.io.Serializable
+ * )
+ */
+ public boolean exists(ID id) {
+
+ return findById(id) == null;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.data.repository.Repository#findAll()
+ */
+ public List findAll() {
+
+ return template.getCollection(getDomainClass());
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.data.repository.Repository#count()
+ */
+ public Long count() {
+
+ return Long.valueOf(findAll().size());
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.repository.Repository#delete(java.lang.Object)
+ */
+ public void delete(T entity) {
+
+ QueryBuilder builder =
+ QueryBuilder.start(entityInformation.getFieldName()).is(
+ entityInformation.getId(entity));
+ template.remove(builder.get());
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.repository.Repository#delete(java.lang.Iterable)
+ */
+ public void delete(Iterable extends T> entities) {
+
+ for (T entity : entities) {
+ delete(entity);
+ }
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.data.repository.Repository#deleteAll()
+ */
+ public void deleteAll() {
+
+ template.dropCollection(template.getDefaultCollectionName());
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.data.repository.support.RepositorySupport#
+ * createIsNewStrategy(java.lang.Class)
+ */
+ @Override
+ protected IsNewAware createIsNewStrategy(Class> domainClass) {
+
+ if (entityInformation == null) {
+ this.entityInformation = new MongoEntityInformation(domainClass);
+ }
+
+ return entityInformation;
+ }
+}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoEntityInformationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoEntityInformationUnitTests.java
new file mode 100644
index 000000000..68e935ccb
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoEntityInformationUnitTests.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2002-2010 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.document.mongodb.repository;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+
+/**
+ * Unit test for {@link MongoEntityInformation}.
+ *
+ * @author Oliver Gierke
+ */
+public class MongoEntityInformationUnitTests {
+
+ @Test
+ public void findsIdField() throws Exception {
+
+ MongoEntityInformation isNewAware =
+ new MongoEntityInformation(Person.class);
+
+ Person person = new Person();
+ assertThat(isNewAware.isNew(person), is(true));
+ person.id = 1L;
+ assertThat(isNewAware.isNew(person), is(false));
+ }
+
+
+ @Test(expected = IllegalArgumentException.class)
+ public void rejectsClassIfNoIdField() throws Exception {
+
+ new MongoEntityInformation(InvalidPerson.class);
+ }
+
+ class Person {
+
+ Long id;
+ }
+
+ class InvalidPerson {
+
+ Long foo;
+ }
+}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java
new file mode 100644
index 000000000..6fc1bb714
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2002-2010 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.document.mongodb.repository;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.data.document.mongodb.Person;
+import org.springframework.data.repository.query.Parameters;
+import org.springframework.data.repository.query.SimpleParameterAccessor;
+import org.springframework.data.repository.query.parser.PartTree;
+
+
+/**
+ * Unit test for {@link MongoQueryCreator}.
+ *
+ * @author Oliver Gierke
+ */
+public class MongoQueryCreatorUnitTests {
+
+ Method findByFirstname;
+ Method findByFirstnameAndFriend;
+
+
+ @Before
+ public void setUp() throws SecurityException, NoSuchMethodException {
+
+ findByFirstname =
+ Sample.class.getMethod("findByFirstname", String.class);
+ findByFirstnameAndFriend =
+ Sample.class.getMethod("findByFirstnameAndFriend",
+ String.class, Person.class);
+
+ }
+
+
+ @Test
+ public void createsQueryCorrectly() throws Exception {
+
+ PartTree tree = new PartTree("findByFirstname", Person.class);
+
+ MongoQueryCreator creator =
+ new MongoQueryCreator(tree, new SimpleParameterAccessor(
+ new Parameters(findByFirstname),
+ new Object[] { "Oliver" }));
+
+ creator.createQuery();
+
+ creator =
+ new MongoQueryCreator(new PartTree("findByFirstnameAndFriend",
+ Person.class), new SimpleParameterAccessor(
+ new Parameters(findByFirstnameAndFriend), new Object[] {
+ "Oliver", new Person() }));
+ creator.createQuery();
+ }
+
+ interface Sample {
+
+ List findByFirstname(String firstname);
+
+
+ List findByFirstnameAndFriend(String firstname, Person friend);
+ }
+}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Person.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Person.java
new file mode 100644
index 000000000..95e20a6b7
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Person.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2002-2010 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.document.mongodb.repository;
+
+import org.bson.types.ObjectId;
+
+
+/**
+ * Sample domain class.
+ *
+ * @author Oliver Gierke
+ */
+public class Person {
+
+ private String id;
+ private String firstname;
+ private String lastname;
+
+
+ public Person() {
+
+ this.id = ObjectId.get().toString();
+ }
+
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(String id) {
+
+ this.id = id;
+ }
+
+
+ /**
+ * @return the id
+ */
+ public String getId() {
+
+ return id;
+ }
+
+
+ /**
+ * @return the firstname
+ */
+ public String getFirstname() {
+
+ return firstname;
+ }
+
+
+ /**
+ * @param firstname the firstname to set
+ */
+ public void setFirstname(String firstname) {
+
+ this.firstname = firstname;
+ }
+
+
+ /**
+ * @return the lastname
+ */
+ public String getLastname() {
+
+ return lastname;
+ }
+
+
+ /**
+ * @param lastname the lastname to set
+ */
+ public void setLastname(String lastname) {
+
+ this.lastname = lastname;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || !getClass().equals(obj.getClass())) {
+ return false;
+ }
+
+ Person that = (Person) obj;
+
+ return this.id.equals(that.id);
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+
+ return id.hashCode();
+ }
+}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepository.java
new file mode 100644
index 000000000..2db31fcea
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepository.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2002-2010 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.document.mongodb.repository;
+
+import java.util.List;
+
+
+/**
+ * Sample repository managing {@link Person} entities.
+ *
+ * @author Oliver Gierke
+ */
+public interface PersonRepository extends MongoRepository {
+
+ List findByLastname(String lastname);
+}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests.java
new file mode 100644
index 000000000..8f8c987eb
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2002-2010 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.document.mongodb.repository;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+
+/**
+ * Integration test for {@link PersonRepository}.
+ *
+ * @author Oliver Gierke
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public class PersonRepositoryIntegrationTests {
+
+ @Autowired
+ PersonRepository repository;
+
+
+ @Test
+ public void createAndExecuteFinderRoundtrip() throws Exception {
+
+ repository.deleteAll();
+
+ Person person = new Person();
+ person.setFirstname("Oliver");
+ person.setLastname("Gierke");
+ person = repository.save(person);
+
+ List result = repository.findByLastname("Gierke");
+ assertThat(result.size(), is(1));
+ assertThat(result, hasItem(person));
+ }
+}
diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml
new file mode 100644
index 000000000..462d3b2e2
--- /dev/null
+++ b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/infrastructure.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/infrastructure.xml
new file mode 100644
index 000000000..e216cb973
--- /dev/null
+++ b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/infrastructure.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-data-mongodb/template.mf b/spring-data-mongodb/template.mf
index 66246669d..f627242f3 100644
--- a/spring-data-mongodb/template.mf
+++ b/spring-data-mongodb/template.mf
@@ -11,7 +11,9 @@ Import-Template:
org.springframework.util.*;version="[3.0.0, 4.0.0)",
org.springframework.transaction.*;version="[3.0.0, 4.0.0)",
org.springframework.data.core.*;version="[1.0.0, 2.0.0)",
+ org.springframework.data.domain.*;version="[1.0.0, 2.0.0)",
org.springframework.data.document.*;version="[1.0.0, 2.0.0)",
+ org.springframework.data.repository.*;version="[1.0.0, 2.0.0)",
com.mongodb.*;version="0",
org.bson.*;version="0",
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,