Compare commits

...

23 Commits

Author SHA1 Message Date
Spring Buildmaster
edd71cac78 Release version 1.0.1.RELEASE. 2012-02-11 06:41:53 -08:00
Oliver Gierke
82bd7a69eb DATAMONGO-395 - Updated changelog for 1.0.1. 2012-02-11 14:33:30 +01:00
Oliver Gierke
b434a0810e DATAMONGO-401 - Fixed NullPointerException in StringBasedMongoQuery. 2012-02-11 14:32:22 +01:00
Oliver Gierke
40236d4099 DATAMONGO-380 - Improved map handling for keys containing dots.
MappingMongoConverter now rejects objects that would result in field keys containing a dot as we cannot reliably escape and unescape them without potentially wrecking correct keys on reading. However I added a property mapKeyReplacement that can be set to e.g. ~ to have all dots in map keys replaced with ~. This will of course cause ~ to be transformed into dots when reading. If further customization is necessary override potentiallyEscapeMapKey(…) and potentiallyUnescapeMapKey(…).
2012-02-10 18:20:43 +01:00
Oliver Gierke
8f6d940036 DATAMONGO-397 - Replaced references to MongoTemplate with MongoOperations in repository package.
The reference in MongoRepositoryFactoryBean to MongoTemplate was unnecessary on the one hand and could cause problems in case the MongoTemplate is proxied as it can't be wired into the factory anymore then.
2012-02-10 17:11:27 +01:00
Oliver Gierke
95a92ccf5d DATAMONGO-395 - Removed invalid XML element. 2012-02-08 21:24:34 +01:00
Oliver Gierke
a6db24554f DATAMONGO-395 - Upgrade to Spring Data Commons 1.2.1. 2012-02-08 21:24:34 +01:00
Oliver Gierke
2f6c61ef9c DATAMONGO-395 - Polished pom.xml for Maven Central release. 2012-02-08 21:24:29 +01:00
Oliver Gierke
d8bf7ebf3f DATAMONGO-395 - Refer to latest core repository documentation. 2012-02-08 20:20:09 +01:00
Oliver Gierke
ce42783e73 DATACMNS-390 - Added UUIDToBinaryConverter to be able to handle UUIDs by default. 2012-02-06 15:16:24 +01:00
Oliver Gierke
69474327c6 DATAMONGO-358 - Fixed collection reading when property type is no a collection.
If you have a property of type object and it contains a collection we didn't property read it back in as creating the collection instance failed due to an invalid call to CollectionFactory. We now default the parameter handed to that call to List in case the property type is not a Collection at all.
2012-02-01 16:26:37 +01:00
Oliver Gierke
1bbe2e8247 DATAMONGO-385 - Added test case to show repositories working with Long id. 2012-02-01 15:30:02 +01:00
Oliver Gierke
94af898ae3 DATAMONGO-387 - Repository query execution for GeoPage results are now working correctly.
Added special handling of GeoPage return types for repository query methods.
2012-02-01 14:42:49 +01:00
Oliver Gierke
f6298f7005 DATAMONGO-375 - Polished XSD by removing unnecessary version numbers. 2012-02-01 10:00:19 +01:00
Oliver Gierke
d5b3c651b2 Consolidate Maven repository usage to use repo.springsource.org/libs-snapshot. 2012-01-31 18:47:52 +01:00
Oliver Gierke
33dd00f0b8 DATAMONGO-379 - Improved entity instantiation.
Huge refactoring of the way MappingMongoConverter instantiates entities. The constructor arguments now have to mirror a property exactly in terms of name. Thus we can pick up mapping information from the property to lookup the correct value from the source document. The @Value annotation can be used to either inject completely arbitrary values into the instance (e.g. by referring to a Spring bean) or simply define an expression against DBObject's fields:

class Sample {
  String foo;
  String bar;

  Sample(String foo, @Value("#root._bar") String bar) {
    this.foo = foo;
    this.bar = bar;
  }
}

trying to create an instance of this class from

{ "foo" : "FOO" } -> new Sample("FOO", null)
{ "_bar" : "BAR" } -> new Sample(null, "BAR").
2012-01-16 18:37:00 +00:00
Oliver Gierke
3207a81555 DATAMONGO-368 - MappingMongoConverter does not remove null values from collections anymore. 2012-01-16 18:36:47 +00:00
Oliver Gierke
d231519012 DATAMONGO-376 - Fixed potential NPE in SpringDataMongodbSerializer. 2012-01-12 12:26:39 +01:00
Oliver Gierke
e052ecc9a4 Polished formatting and Javadoc. 2012-01-12 12:26:10 +01:00
Oliver Gierke
071f2934a1 DATAMONGO-369 - Fixed query mapping when a DBObject is included in the query object.
Replaced premature return with continue to break the for loop appropriately.
2012-01-12 11:20:16 +01:00
Oliver Gierke
d2a18e9b11 DATAMONGO-373 - Fixed potential ClassCastException in QueryMapper.
QueryMapper assumed finding a BasicBSONList for $(n)or operators. This is generally true if the DBObject was created through our Query abstraction. If you use the MongoDB driver QueryBuilder this will fail. We're now only insisting on an Iterable which fixes the issue.
2012-01-12 11:20:05 +01:00
Oliver Gierke
d684fa1f8e Fixed broken integration test. 2012-01-12 11:19:43 +01:00
Oliver Gierke
1a0077231d DATAMONGO-357 - Prepare 1.0.1 development branch. 2012-01-12 11:15:39 +01:00
127 changed files with 2004 additions and 1353 deletions

65
pom.xml
View File

@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-dist</artifactId>
<name>Spring Data MongoDB Distribution</name>
<version>1.0.0.RELEASE</version>
<description>Spring Data project for MongoDB</description>
<url>http://www.springsource.org/spring-data/mongodb</url>
<version>1.0.1.RELEASE</version>
<packaging>pom</packaging>
<modules>
<module>spring-data-mongodb</module>
@@ -14,7 +15,18 @@
<module>spring-data-mongodb-parent</module>
</modules>
<developers>
<developers>
<developer>
<id>ogierke</id>
<name>Oliver Gierke</name>
<email>ogierke at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl>
<roles>
<role>Project lead</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>trisberg</id>
<name>Thomas Risberg</name>
@@ -39,17 +51,6 @@
</roles>
<timezone>-5</timezone>
</developer>
<developer>
<id>ogierke</id>
<name>Oliver Gierke</name>
<email>ogierke at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>jbrisbin</id>
<name>Jon Brisbin</name>
@@ -145,7 +146,7 @@
<htmlCustomization>${project.basedir}/src/docbkx/resources/xsl/html.xsl</htmlCustomization>
<useExtensions>1</useExtensions>
<highlightSource>1</highlightSource>
<highlightDefaultLanguage></highlightDefaultLanguage>
<highlightDefaultLanguage />
<!-- callouts -->
<entities>
<entity>
@@ -156,26 +157,24 @@
<postProcess>
<copy todir="${project.basedir}/target/site/reference">
<fileset dir="${project.basedir}/target/docbkx">
<include name="**/*.html"/>
<include name="**/*.pdf"/>
<include name="**/*.html" />
<include name="**/*.pdf" />
</fileset>
</copy>
<copy todir="${project.basedir}/target/site/reference/html">
<fileset dir="${project.basedir}/src/docbkx/resources">
<include name="**/*.css"/>
<include name="**/*.png"/>
<include name="**/*.gif"/>
<include name="**/*.jpg"/>
<include name="**/*.css" />
<include name="**/*.png" />
<include name="**/*.gif" />
<include name="**/*.jpg" />
</fileset>
</copy>
<copy todir="${project.basedir}/target/site/reference/html">
<fileset dir="${project.basedir}/src/docbkx/resources/images">
<include name="*.png"/>
<include name="*.png" />
</fileset>
</copy>
<move file="${project.basedir}/target/site/reference/pdf/index.pdf"
tofile="${project.basedir}/target/site/reference/pdf/spring-data-mongo-reference.pdf"
failonerror="false"/>
<move file="${project.basedir}/target/site/reference/pdf/index.pdf" tofile="${project.basedir}/target/site/reference/pdf/spring-data-mongo-reference.pdf" failonerror="false" />
</postProcess>
</configuration>
</plugin>
@@ -184,7 +183,7 @@
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.5</version>
<configuration>
<javadoc:aggregate>true</javadoc:aggregate>
<aggregate>true</aggregate>
<breakiterator>true</breakiterator>
<header>Spring Data Document</header>
<source>1.5</source>
@@ -234,7 +233,7 @@
<configuration>
<tasks>
<ant antfile="${basedir}/src/ant/upload-dist.xml">
<target name="upload-dist"/>
<target name="upload-dist" />
</ant>
</tasks>
</configuration>
@@ -270,9 +269,9 @@
<url>http://repository.springsource.com/maven/bundles/release</url>
</pluginRepository>
<pluginRepository>
<id>repository.springframework.maven.release</id>
<id>spring-libs-release</id>
<name>Spring Framework Maven Release Repository</name>
<url>http://repo.springsource.org/release</url>
<url>http://repo.springsource.org/libs-release</url>
</pluginRepository>
</pluginRepositories>
@@ -282,7 +281,7 @@
<site>
<id>static.springframework.org</id>
<url>
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-mongodb/docs/${project.version}
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-mongodb/snapshot-site
</url>
</site>
<repository>
@@ -296,5 +295,7 @@
<url>s3://maven.springframework.org/snapshot</url>
</snapshotRepository>
</distributionManagement>
<scm>
<url>https://github.com/SpringSource/spring-data-mongodb</url>
</scm>
</project>

View File

@@ -1,10 +1,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.0.1.RELEASE</version>
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
</parent>
<artifactId>spring-data-mongodb-cross-store</artifactId>
@@ -151,25 +151,7 @@
</dependency>
</dependencies>
<repositories>
<repository>
<id>jboss-repository</id>
<name>JBoss Public Repository</name>
<url>http://repository.jboss.org/nexus/content/groups/public-jboss</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-maven-milestones</id>
<name>Springframework Maven Milestone Repository</name>
<url>http://maven.springframework.org/milestone</url>
</pluginRepository>
<pluginRepository>
<id>spring-maven-release</id>
<name>Springframework Maven Release Repository</name>
<url>http://maven.springframework.org/release</url>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>

View File

@@ -1,11 +1,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.0.1.RELEASE</version>
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
</parent>
<artifactId>spring-data-mongodb-log4j</artifactId>

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<name>Spring Data MongoDB Parent</name>
<description>Spring Data project for MongoDB</description>
<url>http://www.springsource.org/spring-data/mongodb</url>
<version>1.0.0.RELEASE</version>
<version>1.0.1.RELEASE</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -19,9 +19,82 @@
<org.springframework.version.30>3.0.7.RELEASE</org.springframework.version.30>
<org.springframework.version.40>4.0.0.RELEASE</org.springframework.version.40>
<org.springframework.version.range>[${org.springframework.version.30}, ${org.springframework.version.40})</org.springframework.version.range>
<data.commons.version>1.2.0.RELEASE</data.commons.version>
<data.commons.version>1.2.1.RELEASE</data.commons.version>
<aspectj.version>1.6.11.RELEASE</aspectj.version>
</properties>
<developers>
<developer>
<id>ogierke</id>
<name>Oliver Gierke</name>
<email>ogierke at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl>
<roles>
<role>Project lead</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>trisberg</id>
<name>Thomas Risberg</name>
<email>trisberg at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.SpringSource.com</organizationUrl>
<roles>
<role>Project Admin</role>
<role>Developer</role>
</roles>
<timezone>-5</timezone>
</developer>
<developer>
<id>mpollack</id>
<name>Mark Pollack</name>
<email>mpollack at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.SpringSource.com</organizationUrl>
<roles>
<role>Project Admin</role>
<role>Developer</role>
</roles>
<timezone>-5</timezone>
</developer>
<developer>
<id>jbrisbin</id>
<name>Jon Brisbin</name>
<email>jbrisbin at vmware.com</email>
<organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>-6</timezone>
</developer>
</developers>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
<comments>
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.
</comments>
</license>
</licenses>
<profiles>
<profile>
<id>strict</id>
@@ -65,7 +138,7 @@
<site>
<id>static.springframework.org</id>
<url>
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-mongodb/docs/${project.version}
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-mongodb/snapshot-site
</url>
</site>
<repository>
@@ -79,6 +152,9 @@
<url>s3://maven.springframework.org/snapshot</url>
</snapshotRepository>
</distributionManagement>
<scm>
<url>https://github.com/SpringSource/spring-data-mongodb</url>
</scm>
<dependencyManagement>
<!--
inheritable <dependency> declarations for child poms. children still
@@ -152,7 +228,7 @@
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>${project.version}</version>
<version>1.0.1.RELEASE</version>
</dependency>
<!-- Logging -->
@@ -369,22 +445,14 @@
</build>
<pluginRepositories>
<pluginRepository>
<!-- necessary for bundlor and utils -->
<id>repository.plugin.springsource.release</id>
<name>SpringSource Maven Repository</name>
<url>http://repository.springsource.com/maven/bundles/release</url>
</pluginRepository>
<pluginRepository>
<id>repository.springframework.maven.release</id>
<name>Spring Framework Maven Release Repository</name>
<url>http://repo.springsource.org/release</url>
<id>spring-plugins-release</id>
<url>http://repo.springsource.org/plugins-release</url>
</pluginRepository>
</pluginRepositories>
<repositories>
<repository>
<id>repository.springframework.maven.release</id>
<name>Spring Framework Maven Release Repository</name>
<url>http://repo.springsource.org/release</url>
<id>spring-libs-release</id>
<url>http://repo.springsource.org/libs-release</url>
</repository>
</repositories>
<reporting>

View File

@@ -1,11 +1,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.0.0.RELEASE</version>
<version>1.0.1.RELEASE</version>
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
</parent>
<artifactId>spring-data-mongodb</artifactId>
@@ -128,6 +127,7 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
@@ -154,15 +154,5 @@
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>querydsl</id>
<name>Mysema QueryDsl</name>
<url>http://source.mysema.com/maven2/releases</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

View File

@@ -143,11 +143,11 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
List<Element> customConvertersElements = DomUtils.getChildElementsByTagName(element, "custom-converters");
if (customConvertersElements.size() == 1) {
Element customerConvertersElement = customConvertersElements.get(0);
ManagedList<BeanMetadataElement> converterBeans = new ManagedList<BeanMetadataElement>();
List<Element> converterElements = DomUtils.getChildElementsByTagName(customerConvertersElement, "converter");
if (converterElements != null) {
for (Element listenerElement : converterElements) {
converterBeans.add(parseConverter(listenerElement, parserContext));
@@ -158,9 +158,9 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
String packageToScan = customerConvertersElement.getAttribute(BASE_PACKAGE);
if (StringUtils.hasText(packageToScan)) {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
provider.addExcludeFilter(new NegatingFilter(new AssignableTypeFilter(Converter.class), new AssignableTypeFilter(
GenericConverter.class)));
provider.addExcludeFilter(new NegatingFilter(new AssignableTypeFilter(Converter.class),
new AssignableTypeFilter(GenericConverter.class)));
for (BeanDefinition candidate : provider.findCandidateComponents(packageToScan)) {
converterBeans.add(candidate);
}
@@ -221,7 +221,7 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
/**
* {@link TypeFilter} that returns {@literal false} in case any of the given delegates matches.
*
*
* @author Oliver Gierke
*/
private static class NegatingFilter implements TypeFilter {

View File

@@ -21,15 +21,16 @@ import com.mongodb.DBObject;
import com.mongodb.MongoException;
/**
* An interface used by {@link MongoTemplate} for processing documents returned from a MongoDB query on a per-document basis.
* Implementations of this interface perform the actual work of prcoessing each document but don't need to worry about
* exception handling. {@MongoException}s will be caught and translated by the calling MongoTemplate
* An interface used by {@link MongoTemplate} for processing documents returned from a MongoDB query on a per-document
* basis. Implementations of this interface perform the actual work of prcoessing each document but don't need to worry
* about exception handling. {@MongoException}s will be caught and translated by the calling
* MongoTemplate
*
* An DocumentCallbackHandler is typically stateful: It keeps the result state within the object, to be available later for later
* inspection.
* An DocumentCallbackHandler is typically stateful: It keeps the result state within the object, to be available later
* for later inspection.
*
* @author Mark Pollack
*
*
*/
public interface DocumentCallbackHandler {

View File

@@ -18,9 +18,9 @@ package org.springframework.data.mongodb.core;
public class FindAndModifyOptions {
boolean returnNew;
boolean upsert;
boolean remove;
/**
@@ -31,17 +31,17 @@ public class FindAndModifyOptions {
public static FindAndModifyOptions options() {
return new FindAndModifyOptions();
}
public FindAndModifyOptions returnNew(boolean returnNew) {
this.returnNew = returnNew;
return this;
}
public FindAndModifyOptions upsert(boolean upsert) {
this.upsert = upsert;
return this;
}
public FindAndModifyOptions remove(boolean remove) {
this.remove = remove;
return this;
@@ -58,7 +58,5 @@ public class FindAndModifyOptions {
public boolean isRemove() {
return remove;
}
}

View File

@@ -20,35 +20,38 @@ import com.mongodb.DBObject;
import com.mongodb.WriteConcern;
/**
* Represents an action taken against the collection. Used by {@link WriteConcernResolver} to determine a custom
* Represents an action taken against the collection. Used by {@link WriteConcernResolver} to determine a custom
* WriteConcern based on this information.
*
* Properties that will always be not-null are collectionName and defaultWriteConcern.
* The EntityClass is null only for the MongoActionOperaton.INSERT_LIST.
* Properties that will always be not-null are collectionName and defaultWriteConcern. The EntityClass is null only for
* the MongoActionOperaton.INSERT_LIST.
*
* INSERT, SAVE have null query,
* REMOVE has null document
* INSERT_LIST has null entityClass, document, and query.
* <ul>
* <li>INSERT, SAVE have null query</li>
* <li>REMOVE has null document</li>
* <li>INSERT_LIST has null entityClass, document, and query</li>
* </ul>
*
* @author Mark Pollack
*
*
*/
public class MongoAction {
private String collectionName;
private WriteConcern defaultWriteConcern;
private Class<?> entityClass;
private MongoActionOperation mongoActionOperation;
private DBObject query;
private DBObject document;
/**
* Create an instance of a MongoAction
*
* @param defaultWriteConcern the default write concern
* @param mongoActionOperation action being taken against the collection
* @param collectionName the collection name
@@ -90,7 +93,5 @@ public class MongoAction {
public DBObject getDocument() {
return document;
}
}

View File

@@ -16,18 +16,14 @@
package org.springframework.data.mongodb.core;
/**
* Enumeration for operations on a collection. Used with {@link MongoAction} to help determine the
* WriteConcern to use for a given mutating operation
* Enumeration for operations on a collection. Used with {@link MongoAction} to help determine the WriteConcern to use
* for a given mutating operation
*
* @author Mark Pollack
* @see MongoAction
*
*
*/
public enum MongoActionOperation {
REMOVE,
UPDATE,
INSERT,
INSERT_LIST,
SAVE
REMOVE, UPDATE, INSERT, INSERT_LIST, SAVE
}

View File

@@ -89,9 +89,9 @@ public class QueryMapper {
newKey = "_id";
} else if (key.startsWith("$") && key.endsWith("or")) {
// $or/$nor
BasicBSONList conditions = (BasicBSONList) value;
Iterable<?> conditions = (Iterable<?>) value;
BasicBSONList newConditions = new BasicBSONList();
Iterator<Object> iter = conditions.iterator();
Iterator<?> iter = conditions.iterator();
while (iter.hasNext()) {
newConditions.add(getMappedObject((DBObject) iter.next(), entity));
}
@@ -100,7 +100,7 @@ public class QueryMapper {
value = convertId(value);
} else if (value instanceof DBObject) {
newDbo.put(newKey, getMappedObject((DBObject) value, entity));
return newDbo;
continue;
}
newDbo.put(newKey, converter.convertToMongoType(value));

View File

@@ -56,7 +56,8 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
public SimpleMongoDbFactory(Mongo mongo, String databaseName) {
Assert.notNull(mongo, "Mongo must not be null");
Assert.hasText(databaseName, "Database name must not be empty");
Assert.isTrue(databaseName.matches("[\\w-]+"), "Database name must only contain letters, numbers, underscores and dashes!");
Assert.isTrue(databaseName.matches("[\\w-]+"),
"Database name must only contain letters, numbers, underscores and dashes!");
this.mongo = mongo;
this.databaseName = databaseName;
}
@@ -73,7 +74,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
this.username = userCredentials.getUsername();
this.password = userCredentials.getPassword();
}
/**
* Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoURI}.
*
@@ -82,7 +83,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
* @throws UnknownHostException
* @see MongoURI
*/
public SimpleMongoDbFactory(MongoURI uri) throws MongoException, UnknownHostException {
public SimpleMongoDbFactory(MongoURI uri) throws MongoException, UnknownHostException {
this(new Mongo(uri), uri.getDatabase(), new UserCredentials(uri.getUsername(), parseChars(uri.getPassword())));
}
@@ -94,7 +95,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
public void setWriteConcern(WriteConcern writeConcern) {
this.writeConcern = writeConcern;
}
public WriteConcern getWriteConcern() {
return writeConcern;
}
@@ -130,7 +131,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
public void destroy() throws Exception {
mongo.close();
}
public static String parseChars(char[] chars) {
if (chars == null) {
return null;

View File

@@ -24,14 +24,16 @@ import com.mongodb.WriteConcern;
* Return the passed in default WriteConcern (a property on MongoAction) if no determination can be made.
*
* @author Mark Pollack
*
*
*/
public interface WriteConcernResolver {
/**
* Resolve the WriteConcern given the MongoAction
* @param action describes the context of the Mongo action. Contains a default WriteConcern to use if one should not be resolved.
* @return a WriteConcern based on the passed in MongoAction value, maybe null
*/
WriteConcern resolve(MongoAction action);
/**
* Resolve the WriteConcern given the MongoAction
*
* @param action describes the context of the Mongo action. Contains a default WriteConcern to use if one should not
* be resolved.
* @return a WriteConcern based on the passed in MongoAction value, maybe null
*/
WriteConcern resolve(MongoAction action);
}

View File

@@ -36,8 +36,10 @@ import org.springframework.data.convert.WritingConverter;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalToStringConverter;
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter;
import org.springframework.data.mongodb.core.convert.MongoConverters.BinaryToUUIDConverter;
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
import org.springframework.data.mongodb.core.convert.MongoConverters.UUIDToBinaryConverter;
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
import org.springframework.util.Assert;
@@ -89,6 +91,8 @@ public class CustomConversions {
this.converters.add(StringToBigDecimalConverter.INSTANCE);
this.converters.add(BigIntegerToStringConverter.INSTANCE);
this.converters.add(StringToBigIntegerConverter.INSTANCE);
this.converters.add(UUIDToBinaryConverter.INSTANCE);
this.converters.add(BinaryToUUIDConverter.INSTANCE);
this.converters.addAll(converters);
for (Object c : this.converters) {

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2012 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.mongodb.core.convert;
import java.util.Map;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
import com.mongodb.DBObject;
/**
* {@link PropertyAccessor} to allow entity based field access to {@link DBObject}s.
*
* @author Oliver Gierke
*/
class DBObjectPropertyAccessor extends MapAccessor {
static MapAccessor INSTANCE = new DBObjectPropertyAccessor();
@Override
public Class<?>[] getSpecificTargetClasses() {
return new Class[] { DBObject.class };
}
@Override
public boolean canRead(EvaluationContext context, Object target, String name) {
return true;
}
@Override
@SuppressWarnings("unchecked")
public TypedValue read(EvaluationContext context, Object target, String name) {
Map<String, Object> source = (Map<String, Object>) target;
Object value = source.get(name);
return value == null ? TypedValue.NULL : new TypedValue(value);
}
}

View File

@@ -50,23 +50,22 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
public DefaultMongoTypeMapper() {
this(DEFAULT_TYPE_KEY, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
}
public DefaultMongoTypeMapper(String typeKey) {
super(new DBObjectTypeAliasAccessor(typeKey));
this.typeKey = typeKey;
}
public DefaultMongoTypeMapper(String typeKey, MappingContext<? extends PersistentEntity<?,?>, ?> mappingContext) {
public DefaultMongoTypeMapper(String typeKey, MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext) {
super(new DBObjectTypeAliasAccessor(typeKey), mappingContext, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
this.typeKey = typeKey;
}
public DefaultMongoTypeMapper(String typeKey, List<? extends TypeInformationMapper> mappers) {
super(new DBObjectTypeAliasAccessor(typeKey), mappers);
this.typeKey = typeKey;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.MongoTypeMapper#isTypeKey(java.lang.String)
@@ -75,7 +74,6 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
return typeKey == null ? false : typeKey.equals(key);
}
/* (non-Javadoc)
* @see org.springframework.data.convert.DefaultTypeMapper#getFallbackTypeFor(java.lang.Object)
*/
@@ -83,29 +81,29 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
protected TypeInformation<?> getFallbackTypeFor(DBObject source) {
return source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO;
}
/**
*
* @author Oliver Gierke
*/
public static final class DBObjectTypeAliasAccessor implements TypeAliasAccessor<DBObject> {
private final String typeKey;
public DBObjectTypeAliasAccessor(String typeKey) {
this.typeKey = typeKey;
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeAliasAccessor#readAliasFrom(java.lang.Object)
*/
public Object readAliasFrom(DBObject source) {
if (source instanceof BasicDBList) {
return null;
}
return source.get(typeKey);
}

View File

@@ -0,0 +1,168 @@
/*
* Copyright 2012 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.mongodb.core.convert;
import java.util.HashSet;
import java.util.Set;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PreferredConstructor;
import org.springframework.data.mapping.PreferredConstructor.Parameter;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.context.PersistentPropertyPath;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**
* Abstraction for a {@link PreferredConstructor} alongside mapping information.
*
* @author Oliver Gierke
*/
class MappedConstructor {
private final Set<MappedConstructor.MappedParameter> parameters;
/**
* Creates a new {@link MappedConstructor} from the given {@link MongoPersistentEntity} and {@link MappingContext}.
*
* @param entity must not be {@literal null}.
* @param context must not be {@literal null}.
*/
public MappedConstructor(MongoPersistentEntity<?> entity,
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> context) {
Assert.notNull(entity);
Assert.notNull(context);
this.parameters = new HashSet<MappedConstructor.MappedParameter>();
for (Parameter<?> parameter : entity.getPreferredConstructor().getParameters()) {
parameters.add(new MappedParameter(parameter, entity, context));
}
}
/**
* Returns whether the given {@link PersistentProperty} is referenced in a constructor argument of the
* {@link PersistentEntity} backing this {@link MappedConstructor}.
*
* @param property must not be {@literal null}.
* @return
*/
public boolean isConstructorParameter(PersistentProperty<?> property) {
Assert.notNull(property);
for (MappedConstructor.MappedParameter parameter : parameters) {
if (parameter.maps(property)) {
return true;
}
}
return false;
}
/**
* Returns the {@link MappedParameter} for the given {@link Parameter}.
*
* @param parameter must not be {@literal null}.
* @return
*/
public MappedParameter getFor(Parameter<?> parameter) {
for (MappedParameter mappedParameter : parameters) {
if (mappedParameter.parameter.equals(parameter)) {
return mappedParameter;
}
}
throw new IllegalStateException(String.format("Didn't find a MappedParameter for %s!", parameter.toString()));
}
/**
* Abstraction of a {@link Parameter} alongside mapping information.
*
* @author Oliver Gierke
*/
static class MappedParameter {
private final MongoPersistentProperty property;
private final Parameter<?> parameter;
/**
* Creates a new {@link MappedParameter} for the given {@link Parameter}, {@link MongoPersistentProperty} and
* {@link MappingContext}.
*
* @param parameter must not be {@literal null}.
* @param entity must not be {@literal null}.
* @param context must not be {@literal null}.
*/
public MappedParameter(Parameter<?> parameter, MongoPersistentEntity<?> entity,
MappingContext<? extends MongoPersistentEntity<?>, ? extends MongoPersistentProperty> context) {
Assert.notNull(parameter);
Assert.notNull(entity);
Assert.notNull(context);
this.parameter = parameter;
PropertyPath propertyPath = PropertyPath.from(parameter.getName(), entity.getType());
PersistentPropertyPath<? extends MongoPersistentProperty> path = context.getPersistentPropertyPath(propertyPath);
this.property = path == null ? null : path.getLeafProperty();
}
/**
* Returns whether there is a SpEL expression configured for this parameter.
*
* @return
*/
public boolean hasSpELExpression() {
return parameter.getKey() != null;
}
/**
* Returns the field name to be used to lookup the value which in turn shall be converted into the constructor
* parameter.
*
* @return
*/
public String getFieldName() {
return property.getFieldName();
}
/**
* Returns the type of the property backing the {@link Parameter}.
*
* @return
*/
public TypeInformation<?> getPropertyTypeInformation() {
return property.getTypeInformation();
}
/**
* Returns whether the given {@link PersistentProperty} is mapped by the parameter.
*
* @param property
* @return
*/
public boolean maps(PersistentProperty<?> property) {
return this.property.equals(property);
}
}
}

View File

@@ -37,7 +37,7 @@ import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.data.convert.TypeMapper;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PreferredConstructor;
import org.springframework.data.mapping.PreferredConstructor.Parameter;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.BeanWrapper;
@@ -81,6 +81,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
protected ApplicationContext applicationContext;
protected boolean useFieldAccessOnly = true;
protected MongoTypeMapper typeMapper;
protected String mapKeyDotReplacement = null;
/**
* Creates a new {@link MappingMongoConverter} given the new {@link MongoDbFactory} and {@link MappingContext}.
@@ -116,6 +117,18 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
mappingContext) : typeMapper;
}
/**
* Configure the characters dots potentially contained in a {@link Map} shall be replaced with. By default we don't do
* any translation but rather reject a {@link Map} with keys containing dots causing the conversion for the entire
* object to fail. If further customization of the translation is needed, have a look at
* {@link #potentiallyEscapeMapKey(String)} as well as {@link #potentiallyUnescapeMapKey(String)}.
*
* @param mapKeyDotReplacement the mapKeyDotReplacement to set
*/
public void setMapKeyDotReplacement(String mapKeyDotReplacement) {
this.mapKeyDotReplacement = mapKeyDotReplacement;
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.EntityConverter#getMappingContext()
@@ -164,7 +177,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
if (conversions.hasCustomReadTarget(dbo.getClass(), rawType)) {
return conversionService.convert(dbo, rawType);
}
if (DBObject.class.isAssignableFrom(rawType)) {
return (S) dbo;
}
@@ -189,52 +202,17 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo) {
final StandardEvaluationContext spelCtx = new StandardEvaluationContext();
if (null != applicationContext) {
final StandardEvaluationContext spelCtx = new StandardEvaluationContext(dbo);
spelCtx.addPropertyAccessor(DBObjectPropertyAccessor.INSTANCE);
if (applicationContext != null) {
spelCtx.setBeanResolver(new BeanFactoryResolver(applicationContext));
}
if (!(dbo instanceof BasicDBList)) {
String[] keySet = dbo.keySet().toArray(new String[dbo.keySet().size()]);
for (String key : keySet) {
spelCtx.setVariable(key, dbo.get(key));
}
}
final List<String> ctorParamNames = new ArrayList<String>();
final MongoPersistentProperty idProperty = entity.getIdProperty();
final MappedConstructor constructor = new MappedConstructor(entity, mappingContext);
ParameterValueProvider provider = new SpELAwareParameterValueProvider(spelExpressionParser, spelCtx) {
@Override
@SuppressWarnings("unchecked")
public <T> T getParameterValue(PreferredConstructor.Parameter<T> parameter) {
if (parameter.getKey() != null) {
return super.getParameterValue(parameter);
}
String name = parameter.getName();
TypeInformation<T> type = parameter.getType();
Class<T> rawType = parameter.getRawType();
String key = idProperty == null ? name : idProperty.getName().equals(name) ? idProperty.getFieldName() : name;
Object obj = dbo.get(key);
ctorParamNames.add(name);
if (obj instanceof DBRef) {
return read(type, ((DBRef) obj).fetch());
} else if (obj instanceof BasicDBList) {
BasicDBList objAsDbList = (BasicDBList) obj;
return conversionService.convert(readCollectionOrArray(type, objAsDbList), rawType);
} else if (obj instanceof DBObject) {
return read(type, ((DBObject) obj));
} else if (null != obj && obj.getClass().isAssignableFrom(rawType)) {
return (T) obj;
} else if (null != obj) {
return conversionService.convert(obj, rawType);
}
return null;
}
};
SpELAwareParameterValueProvider delegate = new SpELAwareParameterValueProvider(spelExpressionParser, spelCtx);
ParameterValueProvider provider = new DelegatingParameterValueProvider(constructor, dbo, delegate);
final BeanWrapper<MongoPersistentEntity<S>, S> wrapper = BeanWrapper.create(entity, provider, conversionService);
@@ -242,7 +220,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
public void doWithPersistentProperty(MongoPersistentProperty prop) {
boolean isConstructorProperty = ctorParamNames.contains(prop.getName());
boolean isConstructorProperty = constructor.isConstructorParameter(prop);
boolean hasValueForProperty = dbo.containsField(prop.getFieldName());
if (!hasValueForProperty || isConstructorProperty) {
@@ -286,7 +264,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
boolean handledByCustomConverter = conversions.getCustomWriteTarget(obj.getClass(), DBObject.class) != null;
TypeInformation<? extends Object> type = ClassTypeInformation.from(obj.getClass());
if (!handledByCustomConverter && !(dbo instanceof BasicDBList)) {
typeMapper.writeType(type, dbo);
}
@@ -345,7 +323,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
// Write the ID
final MongoPersistentProperty idProperty = entity.getIdProperty();
if (!dbo.containsField("_id") && null != idProperty) {
try {
Object id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly);
dbo.put("_id", idMapper.convertId(id));
@@ -356,13 +334,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
// Write the properties
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
public void doWithPersistentProperty(MongoPersistentProperty prop) {
if (prop.equals(idProperty)) {
return;
}
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
if (null != propertyObj) {
if (!conversions.isSimpleType(propertyObj.getClass())) {
writePropertyInternal(propertyObj, dbo, prop);
@@ -499,13 +477,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
for (Object element : source) {
if (element == null) {
continue;
}
Class<?> elementType = element == null ? null : element.getClass();
Class<?> elementType = element.getClass();
if (conversions.isSimpleType(elementType)) {
if (elementType == null || conversions.isSimpleType(elementType)) {
sink.add(getPotentiallyConvertedSimpleWrite(element));
} else if (element instanceof Collection || elementType.isArray()) {
sink.add(writeCollectionInternal(asCollection(element), componentType, new BasicDBList()));
@@ -528,14 +502,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @return
*/
protected DBObject writeMapInternal(Map<Object, Object> obj, DBObject dbo, TypeInformation<?> propertyType) {
for (Map.Entry<Object, Object> entry : obj.entrySet()) {
Object key = entry.getKey();
Object val = entry.getValue();
if (conversions.isSimpleType(key.getClass())) {
// Don't use conversion service here as removal of ObjectToString converter results in some primitive types not
// being convertable
String simpleKey = key.toString();
String simpleKey = potentiallyEscapeMapKey(key.toString());
if (val == null || conversions.isSimpleType(val.getClass())) {
writeSimpleInternal(val, dbo, simpleKey);
} else if (val instanceof Collection || val.getClass().isArray()) {
@@ -543,7 +517,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
writeCollectionInternal(asCollection(val), propertyType.getMapValueType(), new BasicDBList()));
} else {
DBObject newDbo = new BasicDBObject();
TypeInformation<?> valueTypeInfo = propertyType.isMap() ? propertyType.getMapValueType() : ClassTypeInformation.OBJECT;
TypeInformation<?> valueTypeInfo = propertyType.isMap() ? propertyType.getMapValueType()
: ClassTypeInformation.OBJECT;
writeInternal(val, newDbo, valueTypeInfo);
dbo.put(simpleKey, newDbo);
}
@@ -551,10 +526,43 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
throw new MappingException("Cannot use a complex object as a key value.");
}
}
return dbo;
}
/**
* Potentially replaces dots in the given map key with the configured map key replacement if configured or aborts
* conversion if none is configured.
*
* @see #setMapKeyDotReplacement(String)
* @param source
* @return
*/
protected String potentiallyEscapeMapKey(String source) {
if (!source.contains(".")) {
return source;
}
if (mapKeyDotReplacement == null) {
throw new MappingException(String.format("Map key %s contains dots but no replacement was configured! Make "
+ "sure map keys don't contain dots in the first place or configure an appropriate replacement!", source));
}
return source.replaceAll("\\.", mapKeyDotReplacement);
}
/**
* Translates the map key replacements in the given key just read with a dot in case a map key replacement has been
* configured.
*
* @param source
* @return
*/
protected String potentiallyUnescapeMapKey(String source) {
return mapKeyDotReplacement == null ? source : source.replaceAll(mapKeyDotReplacement, "\\.");
}
/**
* Adds custom type information to the given {@link DBObject} if necessary. That is if the value is not the same as
* the one given. This is usually the case if you store a subtype of the actual declared type of the property.
@@ -643,7 +651,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
MongoPersistentProperty idProperty = targetEntity.getIdProperty();
BeanWrapper<MongoPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(target, conversionService);
Object id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly);
if (null == id) {
throw new MappingException("Cannot create a reference to an object with a NULL id.");
}
@@ -696,7 +704,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
(BasicDBList) sourceValue);
}
TypeInformation<?> toType = typeMapper.readType((DBObject) sourceValue);
TypeInformation<?> toType = typeMapper.readType((DBObject) sourceValue, prop.getTypeInformation());
// It's a complex object, have to read it in
if (toType != null) {
@@ -725,8 +733,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Assert.notNull(targetType);
Class<?> collectionType = targetType.getType();
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>() : CollectionFactory
.createCollection(targetType.getType(), sourceValue.size());
.createCollection(collectionType, sourceValue.size());
for (int i = 0; i < sourceValue.size(); i++) {
Object dbObjItem = sourceValue.get(i);
@@ -735,7 +746,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
} else if (dbObjItem instanceof DBObject) {
items.add(read(targetType.getComponentType(), (DBObject) dbObjItem));
} else {
items.add(getPotentiallyConvertedSimpleRead(dbObjItem, targetType.getComponentType().getType()));
TypeInformation<?> componentType = targetType.getComponentType();
items.add(getPotentiallyConvertedSimpleRead(dbObjItem, componentType == null ? null : componentType.getType()));
}
}
@@ -763,12 +775,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
continue;
}
Object key = entry.getKey();
Object key = potentiallyUnescapeMapKey(entry.getKey());
TypeInformation<?> keyTypeInformation = type.getComponentType();
if (keyTypeInformation != null) {
Class<?> keyType = keyTypeInformation.getType();
key = conversionService.convert(entry.getKey(), keyType);
key = conversionService.convert(key, keyType);
}
Object value = entry.getValue();
@@ -858,7 +870,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
return newDbl;
}
/**
* Removes the type information from the conversion result.
*
@@ -895,4 +907,55 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return dbObject;
}
private class DelegatingParameterValueProvider implements ParameterValueProvider {
private final DBObject source;
private final ParameterValueProvider delegate;
private final MappedConstructor constructor;
/**
* {@link ParameterValueProvider} to delegate source object lookup to a {@link SpELAwareParameterValueProvider} in
* case a MappCon
*
* @param constructor must not be {@literal null}.
* @param source must not be {@literal null}.
* @param delegate must not be {@literal null}.
*/
public DelegatingParameterValueProvider(MappedConstructor constructor, DBObject source,
SpELAwareParameterValueProvider delegate) {
Assert.notNull(constructor);
Assert.notNull(source);
Assert.notNull(delegate);
this.constructor = constructor;
this.source = source;
this.delegate = delegate;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter)
*/
@SuppressWarnings("unchecked")
public <T> T getParameterValue(Parameter<T> parameter) {
MappedConstructor.MappedParameter mappedParameter = constructor.getFor(parameter);
Object value = mappedParameter.hasSpELExpression() ? delegate.getParameterValue(parameter) : source
.get(mappedParameter.getFieldName());
TypeInformation<?> type = mappedParameter.getPropertyTypeInformation();
if (value instanceof DBRef) {
return (T) read(type, ((DBRef) value).fetch());
} else if (value instanceof BasicDBList) {
return (T) getPotentiallyConvertedSimpleRead(readCollectionOrArray(type, (BasicDBList) value), type.getType());
} else if (value instanceof DBObject) {
return (T) read(type, (DBObject) value);
} else {
return (T) getPotentiallyConvertedSimpleRead(value, type.getType());
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011 the original author or authors.
* Copyright 2011-2012 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.
@@ -15,11 +15,18 @@
*/
package org.springframework.data.mongodb.core.convert;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.UUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bson.BSON;
import org.bson.types.Binary;
import org.bson.types.ObjectId;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.util.StringUtils;
/**
@@ -119,4 +126,52 @@ abstract class MongoConverters {
return StringUtils.hasText(source) ? new BigInteger(source) : null;
}
}
/**
* Custom {@link Converter} to convert {@link UUID}s into {@link Binary}s.
*
* @author Oliver Gierke
*/
public static enum UUIDToBinaryConverter implements Converter<UUID, Binary> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
public Binary convert(UUID source) {
try {
return source == null ? null : new Binary(BSON.B_UUID, source.toString().getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new MappingException(String.format("Could nor convert UUID %s into Binary!", source.toString()), e);
}
}
}
public static enum BinaryToUUIDConverter implements Converter<Binary, UUID> {
INSTANCE;
private static final Log LOG = LogFactory.getLog(BinaryToUUIDConverter.class);
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
public UUID convert(Binary source) {
if (BSON.B_UUID != source.getType()) {
LOG.warn(String.format("Source binary %s is not an UUID actually! Trying to read it nevertheless...",
source.toString()));
}
try {
return source == null ? null : UUID.fromString(new String(source.getData(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new MappingException(String.format("Could not convert Binary %s into UUID!", source.toString()), e);
}
}
}
}

View File

@@ -66,7 +66,7 @@ public class Box implements Shape {
list.add(getUpperRight().asList());
return list;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.geo.Shape#getCommand()
@@ -74,7 +74,7 @@ public class Box implements Shape {
public String getCommand() {
return "$box";
}
@Override
public String toString() {
return String.format("Box [%s, %s]", first, second);

View File

@@ -40,10 +40,10 @@ public class Circle implements Shape {
*/
@PersistenceConstructor
public Circle(Point center, double radius) {
Assert.notNull(center);
Assert.isTrue(radius >= 0, "Radius must not be negative!");
this.center = center;
this.radius = radius;
}
@@ -76,7 +76,7 @@ public class Circle implements Shape {
public double getRadius() {
return radius;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.geo.Shape#asList()
@@ -87,7 +87,7 @@ public class Circle implements Shape {
result.add(getRadius());
return result;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.geo.Shape#getCommand()
@@ -104,26 +104,26 @@ public class Circle implements Shape {
public String toString() {
return String.format("Circle [center=%s, radius=%f]", center, radius);
}
/* (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;
}
Circle that = (Circle) obj;
return this.center.equals(that.center) && this.radius == that.radius;
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()

View File

@@ -50,22 +50,22 @@ public class Polygon implements Shape, Iterable<Point> {
this.points.addAll(Arrays.asList(x, y, z));
this.points.addAll(Arrays.asList(others));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.geo.Shape#asList()
*/
public List<List<Double>> asList() {
List<List<Double>> result = new ArrayList<List<Double>>();
for (Point point : points) {
result.add(point.asList());
}
return result;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.geo.Shape#getCommand()
@@ -73,7 +73,7 @@ public class Polygon implements Shape, Iterable<Point> {
public String getCommand() {
return "$polygon";
}
/*
* (non-Javadoc)
* @see java.lang.Iterable#iterator()
@@ -88,20 +88,20 @@ public class Polygon implements Shape, Iterable<Point> {
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || !getClass().equals(obj.getClass())) {
return false;
}
Polygon that = (Polygon) obj;
return this.points.equals(that.points);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()

View File

@@ -19,7 +19,7 @@ import java.util.List;
/**
* Common interface for all shapes. Allows building MongoDB representations of them.
*
*
* @author Oliver Gierke
*/
public interface Shape {
@@ -31,7 +31,7 @@ public interface Shape {
* @return
*/
List<? extends Object> asList();
/**
* Returns the command to be used to create the {@literal $within} criterion.
*

View File

@@ -31,7 +31,6 @@ public class IndexInfo {
private boolean sparse = false;
public IndexInfo(Map<String, Order> fieldSpec, String name, boolean unique, boolean dropDuplicates, boolean sparse) {
super();
this.fieldSpec = fieldSpec;
@@ -107,9 +106,8 @@ public class IndexInfo {
return true;
}
/**
* [{ "v" : 1 , "key" : { "_id" : 1} , "ns" : "database.person" , "name" : "_id_"},
{ "v" : 1 , "key" : { "age" : -1} , "ns" : "database.person" , "name" : "age_-1" , "unique" : true , "dropDups" : true}]
* [{ "v" : 1 , "key" : { "_id" : 1} , "ns" : "database.person" , "name" : "_id_"}, { "v" : 1 , "key" : { "age" : -1}
* , "ns" : "database.person" , "name" : "age_-1" , "unique" : true , "dropDups" : true}]
*/
}

View File

@@ -23,12 +23,12 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
/**
* An implementation of ApplicationEventPublisher that will only fire MappingContextEvents for use by the index creator when
* MongoTemplate is used 'stand-alone', that is not declared inside a Spring ApplicationContext.
* An implementation of ApplicationEventPublisher that will only fire MappingContextEvents for use by the index creator
* when MongoTemplate is used 'stand-alone', that is not declared inside a Spring ApplicationContext.
*
* Declare MongoTemplate inside an ApplicationContext to enable the publishing of all persistence events such as
* {@link AfterLoadEvent}, {@link AfterSaveEvent}, etc.
*
* Declare MongoTemplate inside an ApplicationContext to enable the publishing of all persistence events such as
* {@link AfterLoadEvent}, {@link AfterSaveEvent}, etc.
*
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class MongoMappingEventPublisher implements ApplicationEventPublisher {

View File

@@ -30,7 +30,8 @@ import org.springframework.data.util.TypeInformation;
* @author Jon Brisbin <jbrisbin@vmware.com>
* @author Oliver Gierke ogierke@vmware.com
*/
public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersistentEntity<?>, MongoPersistentProperty> implements ApplicationContextAware {
public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersistentEntity<?>, MongoPersistentProperty>
implements ApplicationContextAware {
private ApplicationContext context;
@@ -57,16 +58,16 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
*/
@Override
protected <T> BasicMongoPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
BasicMongoPersistentEntity<T> entity = new BasicMongoPersistentEntity<T>(typeInformation);
if (context != null) {
entity.setApplicationContext(context);
}
return entity;
}
/*
* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)

View File

@@ -21,6 +21,7 @@ import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.bson.types.Binary;
import org.bson.types.CodeWScope;
import org.bson.types.ObjectId;
import org.springframework.data.mapping.model.SimpleTypeHolder;
@@ -36,7 +37,7 @@ import com.mongodb.DBRef;
public abstract class MongoSimpleTypes {
public static final Set<Class<?>> AUTOGENERATED_ID_TYPES;
static {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(ObjectId.class);
@@ -50,6 +51,7 @@ public abstract class MongoSimpleTypes {
simpleTypes.add(CodeWScope.class);
simpleTypes.add(DBObject.class);
simpleTypes.add(Pattern.class);
simpleTypes.add(Binary.class);
MONGO_SIMPLE_TYPES = Collections.unmodifiableSet(simpleTypes);
}

View File

@@ -31,7 +31,7 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
protected final Log LOG = LogFactory.getLog(getClass());
private final Class<?> domainClass;
/**
* Creates a new {@link AbstractMongoEventListener}.
*/

View File

@@ -39,9 +39,9 @@ public class AfterLoadEvent<T> extends MongoMappingEvent<DBObject> {
* @param type must not be {@literal null}.
*/
public AfterLoadEvent(DBObject dbo, Class<T> type) {
super(dbo, dbo);
Assert.notNull(type, "Type must not be null!");
this.type = type;
}

View File

@@ -19,24 +19,19 @@ import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Collects the parameters required to perform a group operation on a collection. The query condition and the input collection are specified on the group method as method arguments
* to be consistent with other operations, e.g. map-reduce.
* Collects the parameters required to perform a group operation on a collection. The query condition and the input
* collection are specified on the group method as method arguments to be consistent with other operations, e.g.
* map-reduce.
*
* @author Mark Pollack
*
*/
public class GroupBy {
private DBObject dboKeys;
private String keyFunction;
private String initial;
private DBObject initialDbObject;
private String reduce;
private String finalize;
public GroupBy(String... keys) {
@@ -71,24 +66,22 @@ public class GroupBy {
initial = initialDocument;
return this;
}
public GroupBy initialDocument(DBObject initialDocument) {
initialDbObject = initialDocument;
return this;
}
public GroupBy reduceFunction(String reduceFunction) {
reduce = reduceFunction;
return this;
}
public GroupBy finalizeFunction(String finalizeFunction) {
finalize = finalizeFunction;
return this;
}
public DBObject getGroupByObject() {
// return new GroupCommand(dbCollection, dboKeys, condition, initial, reduce, finalize);
BasicDBObject dbo = new BasicDBObject();
@@ -100,19 +93,15 @@ public class GroupBy {
}
dbo.put("$reduce", reduce);
dbo.put("initial", initialDbObject);
dbo.put("initial", initialDbObject);
if (initial != null) {
dbo.put("initial", initial);
}
if (finalize != null) {
dbo.put("finalize", finalize);
}
return dbo;
return dbo;
}
}

View File

@@ -26,31 +26,27 @@ import com.mongodb.DBObject;
* Collects the results of executing a group operation.
*
* @author Mark Pollack
*
* @param <T> The class in which the results are mapped onto, accessible via an interator.
*/
public class GroupByResults<T> implements Iterable<T> {
private final List<T> mappedResults;
private DBObject rawResults;
private final DBObject rawResults;
private double count;
private int keys;
private String serverUsed;
public GroupByResults(List<T> mappedResults, DBObject rawResults) {
Assert.notNull(mappedResults);
Assert.notNull(rawResults);
this.mappedResults = mappedResults;
this.rawResults = rawResults;
parseKeys();
parseKeys();
parseCount();
parseServerUsed();
}
public double getCount() {
return count;
}
@@ -58,36 +54,36 @@ public class GroupByResults<T> implements Iterable<T> {
public int getKeys() {
return keys;
}
public String getServerUsed() {
return serverUsed;
}
public Iterator<T> iterator() {
return mappedResults.iterator();
return mappedResults.iterator();
}
public DBObject getRawResults() {
return rawResults;
}
private void parseCount() {
Object object = rawResults.get("count");
if (object instanceof Double) {
count = (Double) object;
}
}
private void parseKeys() {
Object object = rawResults.get("keys");
if (object instanceof Integer) {
keys = (Integer) object;
}
}
}
private void parseServerUsed() {
//"serverUsed" : "127.0.0.1:27017"
// "serverUsed" : "127.0.0.1:27017"
Object object = rawResults.get("serverUsed");
if (object instanceof String) {
serverUsed = (String) object;

View File

@@ -15,13 +15,14 @@
*/
package org.springframework.data.mongodb.core.mapreduce;
/**
* @author Mark Pollack
*/
public class MapReduceCounts {
private int inputCount;
private int emitCount;
private int outputCount;
private final int inputCount;
private final int emitCount;
private final int outputCount;
public MapReduceCounts(int inputCount, int emitCount, int outputCount) {
super();
@@ -42,12 +43,20 @@ public class MapReduceCounts {
return outputCount;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "MapReduceCounts [inputCount=" + inputCount + ", emitCount=" + emitCount + ", outputCount=" + outputCount
+ "]";
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
@@ -58,24 +67,31 @@ public class MapReduceCounts {
return result;
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
if (this == obj) {
return true;
if (obj == null)
}
if (obj == null) {
return false;
if (getClass() != obj.getClass())
}
if (getClass() != obj.getClass()) {
return false;
}
MapReduceCounts other = (MapReduceCounts) obj;
if (emitCount != other.emitCount)
if (emitCount != other.emitCount) {
return false;
if (inputCount != other.inputCount)
}
if (inputCount != other.inputCount) {
return false;
if (outputCount != other.outputCount)
}
if (outputCount != other.outputCount) {
return false;
}
return true;
}
}

View File

@@ -39,10 +39,9 @@ public class MapReduceOptions {
private Boolean jsMode;
private Boolean verbose = true;
private Map<String, Object> extraOptions = new HashMap<String, Object>();
/**
* Static factory method to create a MapReduceOptions instance
*
@@ -189,12 +188,12 @@ public class MapReduceOptions {
this.verbose = verbose;
return this;
}
/**
* Add additional extra options that may not have a method on this class. This method will help if you use a
* version of this client library with a server version that has added additional map-reduce options that do not
* yet have an method for use in setting them.
* options
* Add additional extra options that may not have a method on this class. This method will help if you use a version
* of this client library with a server version that has added additional map-reduce options that do not yet have an
* method for use in setting them. options
*
* @param key The key option
* @param value The value of the option
* @return MapReduceOptions so that methods can be chained in a fluent API style
@@ -203,40 +202,39 @@ public class MapReduceOptions {
extraOptions.put(key, value);
return this;
}
public Map<String, Object> getExtraOptions() {
return extraOptions;
return extraOptions;
}
public String getFinalizeFunction() {
return this.finalizeFunction;
}
public Boolean getJavaScriptMode() {
return this.jsMode;
}
public String getOutputCollection() {
return this.outputCollection;
}
public String getOutputDatabase() {
return this.outputDatabase;
}
public Boolean getOutputSharded() {
return this.outputSharded;
}
public MapReduceCommand.OutputType getOutputType() {
return this.outputType;
}
public Map<String, Object> getScopeVariables() {
return this.scopeVariables;
}
public DBObject getOptionsObject() {
BasicDBObject cmd = new BasicDBObject();
@@ -253,7 +251,7 @@ public class MapReduceOptions {
if (scopeVariables != null) {
cmd.put("scope", scopeVariables);
}
if (!extraOptions.keySet().isEmpty()) {
cmd.putAll(extraOptions);
}

View File

@@ -24,77 +24,77 @@ import com.mongodb.DBObject;
/**
* Collects the results of performing a MapReduce operations.
*
* @author Mark Pollack
*
*
* @param <T> The class in which the results are mapped onto, accessible via an interator.
*/
public class MapReduceResults<T> implements Iterable<T> {
private final List<T> mappedResults;
private DBObject rawResults;
private MapReduceTiming mapReduceTiming;
private MapReduceCounts mapReduceCounts;
private String outputCollection;
public MapReduceResults(List<T> mappedResults, DBObject rawResults) {
Assert.notNull(mappedResults);
Assert.notNull(rawResults);
this.mappedResults = mappedResults;
this.rawResults = rawResults;
parseTiming(rawResults);
parseCounts(rawResults);
parseCounts(rawResults);
if (rawResults.get("result") != null) {
this.outputCollection = (String) rawResults.get("result");
}
}
public Iterator<T> iterator() {
return mappedResults.iterator();
return mappedResults.iterator();
}
public MapReduceTiming getTiming() {
return mapReduceTiming;
}
public MapReduceCounts getCounts() {
return mapReduceCounts;
}
public String getOutputCollection() {
return outputCollection;
}
public DBObject getRawResults() {
return rawResults;
}
protected void parseTiming(DBObject rawResults) {
DBObject timing = (DBObject) rawResults.get("timing");
if (timing != null) {
if (timing.get("mapTime") != null && timing.get("emitLoop") != null && timing.get("total") != null) {
mapReduceTiming = new MapReduceTiming( (Long)timing.get("mapTime"),
(Integer)timing.get("emitLoop"),
(Integer)timing.get("total"));
mapReduceTiming = new MapReduceTiming((Long) timing.get("mapTime"), (Integer) timing.get("emitLoop"),
(Integer) timing.get("total"));
}
} else {
mapReduceTiming = new MapReduceTiming(-1,-1,-1);
mapReduceTiming = new MapReduceTiming(-1, -1, -1);
}
}
protected void parseCounts(DBObject rawResults) {
DBObject counts = (DBObject) rawResults.get("counts");
if (counts != null) {
if (counts.get("input") != null && counts.get("emit") != null && counts.get("output") != null) {
mapReduceCounts = new MapReduceCounts( (Integer)counts.get("input"), (Integer)counts.get("emit"), (Integer)counts.get("output"));
mapReduceCounts = new MapReduceCounts((Integer) counts.get("input"), (Integer) counts.get("emit"),
(Integer) counts.get("output"));
}
} else {
mapReduceCounts = new MapReduceCounts(-1,-1,-1);
mapReduceCounts = new MapReduceCounts(-1, -1, -1);
}
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.data.mongodb.core.mapreduce;
public class MapReduceTiming {
private long mapTime;
private long emitLoopTime;
private long totalTime;
public MapReduceTiming(long mapTime, long emitLoopTime, long totalTime) {
this.mapTime = mapTime;
this.emitLoopTime = emitLoopTime;
this.totalTime = totalTime;
this.totalTime = totalTime;
}
public long getMapTime() {
@@ -73,8 +73,5 @@ public class MapReduceTiming {
return false;
return true;
}
}

View File

@@ -69,7 +69,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Static factory method to create a Criteria using the provided key
*
*
* @param key
* @return
*/
@@ -79,7 +79,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Static factory method to create a Criteria using the provided key
*
*
* @return
*/
public Criteria and(String key) {
@@ -88,7 +88,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using equality
*
*
* @param o
* @return
*/
@@ -106,7 +106,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $ne operator
*
*
* @param o
* @return
*/
@@ -117,7 +117,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $lt operator
*
*
* @param o
* @return
*/
@@ -128,7 +128,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $lte operator
*
*
* @param o
* @return
*/
@@ -139,7 +139,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $gt operator
*
*
* @param o
* @return
*/
@@ -150,7 +150,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $gte operator
*
*
* @param o
* @return
*/
@@ -161,7 +161,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $in operator
*
*
* @param o the values to match against
* @return
*/
@@ -176,7 +176,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $in operator
*
*
* @param c the collection containing the values to match against
* @return
*/
@@ -187,7 +187,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $nin operator
*
*
* @param o
* @return
*/
@@ -202,7 +202,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $mod operator
*
*
* @param value
* @param remainder
* @return
@@ -217,7 +217,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $all operator
*
*
* @param o
* @return
*/
@@ -232,7 +232,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $size operator
*
*
* @param s
* @return
*/
@@ -243,7 +243,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $exists operator
*
*
* @param b
* @return
*/
@@ -254,7 +254,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $type operator
*
*
* @param t
* @return
*/
@@ -265,7 +265,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $not meta operator which affects the clause directly following
*
*
* @return
*/
public Criteria not() {
@@ -275,7 +275,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using a $regex
*
*
* @param re
* @return
*/
@@ -286,7 +286,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using a $regex and $options
*
*
* @param re
* @param options
* @return
@@ -301,7 +301,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a geospatial criterion using a $within $center operation. This is only available for Mongo 1.7 and higher.
*
*
* @param circle must not be {@literal null}
* @return
*/
@@ -320,7 +320,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a geospatial criterion using a $near operation
*
*
* @param point must not be {@literal null}
* @return
*/
@@ -332,7 +332,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a geospatial criterion using a $nearSphere operation. This is only available for Mongo 1.7 and higher.
*
*
* @param point must not be {@literal null}
* @return
*/
@@ -344,7 +344,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a geospatical criterion using a $maxDistance operation, for use with $near
*
*
* @param maxDistance
* @return
*/
@@ -355,7 +355,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a criterion using the $elemMatch operator
*
*
* @param c
* @return
*/
@@ -366,7 +366,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates an 'or' criteria using the $or operator for all of the provided criteria
*
*
* @param criteria
*/
public Criteria orOperator(Criteria... criteria) {
@@ -377,7 +377,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a 'nor' criteria using the $nor operator for all of the provided criteria
*
*
* @param criteria
*/
public Criteria norOperator(Criteria... criteria) {
@@ -388,7 +388,7 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates an 'and' criteria using the $and operator for all of the provided criteria
*
*
* @param criteria
*/
public Criteria andOperator(Criteria... criteria) {
@@ -397,7 +397,6 @@ public class Criteria implements CriteriaDefinition {
return this;
}
public String getKey() {
return this.key;
}
@@ -462,11 +461,10 @@ public class Criteria implements CriteriaDefinition {
Object existing = dbo.get(key);
if (existing == null) {
dbo.put(key, value);
}
else {
throw new InvalidMongoDbApiUsageException("Due to limitations of the com.mongodb.BasicDBObject, " +
"you can't add a second '" + key + "' expression specified as '" + key + " : " + value + "'. " +
"Criteria already contains '" + key + " : " + existing + "'.");
} else {
throw new InvalidMongoDbApiUsageException("Due to limitations of the com.mongodb.BasicDBObject, "
+ "you can't add a second '" + key + "' expression specified as '" + key + " : " + value + "'. "
+ "Criteria already contains '" + key + " : " + existing + "'.");
}
}

View File

@@ -36,7 +36,7 @@ public class Query {
/**
* Static factory method to create a Query using the provided criteria
*
*
* @param critera
* @return
*/
@@ -56,11 +56,10 @@ public class Query {
String key = criteria.getKey();
if (existing == null) {
this.criteria.put(key, criteria);
}
else {
throw new InvalidMongoDbApiUsageException("Due to limitations of the com.mongodb.BasicDBObject, " +
"you can't add a second '" + key + "' criteria. " +
"Query already contains '" + existing.getCriteriaObject() + "'.");
} else {
throw new InvalidMongoDbApiUsageException("Due to limitations of the com.mongodb.BasicDBObject, "
+ "you can't add a second '" + key + "' criteria. " + "Query already contains '"
+ existing.getCriteriaObject() + "'.");
}
return this;
}
@@ -93,12 +92,12 @@ public class Query {
this.hint = name;
return this;
}
public Sort sort() {
if (this.sort == null) {
this.sort = new Sort();
}
return this.sort;
}
@@ -137,7 +136,7 @@ public class Query {
public String getHint() {
return hint;
}
protected List<Criteria> getCriteria() {
return new ArrayList<Criteria>(this.criteria.values());
}

View File

@@ -48,7 +48,7 @@ public class MongoRepositoryConfigParser extends
protected void postProcessBeanDefinition(MongoRepositoryConfiguration context, BeanDefinitionBuilder builder,
BeanDefinitionRegistry registry, Object beanSource) {
builder.addPropertyReference("template", context.getMongoTemplateRef());
builder.addPropertyReference("mongoOperations", context.getMongoTemplateRef());
builder.addPropertyValue("createIndexesForQueryMethods", context.getCreateQueryIndexes());
}
}

View File

@@ -15,15 +15,15 @@
*/
package org.springframework.data.mongodb.repository.query;
import static org.springframework.data.mongodb.repository.query.QueryUtils.applyPagination;
import static org.springframework.data.mongodb.repository.query.QueryUtils.*;
import java.util.List;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.geo.Distance;
import org.springframework.data.mongodb.core.geo.GeoPage;
import org.springframework.data.mongodb.core.geo.GeoResult;
import org.springframework.data.mongodb.core.geo.GeoResults;
import org.springframework.data.mongodb.core.geo.Point;
@@ -34,10 +34,6 @@ import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
/**
* Base class for {@link RepositoryQuery} implementations for Mongo.
*
@@ -46,42 +42,47 @@ import com.mongodb.DBObject;
public abstract class AbstractMongoQuery implements RepositoryQuery {
private final MongoQueryMethod method;
private final MongoOperations mongoOperations;
private final MongoOperations operations;
/**
* Creates a new {@link AbstractMongoQuery} from the given {@link MongoQueryMethod} and {@link MongoOperations}.
*
* @param method
* @param template
* @param method must not be {@literal null}.
* @param operations must not be {@literal null}.
*/
public AbstractMongoQuery(MongoQueryMethod method, MongoOperations template) {
public AbstractMongoQuery(MongoQueryMethod method, MongoOperations operations) {
Assert.notNull(template);
Assert.notNull(operations);
Assert.notNull(method);
this.method = method;
this.mongoOperations = template;
this.operations = operations;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()
*/
public MongoQueryMethod getQueryMethod() {
return method;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.query.RepositoryQuery#execute(java .lang.Object[])
*/
* (non-Javadoc)
* @see org.springframework.data.repository.query.RepositoryQuery#execute(java.lang.Object[])
*/
public Object execute(Object[] parameters) {
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(method, parameters);
Query query = createQuery(new ConvertingParameterAccessor(mongoOperations.getConverter(), accessor));
Query query = createQuery(new ConvertingParameterAccessor(operations.getConverter(), accessor));
if (method.isGeoNearQuery()) {
if (method.isGeoNearQuery() && method.isPageQuery()) {
MongoParameterAccessor countAccessor = new MongoParametersParameterAccessor(method, parameters);
Query countQuery = createCountQuery(new ConvertingParameterAccessor(operations.getConverter(), countAccessor));
return new GeoNearExecution(accessor).execute(query, countQuery);
} else if (method.isGeoNearQuery()) {
return new GeoNearExecution(accessor).execute(query);
} else if (method.isCollectionQuery()) {
return new CollectionExecution().execute(query);
@@ -93,14 +94,25 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
}
/**
* Create a {@link Query} instance using the given {@link ParameterAccessor}
* Creates a {@link Query} instance using the given {@link ParameterAccessor}
*
* @param accessor
* @param converter
* @param accessor must not be {@literal null}.
* @return
*/
protected abstract Query createQuery(ConvertingParameterAccessor accessor);
/**
* Creates a {@link Query} instance using the given {@link ConvertingParameterAccessor}. Will delegate to
* {@link #createQuery(ConvertingParameterAccessor)} by default but allows customization of the count query to be
* triggered.
*
* @param accessor must not be {@literal null}.
* @return
*/
protected Query createCountQuery(ConvertingParameterAccessor accessor) {
return createQuery(accessor);
}
private abstract class Execution {
abstract Object execute(Query query);
@@ -110,7 +122,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
String collectionName = metadata.getCollectionName();
return mongoOperations.find(query, metadata.getJavaType(), collectionName);
return operations.find(query, metadata.getJavaType(), collectionName);
}
}
@@ -122,13 +134,11 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
class CollectionExecution extends Execution {
/*
* (non-Javadoc)
*
* @see org.springframework.data.mongodb.repository.MongoQuery.Execution #execute(com.mongodb.DBObject)
*/
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query)
*/
@Override
public Object execute(Query query) {
return readCollection(query);
}
}
@@ -162,24 +172,13 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
Object execute(Query query) {
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
int count = getCollectionCursor(metadata.getCollectionName(), query.getQueryObject()).count();
long count = operations.count(query, metadata.getCollectionName());
List<?> result = mongoOperations.find(applyPagination(query, pageable), metadata.getJavaType(),
List<?> result = operations.find(applyPagination(query, pageable), metadata.getJavaType(),
metadata.getCollectionName());
return new PageImpl(result, pageable, count);
}
private DBCursor getCollectionCursor(String collectionName, final DBObject query) {
return mongoOperations.execute(collectionName, new CollectionCallback<DBCursor>() {
public DBCursor doInCollection(DBCollection collection) {
return collection.find(query);
}
});
}
}
/**
@@ -197,19 +196,19 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
Object execute(Query query) {
MongoEntityInformation<?, ?> entityInformation = method.getEntityInformation();
return mongoOperations.findOne(query, entityInformation.getJavaType());
return operations.findOne(query, entityInformation.getJavaType());
}
}
/**
* {@link Execution} to execute geo-near queries.
*
*
* @author Oliver Gierke
*/
class GeoNearExecution extends Execution {
private final MongoParameterAccessor accessor;
public GeoNearExecution(MongoParameterAccessor accessor) {
this.accessor = accessor;
}
@@ -220,27 +219,48 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
*/
@Override
Object execute(Query query) {
GeoResults<?> results = doExecuteQuery(query);
return isListOfGeoResult() ? results.getContent() : results;
}
/**
* Executes the given {@link Query} to return a page.
*
* @param query must not be {@literal null}.
* @param countQuery must not be {@literal null}.
* @return
*/
Object execute(Query query, Query countQuery) {
MongoEntityInformation<?, ?> information = method.getEntityInformation();
long count = operations.count(countQuery, information.getCollectionName());
return new GeoPage<Object>(doExecuteQuery(query), accessor.getPageable(), count);
}
@SuppressWarnings("unchecked")
private GeoResults<Object> doExecuteQuery(Query query) {
Point nearLocation = accessor.getGeoNearLocation();
NearQuery nearQuery = NearQuery.near(nearLocation);
if (query != null) {
nearQuery.query(query);
}
Distance maxDistance = accessor.getMaxDistance();
if (maxDistance != null) {
nearQuery.maxDistance(maxDistance);
}
MongoEntityInformation<?,?> entityInformation = method.getEntityInformation();
GeoResults<?> results = mongoOperations.geoNear(nearQuery, entityInformation.getJavaType(), entityInformation.getCollectionName());
return isListOfGeoResult() ? results.getContent() : results;
MongoEntityInformation<?, ?> entityInformation = method.getEntityInformation();
return (GeoResults<Object>) operations.geoNear(nearQuery, entityInformation.getJavaType(),
entityInformation.getCollectionName());
}
private boolean isListOfGeoResult() {
TypeInformation<?> returnType = method.getReturnType();
return returnType.getType().equals(List.class) && GeoResult.class.equals(returnType.getComponentType());
}

View File

@@ -42,10 +42,10 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
* @param delegate must not be {@literal null}.
*/
public ConvertingParameterAccessor(MongoWriter<?> writer, MongoParameterAccessor delegate) {
Assert.notNull(writer);
Assert.notNull(delegate);
this.writer = writer;
this.delegate = delegate;
}
@@ -92,7 +92,7 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
public Distance getMaxDistance() {
return delegate.getMaxDistance();
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.MongoParameterAccessor#getGeoNearLocation()
*/

View File

@@ -17,10 +17,9 @@ package org.springframework.data.mongodb.repository.query;
import java.io.Serializable;
/**
* Interface for components being able to provide {@link EntityInformationCreator} for a given {@link Class}.
*
*
* @author Oliver Gierke
*/
public interface EntityInformationCreator {

View File

@@ -33,7 +33,7 @@ public interface MongoParameterAccessor extends ParameterAccessor {
* at all or the given value for it was {@literal null}.
*/
Distance getMaxDistance();
/**
* Returns the {@link Point} to use for a geo-near query.
*

View File

@@ -35,7 +35,7 @@ public class MongoParameters extends Parameters {
private final Integer distanceIndex;
private Integer nearIndex;
/**
* Creates a new {@link MongoParameters} instance from the given {@link Method} and {@link MongoQueryMethod}.
*
@@ -43,55 +43,56 @@ public class MongoParameters extends Parameters {
* @param queryMethod must not be {@literal null}.
*/
public MongoParameters(Method method, boolean isGeoNearMethod) {
super(method);
List<Class<?>> parameterTypes = Arrays.asList(method.getParameterTypes());
this.distanceIndex = parameterTypes.indexOf(Distance.class);
if (this.nearIndex == null && isGeoNearMethod) {
this.nearIndex = getNearIndex(parameterTypes);
} else if (this.nearIndex == null) {
this.nearIndex = -1;
}
}
@SuppressWarnings("unchecked")
private final int getNearIndex(List<Class<?>> parameterTypes) {
for (Class<?> reference : Arrays.asList(Point.class, double[].class)) {
int nearIndex = parameterTypes.indexOf(reference);
if (nearIndex == -1) {
continue;
}
if (nearIndex == parameterTypes.lastIndexOf(reference)) {
return nearIndex;
} else {
throw new IllegalStateException("Multiple Point parameters found but none annotated with @Near!");
}
}
return -1;
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.Parameters#createParameter(org.springframework.core.MethodParameter)
*/
@Override
protected Parameter createParameter(MethodParameter parameter) {
MongoParameter mongoParameter = new MongoParameter(parameter);
// Detect manually annotated @Near Point and reject multiple annotated ones
if (this.nearIndex == null && mongoParameter.isManuallyAnnotatedNearParameter()) {
this.nearIndex = mongoParameter.getIndex();
} else if (mongoParameter.isManuallyAnnotatedNearParameter()) {
throw new IllegalStateException(String.format("Found multiple @Near annotations ond method %s! Only one allowed!", parameter.getMethod().toString()));
throw new IllegalStateException(String.format(
"Found multiple @Near annotations ond method %s! Only one allowed!", parameter.getMethod().toString()));
}
return mongoParameter;
}
@@ -103,7 +104,7 @@ public class MongoParameters extends Parameters {
public int getDistanceIndex() {
return distanceIndex;
}
/**
* Returns the index of the parameter to be used to start a geo-near query from.
*
@@ -112,16 +113,16 @@ public class MongoParameters extends Parameters {
public int getNearIndex() {
return nearIndex;
}
/**
* Custom {@link Parameter} implementation adding parameters of type {@link Distance} to the special ones.
*
*
* @author Oliver Gierke
*/
class MongoParameter extends Parameter {
private final MethodParameter parameter;
/**
* Creates a new {@link MongoParameter}.
*
@@ -130,7 +131,7 @@ public class MongoParameters extends Parameters {
MongoParameter(MethodParameter parameter) {
super(parameter);
this.parameter = parameter;
if (!isPoint() && hasNearAnnotation()) {
throw new IllegalArgumentException("Near annotation is only allowed at Point parameter!");
}
@@ -142,23 +143,22 @@ public class MongoParameters extends Parameters {
*/
@Override
public boolean isSpecialParameter() {
return super.isSpecialParameter() || getType().equals(Distance.class)
|| isNearParameter();
return super.isSpecialParameter() || getType().equals(Distance.class) || isNearParameter();
}
private boolean isNearParameter() {
Integer nearIndex = MongoParameters.this.nearIndex;
return nearIndex != null && nearIndex.equals(getIndex());
}
private boolean isManuallyAnnotatedNearParameter() {
return isPoint() && hasNearAnnotation();
}
private boolean isPoint() {
return getType().equals(Point.class) || getType().equals(double[].class);
}
private boolean hasNearAnnotation() {
return parameter.getParameterAnnotation(Near.class) != null;
}

View File

@@ -21,13 +21,13 @@ import org.springframework.data.repository.query.ParametersParameterAccessor;
/**
* Mongo-specific {@link ParametersParameterAccessor} to allow access to the {@link Distance} parameter.
*
*
* @author Oliver Gierke
*/
public class MongoParametersParameterAccessor extends ParametersParameterAccessor implements MongoParameterAccessor {
private final MongoQueryMethod method;
/**
* Creates a new {@link MongoParametersParameterAccessor}.
*
@@ -47,25 +47,25 @@ public class MongoParametersParameterAccessor extends ParametersParameterAccesso
int index = method.getParameters().getDistanceIndex();
return index == -1 ? null : (Distance) getValue(index);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.MongoParameterAccessor#getGeoNearLocation()
*/
public Point getGeoNearLocation() {
int nearIndex = method.getParameters().getNearIndex();
if (nearIndex == -1) {
return null;
}
Object value = getValue(nearIndex);
if (value == null) {
return null;
}
if (value instanceof double[]) {
double[] typedValue = (double[]) value;
if (typedValue.length != 2) {
@@ -74,7 +74,7 @@ public class MongoParametersParameterAccessor extends ParametersParameterAccesso
return new Point(typedValue[0], typedValue[1]);
}
}
return (Point) value;
}
}

View File

@@ -203,7 +203,8 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Query> {
case NEAR:
Distance distance = accessor.getMaxDistance();
Point point = nextAs(parameters, Point.class);
Point point = accessor.getGeoNearLocation();
point = point == null ? nextAs(parameters, Point.class) : point;
if (distance == null) {
return criteria.near(point);

View File

@@ -38,8 +38,8 @@ public class PartTreeMongoQuery extends AbstractMongoQuery {
/**
* Creates a new {@link PartTreeMongoQuery} from the given {@link QueryMethod} and {@link MongoTemplate}.
*
* @param method
* @param template
* @param method must not be {@literal null}.
* @param template must not be {@literal null}.
*/
public PartTreeMongoQuery(MongoQueryMethod method, MongoOperations mongoOperations) {
@@ -50,6 +50,8 @@ public class PartTreeMongoQuery extends AbstractMongoQuery {
}
/**
* Return the {@link PartTree} backing the query.
*
* @return the tree
*/
public PartTree getTree() {
@@ -57,16 +59,22 @@ public class PartTreeMongoQuery extends AbstractMongoQuery {
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.mongodb.repository.AbstractMongoQuery#createQuery(org.springframework.data.
* document.mongodb.repository.ConvertingParameterAccessor)
*/
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery#createQuery(org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor, boolean)
*/
@Override
protected Query createQuery(ConvertingParameterAccessor accessor) {
MongoQueryCreator creator = new MongoQueryCreator(tree, accessor, context, isGeoNearQuery);
return creator.createQuery();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery#createCountQuery(org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor)
*/
@Override
protected Query createCountQuery(ConvertingParameterAccessor accessor) {
return new MongoQueryCreator(tree, accessor, context, false).createQuery();
}
}

View File

@@ -74,7 +74,7 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
} else {
query = new BasicQuery(queryString);
}
QueryUtils.applySorting(query, accessor.getSort());
if (LOG.isDebugEnabled()) {
@@ -99,8 +99,12 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
}
private String getParameterWithIndex(ConvertingParameterAccessor accessor, int index) {
Object parameter = accessor.getBindableValue(index);
if (parameter instanceof String || parameter.getClass().isEnum()) {
if (parameter == null) {
return "null";
} else if (parameter instanceof String || parameter.getClass().isEnum()) {
return String.format("\"%s\"", parameter);
} else if (parameter instanceof ObjectId) {
return String.format("{ '$oid' : '%s' }", parameter);

View File

@@ -25,7 +25,8 @@ import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.util.Assert;
/**
* Simple {@link EntityInformationCreator} to to create {@link MongoEntityInformation} instances based on a {@link MappingContext}.
* Simple {@link EntityInformationCreator} to to create {@link MongoEntityInformation} instances based on a
* {@link MappingContext}.
*
* @author Oliver Gierke
*/

View File

@@ -44,7 +44,7 @@ class IndexEnsuringQueryCreationListener implements QueryCreationListener<PartTr
private static final Set<Type> GEOSPATIAL_TYPES = new HashSet<Type>(Arrays.asList(Type.NEAR, Type.WITHIN));
private static final Log LOG = LogFactory.getLog(IndexEnsuringQueryCreationListener.class);
private final MongoOperations operations;
/**

View File

@@ -17,7 +17,7 @@ package org.springframework.data.mongodb.repository.support;
import java.io.Serializable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
@@ -32,17 +32,17 @@ import org.springframework.util.Assert;
public class MongoRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends
RepositoryFactoryBeanSupport<T, S, ID> {
private MongoTemplate template;
private MongoOperations operations;
private boolean createIndexesForQueryMethods = false;
/**
* Configures the {@link MongoTemplate} to be used.
* Configures the {@link MongoOperations} to be used.
*
* @param template the template to set
* @param operations the operations to set
*/
public void setTemplate(MongoTemplate template) {
public void setMongoOperations(MongoOperations operations) {
this.template = template;
this.operations = operations;
}
/**
@@ -64,10 +64,10 @@ public class MongoRepositoryFactoryBean<T extends Repository<S, ID>, S, ID exten
@Override
protected final RepositoryFactorySupport createRepositoryFactory() {
RepositoryFactorySupport factory = getFactoryInstance(template);
RepositoryFactorySupport factory = getFactoryInstance(operations);
if (createIndexesForQueryMethods) {
factory.addQueryCreationListener(new IndexEnsuringQueryCreationListener(template));
factory.addQueryCreationListener(new IndexEnsuringQueryCreationListener(operations));
}
return factory;
@@ -76,11 +76,11 @@ public class MongoRepositoryFactoryBean<T extends Repository<S, ID>, S, ID exten
/**
* Creates and initializes a {@link RepositoryFactorySupport} instance.
*
* @param template
* @param operations
* @return
*/
protected RepositoryFactorySupport getFactoryInstance(MongoTemplate template) {
return new MongoRepositoryFactory(template);
protected RepositoryFactorySupport getFactoryInstance(MongoOperations operations) {
return new MongoRepositoryFactory(operations);
}
/*
@@ -94,6 +94,6 @@ public class MongoRepositoryFactoryBean<T extends Repository<S, ID>, S, ID exten
public void afterPropertiesSet() {
super.afterPropertiesSet();
Assert.notNull(template, "MongoTemplate must not be null!");
Assert.notNull(operations, "MongoTemplate must not be null!");
}
}

View File

@@ -252,7 +252,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
Path<?> parent = metadata.getParent();
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(parent.getType());
MongoPersistentProperty property = entity.getPersistentProperty(metadata.getExpression().toString());
return property.getFieldName();
return property == null ? super.getKeyForPath(expr, metadata) : property.getFieldName();
}
@Override

View File

@@ -61,12 +61,10 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements Paging
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#save(java.lang.Object)
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
*/
public T save(T entity) {
Assert.notNull(entity, "Entity must not be null!");
mongoOperations.save(entity, entityInformation.getCollectionName());
@@ -75,14 +73,12 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements Paging
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#save(java.lang.Iterable)
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
*/
public List<T> save(Iterable<? extends T> entities) {
Assert.notNull(entities, "The given Iterable of entities not be null!");
List<T> result = new ArrayList<T>();
for (T entity : entities) {
@@ -95,10 +91,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements Paging
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#findById(java.io.Serializable
* )
* @see org.springframework.data.repository.CrudRepository#findOne(java.io.Serializable)
*/
public T findOne(ID id) {
Assert.notNull(id, "The given id must not be null!");
@@ -115,10 +108,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements Paging
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#exists(java.io.Serializable
* )
* @see org.springframework.data.repository.CrudRepository#exists(java.io.Serializable)
*/
public boolean exists(ID id) {
@@ -129,8 +119,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements Paging
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.Repository#count()
* @see org.springframework.data.repository.CrudRepository#count()
*/
public long count() {
@@ -139,7 +128,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements Paging
/*
* (non-Javadoc)
* @see org.springframework.data.repository.Repository#delete(java.io.Serializable)
* @see org.springframework.data.repository.CrudRepository#delete(java.io.Serializable)
*/
public void delete(ID id) {
Assert.notNull(id, "The given id must not be null!");
@@ -148,9 +137,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements Paging
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#delete(java.lang.Object)
* @see org.springframework.data.repository.CrudRepository#delete(java.lang.Object)
*/
public void delete(T entity) {
Assert.notNull(entity, "The given entity must not be null!");
@@ -159,14 +146,12 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements Paging
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#delete(java.lang.Iterable)
* @see org.springframework.data.repository.CrudRepository#delete(java.lang.Iterable)
*/
public void delete(Iterable<? extends T> entities) {
Assert.notNull(entities, "The given Iterable of entities not be null!");
for (T entity : entities) {
delete(entity);
}
@@ -174,8 +159,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements Paging
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.Repository#deleteAll()
* @see org.springframework.data.repository.CrudRepository#deleteAll()
*/
public void deleteAll() {
@@ -184,8 +168,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements Paging
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.Repository#findAll()
* @see org.springframework.data.repository.CrudRepository#findAll()
*/
public List<T> findAll() {
@@ -194,10 +177,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements Paging
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.PagingAndSortingRepository#findAll
* (org.springframework.data.domain.Pageable)
* @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Pageable)
*/
public Page<T> findAll(final Pageable pageable) {
@@ -209,43 +189,13 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements Paging
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.PagingAndSortingRepository#findAll
* (org.springframework.data.domain.Sort)
* @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
*/
public List<T> findAll(final Sort sort) {
return findAll(QueryUtils.applySorting(new Query(), sort));
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.Repository#findAll(java.lang.Iterable
* )
*/
public List<T> findAll(Iterable<ID> ids) {
Query query = null;
//TODO: verify intent
// for (ID id : ids) {
// if (query == null) {
// query = getIdQuery(id);
// } else {
// query = new Query().or(getIdQuery(id));
// }
// }
List<ID> idList = new ArrayList<ID>();
for (ID id : ids) {
idList.add(id);
}
query = new Query(Criteria.where(entityInformation.getIdAttribute()).in(idList));
return findAll(query);
}
private List<T> findAll(Query query) {
if (query == null) {

View File

@@ -7,16 +7,14 @@
xmlns:context="http://www.springframework.org/schema/context"
xmlns:repository="http://www.springframework.org/schema/data/repository"
targetNamespace="http://www.springframework.org/schema/data/mongo"
elementFormDefault="qualified" attributeFormDefault="unqualified"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:import namespace="http://www.springframework.org/schema/tool" />
<xsd:import namespace="http://www.springframework.org/schema/context"
schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd"/>
schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd" />
<xsd:import namespace="http://www.springframework.org/schema/data/repository"
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd"/>
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd" />
<xsd:element name="mongo" type="mongoType">
<xsd:annotation>

View File

@@ -42,10 +42,9 @@ import com.mongodb.DBObject;
* @author Oliver Gierke
*/
public class MappingMongoConverterParserIntegrationTests {
DefaultListableBeanFactory factory;
@Before
public void setUp() {
factory = new DefaultListableBeanFactory();
@@ -55,26 +54,26 @@ public class MappingMongoConverterParserIntegrationTests {
@Test
public void allowsDbFactoryRefAttribute() {
factory.getBeanDefinition("converter");
factory.getBean("converter");
}
@Test
public void scansForConverterAndSetsUpCustomConversionsAccordingly() {
CustomConversions conversions = factory.getBean(CustomConversions.class);
assertThat(conversions.hasCustomWriteTarget(Person.class), is(true));
assertThat(conversions.hasCustomWriteTarget(Account.class), is(true));
}
@Component
public static class SampleConverter implements Converter<Person, DBObject> {
public DBObject convert(Person source) {
return null;
}
}
@Component
public static class SampleConverterFactory implements GenericConverter {

View File

@@ -29,17 +29,17 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Integration tests for {@link MongoDbFactory}.
*
*
* @author Thomas Risbergf
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class MongoDbFactoryNoDatabaseRunningTests {
@Autowired
MongoTemplate mongoTemplate;
/**
* @see DATADOC-139
*/
@@ -47,7 +47,7 @@ public class MongoDbFactoryNoDatabaseRunningTests {
public void startsUpWithoutADatabaseRunning() {
assertThat(mongoTemplate.getClass().getName(), is("org.springframework.data.mongodb.core.MongoTemplate"));
}
@Test(expected = DataAccessResourceFailureException.class)
public void failsDataAccessWithoutADatabaseRunning() {
mongoTemplate.getCollectionNames();

View File

@@ -40,14 +40,14 @@ import com.mongodb.WriteConcern;
/**
* Integration tests for {@link MongoDbFactoryParser}.
*
*
* @author Oliver Gierke
*/
public class MongoDbFactoryParserIntegrationTests {
DefaultListableBeanFactory factory;
BeanDefinitionReader reader;
@Before
public void setUp() {
factory = new DefaultListableBeanFactory();
@@ -61,29 +61,30 @@ public class MongoDbFactoryParserIntegrationTests {
dbFactory.getDb();
assertThat(WriteConcern.SAFE, is(dbFactory.getWriteConcern()));
}
@Test
public void parsesWriteConcern() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("namespace/db-factory-bean.xml");
assertWriteConcern(ctx, WriteConcern.SAFE);
}
@Test
public void parsesCustomWriteConcern() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("namespace/db-factory-bean-custom-write-concern.xml");
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
"namespace/db-factory-bean-custom-write-concern.xml");
assertWriteConcern(ctx, new WriteConcern("rack1"));
}
/**
* @see DATAMONGO-331
*/
@Test
public void readsReplicasWriteConcernCorrectly() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("namespace/db-factory-bean-custom-write-concern.xml");
MongoDbFactory factory = ctx.getBean("second", MongoDbFactory.class);
DB db = factory.getDb();
assertThat(db.getWriteConcern(), is(WriteConcern.REPLICAS_SAFE));
}
@@ -96,75 +97,72 @@ public class MongoDbFactoryParserIntegrationTests {
MyWriteConcern myDbWriteConcern = new MyWriteConcern(db.getWriteConcern());
MyWriteConcern myExpectedWriteConcern = new MyWriteConcern(expectedWriteConcern);
assertThat(myDbFactoryWriteConcern, equalTo(myExpectedWriteConcern));
assertThat(myDbWriteConcern, equalTo(myExpectedWriteConcern));
assertThat(myDbWriteConcern, equalTo(myDbFactoryWriteConcern));
}
//This test will fail since equals in WriteConcern uses == for _w and not .equals
// This test will fail since equals in WriteConcern uses == for _w and not .equals
public void testWriteConcernEquality() {
String s1 = new String("rack1");
String s2 = new String("rack1");
String s1 = new String("rack1");
String s2 = new String("rack1");
WriteConcern wc1 = new WriteConcern(s1);
WriteConcern wc2 = new WriteConcern(s2);
assertThat(wc1, equalTo(wc2));
}
@Test
public void createsDbFactoryBean() {
reader.loadBeanDefinitions(new ClassPathResource("namespace/db-factory-bean.xml"));
factory.getBean("first");
}
/**
* @see DATADOC-280
*/
@Test
public void parsesMaxAutoConnectRetryTimeCorrectly() {
reader.loadBeanDefinitions(new ClassPathResource("namespace/db-factory-bean.xml"));
Mongo mongo = factory.getBean(Mongo.class);
assertThat(mongo.getMongoOptions().maxAutoConnectRetryTime, is(27L));
}
/**
* @see DATADOC-295
*/
@Test
public void setsUpMongoDbFactoryUsingAMongoUri() {
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-uri.xml"));
BeanDefinition definition = factory.getBeanDefinition("mongoDbFactory");
ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues();
assertThat(constructorArguments.getArgumentCount(), is(1));
ValueHolder argument = constructorArguments.getArgumentValue(0, MongoURI.class);
assertThat(argument, is(notNullValue()));
}
/**
* @see DATADOC-306
*/
@Test
public void setsUpMongoDbFactoryUsingAMongoUriWithoutCredentials() {
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-uri-no-credentials.xml"));
BeanDefinition definition = factory.getBeanDefinition("mongoDbFactory");
ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues();
assertThat(constructorArguments.getArgumentCount(), is(1));
ValueHolder argument = constructorArguments.getArgumentValue(0, MongoURI.class);
assertThat(argument, is(notNullValue()));
MongoDbFactory dbFactory = factory.getBean("mongoDbFactory", MongoDbFactory.class);
DB db = dbFactory.getDb();
assertThat(db.getName(), is("database"));
}
/**
* @see DATADOC-295
*/

View File

@@ -3,7 +3,7 @@ package org.springframework.data.mongodb.config;
import com.mongodb.WriteConcern;
public class MyWriteConcern {
public MyWriteConcern(WriteConcern wc) {
this._w = wc.getWObject();
this._continueOnErrorForInsert = wc.getContinueOnErrorForInsert();
@@ -12,11 +12,12 @@ public class MyWriteConcern {
this._wtimeout = wc.getWtimeout();
}
Object _w = 0;
int _wtimeout = 0;
boolean _fsync = false;
boolean _j = false;
boolean _continueOnErrorForInsert = false;
Object _w = 0;
int _wtimeout = 0;
boolean _fsync = false;
boolean _j = false;
boolean _continueOnErrorForInsert = false;
@Override
public int hashCode() {
final int prime = 31;
@@ -28,6 +29,7 @@ public class MyWriteConcern {
result = prime * result + _wtimeout;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
@@ -52,5 +54,5 @@ public class MyWriteConcern {
return false;
return true;
}
}

View File

@@ -20,24 +20,23 @@ import java.lang.reflect.Field;
public class NamespaceTestSupport {
@SuppressWarnings({ "unchecked" })
public static <T> T readField(String name, Object target) throws Exception {
Field field = null;
Class<?> clazz = target.getClass();
do {
try {
field = clazz.getDeclaredField(name);
} catch (Exception ex) {
}
@SuppressWarnings({ "unchecked" })
public static <T> T readField(String name, Object target) throws Exception {
Field field = null;
Class<?> clazz = target.getClass();
do {
try {
field = clazz.getDeclaredField(name);
} catch (Exception ex) {
}
clazz = clazz.getSuperclass();
} while (field == null && !clazz.equals(Object.class));
clazz = clazz.getSuperclass();
} while (field == null && !clazz.equals(Object.class));
if (field == null)
throw new IllegalArgumentException("Cannot find field '" + name + "' in the class hierarchy of "
+ target.getClass());
field.setAccessible(true);
return (T) field.get(target);
}
if (field == null)
throw new IllegalArgumentException("Cannot find field '" + name + "' in the class hierarchy of "
+ target.getClass());
field.setAccessible(true);
return (T) field.get(target);
}
}

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.data.mongodb.core;
public class Friend {
private String id;

View File

@@ -23,7 +23,7 @@ import static org.junit.Assert.*;
/**
* Unit tests for {@link MongoOptionsFactoryBean}.
*
*
* @author Oliver Gierke
*/
public class MongoOptionsFactoryBeanUnitTests {
@@ -33,11 +33,11 @@ public class MongoOptionsFactoryBeanUnitTests {
*/
@Test
public void setsMaxConnectRetryTime() {
MongoOptionsFactoryBean bean = new MongoOptionsFactoryBean();
bean.setMaxAutoConnectRetryTime(27);
bean.afterPropertiesSet();
MongoOptions options = bean.getObject();
assertThat(options.maxAutoConnectRetryTime, is(27L));
}

View File

@@ -1041,7 +1041,7 @@ public class MongoTemplateTests {
List<TestClass> testClassList = mappingTemplate.find(new Query(Criteria.where("myDate").is(dateTime.toDate())),
TestClass.class);
assertThat(testClassList.size(), is(1));
assertThat(testClassList.get(0).getMyDate(), is(testClass.getMyDate()));
assertThat(testClassList.get(0).myDate, is(testClass.myDate));
}
/**
@@ -1080,23 +1080,19 @@ public class MongoTemplateTests {
assertThat(template.findOne(query(where("id").is(id)), Sample.class), is(nullValue()));
}
public class Sample {
public static class Sample {
@Id
String id;
}
public class TestClass {
static class TestClass {
private DateTime myDate;
DateTime myDate;
@PersistenceConstructor
public TestClass(DateTime date) {
this.myDate = date;
}
public DateTime getMyDate() {
return myDate;
TestClass(DateTime myDate) {
this.myDate = myDate;
}
}

View File

@@ -31,7 +31,7 @@ import com.mongodb.DBCursor;
/**
* Unit tests for {@link QueryCursorPreparer}.
*
*
* @author Oliver Gierke
*/
@RunWith(MockitoJUnitRunner.class)
@@ -41,18 +41,18 @@ public class QueryCursorPreparerUnitTests {
MongoDbFactory factory;
@Mock
DBCursor cursor;
/**
* @see DATAMONGO-185
*/
@Test
public void appliesHintsCorrectly() {
Query query = query(where("foo").is("bar")).withHint("hint");
CursorPreparer preparer = new MongoTemplate(factory).new QueryCursorPreparer(query);
preparer.prepare(cursor);
verify(cursor).hint("hint");
}
}

View File

@@ -49,7 +49,7 @@ public class SimpleMongoDbFactoryUnitTests {
rejectsDatabaseName("foo.bar");
rejectsDatabaseName("foo!bar");
}
/**
* @see DATADOC-254
*/
@@ -66,16 +66,16 @@ public class SimpleMongoDbFactoryUnitTests {
*/
@Test
public void mongoUriConstructor() throws UnknownHostException {
MongoURI mongoURI = new MongoURI("mongodb://myUsername:myPassword@localhost/myDatabase.myCollection");
MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoURI);
assertThat(ReflectionTestUtils.getField(mongoDbFactory, "username").toString(), is("myUsername"));
assertThat(ReflectionTestUtils.getField(mongoDbFactory, "password").toString(), is("myPassword"));
assertThat(ReflectionTestUtils.getField(mongoDbFactory, "databaseName").toString(), is("myDatabase"));
assertThat(ReflectionTestUtils.getField(mongoDbFactory, "databaseName").toString(), is("myDatabase"));
}
private void rejectsDatabaseName(String databaseName) {
try {

View File

@@ -35,5 +35,4 @@ public class TestMongoConfiguration extends AbstractMongoConfiguration {
converter.setCustomConversions(new CustomConversions(converters));
}
}

View File

@@ -3,14 +3,17 @@ package org.springframework.data.mongodb.core.convert;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.text.DateFormat;
import java.text.Format;
import java.util.Arrays;
import java.util.Locale;
import java.util.UUID;
import org.bson.types.Binary;
import org.bson.types.ObjectId;
import org.junit.Test;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
@@ -27,13 +30,13 @@ public class CustomConversionsUnitTests {
@SuppressWarnings("unchecked")
public void findsBasicReadAndWriteConversions() {
CustomConversions conversions = new CustomConversions(Arrays.asList(UuidToStringConverter.INSTANCE,
StringToUUIDConverter.INSTANCE));
CustomConversions conversions = new CustomConversions(Arrays.asList(FormatToStringConverter.INSTANCE,
StringToFormatConverter.INSTANCE));
assertThat(conversions.getCustomWriteTarget(UUID.class, null), is(typeCompatibleWith(String.class)));
assertThat(conversions.getCustomWriteTarget(Format.class, null), is(typeCompatibleWith(String.class)));
assertThat(conversions.getCustomWriteTarget(String.class, null), is(nullValue()));
assertThat(conversions.hasCustomReadTarget(String.class, UUID.class), is(true));
assertThat(conversions.hasCustomReadTarget(String.class, Format.class), is(true));
assertThat(conversions.hasCustomReadTarget(String.class, Locale.class), is(false));
}
@@ -51,7 +54,7 @@ public class CustomConversionsUnitTests {
@Test
public void considersTypesWeRegisteredConvertersForAsSimple() {
CustomConversions conversions = new CustomConversions(Arrays.asList(UuidToStringConverter.INSTANCE));
CustomConversions conversions = new CustomConversions(Arrays.asList(FormatToStringConverter.INSTANCE));
assertThat(conversions.isSimpleType(UUID.class), is(true));
}
@@ -95,14 +98,13 @@ public class CustomConversionsUnitTests {
@Test
public void populatesConversionServiceCorrectly() {
@SuppressWarnings("deprecation")
GenericConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
GenericConversionService conversionService = new DefaultConversionService();
assertThat(conversionService.canConvert(String.class, UUID.class), is(false));
CustomConversions conversions = new CustomConversions(Arrays.asList(StringToUUIDConverter.INSTANCE));
CustomConversions conversions = new CustomConversions(Arrays.asList(StringToFormatConverter.INSTANCE));
conversions.registerConvertersIn(conversionService);
assertThat(conversionService.canConvert(String.class, UUID.class), is(true));
assertThat(conversionService.canConvert(String.class, Format.class), is(true));
}
/**
@@ -110,8 +112,8 @@ public class CustomConversionsUnitTests {
*/
@Test
public void doesNotConsiderTypeSimpleIfOnlyReadConverterIsRegistered() {
CustomConversions conversions = new CustomConversions(Arrays.asList(StringToUUIDConverter.INSTANCE));
assertThat(conversions.isSimpleType(UUID.class), is(false));
CustomConversions conversions = new CustomConversions(Arrays.asList(StringToFormatConverter.INSTANCE));
assertThat(conversions.isSimpleType(Format.class), is(false));
}
/**
@@ -140,18 +142,38 @@ public class CustomConversionsUnitTests {
assertThat(conversions.getCustomWriteTarget(String.class), is(nullValue()));
}
enum UuidToStringConverter implements Converter<UUID, String> {
/**
* @see DATAMONGO-390
*/
@Test
public void considersBinaryASimpleType() {
CustomConversions conversions = new CustomConversions();
assertThat(conversions.isSimpleType(Binary.class), is(true));
}
/**
* @see DATAMONGO-390
*/
@Test
public void convertsUUIDsToBinaryByDefault() {
CustomConversions conversions = new CustomConversions();
assertThat(conversions.hasCustomWriteTarget(UUID.class), is(true));
}
enum FormatToStringConverter implements Converter<Format, String> {
INSTANCE;
public String convert(UUID source) {
public String convert(Format source) {
return source.toString();
}
}
enum StringToUUIDConverter implements Converter<String, UUID> {
enum StringToFormatConverter implements Converter<String, Format> {
INSTANCE;
public UUID convert(String source) {
return UUID.fromString(source);
public Format convert(String source) {
return DateFormat.getInstance();
}
}

View File

@@ -39,7 +39,7 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
/**
* Test case to verify correct usage of custom {@link Converter} implementations to be used.
*
*
* @author Oliver Gierke
* @see DATADOC-101
*/
@@ -65,9 +65,9 @@ public class CustomConvertersUnitTests {
when(barToDBObjectConverter.convert(any(Bar.class))).thenReturn(new BasicDBObject());
when(dbObjectToBarConverter.convert(any(DBObject.class))).thenReturn(new Bar());
CustomConversions conversions = new CustomConversions(Arrays.asList(barToDBObjectConverter, dbObjectToBarConverter));
context = new MongoMappingContext();
context.setInitialEntitySet(new HashSet<Class<?>>(Arrays.asList(Foo.class, Bar.class)));
context.setSimpleTypeHolder(conversions.getSimpleTypeHolder());

View File

@@ -175,7 +175,7 @@ public class DataDoc273Test {
@SuppressWarnings("rawtypes")
public class Shipment {
Map boxes = new HashMap();
public Shipment(Map boxes) {

View File

@@ -38,27 +38,27 @@ public class DefaultMongoTypeMapperUnitTests {
ConfigurableTypeInformationMapper configurableTypeInformationMapper;
SimpleTypeInformationMapper simpleTypeInformationMapper;
DefaultMongoTypeMapper typeMapper;
@Before
public void setUp() {
configurableTypeInformationMapper = new ConfigurableTypeInformationMapper(Collections.singletonMap(String.class, "1"));
configurableTypeInformationMapper = new ConfigurableTypeInformationMapper(Collections.singletonMap(String.class,
"1"));
simpleTypeInformationMapper = SimpleTypeInformationMapper.INSTANCE;
typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Arrays.asList(
configurableTypeInformationMapper));
typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY,
Arrays.asList(configurableTypeInformationMapper));
}
@Test
public void defaultInstanceWritesClasses() {
typeMapper = new DefaultMongoTypeMapper();
writesTypeToField(new BasicDBObject(), String.class, String.class.getName());
}
@Test
public void defaultInstanceReadsClasses() {
typeMapper = new DefaultMongoTypeMapper();
@@ -74,10 +74,10 @@ public class DefaultMongoTypeMapperUnitTests {
@Test
public void writesClassNamesForUnmappedValuesIfConfigured() {
typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Arrays.asList(
configurableTypeInformationMapper, simpleTypeInformationMapper));
writesTypeToField(new BasicDBObject(), String.class, "1");
writesTypeToField(new BasicDBObject(), Object.class, Object.class.getName());
}
@@ -90,10 +90,10 @@ public class DefaultMongoTypeMapperUnitTests {
@Test
public void readsTypeLoadingClassesForUnmappedTypesIfConfigured() {
typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Arrays.asList(
configurableTypeInformationMapper, simpleTypeInformationMapper));
readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, "1"), String.class);
readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Object.class.getName()), Object.class);
}

View File

@@ -19,27 +19,47 @@ import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.math.BigDecimal;
import java.util.UUID;
import org.bson.BSON;
import org.bson.types.Binary;
import org.junit.Test;
import org.springframework.data.mongodb.core.convert.MongoConverters;
import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalToStringConverter;
import org.springframework.data.mongodb.core.convert.MongoConverters.BinaryToUUIDConverter;
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
import org.springframework.data.mongodb.core.convert.MongoConverters.UUIDToBinaryConverter;
/**
* Unit tests for {@link MongoConverters}.
*
*
* @author Oliver Gierke
*/
public class MongoConvertersUnitTests {
@Test
public void convertsBigDecimalToStringAndBackCorrectly() {
BigDecimal bigDecimal = BigDecimal.valueOf(254, 1);
String value = BigDecimalToStringConverter.INSTANCE.convert(bigDecimal);
assertThat(value, is("25.4"));
BigDecimal reference = StringToBigDecimalConverter.INSTANCE.convert(value);
assertThat(reference, is(bigDecimal));
}
/**
* @see DATAMONGO-390
*/
@Test
public void convertsUUIDToBinaryCorrectly() {
UUID uuid = UUID.randomUUID();
Binary binary = UUIDToBinaryConverter.INSTANCE.convert(uuid);
assertThat(binary, is(notNullValue()));
assertThat(binary.getType(), is(BSON.B_UUID));
UUID result = BinaryToUUIDConverter.INSTANCE.convert(binary);
assertThat(result, is(uuid));
}
}

View File

@@ -24,26 +24,26 @@ import org.springframework.data.mongodb.core.geo.Point;
/**
* Unit tests for {@link Box}.
*
*
* @author Oliver Gierke
*/
public class BoxUnitTests {
Box first = new Box(new Point(1d, 1d), new Point(2d, 2d));
Box second = new Box(new Point(1d, 1d), new Point(2d, 2d));
Box third = new Box(new Point(3d, 3d), new Point(1d, 1d));
@Test
public void equalsWorksCorrectly() {
assertThat(first.equals(second), is(true));
assertThat(second.equals(first), is(true));
assertThat(first.equals(third), is(false));
}
@Test
public void hashCodeWorksCorrectly() {
assertThat(first.hashCode(), is(second.hashCode()));
assertThat(first.hashCode(), is(not(third.hashCode())));
}

View File

@@ -22,7 +22,7 @@ import org.junit.Test;
/**
* Unit tests for {@link Circle}.
*
*
* @author Oliver Gierke
*/
public class CircleUnitTests {
@@ -31,23 +31,23 @@ public class CircleUnitTests {
public void rejectsNullOrigin() {
new Circle(null, 0);
}
@Test(expected = IllegalArgumentException.class)
public void rejectsNegativeRadius() {
new Circle(1, 1, -1);
}
@Test
public void considersTwoCirclesEqualCorrectly() {
Circle left = new Circle(1, 1, 1);
Circle right = new Circle(1, 1, 1);
assertThat(left, is(right));
assertThat(right, is(left));
right = new Circle(new Point(1,1), 1);
right = new Circle(new Point(1, 1), 1);
assertThat(left, is(right));
assertThat(right, is(left));
}

View File

@@ -27,7 +27,7 @@ import org.junit.Test;
* @author Oliver Gierke
*/
public class DistanceUnitTests {
@Test
public void defaultsMetricToNeutralOne() {
assertThat(new Distance(2.5).getMetric(), is((Metric) Metrics.NEUTRAL));
@@ -40,7 +40,7 @@ public class DistanceUnitTests {
Distance right = new Distance(2.5, KILOMETERS);
assertThat(left.add(right), is(new Distance(5.0, KILOMETERS)));
}
@Test
public void addsDistancesWithExplicitMetric() {
Distance left = new Distance(2.5, KILOMETERS);

View File

@@ -21,11 +21,11 @@ import org.junit.Test;
/**
* Unit tests for {@link GeoResult}.
*
*
* @author Oliver Gierke
*/
public class GeoResultUnitTests {
GeoResult<String> first = new GeoResult<String>("Foo", new Distance(2.5));
GeoResult<String> second = new GeoResult<String>("Foo", new Distance(2.5));
GeoResult<String> third = new GeoResult<String>("Bar", new Distance(2.5));
@@ -33,10 +33,10 @@ public class GeoResultUnitTests {
@Test
public void considersSameInstanceEqual() {
assertThat(first.equals(first), is(true));
}
@Test
public void considersSameValuesAsEqual() {
assertThat(first.equals(second), is(true));
@@ -46,7 +46,7 @@ public class GeoResultUnitTests {
assertThat(first.equals(fourth), is(false));
assertThat(fourth.equals(first), is(false));
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test(expected = IllegalArgumentException.class)
public void rejectsNullContent() {

View File

@@ -24,7 +24,7 @@ import org.junit.Test;
/**
* Unit tests for {@link GeoResults}.
*
*
* @author Oliver Gierke
*/
public class GeoResultsUnitTests {
@@ -32,11 +32,11 @@ public class GeoResultsUnitTests {
@Test
@SuppressWarnings("unchecked")
public void calculatesAverageForGivenGeoResults() {
GeoResult<Object> first = new GeoResult<Object>(new Object(), new Distance(2));
GeoResult<Object> second = new GeoResult<Object>(new Object(), new Distance(5));
GeoResults<Object> geoResults = new GeoResults<Object>(Arrays.asList(first, second));
assertThat(geoResults.getAverageDistance(), is(new Distance(3.5)));
}
}

View File

@@ -54,7 +54,6 @@ import com.mongodb.WriteConcern;
* Modified from https://github.com/deftlabs/mongo-java-geospatial-example
*
* @author Mark Pollack
*
*/
public class GeoSpatialTests {

View File

@@ -17,14 +17,14 @@ public class PointUnitTests {
public void rejectsNullforCopyConstructor() {
new Point(null);
}
@Test
public void equalsIsImplementedCorrectly() {
assertThat(new Point(1.5, 1.5), is(equalTo(new Point(1.5, 1.5))));
assertThat(new Point(1.5, 1.5), is(not(equalTo(new Point(2.0, 2.0)))));
assertThat(new Point(2.0, 2.0), is(not(equalTo(new Point(1.5, 1.5)))));
}
@Test
public void invokingToStringWorksCorrectly() {
new Point(1.5, 1.5).toString();

View File

@@ -35,19 +35,19 @@ public class PolygonUnitTests {
public void rejectsNullPoints() {
new Polygon(null, null, null);
}
@Test
public void createsSimplePolygon() {
Polygon polygon = new Polygon(third, second, first);
assertThat(polygon, is(notNullValue()));
}
@Test
public void isEqualForSamePoints() {
Polygon left = new Polygon(third, second, first);
Polygon right = new Polygon(third, second, first);
assertThat(left, is(right));
assertThat(right, is(left));
}

View File

@@ -36,13 +36,13 @@ import com.mongodb.MongoException;
/**
* Integration tests for index handling.
*
*
* @author Oliver Gierke
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:infrastructure.xml")
public class IndexingIntegrationTests {
@Autowired
MongoOperations operations;
@@ -50,25 +50,24 @@ public class IndexingIntegrationTests {
public void tearDown() {
operations.dropCollection(IndexedPerson.class);
}
/**
* @see DATADOC-237
*/
@Test
public void createsIndexWithFieldName() {
operations.save(new IndexedPerson());
assertThat(hasIndex("_firstname", IndexedPerson.class), is(true));
}
class IndexedPerson {
@Field("_firstname")
@Indexed
String firstname;
}
/**
* Returns whether an index with the given name exists for the given entity type.
*
@@ -77,7 +76,7 @@ public class IndexingIntegrationTests {
* @return
*/
private boolean hasIndex(final String indexName, Class<?> entityType) {
return operations.execute(entityType, new CollectionCallback<Boolean>() {
public Boolean doInCollection(DBCollection collection) throws MongoException, DataAccessException {
for (DBObject indexInfo : collection.getIndexInfo()) {

View File

@@ -28,7 +28,7 @@ import org.springframework.data.util.ClassTypeInformation;
/**
* Unit tests for {@link BasicMongoPersistentEntity}.
*
*
* @author Oliver Gierke
*/
@RunWith(MockitoJUnitRunner.class)
@@ -36,59 +36,61 @@ public class BasicMongoPersistentEntityUnitTests {
@Mock
ApplicationContext context;
@Test
public void subclassInheritsAtDocumentAnnotation() {
BasicMongoPersistentEntity<Person> entity = new BasicMongoPersistentEntity<Person>(
ClassTypeInformation.from(Person.class));
assertThat(entity.getCollection(), is("contacts"));
}
@Test
public void evaluatesSpELExpression() {
MongoPersistentEntity<Company> entity = new BasicMongoPersistentEntity<Company>(ClassTypeInformation.from(Company.class));
MongoPersistentEntity<Company> entity = new BasicMongoPersistentEntity<Company>(
ClassTypeInformation.from(Company.class));
assertThat(entity.getCollection(), is("35"));
}
@Test
public void collectionAllowsReferencingSpringBean() {
CollectionProvider provider = new CollectionProvider();
provider.collectionName = "reference";
when(context.getBean("myBean")).thenReturn(provider);
when(context.containsBean("myBean")).thenReturn(true);
BasicMongoPersistentEntity<DynamicallyMapped> entity = new BasicMongoPersistentEntity<DynamicallyMapped>(ClassTypeInformation.from(DynamicallyMapped.class));
BasicMongoPersistentEntity<DynamicallyMapped> entity = new BasicMongoPersistentEntity<DynamicallyMapped>(
ClassTypeInformation.from(DynamicallyMapped.class));
entity.setApplicationContext(context);
assertThat(entity.getCollection(), is("reference"));
}
@Document(collection = "contacts")
class Contact {
}
class Person extends Contact {
}
@Document(collection = "#{35}")
class Company {
}
@Document(collection = "#{myBean.collectionName}")
class DynamicallyMapped {
}
class CollectionProvider {
String collectionName;
public String getCollectionName() {
return collectionName;
}

View File

@@ -36,9 +36,9 @@ import org.springframework.util.ReflectionUtils;
* @author Oliver Gierke
*/
public class BasicMongoPersistentPropertyUnitTests {
MongoPersistentEntity<Person> entity;
@Before
public void setup() {
entity = new BasicMongoPersistentEntity<Person>(ClassTypeInformation.from(Person.class));
@@ -46,11 +46,11 @@ public class BasicMongoPersistentPropertyUnitTests {
@Test
public void usesAnnotatedFieldName() {
Field field = ReflectionUtils.findField(Person.class, "firstname");
assertThat(getPropertyFor(field).getFieldName(), is("foo"));
}
@Test
public void returns_IdForIdProperty() {
Field field = ReflectionUtils.findField(Person.class, "id");
@@ -58,32 +58,32 @@ public class BasicMongoPersistentPropertyUnitTests {
assertThat(property.isIdProperty(), is(true));
assertThat(property.getFieldName(), is("_id"));
}
@Test
public void returnsPropertyNameForUnannotatedProperties() {
Field field = ReflectionUtils.findField(Person.class, "lastname");
assertThat(getPropertyFor(field).getFieldName(), is("lastname"));
}
@Test
public void preventsNegativeOrder() {
getPropertyFor(ReflectionUtils.findField(Person.class, "ssn"));
}
private MongoPersistentProperty getPropertyFor(Field field) {
return new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder());
}
class Person {
@Id
String id;
@org.springframework.data.mongodb.core.mapping.Field("foo")
String firstname;
String lastname;
@org.springframework.data.mongodb.core.mapping.Field(order = -20)
String ssn;
}

View File

@@ -20,8 +20,7 @@ import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.util.Collections;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -30,7 +29,9 @@ import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Unit tests for testing the mapping works with generic types.
@@ -42,7 +43,7 @@ public class GenericMappingTests {
MongoMappingContext context;
MongoConverter converter;
@Mock
MongoDbFactory factory;
@@ -85,15 +86,15 @@ public class GenericMappingTests {
assertThat(result.container.content, is("Foo!"));
}
public class StringWrapper extends Wrapper<String> {
static class StringWrapper extends Wrapper<String> {
}
public class Wrapper<S> {
static class Wrapper<S> {
Container<S> container;
}
public class Container<T> {
static class Container<T> {
T content;
}
}

View File

@@ -25,9 +25,9 @@ public class GeoIndexedAppConfig extends AbstractMongoConfiguration {
public String getMappingBasePackage() {
return "org.springframework.data.mongodb.core.core.mapping";
}
@Bean
public LoggingEventListener mappingEventsListener() {
return new LoggingEventListener();
}
@Bean
public LoggingEventListener mappingEventsListener() {
return new LoggingEventListener();
}
}

View File

@@ -42,7 +42,7 @@ import com.mongodb.MongoException;
*/
public class GeoIndexedTests {
private final String[] collectionsToDrop = new String[] { GeoIndexedAppConfig.GEO_COLLECTION, "Person"};
private final String[] collectionsToDrop = new String[] { GeoIndexedAppConfig.GEO_COLLECTION, "Person" };
ApplicationContext applicationContext;
MongoTemplate template;

View File

@@ -28,11 +28,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bson.types.ObjectId;
@@ -46,19 +41,24 @@ import org.springframework.data.mongodb.MongoCollectionUtils;
import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoDbUtils;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Order;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.test.util.ReflectionTestUtils;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class MappingTests {
private static final Log LOGGER = LogFactory.getLog(MongoDbUtils.class);
private final String[] collectionsToDrop = new String[]{
private final String[] collectionsToDrop = new String[] {
MongoCollectionUtils.getPreferredCollectionName(Person.class),
MongoCollectionUtils.getPreferredCollectionName(PersonMapProperty.class),
MongoCollectionUtils.getPreferredCollectionName(PersonWithObjectId.class),
@@ -72,8 +72,8 @@ public class MappingTests {
MongoCollectionUtils.getPreferredCollectionName(PersonWithLongDBRef.class),
MongoCollectionUtils.getPreferredCollectionName(PersonNullProperties.class),
MongoCollectionUtils.getPreferredCollectionName(Account.class),
MongoCollectionUtils.getPreferredCollectionName(PrimitiveId.class),
"foobar", "geolocation", "person1", "person2", "account"};
MongoCollectionUtils.getPreferredCollectionName(PrimitiveId.class), "foobar", "geolocation", "person1",
"person2", "account" };
ApplicationContext applicationContext;
Mongo mongo;
@@ -110,7 +110,8 @@ public class MappingTests {
LOGGER.info("done inserting");
assertNotNull(p.getId());
List<PersonWithObjectId> result = template.find(new Query(Criteria.where("ssn").is(12345)), PersonWithObjectId.class);
List<PersonWithObjectId> result = template.find(new Query(Criteria.where("ssn").is(12345)),
PersonWithObjectId.class);
assertThat(result.size(), is(1));
assertThat(result.get(0).getSsn(), is(12345));
}
@@ -166,11 +167,11 @@ public class MappingTests {
}
@Test
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({ "unchecked", "rawtypes" })
public void testWriteEntity() {
Address addr = new Address();
addr.setLines(new String[]{"1234 W. 1st Street", "Apt. 12"});
addr.setLines(new String[] { "1234 W. 1st Street", "Apt. 12" });
addr.setCity("Anytown");
addr.setPostalCode(12345);
addr.setCountry("USA");
@@ -202,10 +203,10 @@ public class MappingTests {
}
@Test
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({ "unchecked", "rawtypes" })
public void testUniqueIndex() {
Address addr = new Address();
addr.setLines(new String[]{"1234 W. 1st Street", "Apt. 12"});
addr.setLines(new String[] { "1234 W. 1st Street", "Apt. 12" });
addr.setCity("Anytown");
addr.setPostalCode(12345);
addr.setCountry("USA");
@@ -229,17 +230,17 @@ public class MappingTests {
persons.add(new PersonCustomCollection2(66666, "Person", "Two"));
template.insertAll(persons);
List<PersonCustomCollection1> p1Results = template.find(new Query(Criteria.where("ssn").is(55555)), PersonCustomCollection1.class,
"person1");
List<PersonCustomCollection2> p2Results = template.find(new Query(Criteria.where("ssn").is(66666)), PersonCustomCollection2.class,
"person2");
List<PersonCustomCollection1> p1Results = template.find(new Query(Criteria.where("ssn").is(55555)),
PersonCustomCollection1.class, "person1");
List<PersonCustomCollection2> p2Results = template.find(new Query(Criteria.where("ssn").is(66666)),
PersonCustomCollection2.class, "person2");
assertThat(p1Results.size(), is(1));
assertThat(p2Results.size(), is(1));
}
@Test
public void testPrimitivesAndCustomCollectionName() {
Location loc = new Location(new double[]{1.0, 2.0}, new int[]{1, 2, 3, 4}, new float[]{1.0f, 2.0f});
Location loc = new Location(new double[] { 1.0, 2.0 }, new int[] { 1, 2, 3, 4 }, new float[] { 1.0f, 2.0f });
template.insert(loc);
List<Location> result = template.find(new Query(Criteria.where("_id").is(loc.getId())), Location.class, "places");
@@ -255,7 +256,8 @@ public class MappingTests {
public Boolean doInCollection(DBCollection collection) throws MongoException, DataAccessException {
List<DBObject> indexes = collection.getIndexInfo();
for (DBObject dbo : indexes) {
if (dbo.get("name") != null && dbo.get("name") instanceof String && ((String)dbo.get("name")).startsWith("name")) {
if (dbo.get("name") != null && dbo.get("name") instanceof String
&& ((String) dbo.get("name")).startsWith("name")) {
return true;
}
}
@@ -271,7 +273,8 @@ public class MappingTests {
public Boolean doInCollection(DBCollection collection) throws MongoException, DataAccessException {
List<DBObject> indexes = collection.getIndexInfo();
for (DBObject dbo : indexes) {
if (dbo.get("name") != null && dbo.get("name") instanceof String && ((String)dbo.get("name")).startsWith("name")) {
if (dbo.get("name") != null && dbo.get("name") instanceof String
&& ((String) dbo.get("name")).startsWith("name")) {
return true;
}
}
@@ -282,8 +285,8 @@ public class MappingTests {
@Test
public void testMultiDimensionalArrayProperties() {
String[][] grid = new String[][]{new String[]{"1", "2", "3", "4"}, new String[]{"5", "6", "7", "8"},
new String[]{"9", "10", "11", "12"}};
String[][] grid = new String[][] { new String[] { "1", "2", "3", "4" }, new String[] { "5", "6", "7", "8" },
new String[] { "9", "10", "11", "12" } };
PersonMultiDimArrays p = new PersonMultiDimArrays(123, "Multi", "Dimensional", grid);
template.insert(p);
@@ -316,7 +319,7 @@ public class MappingTests {
@Test
public void testDbRef() {
double[] pos = new double[]{37.0625, -95.677068};
double[] pos = new double[] { 37.0625, -95.677068 };
GeoLocation geo = new GeoLocation(pos);
template.insert(geo);
@@ -340,7 +343,7 @@ public class MappingTests {
@SuppressWarnings({ "rawtypes", "unchecked" })
public void testQueryUpdate() {
Address addr = new Address();
addr.setLines(new String[]{"1234 W. 1st Street", "Apt. 12"});
addr.setLines(new String[] { "1234 W. 1st Street", "Apt. 12" });
addr.setCity("Anytown");
addr.setPostalCode(12345);
addr.setCountry("USA");
@@ -354,31 +357,33 @@ public class MappingTests {
Person p2 = template.findOne(query(where("ssn").is(1111)), Person.class);
assertThat(p2.getAddress().getCity(), is("New Town"));
}
@Test
@SuppressWarnings("rawtypes")
public void testUpsert() {
Address addr = new Address();
addr.setLines(new String[]{"1234 W. 1st Street", "Apt. 12"});
addr.setLines(new String[] { "1234 W. 1st Street", "Apt. 12" });
addr.setCity("Anytown");
addr.setPostalCode(12345);
addr.setCountry("USA");
Person p2 = template.findOne(query(where("ssn").is(1111)), Person.class);
assertNull(p2);
template.upsert(query(where("ssn").is(1111).and("firstName").is("Query").and("lastName").is("Update")), update("address", addr), Person.class);
template.upsert(query(where("ssn").is(1111).and("firstName").is("Query").and("lastName").is("Update")),
update("address", addr), Person.class);
p2 = template.findOne(query(where("ssn").is(1111)), Person.class);
assertThat(p2.getAddress().getCity(), is("Anytown"));
template.dropCollection(Person.class);
template.upsert(query(where("ssn").is(1111).and("firstName").is("Query").and("lastName").is("Update")), update("address", addr), "person");
template.upsert(query(where("ssn").is(1111).and("firstName").is("Query").and("lastName").is("Update")),
update("address", addr), "person");
p2 = template.findOne(query(where("ssn").is(1111)), Person.class);
assertThat(p2.getAddress().getCity(), is("Anytown"));
}
@Test
public void testOrQuery() {
PersonWithObjectId p1 = new PersonWithObjectId(1, "first", "");
@@ -386,8 +391,8 @@ public class MappingTests {
PersonWithObjectId p2 = new PersonWithObjectId(2, "second", "");
template.save(p2);
List<PersonWithObjectId> results = template.find(new Query(
new Criteria().orOperator(where("ssn").is(1), where("ssn").is(2))), PersonWithObjectId.class);
List<PersonWithObjectId> results = template.find(
new Query(new Criteria().orOperator(where("ssn").is(1), where("ssn").is(2))), PersonWithObjectId.class);
assertNotNull(results);
assertThat(results.size(), is(2));
@@ -426,42 +431,35 @@ public class MappingTests {
public void testNoMappingAnnotationsUsingLongAsId() {
PersonPojoLongId p = new PersonPojoLongId(1, "Text");
template.insert(p);
template.updateFirst(query(where("id").is(1)), update("text", "New Text"),
PersonPojoLongId.class);
template.updateFirst(query(where("id").is(1)), update("text", "New Text"), PersonPojoLongId.class);
PersonPojoLongId p2 = template.findOne(query(where("id").is(1)),
PersonPojoLongId.class);
PersonPojoLongId p2 = template.findOne(query(where("id").is(1)), PersonPojoLongId.class);
assertEquals("New Text", p2.getText());
p.setText("Different Text");
template.save(p);
PersonPojoLongId p3 = template.findOne(query(where("id").is(1)),
PersonPojoLongId.class);
PersonPojoLongId p3 = template.findOne(query(where("id").is(1)), PersonPojoLongId.class);
assertEquals("Different Text", p3.getText());
}
@Test
public void testNoMappingAnnotationsUsingStringAsId() {
//Assign the String Id in code
// Assign the String Id in code
PersonPojoStringId p = new PersonPojoStringId("1", "Text");
template.insert(p);
template.updateFirst(query(where("id").is("1")), update("text", "New Text"),
PersonPojoStringId.class);
template.updateFirst(query(where("id").is("1")), update("text", "New Text"), PersonPojoStringId.class);
PersonPojoStringId p2 = template.findOne(query(where("id").is("1")),
PersonPojoStringId.class);
PersonPojoStringId p2 = template.findOne(query(where("id").is("1")), PersonPojoStringId.class);
assertEquals("New Text", p2.getText());
p.setText("Different Text");
template.save(p);
PersonPojoStringId p3 = template.findOne(query(where("id").is("1")),
PersonPojoStringId.class);
PersonPojoStringId p3 = template.findOne(query(where("id").is("1")), PersonPojoStringId.class);
assertEquals("Different Text", p3.getText());
PersonPojoStringId p4 = new PersonPojoStringId("2", "Text-2");
template.insert(p4);
@@ -513,8 +511,7 @@ public class MappingTests {
assertThat(result.items.get(0).id, is(items.id));
}
class Container {
static class Container {
@Id
final String id;
@@ -529,7 +526,7 @@ public class MappingTests {
List<Item> items;
}
class Item {
static class Item {
@Id
final String id;

View File

@@ -24,7 +24,7 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
/**
* Unit tests for {@link MongoMappingContext}.
*
*
* @author Oliver Gierke
*/
public class MongoMappingContextUnitTests {

View File

@@ -18,31 +18,31 @@ import static org.mockito.Mockito.*;
/**
* Unit tests for {@link MongoPersistentPropertyComparator}.
*
*
* @author Oliver Gierke
*/
@RunWith(MockitoJUnitRunner.class)
public class MongoPersistentPropertyComparatorUnitTests {
@Mock
MongoPersistentProperty firstName;
@Mock
MongoPersistentProperty lastName;
@Mock
MongoPersistentProperty ssn;
@Test
public void ordersPropertiesCorrectly() {
when(ssn.getFieldOrder()).thenReturn(10);
when(firstName.getFieldOrder()).thenReturn(20);
when(lastName.getFieldOrder()).thenReturn(Integer.MAX_VALUE);
List<MongoPersistentProperty> properties = Arrays.asList(firstName, lastName, ssn);
Collections.sort(properties, MongoPersistentPropertyComparator.INSTANCE);
assertThat(properties.get(0), is(ssn));
assertThat(properties.get(1), is(firstName));
assertThat(properties.get(2), is(lastName));

View File

@@ -17,10 +17,10 @@ public class SimpleMappingContextUnitTests {
@Test
public void returnsIdPropertyCorrectly() {
SimpleMongoMappingContext context = new SimpleMongoMappingContext();
SimpleMongoPersistentEntity<?> entity = context.getPersistentEntity(Person.class);
MongoPersistentProperty idProperty = entity.getIdProperty();
assertThat(idProperty, is(notNullValue()));
assertThat(idProperty.getName(), is("id"));

View File

@@ -29,37 +29,37 @@ import com.mongodb.DBObject;
/**
* Unit tests for {@link AbstractMongoEventListener}.
*
*
* @author Oliver Gierke
*/
public class AbstractMongoEventListenerUnitTests {
@Test
public void invokesCallbackForEventForPerson() {
MongoMappingEvent<Person> event = new BeforeConvertEvent<Person>(new Person("Dave", "Matthews"));
SamplePersonEventListener listener = new SamplePersonEventListener();
listener.onApplicationEvent(event);
assertThat(listener.invokedOnBeforeConvert, is(true));
}
@Test
public void dropsEventIfNotForCorrectDomainType() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
context.refresh();
SamplePersonEventListener listener = new SamplePersonEventListener();
context.addApplicationListener(listener);
context.publishEvent(new BeforeConvertEvent<Person>(new Person("Dave", "Matthews")));
assertThat(listener.invokedOnBeforeConvert, is(true));
listener.invokedOnBeforeConvert = false;
context.publishEvent(new BeforeConvertEvent<String>("Test"));
assertThat(listener.invokedOnBeforeConvert, is(false));
}
/**
* @see DATADOC-289
*/
@@ -115,14 +115,14 @@ public class AbstractMongoEventListenerUnitTests {
assertThat(personListener.invokedOnAfterLoad, is(false));
assertThat(contactListener.invokedOnAfterLoad, is(true));
}
/**
* @see DATADOC-333
*/
@Test
@SuppressWarnings({ "rawtypes", "unchecked" })
public void handlesUntypedImplementations() {
UntypedEventListener listener = new UntypedEventListener();
listener.onApplicationEvent(new MongoMappingEvent(new Object(), new BasicDBObject()));
}
@@ -131,12 +131,12 @@ public class AbstractMongoEventListenerUnitTests {
boolean invokedOnBeforeConvert;
boolean invokedOnAfterLoad;
@Override
public void onBeforeConvert(Person source) {
invokedOnBeforeConvert = true;
}
@Override
public void onAfterLoad(DBObject dbo) {
invokedOnAfterLoad = true;
@@ -177,6 +177,6 @@ public class AbstractMongoEventListenerUnitTests {
@SuppressWarnings("rawtypes")
class UntypedEventListener extends AbstractMongoEventListener {
}
}

View File

@@ -65,46 +65,47 @@ public class ApplicationContextEventTests {
db.getCollection(coll).drop();
}
}
@Test
@Test
@SuppressWarnings("unchecked")
public void beforeSaveEvent() {
PersonBeforeSaveListener personBeforeSaveListener = applicationContext.getBean(PersonBeforeSaveListener.class);
AfterSaveListener afterSaveListener = applicationContext.getBean(AfterSaveListener.class);
SimpleMappingEventListener simpleMappingEventListener = applicationContext.getBean(SimpleMappingEventListener.class);
SimpleMappingEventListener simpleMappingEventListener = applicationContext
.getBean(SimpleMappingEventListener.class);
assertEquals(0, personBeforeSaveListener.seenEvents.size());
assertEquals(0, afterSaveListener.seenEvents.size());
assertEquals(0, simpleMappingEventListener.onBeforeSaveEvents.size());
assertEquals(0, simpleMappingEventListener.onAfterSaveEvents.size());
PersonPojoStringId p = new PersonPojoStringId("1", "Text");
template.insert(p);
assertEquals(1, personBeforeSaveListener.seenEvents.size());
assertEquals(1, afterSaveListener.seenEvents.size());
assertEquals(1, simpleMappingEventListener.onBeforeSaveEvents.size());
assertEquals(1, simpleMappingEventListener.onAfterSaveEvents.size());
Assert.assertTrue(personBeforeSaveListener.seenEvents.get(0) instanceof BeforeSaveEvent<?>);
Assert.assertTrue(afterSaveListener.seenEvents.get(0) instanceof AfterSaveEvent<?>);
BeforeSaveEvent<PersonPojoStringId> beforeSaveEvent = (BeforeSaveEvent<PersonPojoStringId>)personBeforeSaveListener.seenEvents.get(0);
BeforeSaveEvent<PersonPojoStringId> beforeSaveEvent = (BeforeSaveEvent<PersonPojoStringId>) personBeforeSaveListener.seenEvents
.get(0);
PersonPojoStringId p2 = beforeSaveEvent.getSource();
DBObject dbo = beforeSaveEvent.getDBObject();
comparePersonAndDbo(p, p2, dbo);
AfterSaveEvent<Object> afterSaveEvent = (AfterSaveEvent<Object>)afterSaveListener.seenEvents.get(0);
AfterSaveEvent<Object> afterSaveEvent = (AfterSaveEvent<Object>) afterSaveListener.seenEvents.get(0);
Assert.assertTrue(afterSaveEvent.getSource() instanceof PersonPojoStringId);
p2 = (PersonPojoStringId)afterSaveEvent.getSource();
p2 = (PersonPojoStringId) afterSaveEvent.getSource();
dbo = beforeSaveEvent.getDBObject();
comparePersonAndDbo(p, p2, dbo);
}
private void comparePersonAndDbo(PersonPojoStringId p, PersonPojoStringId p2, DBObject dbo) {

View File

@@ -39,12 +39,12 @@ public class ApplicationContextEventTestsAppConfig extends AbstractMongoConfigur
public PersonBeforeSaveListener personBeforeSaveListener() {
return new PersonBeforeSaveListener();
}
@Bean
public AfterSaveListener afterSaveListener() {
return new AfterSaveListener();
}
@Bean
public SimpleMappingEventListener simpleMappingEventListener() {
return new SimpleMappingEventListener();

View File

@@ -19,7 +19,6 @@ import java.util.ArrayList;
import com.mongodb.DBObject;
public class SimpleMappingEventListener extends AbstractMongoEventListener<Object> {
public final ArrayList<BeforeConvertEvent<Object>> onBeforeConvertEvents = new ArrayList<BeforeConvertEvent<Object>>();
@@ -27,7 +26,7 @@ public class SimpleMappingEventListener extends AbstractMongoEventListener<Objec
public final ArrayList<AfterSaveEvent<Object>> onAfterSaveEvents = new ArrayList<AfterSaveEvent<Object>>();
public final ArrayList<AfterLoadEvent<Object>> onAfterLoadEvents = new ArrayList<AfterLoadEvent<Object>>();
public final ArrayList<AfterConvertEvent<Object>> onAfterConvertEvents = new ArrayList<AfterConvertEvent<Object>>();
@Override
public void onBeforeConvert(Object source) {
onBeforeConvertEvents.add(new BeforeConvertEvent<Object>(source));

View File

@@ -3,17 +3,17 @@ package org.springframework.data.mongodb.core.mapreduce;
public class ContentAndVersion {
private String id;
private String document_id;
private String content;
private String author;
private Long version;
private Long value;
public String getAuthor() {
return author;
}
@@ -38,7 +38,6 @@ public class ContentAndVersion {
this.document_id = documentId;
}
public String getId() {
return id;
}
@@ -68,6 +67,5 @@ public class ContentAndVersion {
return "ContentAndVersion [id=" + id + ", document_id=" + document_id + ", content=" + content + ", author="
+ author + ", version=" + version + ", value=" + value + "]";
}
}

View File

@@ -46,33 +46,30 @@ public class GroupByTests {
@Autowired
MongoDbFactory factory;
@Autowired
ApplicationContext applicationContext;
//@Autowired
//MongoTemplate mongoTemplate;
// @Autowired
// MongoTemplate mongoTemplate;
MongoTemplate mongoTemplate;
@Autowired
@SuppressWarnings("unchecked")
public void setMongo(Mongo mongo) throws Exception {
MongoMappingContext mappingContext = new MongoMappingContext();
mappingContext.setInitialEntitySet(new HashSet<Class<?>>(Arrays.asList(XObject.class)));
mappingContext.afterPropertiesSet();
MappingMongoConverter mappingConverter = new MappingMongoConverter(factory, mappingContext);
MappingMongoConverter mappingConverter = new MappingMongoConverter(factory, mappingContext);
mappingConverter.afterPropertiesSet();
this.mongoTemplate = new MongoTemplate(factory, mappingConverter);
mongoTemplate.setApplicationContext(applicationContext);
}
@Before
public void setUp() {
cleanDb();
@@ -87,92 +84,95 @@ public class GroupByTests {
mongoTemplate.dropCollection(mongoTemplate.getCollectionName(XObject.class));
mongoTemplate.dropCollection("group_test_collection");
}
@Test
public void singleKeyCreation() {
DBObject gc = new GroupBy("a").getGroupByObject();
//String expected = "{ \"group\" : { \"ns\" : \"test\" , \"key\" : { \"a\" : 1} , \"cond\" : null , \"$reduce\" : null , \"initial\" : null }}";
String expected = "{ \"key\" : { \"a\" : 1} , \"$reduce\" : null , \"initial\" : null }";
Assert.assertEquals(expected, gc.toString());
public void singleKeyCreation() {
DBObject gc = new GroupBy("a").getGroupByObject();
// String expected =
// "{ \"group\" : { \"ns\" : \"test\" , \"key\" : { \"a\" : 1} , \"cond\" : null , \"$reduce\" : null , \"initial\" : null }}";
String expected = "{ \"key\" : { \"a\" : 1} , \"$reduce\" : null , \"initial\" : null }";
Assert.assertEquals(expected, gc.toString());
}
@Test
public void multipleKeyCreation() {
DBObject gc = GroupBy.key("a","b").getGroupByObject();
//String expected = "{ \"group\" : { \"ns\" : \"test\" , \"key\" : { \"a\" : 1 , \"b\" : 1} , \"cond\" : null , \"$reduce\" : null , \"initial\" : null }}";
String expected = "{ \"key\" : { \"a\" : 1 , \"b\" : 1} , \"$reduce\" : null , \"initial\" : null }";
Assert.assertEquals(expected, gc.toString());
DBObject gc = GroupBy.key("a", "b").getGroupByObject();
// String expected =
// "{ \"group\" : { \"ns\" : \"test\" , \"key\" : { \"a\" : 1 , \"b\" : 1} , \"cond\" : null , \"$reduce\" : null , \"initial\" : null }}";
String expected = "{ \"key\" : { \"a\" : 1 , \"b\" : 1} , \"$reduce\" : null , \"initial\" : null }";
Assert.assertEquals(expected, gc.toString());
}
@Test
public void keyFunctionCreation() {
DBObject gc = GroupBy.keyFunction("classpath:keyFunction.js").getGroupByObject();
String expected = "{ \"$keyf\" : \"classpath:keyFunction.js\" , \"$reduce\" : null , \"initial\" : null }";
Assert.assertEquals(expected, gc.toString());
DBObject gc = GroupBy.keyFunction("classpath:keyFunction.js").getGroupByObject();
String expected = "{ \"$keyf\" : \"classpath:keyFunction.js\" , \"$reduce\" : null , \"initial\" : null }";
Assert.assertEquals(expected, gc.toString());
}
@Test
public void SimpleGroup() {
createGroupByData();
GroupByResults<XObject> results;
results = mongoTemplate.group("group_test_collection",
GroupBy.key("x").initialDocument(new BasicDBObject("count", 0)).reduceFunction("function(doc, prev) { prev.count += 1 }"), XObject.class);
results = mongoTemplate.group(
"group_test_collection",
GroupBy.key("x").initialDocument(new BasicDBObject("count", 0))
.reduceFunction("function(doc, prev) { prev.count += 1 }"), XObject.class);
assertMapReduceResults(results);
}
@Test
public void SimpleGroupWithKeyFunction() {
createGroupByData();
GroupByResults<XObject> results;
results = mongoTemplate.group("group_test_collection",
GroupBy.keyFunction("function(doc) { return { x : doc.x }; }").initialDocument("{ count: 0 }").reduceFunction("function(doc, prev) { prev.count += 1 }"), XObject.class);
assertMapReduceResults(results);
results = mongoTemplate.group(
"group_test_collection",
GroupBy.keyFunction("function(doc) { return { x : doc.x }; }").initialDocument("{ count: 0 }")
.reduceFunction("function(doc, prev) { prev.count += 1 }"), XObject.class);
assertMapReduceResults(results);
}
@Test
public void SimpleGroupWithFunctionsAsResources() {
createGroupByData();
GroupByResults<XObject> results;
results = mongoTemplate.group("group_test_collection",
GroupBy.keyFunction("classpath:keyFunction.js").initialDocument("{ count: 0 }").reduceFunction("classpath:groupReduce.js"), XObject.class);
assertMapReduceResults(results);
results = mongoTemplate.group("group_test_collection", GroupBy.keyFunction("classpath:keyFunction.js")
.initialDocument("{ count: 0 }").reduceFunction("classpath:groupReduce.js"), XObject.class);
assertMapReduceResults(results);
}
@Test
public void SimpleGroupWithQueryAndFunctionsAsResources() {
createGroupByData();
GroupByResults<XObject> results;
results = mongoTemplate.group(where("x").gt(0),
"group_test_collection",
keyFunction("classpath:keyFunction.js").initialDocument("{ count: 0 }").reduceFunction("classpath:groupReduce.js"), XObject.class);
assertMapReduceResults(results);
results = mongoTemplate.group(where("x").gt(0), "group_test_collection", keyFunction("classpath:keyFunction.js")
.initialDocument("{ count: 0 }").reduceFunction("classpath:groupReduce.js"), XObject.class);
assertMapReduceResults(results);
}
private void assertMapReduceResults(GroupByResults<XObject> results) {
DBObject dboRawResults = results.getRawResults();
String expected = "{ \"serverUsed\" : \"127.0.0.1:27017\" , \"retval\" : [ { \"x\" : 1.0 , \"count\" : 2.0} , { \"x\" : 2.0 , \"count\" : 1.0} , { \"x\" : 3.0 , \"count\" : 3.0}] , \"count\" : 6.0 , \"keys\" : 3 , \"ok\" : 1.0}";
Assert.assertEquals(expected, dboRawResults.toString());
int numResults = 0;
for (XObject xObject : results) {
if (xObject.getX() == 1) {
if (xObject.getX() == 1) {
Assert.assertEquals(2, xObject.getCount(), 0.001);
}
if (xObject.getX() == 2) {
if (xObject.getX() == 2) {
Assert.assertEquals(1, xObject.getCount(), 0.001);
}
if (xObject.getX() == 3) {
if (xObject.getX() == 3) {
Assert.assertEquals(3, xObject.getCount(), 0.001);
}
numResults++;
@@ -182,7 +182,6 @@ public class GroupByTests {
Assert.assertEquals(3, results.getKeys());
}
private void createGroupByData() {
DBCollection c = mongoTemplate.getDb().getCollection("group_test_collection");
c.save(new BasicDBObject("x", 1));

View File

@@ -19,7 +19,6 @@ import org.junit.Test;
public class MapReduceOptionsTests {
@Test
public void testFinalize() {
new MapReduceOptions().finalizeFunction("code");

View File

@@ -112,10 +112,10 @@ public class MapReduceTests {
String reduce = "function (key, values) { return Math.max.apply(Math, values); }";
MapReduceResults<ContentAndVersion> results = mongoTemplate.mapReduce("jmr2", map, reduce,
new MapReduceOptions().outputCollection("jmr2_out"), ContentAndVersion.class);
int size = 0;
for (ContentAndVersion cv : results) {
if (cv.getId().equals("Resume")) {
if (cv.getId().equals("Resume")) {
assertEquals(6, cv.getValue().longValue());
}
if (cv.getId().equals("Schema")) {
@@ -126,7 +126,7 @@ public class MapReduceTests {
}
size++;
}
assertEquals(3,size);
assertEquals(3, size);
}
@Test
@@ -134,11 +134,11 @@ public class MapReduceTests {
createNumberAndVersionData();
String map = "function () { emit(this.number, this.version); }";
String reduce = "function (key, values) { return Math.max.apply(Math, values); }";
MapReduceResults<NumberAndVersion> results =
mongoTemplate.mapReduce("jmr2", map, reduce, new MapReduceOptions().outputCollection("jmr2_out"), NumberAndVersion.class);
int size = 0;
MapReduceResults<NumberAndVersion> results = mongoTemplate.mapReduce("jmr2", map, reduce,
new MapReduceOptions().outputCollection("jmr2_out"), NumberAndVersion.class);
int size = 0;
for (NumberAndVersion nv : results) {
if (nv.getId().equals("1")) {
if (nv.getId().equals("1")) {
assertEquals(2, nv.getValue().longValue());
}
if (nv.getId().equals("2")) {
@@ -149,7 +149,7 @@ public class MapReduceTests {
}
size++;
}
assertEquals(3,size);
assertEquals(3, size);
}
private void createNumberAndVersionData() {

View File

@@ -6,35 +6,42 @@ public class NumberAndVersion {
private Long number;
private Long version;
private Long value;
public Long getValue() {
return value;
}
public void setValue(Long value) {
this.value = value;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Long getNumber() {
return number;
}
public void setNumber(Long number) {
this.number = number;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
@Override
public String toString() {
return "NumberAndVersion [id=" + id + ", number=" + number + ", version=" + version + ", value=" + value + "]";
}
}

View File

@@ -3,7 +3,7 @@ package org.springframework.data.mongodb.core.mapreduce;
public class ValueObject {
private String id;
public String getId() {
return id;
}
@@ -22,5 +22,5 @@ public class ValueObject {
public String toString() {
return "ValueObject [id=" + id + ", value=" + value + "]";
}
}

View File

@@ -3,33 +3,28 @@ package org.springframework.data.mongodb.core.mapreduce;
public class XObject {
private float x;
private float count;
private float count;
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getCount() {
return count;
}
public void setCount(float count) {
this.count = count;
}
@Override
public String toString() {
return "XObject [x=" + x + " count = " + count + "]";
}
}

View File

@@ -26,11 +26,11 @@ import com.mongodb.DBObject;
/**
* Unit tests for {@link BasicQuery}.
*
*
* @author Oliver Gierke
*/
public class BasicQueryUnitTests {
@Test
public void createsQueryFromPlainJson() {
Query q = new BasicQuery("{ \"name\" : \"Thomas\"}");
@@ -45,14 +45,14 @@ public class BasicQueryUnitTests {
reference.put("age", new BasicDBObject("$lt", 80));
assertThat(q.getQueryObject(), is(reference));
}
@Test
public void overridesSortCorrectly() {
BasicQuery query = new BasicQuery("{}");
query.setSortObject(new BasicDBObject("name", -1));
query.sort().on("lastname", Order.ASCENDING);
DBObject sortReference = new BasicDBObject("name", -1);
sortReference.put("lastname", 1);
assertThat(query.getSortObject(), is(sortReference));

Some files were not shown because too many files have changed in this diff Show More