Compare commits
101 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cdd59ffd4 | ||
|
|
5160cdadb6 | ||
|
|
296ca28efa | ||
|
|
86fa1d902a | ||
|
|
80834d8321 | ||
|
|
30b0ec8f57 | ||
|
|
b157981507 | ||
|
|
bfd96d529c | ||
|
|
bf51bcd7ea | ||
|
|
f9317b9f09 | ||
|
|
99bb92db4e | ||
|
|
87d609e1c4 | ||
|
|
8f223bf12f | ||
|
|
a96253f9a4 | ||
|
|
a0884b8227 | ||
|
|
2e6efae925 | ||
|
|
4e688574fc | ||
|
|
3abd38953c | ||
|
|
026f3fadd3 | ||
|
|
14e352aeae | ||
|
|
41aa498a1e | ||
|
|
74cead91fc | ||
|
|
559f160b21 | ||
|
|
62fdd3e519 | ||
|
|
1a414fa2b6 | ||
|
|
29a712e298 | ||
|
|
65a164874a | ||
|
|
d6ff5162b3 | ||
|
|
28a84cafc5 | ||
|
|
eb10b5c426 | ||
|
|
b7b24215e3 | ||
|
|
2a27eb7404 | ||
|
|
ad3ad1f65f | ||
|
|
e7278888a7 | ||
|
|
374fa5a1f2 | ||
|
|
be92489c58 | ||
|
|
88172c8674 | ||
|
|
2dc2072fce | ||
|
|
a7b70d68d7 | ||
|
|
6dc2de03ad | ||
|
|
dc0a03ee63 | ||
|
|
504c44cdf3 | ||
|
|
9ea8b6f6d1 | ||
|
|
37c9de6af9 | ||
|
|
9a1ee81f3f | ||
|
|
c8331c3a1c | ||
|
|
b794d536c5 | ||
|
|
afa05122d2 | ||
|
|
cf06a6527c | ||
|
|
0760a8b425 | ||
|
|
f65cd1d235 | ||
|
|
6f86208111 | ||
|
|
0c33f7e01a | ||
|
|
047df58724 | ||
|
|
9716a93576 | ||
|
|
03e5ebb741 | ||
|
|
6ac908b72e | ||
|
|
5f1049f2de | ||
|
|
07c79e8ba9 | ||
|
|
a94cca3494 | ||
|
|
90842844d4 | ||
|
|
f4c27407ac | ||
|
|
00e1ebb880 | ||
|
|
dd32479ad4 | ||
|
|
ce5fe50550 | ||
|
|
3a04bcb5d3 | ||
|
|
acfe6ccc2c | ||
|
|
3f3ec19364 | ||
|
|
24cbef9bc5 | ||
|
|
b5f74444de | ||
|
|
1b7e077296 | ||
|
|
7ebaf935d4 | ||
|
|
295d7579cb | ||
|
|
a99950d83e | ||
|
|
0bf4ee2711 | ||
|
|
5b8da8dd41 | ||
|
|
b56ca97f68 | ||
|
|
f183b5c7e6 | ||
|
|
1fdde8f0c3 | ||
|
|
b7c3e69653 | ||
|
|
e64d69b8f5 | ||
|
|
d81ed203db | ||
|
|
eae463622c | ||
|
|
6ba8144bca | ||
|
|
9d1c1a9fc5 | ||
|
|
f552ca8073 | ||
|
|
d7bd82c643 | ||
|
|
078cca83e3 | ||
|
|
93ae6815bd | ||
|
|
13dcb8cda1 | ||
|
|
a4497bcf8a | ||
|
|
6a82c47a4d | ||
|
|
8f8f5b7ce4 | ||
|
|
c683813a7a | ||
|
|
dbe983c3cb | ||
|
|
8e11fe84df | ||
|
|
9eb2856840 | ||
|
|
828b379f1f | ||
|
|
161fd8c09d | ||
|
|
dc037dfef6 | ||
|
|
c41653f9da |
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,9 +0,0 @@
|
|||||||
Thank you for proposing a pull request. This template will guide you through the essential steps necessary for a pull request.
|
|
||||||
Make sure that:
|
|
||||||
|
|
||||||
- [ ] You have read the [Spring Data contribution guidelines](https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.adoc).
|
|
||||||
- [ ] There is a ticket in the bug tracker for the project in our [JIRA](https://jira.spring.io/browse/DATAMONGO).
|
|
||||||
- [ ] You use the code formatters provided [here](https://github.com/spring-projects/spring-data-build/tree/master/etc/ide) and have them applied to your changes. Don’t submit any formatting related changes.
|
|
||||||
- [ ] You submit test cases (unit or integration tests) that back your changes.
|
|
||||||
- [ ] You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only).
|
|
||||||
- [ ] You provide your full name and an email address registered with your GitHub account. If you’re a first-time submitter, make sure you have completed the [Contributor’s License Agreement form](https://support.springsource.com/spring_committer_signup).
|
|
||||||
37
.travis.yml
37
.travis.yml
@@ -1,37 +0,0 @@
|
|||||||
language: java
|
|
||||||
|
|
||||||
jdk:
|
|
||||||
- oraclejdk8
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- mongod --version
|
|
||||||
|
|
||||||
env:
|
|
||||||
matrix:
|
|
||||||
- PROFILE=ci
|
|
||||||
- PROFILE=mongo-next
|
|
||||||
- PROFILE=mongo3
|
|
||||||
- PROFILE=mongo3-next
|
|
||||||
- PROFILE=mongo31
|
|
||||||
- PROFILE=mongo32
|
|
||||||
- PROFILE=mongo33
|
|
||||||
|
|
||||||
# Current MongoDB version is 2.4.2 as of 2016-04, see https://github.com/travis-ci/travis-ci/issues/3694
|
|
||||||
# apt-get starts a MongoDB instance so it's not started using before_script
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- mongodb-3.2-precise
|
|
||||||
packages:
|
|
||||||
- mongodb-org-server
|
|
||||||
- mongodb-org-shell
|
|
||||||
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.m2
|
|
||||||
|
|
||||||
install: true
|
|
||||||
|
|
||||||
script: "mvn clean dependency:list test -P${PROFILE} -Dsort"
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
= Contributor Code of Conduct
|
|
||||||
|
|
||||||
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
|
||||||
|
|
||||||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery
|
|
||||||
* Personal attacks
|
|
||||||
* Trolling or insulting/derogatory comments
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing other's private information, such as physical or electronic addresses,
|
|
||||||
without explicit permission
|
|
||||||
* Other unethical or unprofessional conduct
|
|
||||||
|
|
||||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
|
||||||
|
|
||||||
By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
|
||||||
|
|
||||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at spring-code-of-conduct@pivotal.io.
|
|
||||||
All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
|
|
||||||
Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident.
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the http://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at http://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/].
|
|
||||||
1
CONTRIBUTING.MD
Normal file
1
CONTRIBUTING.MD
Normal file
@@ -0,0 +1 @@
|
|||||||
|
You find the contribution guidelines for Spring Data projects [here](https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.md).
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
= Spring Data contribution guidelines
|
|
||||||
|
|
||||||
You find the contribution guidelines for Spring Data projects https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.adoc[here].
|
|
||||||
@@ -1,6 +1,3 @@
|
|||||||
[](http://projects.spring.io/spring-data-mongodb#quick-start)
|
|
||||||
[](http://projects.spring.io/spring-data-mongodb#quick-start)
|
|
||||||
|
|
||||||
# Spring Data MongoDB
|
# Spring Data MongoDB
|
||||||
|
|
||||||
The primary goal of the [Spring Data](http://projects.spring.io/spring-data) project is to make it easier to build Spring-powered applications that use new data access technologies such as non-relational databases, map-reduce frameworks, and cloud based data services.
|
The primary goal of the [Spring Data](http://projects.spring.io/spring-data) project is to make it easier to build Spring-powered applications that use new data access technologies such as non-relational databases, map-reduce frameworks, and cloud based data services.
|
||||||
@@ -29,7 +26,7 @@ Add the Maven dependency:
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb</artifactId>
|
<artifactId>spring-data-mongodb</artifactId>
|
||||||
<version>${version}.RELEASE</version>
|
<version>1.5.0.RELEASE</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -39,7 +36,7 @@ If you'd rather like the latest snapshots of the upcoming major version, use our
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb</artifactId>
|
<artifactId>spring-data-mongodb</artifactId>
|
||||||
<version>${version}.BUILD-SNAPSHOT</version>
|
<version>1.6.0.BUILD-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<repository>
|
<repository>
|
||||||
|
|||||||
72
pom.xml
72
pom.xml
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
<version>1.10.0.M1</version>
|
<version>1.6.5.BUILD-SNAPSHOT</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<name>Spring Data MongoDB</name>
|
<name>Spring Data MongoDB</name>
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data.build</groupId>
|
<groupId>org.springframework.data.build</groupId>
|
||||||
<artifactId>spring-data-parent</artifactId>
|
<artifactId>spring-data-parent</artifactId>
|
||||||
<version>1.9.0.M1</version>
|
<version>1.5.5.BUILD-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
@@ -28,9 +28,9 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<project.type>multi</project.type>
|
<project.type>multi</project.type>
|
||||||
<dist.id>spring-data-mongodb</dist.id>
|
<dist.id>spring-data-mongodb</dist.id>
|
||||||
<springdata.commons>1.13.0.M1</springdata.commons>
|
<springdata.commons>1.9.5.BUILD-SNAPSHOT</springdata.commons>
|
||||||
<mongo>2.14.3</mongo>
|
<mongo>2.12.5</mongo>
|
||||||
<mongo.osgi>2.13.0</mongo.osgi>
|
<mongo.osgi>2.12.5</mongo.osgi>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
@@ -107,7 +107,7 @@
|
|||||||
|
|
||||||
<id>mongo-next</id>
|
<id>mongo-next</id>
|
||||||
<properties>
|
<properties>
|
||||||
<mongo>2.15.0-SNAPSHOT</mongo>
|
<mongo>2.14.0-SNAPSHOT</mongo>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
@@ -123,16 +123,16 @@
|
|||||||
|
|
||||||
<id>mongo3</id>
|
<id>mongo3</id>
|
||||||
<properties>
|
<properties>
|
||||||
<mongo>3.0.4</mongo>
|
<mongo>3.0.2</mongo>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
<profile>
|
<profile>
|
||||||
|
|
||||||
<id>mongo3-next</id>
|
<id>mongo-3-next</id>
|
||||||
<properties>
|
<properties>
|
||||||
<mongo>3.0.5-SNAPSHOT</mongo>
|
<mongo>3.0.0-SNAPSHOT</mongo>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
@@ -143,54 +143,6 @@
|
|||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
<profile>
|
|
||||||
|
|
||||||
<id>mongo31</id>
|
|
||||||
<properties>
|
|
||||||
<mongo>3.1.1</mongo>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</profile>
|
|
||||||
|
|
||||||
<profile>
|
|
||||||
|
|
||||||
<id>mongo32</id>
|
|
||||||
<properties>
|
|
||||||
<mongo>3.2.2</mongo>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</profile>
|
|
||||||
|
|
||||||
<profile>
|
|
||||||
|
|
||||||
<id>mongo33</id>
|
|
||||||
<properties>
|
|
||||||
<mongo>3.3.0</mongo>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>mongo-snapshots</id>
|
|
||||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
</profile>
|
|
||||||
|
|
||||||
<profile>
|
|
||||||
<id>release</id>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.jfrog.buildinfo</groupId>
|
|
||||||
<artifactId>artifactory-maven-plugin</artifactId>
|
|
||||||
<inherited>false</inherited>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
|
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -204,15 +156,15 @@
|
|||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>spring-libs-milestone</id>
|
<id>spring-libs-snapshot</id>
|
||||||
<url>https://repo.spring.io/libs-milestone</url>
|
<url>https://repo.spring.io/libs-snapshot</url>
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<pluginRepositories>
|
<pluginRepositories>
|
||||||
<pluginRepository>
|
<pluginRepository>
|
||||||
<id>spring-plugins-release</id>
|
<id>spring-plugins-release</id>
|
||||||
<url>https://repo.spring.io/plugins-release</url>
|
<url>http://repo.spring.io/plugins-release</url>
|
||||||
</pluginRepository>
|
</pluginRepository>
|
||||||
</pluginRepositories>
|
</pluginRepositories>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
<version>1.10.0.M1</version>
|
<version>1.6.5.BUILD-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb</artifactId>
|
<artifactId>spring-data-mongodb</artifactId>
|
||||||
<version>1.10.0.M1</version>
|
<version>1.6.5.BUILD-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.validation</groupId>
|
<groupId>javax.validation</groupId>
|
||||||
<artifactId>validation-api</artifactId>
|
<artifactId>validation-api</artifactId>
|
||||||
<version>${validation}</version>
|
<version>1.0.0.GA</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2016 the original author or authors.
|
* Copyright 2011-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -37,8 +37,6 @@ import com.mongodb.MongoException;
|
|||||||
/**
|
/**
|
||||||
* @author Thomas Risberg
|
* @author Thomas Risberg
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Alex Vengrovsk
|
|
||||||
* @author Mark Paluch
|
|
||||||
*/
|
*/
|
||||||
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||||
|
|
||||||
@@ -47,7 +45,7 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
private static final String ENTITY_FIELD_NAME = "_entity_field_name";
|
private static final String ENTITY_FIELD_NAME = "_entity_field_name";
|
||||||
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
|
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
|
||||||
|
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
private MongoTemplate mongoTemplate;
|
private MongoTemplate mongoTemplate;
|
||||||
private EntityManagerFactory entityManagerFactory;
|
private EntityManagerFactory entityManagerFactory;
|
||||||
@@ -78,25 +76,25 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
dbk.put(ENTITY_ID, id);
|
dbk.put(ENTITY_ID, id);
|
||||||
dbk.put(ENTITY_CLASS, entityClass.getName());
|
dbk.put(ENTITY_CLASS, entityClass.getName());
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Loading MongoDB data for {}", dbk);
|
log.debug("Loading MongoDB data for " + dbk);
|
||||||
}
|
}
|
||||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
for (DBObject dbo : collection.find(dbk)) {
|
for (DBObject dbo : collection.find(dbk)) {
|
||||||
String key = (String) dbo.get(ENTITY_FIELD_NAME);
|
String key = (String) dbo.get(ENTITY_FIELD_NAME);
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Processing key: {}", key);
|
log.debug("Processing key: " + key);
|
||||||
}
|
}
|
||||||
if (!changeSet.getValues().containsKey(key)) {
|
if (!changeSet.getValues().containsKey(key)) {
|
||||||
String className = (String) dbo.get(ENTITY_FIELD_CLASS);
|
String className = (String) dbo.get(ENTITY_FIELD_CLASS);
|
||||||
if (className == null) {
|
if (className == null) {
|
||||||
throw new DataIntegrityViolationException(
|
throw new DataIntegrityViolationException("Unble to convert property " + key + ": Invalid metadata, "
|
||||||
"Unble to convert property " + key + ": Invalid metadata, " + ENTITY_FIELD_CLASS + " not available");
|
+ ENTITY_FIELD_CLASS + " not available");
|
||||||
}
|
}
|
||||||
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
|
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
|
||||||
Object value = mongoTemplate.getConverter().read(clazz, dbo);
|
Object value = mongoTemplate.getConverter().read(clazz, dbo);
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Adding to ChangeSet: {}", key);
|
log.debug("Adding to ChangeSet: " + key);
|
||||||
}
|
}
|
||||||
changeSet.set(key, value);
|
changeSet.set(key, value);
|
||||||
}
|
}
|
||||||
@@ -111,9 +109,9 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentId(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
|
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentId(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
|
||||||
*/
|
*/
|
||||||
public Object getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
public Object getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.debug("getPersistentId called on {}", entity);
|
log.debug("getPersistentId called on " + entity);
|
||||||
}
|
|
||||||
if (entityManagerFactory == null) {
|
if (entityManagerFactory == null) {
|
||||||
throw new DataAccessResourceFailureException("EntityManagerFactory cannot be null");
|
throw new DataAccessResourceFailureException("EntityManagerFactory cannot be null");
|
||||||
}
|
}
|
||||||
@@ -132,7 +130,7 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Flush: changeset: {}", cs.getValues());
|
log.debug("Flush: changeset: " + cs.getValues());
|
||||||
}
|
}
|
||||||
|
|
||||||
String collName = getCollectionNameForEntity(entity.getClass());
|
String collName = getCollectionNameForEntity(entity.getClass());
|
||||||
@@ -154,7 +152,7 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
});
|
});
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Flush: removing: {}", dbQuery);
|
log.debug("Flush: removing: " + dbQuery);
|
||||||
}
|
}
|
||||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
@@ -166,7 +164,7 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
final DBObject dbDoc = new BasicDBObject();
|
final DBObject dbDoc = new BasicDBObject();
|
||||||
dbDoc.putAll(dbQuery);
|
dbDoc.putAll(dbQuery);
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Flush: saving: {}", dbQuery);
|
log.debug("Flush: saving: " + dbQuery);
|
||||||
}
|
}
|
||||||
mongoTemplate.getConverter().write(value, dbDoc);
|
mongoTemplate.getConverter().write(value, dbDoc);
|
||||||
dbDoc.put(ENTITY_FIELD_CLASS, value.getClass().getName());
|
dbDoc.put(ENTITY_FIELD_CLASS, value.getClass().getName());
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
<version>1.10.0.M1</version>
|
<version>1.6.5.BUILD-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
<version>1.10.0.M1</version>
|
<version>1.6.5.BUILD-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ public class MongoLog4jAppender extends AppenderSkeleton {
|
|||||||
|
|
||||||
// Copy properties into document
|
// Copy properties into document
|
||||||
Map<Object, Object> props = event.getProperties();
|
Map<Object, Object> props = event.getProperties();
|
||||||
if (null != props && !props.isEmpty()) {
|
if (null != props && props.size() > 0) {
|
||||||
BasicDBObject propsDbo = new BasicDBObject();
|
BasicDBObject propsDbo = new BasicDBObject();
|
||||||
for (Map.Entry<Object, Object> entry : props.entrySet()) {
|
for (Map.Entry<Object, Object> entry : props.entrySet()) {
|
||||||
propsDbo.put(entry.getKey().toString(), entry.getValue().toString());
|
propsDbo.put(entry.getKey().toString(), entry.getValue().toString());
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public class MongoLog4jAppenderIntegrationTests {
|
|||||||
|
|
||||||
static final String NAME = MongoLog4jAppenderIntegrationTests.class.getName();
|
static final String NAME = MongoLog4jAppenderIntegrationTests.class.getName();
|
||||||
|
|
||||||
private static final Logger log = Logger.getLogger(NAME);
|
Logger log = Logger.getLogger(NAME);
|
||||||
Mongo mongo;
|
Mongo mongo;
|
||||||
DB db;
|
DB db;
|
||||||
String collection;
|
String collection;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<context version="7.2.2.230">
|
<context version="7.1.10.209">
|
||||||
<scope type="Project" name="spring-data-mongodb">
|
<scope type="Project" name="spring-data-mongodb">
|
||||||
<element type="TypeFilterReferenceOverridden" name="Filter">
|
<element type="TypeFilterReferenceOverridden" name="Filter">
|
||||||
<element type="IncludeTypePattern" name="org.springframework.data.mongodb.**"/>
|
<element type="IncludeTypePattern" name="org.springframework.data.mongodb.**"/>
|
||||||
@@ -35,12 +35,6 @@
|
|||||||
<dependency toName="Project|spring-data-mongodb::Layer|Repositories::Subsystem|API" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Repositories::Subsystem|API" type="AllowedDependency"/>
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Repositories::Subsystem|Implementation" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Repositories::Subsystem|Implementation" type="AllowedDependency"/>
|
||||||
</element>
|
</element>
|
||||||
<element type="Subsystem" name="CDI">
|
|
||||||
<element type="TypeFilter" name="Assignment">
|
|
||||||
<element type="IncludeTypePattern" name="**.cdi.**"/>
|
|
||||||
</element>
|
|
||||||
<stereotype name="Unrestricted"/>
|
|
||||||
</element>
|
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Config" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Config" type="AllowedDependency"/>
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Core" type="AllowedDependency"/>
|
||||||
</element>
|
</element>
|
||||||
@@ -82,11 +76,6 @@
|
|||||||
</element>
|
</element>
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Geospatial" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Geospatial" type="AllowedDependency"/>
|
||||||
</element>
|
</element>
|
||||||
<element type="Subsystem" name="Script">
|
|
||||||
<element type="TypeFilter" name="Assignment">
|
|
||||||
<element type="IncludeTypePattern" name="**.script.**"/>
|
|
||||||
</element>
|
|
||||||
</element>
|
|
||||||
<element type="Subsystem" name="Conversion">
|
<element type="Subsystem" name="Conversion">
|
||||||
<element type="TypeFilter" name="Assignment">
|
<element type="TypeFilter" name="Assignment">
|
||||||
<element type="IncludeTypePattern" name="**.core.convert.**"/>
|
<element type="IncludeTypePattern" name="**.core.convert.**"/>
|
||||||
@@ -94,7 +83,6 @@
|
|||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Geospatial" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Geospatial" type="AllowedDependency"/>
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Mapping" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Mapping" type="AllowedDependency"/>
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Query" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Query" type="AllowedDependency"/>
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Script" type="AllowedDependency"/>
|
|
||||||
</element>
|
</element>
|
||||||
<element type="Subsystem" name="SpEL">
|
<element type="Subsystem" name="SpEL">
|
||||||
<element type="TypeFilter" name="Assignment">
|
<element type="TypeFilter" name="Assignment">
|
||||||
@@ -117,11 +105,6 @@
|
|||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Mapping" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Mapping" type="AllowedDependency"/>
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Query" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Query" type="AllowedDependency"/>
|
||||||
</element>
|
</element>
|
||||||
<element type="Subsystem" name="MapReduce">
|
|
||||||
<element type="TypeFilter" name="Assignment">
|
|
||||||
<element type="IncludeTypePattern" name="**.mapreduce.**"/>
|
|
||||||
</element>
|
|
||||||
</element>
|
|
||||||
<element type="Subsystem" name="Core">
|
<element type="Subsystem" name="Core">
|
||||||
<element type="TypeFilter" name="Assignment">
|
<element type="TypeFilter" name="Assignment">
|
||||||
<element type="WeakTypePattern" name="**.core.**"/>
|
<element type="WeakTypePattern" name="**.core.**"/>
|
||||||
@@ -130,10 +113,8 @@
|
|||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Conversion" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Conversion" type="AllowedDependency"/>
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Geospatial" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Geospatial" type="AllowedDependency"/>
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Index" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Index" type="AllowedDependency"/>
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|MapReduce" type="AllowedDependency"/>
|
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Mapping" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Mapping" type="AllowedDependency"/>
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Query" type="AllowedDependency"/>
|
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Query" type="AllowedDependency"/>
|
||||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Script" type="AllowedDependency"/>
|
|
||||||
</element>
|
</element>
|
||||||
<element type="Subsystem" name="Util">
|
<element type="Subsystem" name="Util">
|
||||||
<element type="TypeFilter" name="Assignment">
|
<element type="TypeFilter" name="Assignment">
|
||||||
@@ -188,32 +169,7 @@
|
|||||||
</element>
|
</element>
|
||||||
<element type="Subsystem" name="Querydsl">
|
<element type="Subsystem" name="Querydsl">
|
||||||
<element type="TypeFilter" name="Assignment">
|
<element type="TypeFilter" name="Assignment">
|
||||||
<element type="IncludeTypePattern" name="com.querydsl.**"/>
|
<element type="IncludeTypePattern" name="com.mysema.query.**"/>
|
||||||
</element>
|
|
||||||
</element>
|
|
||||||
<element type="Subsystem" name="Slf4j">
|
|
||||||
<element type="TypeFilter" name="Assignment">
|
|
||||||
<element type="IncludeTypePattern" name="org.slf4j.**"/>
|
|
||||||
</element>
|
|
||||||
</element>
|
|
||||||
<element type="Subsystem" name="Jackson">
|
|
||||||
<element type="TypeFilter" name="Assignment">
|
|
||||||
<element type="IncludeTypePattern" name="com.fasterxml.jackson.**"/>
|
|
||||||
</element>
|
|
||||||
</element>
|
|
||||||
<element type="Subsystem" name="DOM">
|
|
||||||
<element type="TypeFilter" name="Assignment">
|
|
||||||
<element type="IncludeTypePattern" name="org.w3c.dom.**"/>
|
|
||||||
</element>
|
|
||||||
</element>
|
|
||||||
<element type="Subsystem" name="AOP Alliance">
|
|
||||||
<element type="TypeFilter" name="Assignment">
|
|
||||||
<element type="IncludeTypePattern" name="org.aopalliance.**"/>
|
|
||||||
</element>
|
|
||||||
</element>
|
|
||||||
<element type="Subsystem" name="Guava">
|
|
||||||
<element type="TypeFilter" name="Assignment">
|
|
||||||
<element type="IncludeTypePattern" name="com.google.common.**"/>
|
|
||||||
</element>
|
</element>
|
||||||
</element>
|
</element>
|
||||||
</architecture>
|
</architecture>
|
||||||
|
|||||||
@@ -11,11 +11,12 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
<version>1.10.0.M1</version>
|
<version>1.6.5.BUILD-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
<validation>1.0.0.GA</validation>
|
||||||
<objenesis>1.3</objenesis>
|
<objenesis>1.3</objenesis>
|
||||||
<equalsverifier>1.5</equalsverifier>
|
<equalsverifier>1.5</equalsverifier>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -58,14 +59,14 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.querydsl</groupId>
|
<groupId>com.mysema.querydsl</groupId>
|
||||||
<artifactId>querydsl-mongodb</artifactId>
|
<artifactId>querydsl-mongodb</artifactId>
|
||||||
<version>${querydsl}</version>
|
<version>${querydsl}</version>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.querydsl</groupId>
|
<groupId>com.mysema.querydsl</groupId>
|
||||||
<artifactId>querydsl-apt</artifactId>
|
<artifactId>querydsl-apt</artifactId>
|
||||||
<version>${querydsl}</version>
|
<version>${querydsl}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
@@ -137,20 +138,6 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.threeten</groupId>
|
|
||||||
<artifactId>threetenbp</artifactId>
|
|
||||||
<version>${threetenbp}</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-databind</artifactId>
|
|
||||||
<version>${jackson}</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>jul-to-slf4j</artifactId>
|
<artifactId>jul-to-slf4j</artifactId>
|
||||||
@@ -164,13 +151,6 @@
|
|||||||
<version>${equalsverifier}</version>
|
<version>${equalsverifier}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-webmvc</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -182,7 +162,7 @@
|
|||||||
<version>${apt}</version>
|
<version>${apt}</version>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.querydsl</groupId>
|
<groupId>com.mysema.querydsl</groupId>
|
||||||
<artifactId>querydsl-apt</artifactId>
|
<artifactId>querydsl-apt</artifactId>
|
||||||
<version>${querydsl}</version>
|
<version>${querydsl}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.dao.DataAccessException;
|
|
||||||
|
|
||||||
import com.mongodb.BulkWriteError;
|
|
||||||
import com.mongodb.BulkWriteException;
|
|
||||||
import com.mongodb.BulkWriteResult;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is thrown when errors occur during bulk operations.
|
|
||||||
*
|
|
||||||
* @author Tobias Trelle
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.9
|
|
||||||
*/
|
|
||||||
public class BulkOperationException extends DataAccessException {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 73929601661154421L;
|
|
||||||
|
|
||||||
private final List<BulkWriteError> errors;
|
|
||||||
private final BulkWriteResult result;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link BulkOperationException} with the given message and source {@link BulkWriteException}.
|
|
||||||
*
|
|
||||||
* @param message must not be {@literal null}.
|
|
||||||
* @param source must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public BulkOperationException(String message, BulkWriteException source) {
|
|
||||||
|
|
||||||
super(message, source);
|
|
||||||
|
|
||||||
this.errors = source.getWriteErrors();
|
|
||||||
this.result = source.getWriteResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<BulkWriteError> getErrors() {
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BulkWriteResult getResult() {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2015 the original author or authors.
|
* Copyright 2011-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -46,7 +46,6 @@ import org.springframework.util.ClassUtils;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.mongodb.Mongo;
|
import com.mongodb.Mongo;
|
||||||
import com.mongodb.MongoClient;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for Spring Data MongoDB configuration using JavaConfig.
|
* Base class for Spring Data MongoDB configuration using JavaConfig.
|
||||||
@@ -55,7 +54,6 @@ import com.mongodb.MongoClient;
|
|||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Ryan Tenney
|
* @author Ryan Tenney
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public abstract class AbstractMongoConfiguration {
|
public abstract class AbstractMongoConfiguration {
|
||||||
@@ -72,10 +70,7 @@ public abstract class AbstractMongoConfiguration {
|
|||||||
* returned by {@link #getDatabaseName()} later on effectively.
|
* returned by {@link #getDatabaseName()} later on effectively.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* @deprecated since 1.7. {@link MongoClient} should hold authentication data within
|
|
||||||
* {@link MongoClient#getCredentialsList()}
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
protected String getAuthenticationDatabaseName() {
|
protected String getAuthenticationDatabaseName() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -134,10 +129,7 @@ public abstract class AbstractMongoConfiguration {
|
|||||||
* be used.
|
* be used.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* @deprecated since 1.7. {@link MongoClient} should hold authentication data within
|
|
||||||
* {@link MongoClient#getCredentialsList()}
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
protected UserCredentials getUserCredentials() {
|
protected UserCredentials getUserCredentials() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.config;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
|
||||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
|
||||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
|
||||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
|
||||||
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
|
||||||
import org.springframework.data.config.ParsingUtils;
|
|
||||||
import org.springframework.data.mongodb.core.MongoClientFactoryBean;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parser for {@code mongo-client} definitions.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public class MongoClientParser implements BeanDefinitionParser {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
|
||||||
*/
|
|
||||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
|
||||||
|
|
||||||
Object source = parserContext.extractSource(element);
|
|
||||||
String id = element.getAttribute("id");
|
|
||||||
|
|
||||||
BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext);
|
|
||||||
|
|
||||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MongoClientFactoryBean.class);
|
|
||||||
|
|
||||||
ParsingUtils.setPropertyValue(builder, element, "port", "port");
|
|
||||||
ParsingUtils.setPropertyValue(builder, element, "host", "host");
|
|
||||||
ParsingUtils.setPropertyValue(builder, element, "credentials", "credentials");
|
|
||||||
|
|
||||||
MongoParsingUtils.parseMongoClientOptions(element, builder);
|
|
||||||
MongoParsingUtils.parseReplicaSet(element, builder);
|
|
||||||
|
|
||||||
String defaultedId = StringUtils.hasText(id) ? id : BeanNames.MONGO_BEAN_NAME;
|
|
||||||
|
|
||||||
parserContext.pushContainingComponent(new CompositeComponentDefinition("Mongo", source));
|
|
||||||
|
|
||||||
BeanComponentDefinition mongoComponent = helper.getComponent(builder, defaultedId);
|
|
||||||
parserContext.registerBeanComponent(mongoComponent);
|
|
||||||
|
|
||||||
BeanComponentDefinition serverAddressPropertyEditor = helper.getComponent(MongoParsingUtils
|
|
||||||
.getServerAddressPropertyEditorBuilder());
|
|
||||||
parserContext.registerBeanComponent(serverAddressPropertyEditor);
|
|
||||||
|
|
||||||
BeanComponentDefinition writeConcernEditor = helper.getComponent(MongoParsingUtils
|
|
||||||
.getWriteConcernPropertyEditorBuilder());
|
|
||||||
parserContext.registerBeanComponent(writeConcernEditor);
|
|
||||||
|
|
||||||
BeanComponentDefinition readPreferenceEditor = helper.getComponent(MongoParsingUtils
|
|
||||||
.getReadPreferencePropertyEditorBuilder());
|
|
||||||
parserContext.registerBeanComponent(readPreferenceEditor);
|
|
||||||
|
|
||||||
BeanComponentDefinition credentialsEditor = helper.getComponent(MongoParsingUtils
|
|
||||||
.getMongoCredentialPropertyEditor());
|
|
||||||
parserContext.registerBeanComponent(credentialsEditor);
|
|
||||||
|
|
||||||
parserContext.popAndRegisterContainingComponent();
|
|
||||||
|
|
||||||
return mongoComponent.getBeanDefinition();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.config;
|
|
||||||
|
|
||||||
import java.beans.PropertyEditorSupport;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import com.mongodb.MongoCredential;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a {@link String} to a Collection of {@link MongoCredential}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
|
|
||||||
|
|
||||||
private static final Pattern GROUP_PATTERN = Pattern.compile("(\\\\?')(.*?)\\1");
|
|
||||||
|
|
||||||
private static final String AUTH_MECHANISM_KEY = "uri.authMechanism";
|
|
||||||
private static final String USERNAME_PASSWORD_DELIMINATOR = ":";
|
|
||||||
private static final String DATABASE_DELIMINATOR = "@";
|
|
||||||
private static final String OPTIONS_DELIMINATOR = "?";
|
|
||||||
private static final String OPTION_VALUE_DELIMINATOR = "&";
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setAsText(String text) throws IllegalArgumentException {
|
|
||||||
|
|
||||||
if (!StringUtils.hasText(text)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<MongoCredential> credentials = new ArrayList<MongoCredential>();
|
|
||||||
|
|
||||||
for (String credentialString : extractCredentialsString(text)) {
|
|
||||||
|
|
||||||
String[] userNameAndPassword = extractUserNameAndPassword(credentialString);
|
|
||||||
String database = extractDB(credentialString);
|
|
||||||
Properties options = extractOptions(credentialString);
|
|
||||||
|
|
||||||
if (!options.isEmpty()) {
|
|
||||||
|
|
||||||
if (options.containsKey(AUTH_MECHANISM_KEY)) {
|
|
||||||
|
|
||||||
String authMechanism = options.getProperty(AUTH_MECHANISM_KEY);
|
|
||||||
|
|
||||||
if (MongoCredential.GSSAPI_MECHANISM.equals(authMechanism)) {
|
|
||||||
|
|
||||||
verifyUserNamePresent(userNameAndPassword);
|
|
||||||
credentials.add(MongoCredential.createGSSAPICredential(userNameAndPassword[0]));
|
|
||||||
} else if (MongoCredential.MONGODB_CR_MECHANISM.equals(authMechanism)) {
|
|
||||||
|
|
||||||
verifyUsernameAndPasswordPresent(userNameAndPassword);
|
|
||||||
verifyDatabasePresent(database);
|
|
||||||
credentials.add(MongoCredential.createMongoCRCredential(userNameAndPassword[0], database,
|
|
||||||
userNameAndPassword[1].toCharArray()));
|
|
||||||
} else if (MongoCredential.MONGODB_X509_MECHANISM.equals(authMechanism)) {
|
|
||||||
|
|
||||||
verifyUserNamePresent(userNameAndPassword);
|
|
||||||
credentials.add(MongoCredential.createMongoX509Credential(userNameAndPassword[0]));
|
|
||||||
} else if (MongoCredential.PLAIN_MECHANISM.equals(authMechanism)) {
|
|
||||||
|
|
||||||
verifyUsernameAndPasswordPresent(userNameAndPassword);
|
|
||||||
verifyDatabasePresent(database);
|
|
||||||
credentials.add(MongoCredential.createPlainCredential(userNameAndPassword[0], database,
|
|
||||||
userNameAndPassword[1].toCharArray()));
|
|
||||||
} else if (MongoCredential.SCRAM_SHA_1_MECHANISM.equals(authMechanism)) {
|
|
||||||
|
|
||||||
verifyUsernameAndPasswordPresent(userNameAndPassword);
|
|
||||||
verifyDatabasePresent(database);
|
|
||||||
credentials.add(MongoCredential.createScramSha1Credential(userNameAndPassword[0], database,
|
|
||||||
userNameAndPassword[1].toCharArray()));
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
String.format("Cannot create MongoCredentials for unknown auth mechanism '%s'!", authMechanism));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
verifyUsernameAndPasswordPresent(userNameAndPassword);
|
|
||||||
verifyDatabasePresent(database);
|
|
||||||
credentials.add(
|
|
||||||
MongoCredential.createCredential(userNameAndPassword[0], database, userNameAndPassword[1].toCharArray()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setValue(credentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> extractCredentialsString(String source) {
|
|
||||||
|
|
||||||
Matcher matcher = GROUP_PATTERN.matcher(source);
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
|
|
||||||
while (matcher.find()) {
|
|
||||||
|
|
||||||
String value = StringUtils.trimLeadingCharacter(matcher.group(), '\'');
|
|
||||||
list.add(StringUtils.trimTrailingCharacter(value, '\''));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!list.isEmpty()) {
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Arrays.asList(source.split(","));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String[] extractUserNameAndPassword(String text) {
|
|
||||||
|
|
||||||
int index = text.lastIndexOf(DATABASE_DELIMINATOR);
|
|
||||||
|
|
||||||
index = index != -1 ? index : text.lastIndexOf(OPTIONS_DELIMINATOR);
|
|
||||||
|
|
||||||
return index == -1 ? new String[] {} : text.substring(0, index).split(USERNAME_PASSWORD_DELIMINATOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String extractDB(String text) {
|
|
||||||
|
|
||||||
int dbSeperationIndex = text.lastIndexOf(DATABASE_DELIMINATOR);
|
|
||||||
|
|
||||||
if (dbSeperationIndex == -1) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
String tmp = text.substring(dbSeperationIndex + 1);
|
|
||||||
int optionsSeperationIndex = tmp.lastIndexOf(OPTIONS_DELIMINATOR);
|
|
||||||
|
|
||||||
return optionsSeperationIndex > -1 ? tmp.substring(0, optionsSeperationIndex) : tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Properties extractOptions(String text) {
|
|
||||||
|
|
||||||
int optionsSeperationIndex = text.lastIndexOf(OPTIONS_DELIMINATOR);
|
|
||||||
int dbSeperationIndex = text.lastIndexOf(OPTIONS_DELIMINATOR);
|
|
||||||
|
|
||||||
if (optionsSeperationIndex == -1 || dbSeperationIndex > optionsSeperationIndex) {
|
|
||||||
return new Properties();
|
|
||||||
}
|
|
||||||
|
|
||||||
Properties properties = new Properties();
|
|
||||||
|
|
||||||
for (String option : text.substring(optionsSeperationIndex + 1).split(OPTION_VALUE_DELIMINATOR)) {
|
|
||||||
String[] optionArgs = option.split("=");
|
|
||||||
properties.put(optionArgs[0], optionArgs[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void verifyUsernameAndPasswordPresent(String[] source) {
|
|
||||||
|
|
||||||
verifyUserNamePresent(source);
|
|
||||||
|
|
||||||
if (source.length != 2) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Credentials need to specify username and password like in 'username:password@database'!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void verifyDatabasePresent(String source) {
|
|
||||||
|
|
||||||
if (!StringUtils.hasText(source)) {
|
|
||||||
throw new IllegalArgumentException("Credentials need to specify database like in 'username:password@database'!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void verifyUserNamePresent(String[] source) {
|
|
||||||
|
|
||||||
if (source.length == 0 || !StringUtils.hasText(source[0])) {
|
|
||||||
throw new IllegalArgumentException("Credentials need to specify username!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2015 by the original author(s).
|
* Copyright 2011-2014 by the original author(s).
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -18,10 +18,6 @@ package org.springframework.data.mongodb.config;
|
|||||||
import static org.springframework.data.config.ParsingUtils.*;
|
import static org.springframework.data.config.ParsingUtils.*;
|
||||||
import static org.springframework.data.mongodb.config.MongoParsingUtils.*;
|
import static org.springframework.data.mongodb.config.MongoParsingUtils.*;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
@@ -38,7 +34,6 @@ import org.springframework.util.StringUtils;
|
|||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
import com.mongodb.Mongo;
|
import com.mongodb.Mongo;
|
||||||
import com.mongodb.MongoClientURI;
|
|
||||||
import com.mongodb.MongoURI;
|
import com.mongodb.MongoURI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,22 +42,9 @@ import com.mongodb.MongoURI;
|
|||||||
* @author Jon Brisbin
|
* @author Jon Brisbin
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Viktor Khoroshko
|
|
||||||
*/
|
*/
|
||||||
public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||||
|
|
||||||
private static final Set<String> MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES;
|
|
||||||
|
|
||||||
static {
|
|
||||||
|
|
||||||
Set<String> mongoUriAllowedAdditionalAttributes = new HashSet<String>();
|
|
||||||
mongoUriAllowedAdditionalAttributes.add("id");
|
|
||||||
mongoUriAllowedAdditionalAttributes.add("write-concern");
|
|
||||||
|
|
||||||
MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES = Collections.unmodifiableSet(mongoUriAllowedAdditionalAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
||||||
@@ -82,25 +64,29 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
|||||||
@Override
|
@Override
|
||||||
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
||||||
|
|
||||||
// Common setup
|
Object source = parserContext.extractSource(element);
|
||||||
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
|
|
||||||
setPropertyValue(dbFactoryBuilder, element, "write-concern", "writeConcern");
|
|
||||||
|
|
||||||
BeanDefinition mongoUri = getMongoUri(element, parserContext);
|
|
||||||
|
|
||||||
if (mongoUri != null) {
|
|
||||||
|
|
||||||
dbFactoryBuilder.addConstructorArgValue(mongoUri);
|
|
||||||
return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
|
|
||||||
}
|
|
||||||
|
|
||||||
BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext);
|
BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext);
|
||||||
|
|
||||||
|
String uri = element.getAttribute("uri");
|
||||||
String mongoRef = element.getAttribute("mongo-ref");
|
String mongoRef = element.getAttribute("mongo-ref");
|
||||||
String dbname = element.getAttribute("dbname");
|
String dbname = element.getAttribute("dbname");
|
||||||
|
|
||||||
BeanDefinition userCredentials = getUserCredentialsBeanDefinition(element, parserContext);
|
BeanDefinition userCredentials = getUserCredentialsBeanDefinition(element, parserContext);
|
||||||
|
|
||||||
|
// Common setup
|
||||||
|
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
|
||||||
|
setPropertyValue(dbFactoryBuilder, element, "write-concern", "writeConcern");
|
||||||
|
|
||||||
|
if (StringUtils.hasText(uri)) {
|
||||||
|
if (StringUtils.hasText(mongoRef) || StringUtils.hasText(dbname) || userCredentials != null) {
|
||||||
|
parserContext.getReaderContext().error("Configure either Mongo URI or details individually!", source);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbFactoryBuilder.addConstructorArgValue(getMongoUri(uri));
|
||||||
|
return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
|
||||||
|
}
|
||||||
|
|
||||||
// Defaulting
|
// Defaulting
|
||||||
if (StringUtils.hasText(mongoRef)) {
|
if (StringUtils.hasText(mongoRef)) {
|
||||||
dbFactoryBuilder.addConstructorArgReference(mongoRef);
|
dbFactoryBuilder.addConstructorArgReference(mongoRef);
|
||||||
@@ -161,42 +147,14 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link BeanDefinition} for a {@link MongoURI} or {@link MongoClientURI} depending on configured
|
* Creates a {@link BeanDefinition} for a {@link MongoURI}.
|
||||||
* attributes. <br />
|
|
||||||
* Errors when configured element contains {@literal uri} or {@literal client-uri} along with other attributes except
|
|
||||||
* {@literal write-concern} and/or {@literal id}.
|
|
||||||
*
|
*
|
||||||
* @param element must not be {@literal null}.
|
* @param uri
|
||||||
* @param parserContext
|
* @return
|
||||||
* @return {@literal null} in case no client-/uri defined.
|
|
||||||
*/
|
*/
|
||||||
private BeanDefinition getMongoUri(Element element, ParserContext parserContext) {
|
private BeanDefinition getMongoUri(String uri) {
|
||||||
|
|
||||||
boolean hasClientUri = element.hasAttribute("client-uri");
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MongoURI.class);
|
||||||
|
|
||||||
if (!hasClientUri && !element.hasAttribute("uri")) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int allowedAttributesCount = 1;
|
|
||||||
for (String attribute : MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES) {
|
|
||||||
|
|
||||||
if (element.hasAttribute(attribute)) {
|
|
||||||
allowedAttributesCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element.getAttributes().getLength() > allowedAttributesCount) {
|
|
||||||
|
|
||||||
parserContext.getReaderContext().error(
|
|
||||||
"Configure either " + (hasClientUri ? "Mongo Client URI" : "Mongo URI") + " or details individually!",
|
|
||||||
parserContext.extractSource(element));
|
|
||||||
}
|
|
||||||
|
|
||||||
Class<?> type = hasClientUri ? MongoClientURI.class : MongoURI.class;
|
|
||||||
String uri = hasClientUri ? element.getAttribute("client-uri") : element.getAttribute("uri");
|
|
||||||
|
|
||||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(type);
|
|
||||||
builder.addConstructorArgValue(uri);
|
builder.addConstructorArgValue(uri);
|
||||||
|
|
||||||
return builder.getBeanDefinition();
|
return builder.getBeanDefinition();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2015 the original author or authors.
|
* Copyright 2011-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -22,7 +22,6 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
|||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Martin Baumgartner
|
* @author Martin Baumgartner
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public class MongoNamespaceHandler extends NamespaceHandlerSupport {
|
public class MongoNamespaceHandler extends NamespaceHandlerSupport {
|
||||||
|
|
||||||
@@ -34,7 +33,6 @@ public class MongoNamespaceHandler extends NamespaceHandlerSupport {
|
|||||||
|
|
||||||
registerBeanDefinitionParser("mapping-converter", new MappingMongoConverterParser());
|
registerBeanDefinitionParser("mapping-converter", new MappingMongoConverterParser());
|
||||||
registerBeanDefinitionParser("mongo", new MongoParser());
|
registerBeanDefinitionParser("mongo", new MongoParser());
|
||||||
registerBeanDefinitionParser("mongo-client", new MongoClientParser());
|
|
||||||
registerBeanDefinitionParser("db-factory", new MongoDbFactoryParser());
|
registerBeanDefinitionParser("db-factory", new MongoDbFactoryParser());
|
||||||
registerBeanDefinitionParser("jmx", new MongoJmxParser());
|
registerBeanDefinitionParser("jmx", new MongoJmxParser());
|
||||||
registerBeanDefinitionParser("auditing", new MongoAuditingBeanDefinitionParser());
|
registerBeanDefinitionParser("auditing", new MongoAuditingBeanDefinitionParser());
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2015 the original author or authors.
|
* Copyright 2011-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -15,10 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.config;
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.CustomEditorConfigurer;
|
||||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.ManagedMap;
|
||||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
||||||
@@ -32,7 +36,6 @@ import org.w3c.dom.Element;
|
|||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public class MongoParser implements BeanDefinitionParser {
|
public class MongoParser implements BeanDefinitionParser {
|
||||||
|
|
||||||
@@ -61,8 +64,7 @@ public class MongoParser implements BeanDefinitionParser {
|
|||||||
|
|
||||||
BeanComponentDefinition mongoComponent = helper.getComponent(builder, defaultedId);
|
BeanComponentDefinition mongoComponent = helper.getComponent(builder, defaultedId);
|
||||||
parserContext.registerBeanComponent(mongoComponent);
|
parserContext.registerBeanComponent(mongoComponent);
|
||||||
BeanComponentDefinition serverAddressPropertyEditor = helper.getComponent(MongoParsingUtils
|
BeanComponentDefinition serverAddressPropertyEditor = helper.getComponent(registerServerAddressPropertyEditor());
|
||||||
.getServerAddressPropertyEditorBuilder());
|
|
||||||
parserContext.registerBeanComponent(serverAddressPropertyEditor);
|
parserContext.registerBeanComponent(serverAddressPropertyEditor);
|
||||||
BeanComponentDefinition writeConcernPropertyEditor = helper.getComponent(MongoParsingUtils
|
BeanComponentDefinition writeConcernPropertyEditor = helper.getComponent(MongoParsingUtils
|
||||||
.getWriteConcernPropertyEditorBuilder());
|
.getWriteConcernPropertyEditorBuilder());
|
||||||
@@ -73,4 +75,19 @@ public class MongoParser implements BeanDefinitionParser {
|
|||||||
return mongoComponent.getBeanDefinition();
|
return mongoComponent.getBeanDefinition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One should only register one bean definition but want to have the convenience of using
|
||||||
|
* AbstractSingleBeanDefinitionParser but have the side effect of registering a 'default' property editor with the
|
||||||
|
* container.
|
||||||
|
*/
|
||||||
|
private BeanDefinitionBuilder registerServerAddressPropertyEditor() {
|
||||||
|
|
||||||
|
Map<String, String> customEditors = new ManagedMap<String, String>();
|
||||||
|
customEditors.put("com.mongodb.ServerAddress[]",
|
||||||
|
"org.springframework.data.mongodb.config.ServerAddressPropertyEditor");
|
||||||
|
|
||||||
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
||||||
|
builder.addPropertyValue("customEditors", customEditors);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2015 the original author or authors.
|
* Copyright 2011-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -24,7 +24,6 @@ import org.springframework.beans.factory.config.CustomEditorConfigurer;
|
|||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.ManagedMap;
|
import org.springframework.beans.factory.support.ManagedMap;
|
||||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
import org.springframework.data.mongodb.core.MongoClientOptionsFactoryBean;
|
|
||||||
import org.springframework.data.mongodb.core.MongoOptionsFactoryBean;
|
import org.springframework.data.mongodb.core.MongoOptionsFactoryBean;
|
||||||
import org.springframework.util.xml.DomUtils;
|
import org.springframework.util.xml.DomUtils;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
@@ -34,13 +33,13 @@ import org.w3c.dom.Element;
|
|||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
abstract class MongoParsingUtils {
|
abstract class MongoParsingUtils {
|
||||||
|
|
||||||
private MongoParsingUtils() {}
|
private MongoParsingUtils() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the mongo replica-set element.
|
* Parses the mongo replica-set element.
|
||||||
@@ -55,14 +54,12 @@ abstract class MongoParsingUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the {@code mongo:options} sub-element. Populates the given attribute factory with the proper attributes.
|
* Parses the mongo:options sub-element. Populates the given attribute factory with the proper attributes.
|
||||||
*
|
*
|
||||||
* @return true if parsing actually occured, {@literal false} otherwise
|
* @return true if parsing actually occured, false otherwise
|
||||||
*/
|
*/
|
||||||
static boolean parseMongoOptions(Element element, BeanDefinitionBuilder mongoBuilder) {
|
static boolean parseMongoOptions(Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||||
|
|
||||||
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
|
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
|
||||||
|
|
||||||
if (optionsElement == null) {
|
if (optionsElement == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -83,58 +80,13 @@ abstract class MongoParsingUtils {
|
|||||||
setPropertyValue(optionsDefBuilder, optionsElement, "write-timeout", "writeTimeout");
|
setPropertyValue(optionsDefBuilder, optionsElement, "write-timeout", "writeTimeout");
|
||||||
setPropertyValue(optionsDefBuilder, optionsElement, "write-fsync", "writeFsync");
|
setPropertyValue(optionsDefBuilder, optionsElement, "write-fsync", "writeFsync");
|
||||||
setPropertyValue(optionsDefBuilder, optionsElement, "slave-ok", "slaveOk");
|
setPropertyValue(optionsDefBuilder, optionsElement, "slave-ok", "slaveOk");
|
||||||
setPropertyValue(optionsDefBuilder, optionsElement, "ssl", "ssl");
|
setPropertyValue(optionsDefBuilder, optionsElement, "ssl", "ssl");
|
||||||
setPropertyReference(optionsDefBuilder, optionsElement, "ssl-socket-factory-ref", "sslSocketFactory");
|
setPropertyReference(optionsDefBuilder, optionsElement, "ssl-socket-factory-ref", "sslSocketFactory");
|
||||||
|
|
||||||
mongoBuilder.addPropertyValue("mongoOptions", optionsDefBuilder.getBeanDefinition());
|
mongoBuilder.addPropertyValue("mongoOptions", optionsDefBuilder.getBeanDefinition());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the {@code mongo:client-options} sub-element. Populates the given attribute factory with the proper
|
|
||||||
* attributes.
|
|
||||||
*
|
|
||||||
* @param element must not be {@literal null}.
|
|
||||||
* @param mongoClientBuilder must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public static boolean parseMongoClientOptions(Element element, BeanDefinitionBuilder mongoClientBuilder) {
|
|
||||||
|
|
||||||
Element optionsElement = DomUtils.getChildElementByTagName(element, "client-options");
|
|
||||||
|
|
||||||
if (optionsElement == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BeanDefinitionBuilder clientOptionsDefBuilder = BeanDefinitionBuilder
|
|
||||||
.genericBeanDefinition(MongoClientOptionsFactoryBean.class);
|
|
||||||
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "description", "description");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "min-connections-per-host", "minConnectionsPerHost");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "connections-per-host", "connectionsPerHost");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "threads-allowed-to-block-for-connection-multiplier",
|
|
||||||
"threadsAllowedToBlockForConnectionMultiplier");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-wait-time", "maxWaitTime");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-connection-idle-time", "maxConnectionIdleTime");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-connection-life-time", "maxConnectionLifeTime");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "connect-timeout", "connectTimeout");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "socket-timeout", "socketTimeout");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "socket-keep-alive", "socketKeepAlive");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "read-preference", "readPreference");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "write-concern", "writeConcern");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-frequency", "heartbeatFrequency");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "min-heartbeat-frequency", "minHeartbeatFrequency");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-connect-timeout", "heartbeatConnectTimeout");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-socket-timeout", "heartbeatSocketTimeout");
|
|
||||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "ssl", "ssl");
|
|
||||||
setPropertyReference(clientOptionsDefBuilder, optionsElement, "ssl-socket-factory-ref", "sslSocketFactory");
|
|
||||||
|
|
||||||
mongoClientBuilder.addPropertyValue("mongoClientOptions", clientOptionsDefBuilder.getBeanDefinition());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
||||||
* {@link WriteConcernPropertyEditor}.
|
* {@link WriteConcernPropertyEditor}.
|
||||||
@@ -151,56 +103,4 @@ abstract class MongoParsingUtils {
|
|||||||
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* One should only register one bean definition but want to have the convenience of using
|
|
||||||
* AbstractSingleBeanDefinitionParser but have the side effect of registering a 'default' property editor with the
|
|
||||||
* container.
|
|
||||||
*/
|
|
||||||
static BeanDefinitionBuilder getServerAddressPropertyEditorBuilder() {
|
|
||||||
|
|
||||||
Map<String, String> customEditors = new ManagedMap<String, String>();
|
|
||||||
customEditors.put("com.mongodb.ServerAddress[]",
|
|
||||||
"org.springframework.data.mongodb.config.ServerAddressPropertyEditor");
|
|
||||||
|
|
||||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
|
||||||
builder.addPropertyValue("customEditors", customEditors);
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
|
||||||
* {@link ReadPreferencePropertyEditor}.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
static BeanDefinitionBuilder getReadPreferencePropertyEditorBuilder() {
|
|
||||||
|
|
||||||
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
|
|
||||||
customEditors.put("com.mongodb.ReadPreference", ReadPreferencePropertyEditor.class);
|
|
||||||
|
|
||||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
|
||||||
builder.addPropertyValue("customEditors", customEditors);
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
|
||||||
* {@link MongoCredentialPropertyEditor}.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
static BeanDefinitionBuilder getMongoCredentialPropertyEditor() {
|
|
||||||
|
|
||||||
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
|
|
||||||
customEditors.put("com.mongodb.MongoCredential[]", MongoCredentialPropertyEditor.class);
|
|
||||||
|
|
||||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
|
||||||
builder.addPropertyValue("customEditors", customEditors);
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.config;
|
|
||||||
|
|
||||||
import java.beans.PropertyEditorSupport;
|
|
||||||
|
|
||||||
import com.mongodb.ReadPreference;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a {@link String} to a {@link ReadPreference}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public class ReadPreferencePropertyEditor extends PropertyEditorSupport {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setAsText(String readPreferenceString) throws IllegalArgumentException {
|
|
||||||
|
|
||||||
if (readPreferenceString == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadPreference preference = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
preference = ReadPreference.valueOf(readPreferenceString);
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
// ignore this one and try to map it differently
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preference != null) {
|
|
||||||
setValue(preference);
|
|
||||||
} else if ("PRIMARY".equalsIgnoreCase(readPreferenceString)) {
|
|
||||||
setValue(ReadPreference.primary());
|
|
||||||
} else if ("PRIMARY_PREFERRED".equalsIgnoreCase(readPreferenceString)) {
|
|
||||||
setValue(ReadPreference.primaryPreferred());
|
|
||||||
} else if ("SECONDARY".equalsIgnoreCase(readPreferenceString)) {
|
|
||||||
setValue(ReadPreference.secondary());
|
|
||||||
} else if ("SECONDARY_PREFERRED".equalsIgnoreCase(readPreferenceString)) {
|
|
||||||
setValue(ReadPreference.secondaryPreferred());
|
|
||||||
} else if ("NEAREST".equalsIgnoreCase(readPreferenceString)) {
|
|
||||||
setValue(ReadPreference.nearest());
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(String.format("Cannot find matching ReadPreference for %s",
|
|
||||||
readPreferenceString));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015-2016 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;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
|
||||||
import org.springframework.data.mongodb.core.query.Update;
|
|
||||||
import org.springframework.data.util.Pair;
|
|
||||||
|
|
||||||
import com.mongodb.BulkWriteResult;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bulk operations for insert/update/remove actions on a collection. These bulks operation are available since MongoDB
|
|
||||||
* 2.6 and make use of low level bulk commands on the protocol level. This interface defines a fluent API to add
|
|
||||||
* multiple single operations or list of similar operations in sequence which can then eventually be executed by calling
|
|
||||||
* {@link #execute()}.
|
|
||||||
*
|
|
||||||
* @author Tobias Trelle
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.9
|
|
||||||
*/
|
|
||||||
public interface BulkOperations {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mode for bulk operation.
|
|
||||||
**/
|
|
||||||
public enum BulkMode {
|
|
||||||
|
|
||||||
/** Perform bulk operations in sequence. The first error will cancel processing. */
|
|
||||||
ORDERED,
|
|
||||||
|
|
||||||
/** Perform bulk operations in parallel. Processing will continue on errors. */
|
|
||||||
UNORDERED
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a single insert to the bulk operation.
|
|
||||||
*
|
|
||||||
* @param documents the document to insert, must not be {@literal null}.
|
|
||||||
* @return the current {@link BulkOperations} instance with the insert added, will never be {@literal null}.
|
|
||||||
*/
|
|
||||||
BulkOperations insert(Object documents);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a list of inserts to the bulk operation.
|
|
||||||
*
|
|
||||||
* @param documents List of documents to insert, must not be {@literal null}.
|
|
||||||
* @return the current {@link BulkOperations} instance with the insert added, will never be {@literal null}.
|
|
||||||
*/
|
|
||||||
BulkOperations insert(List<? extends Object> documents);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a single update to the bulk operation. For the update request, only the first matching document is updated.
|
|
||||||
*
|
|
||||||
* @param query update criteria, must not be {@literal null}.
|
|
||||||
* @param update {@link Update} operation to perform, must not be {@literal null}.
|
|
||||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
|
||||||
*/
|
|
||||||
BulkOperations updateOne(Query query, Update update);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a list of updates to the bulk operation. For each update request, only the first matching document is updated.
|
|
||||||
*
|
|
||||||
* @param updates Update operations to perform.
|
|
||||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
|
||||||
*/
|
|
||||||
BulkOperations updateOne(List<Pair<Query, Update>> updates);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a single update to the bulk operation. For the update request, all matching documents are updated.
|
|
||||||
*
|
|
||||||
* @param query Update criteria.
|
|
||||||
* @param update Update operation to perform.
|
|
||||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
|
||||||
*/
|
|
||||||
BulkOperations updateMulti(Query query, Update update);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a list of updates to the bulk operation. For each update request, all matching documents are updated.
|
|
||||||
*
|
|
||||||
* @param updates Update operations to perform.
|
|
||||||
* @return The bulk operation.
|
|
||||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
|
||||||
*/
|
|
||||||
BulkOperations updateMulti(List<Pair<Query, Update>> updates);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a single upsert to the bulk operation. An upsert is an update if the set of matching documents is not empty,
|
|
||||||
* else an insert.
|
|
||||||
*
|
|
||||||
* @param query Update criteria.
|
|
||||||
* @param update Update operation to perform.
|
|
||||||
* @return The bulk operation.
|
|
||||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
|
||||||
*/
|
|
||||||
BulkOperations upsert(Query query, Update update);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a list of upserts to the bulk operation. An upsert is an update if the set of matching documents is not empty,
|
|
||||||
* else an insert.
|
|
||||||
*
|
|
||||||
* @param updates Updates/insert operations to perform.
|
|
||||||
* @return The bulk operation.
|
|
||||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
|
||||||
*/
|
|
||||||
BulkOperations upsert(List<Pair<Query, Update>> updates);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a single remove operation to the bulk operation.
|
|
||||||
*
|
|
||||||
* @param remove the {@link Query} to select the documents to be removed, must not be {@literal null}.
|
|
||||||
* @return the current {@link BulkOperations} instance with the removal added, will never be {@literal null}.
|
|
||||||
*/
|
|
||||||
BulkOperations remove(Query remove);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a list of remove operations to the bulk operation.
|
|
||||||
*
|
|
||||||
* @param removes the remove operations to perform, must not be {@literal null}.
|
|
||||||
* @return the current {@link BulkOperations} instance with the removal added, will never be {@literal null}.
|
|
||||||
*/
|
|
||||||
BulkOperations remove(List<Query> removes);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute all bulk operations using the default write concern.
|
|
||||||
*
|
|
||||||
* @return Result of the bulk operation providing counters for inserts/updates etc.
|
|
||||||
* @throws {@link BulkOperationException} if an error occurred during bulk processing.
|
|
||||||
*/
|
|
||||||
BulkWriteResult execute();
|
|
||||||
}
|
|
||||||
@@ -1,327 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015-2016 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;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.dao.DataAccessException;
|
|
||||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
|
||||||
import org.springframework.data.mongodb.core.query.Update;
|
|
||||||
import org.springframework.data.util.Pair;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import com.mongodb.BulkWriteException;
|
|
||||||
import com.mongodb.BulkWriteOperation;
|
|
||||||
import com.mongodb.BulkWriteRequestBuilder;
|
|
||||||
import com.mongodb.BulkWriteResult;
|
|
||||||
import com.mongodb.DBCollection;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import com.mongodb.WriteConcern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default implementation for {@link BulkOperations}.
|
|
||||||
*
|
|
||||||
* @author Tobias Trelle
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.9
|
|
||||||
*/
|
|
||||||
class DefaultBulkOperations implements BulkOperations {
|
|
||||||
|
|
||||||
private final MongoOperations mongoOperations;
|
|
||||||
private final BulkMode bulkMode;
|
|
||||||
private final String collectionName;
|
|
||||||
private final Class<?> entityType;
|
|
||||||
|
|
||||||
private PersistenceExceptionTranslator exceptionTranslator;
|
|
||||||
private WriteConcernResolver writeConcernResolver;
|
|
||||||
private WriteConcern defaultWriteConcern;
|
|
||||||
|
|
||||||
private BulkWriteOperation bulk;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link DefaultBulkOperations} for the given {@link MongoOperations}, {@link BulkMode}, collection
|
|
||||||
* name and {@link WriteConcern}.
|
|
||||||
*
|
|
||||||
* @param mongoOperations The underlying {@link MongoOperations}, must not be {@literal null}.
|
|
||||||
* @param bulkMode must not be {@literal null}.
|
|
||||||
* @param collectionName Name of the collection to work on, must not be {@literal null} or empty.
|
|
||||||
* @param entityType the entity type, can be {@literal null}.
|
|
||||||
*/
|
|
||||||
DefaultBulkOperations(MongoOperations mongoOperations, BulkMode bulkMode, String collectionName,
|
|
||||||
Class<?> entityType) {
|
|
||||||
|
|
||||||
Assert.notNull(mongoOperations, "MongoOperations must not be null!");
|
|
||||||
Assert.notNull(bulkMode, "BulkMode must not be null!");
|
|
||||||
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
|
||||||
|
|
||||||
this.mongoOperations = mongoOperations;
|
|
||||||
this.bulkMode = bulkMode;
|
|
||||||
this.collectionName = collectionName;
|
|
||||||
this.entityType = entityType;
|
|
||||||
|
|
||||||
this.exceptionTranslator = new MongoExceptionTranslator();
|
|
||||||
this.writeConcernResolver = DefaultWriteConcernResolver.INSTANCE;
|
|
||||||
|
|
||||||
this.bulk = initBulkOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the {@link PersistenceExceptionTranslator} to be used. Defaults to {@link MongoExceptionTranslator}.
|
|
||||||
*
|
|
||||||
* @param exceptionTranslator can be {@literal null}.
|
|
||||||
*/
|
|
||||||
public void setExceptionTranslator(PersistenceExceptionTranslator exceptionTranslator) {
|
|
||||||
this.exceptionTranslator = exceptionTranslator == null ? new MongoExceptionTranslator() : exceptionTranslator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the {@link WriteConcernResolver} to be used. Defaults to {@link DefaultWriteConcernResolver}.
|
|
||||||
*
|
|
||||||
* @param writeConcernResolver can be {@literal null}.
|
|
||||||
*/
|
|
||||||
public void setWriteConcernResolver(WriteConcernResolver writeConcernResolver) {
|
|
||||||
this.writeConcernResolver = writeConcernResolver == null ? DefaultWriteConcernResolver.INSTANCE
|
|
||||||
: writeConcernResolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the default {@link WriteConcern} to be used. Defaults to {@literal null}.
|
|
||||||
*
|
|
||||||
* @param defaultWriteConcern can be {@literal null}.
|
|
||||||
*/
|
|
||||||
public void setDefaultWriteConcern(WriteConcern defaultWriteConcern) {
|
|
||||||
this.defaultWriteConcern = defaultWriteConcern;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.BulkOperations#insert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BulkOperations insert(Object document) {
|
|
||||||
|
|
||||||
Assert.notNull(document, "Document must not be null!");
|
|
||||||
|
|
||||||
bulk.insert((DBObject) mongoOperations.getConverter().convertToMongoType(document));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.BulkOperations#insert(java.util.List)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BulkOperations insert(List<? extends Object> documents) {
|
|
||||||
|
|
||||||
Assert.notNull(documents, "Documents must not be null!");
|
|
||||||
|
|
||||||
for (Object document : documents) {
|
|
||||||
insert(document);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.BulkOperations#updateOne(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public BulkOperations updateOne(Query query, Update update) {
|
|
||||||
|
|
||||||
Assert.notNull(query, "Query must not be null!");
|
|
||||||
Assert.notNull(update, "Update must not be null!");
|
|
||||||
|
|
||||||
return updateOne(Arrays.asList(Pair.of(query, update)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.BulkOperations#updateOne(java.util.List)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BulkOperations updateOne(List<Pair<Query, Update>> updates) {
|
|
||||||
|
|
||||||
Assert.notNull(updates, "Updates must not be null!");
|
|
||||||
|
|
||||||
for (Pair<Query, Update> update : updates) {
|
|
||||||
update(update.getFirst(), update.getSecond(), false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.BulkOperations#updateMulti(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public BulkOperations updateMulti(Query query, Update update) {
|
|
||||||
|
|
||||||
Assert.notNull(query, "Query must not be null!");
|
|
||||||
Assert.notNull(update, "Update must not be null!");
|
|
||||||
|
|
||||||
return updateMulti(Arrays.asList(Pair.of(query, update)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.BulkOperations#updateMulti(java.util.List)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BulkOperations updateMulti(List<Pair<Query, Update>> updates) {
|
|
||||||
|
|
||||||
Assert.notNull(updates, "Updates must not be null!");
|
|
||||||
|
|
||||||
for (Pair<Query, Update> update : updates) {
|
|
||||||
update(update.getFirst(), update.getSecond(), false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.BulkOperations#upsert(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BulkOperations upsert(Query query, Update update) {
|
|
||||||
return update(query, update, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.BulkOperations#upsert(java.util.List)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BulkOperations upsert(List<Pair<Query, Update>> updates) {
|
|
||||||
|
|
||||||
for (Pair<Query, Update> update : updates) {
|
|
||||||
upsert(update.getFirst(), update.getSecond());
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.BulkOperations#remove(org.springframework.data.mongodb.core.query.Query)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BulkOperations remove(Query query) {
|
|
||||||
|
|
||||||
Assert.notNull(query, "Query must not be null!");
|
|
||||||
|
|
||||||
bulk.find(query.getQueryObject()).remove();
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.BulkOperations#remove(java.util.List)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BulkOperations remove(List<Query> removes) {
|
|
||||||
|
|
||||||
Assert.notNull(removes, "Removals must not be null!");
|
|
||||||
|
|
||||||
for (Query query : removes) {
|
|
||||||
remove(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.BulkOperations#executeBulk()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BulkWriteResult execute() {
|
|
||||||
|
|
||||||
MongoAction action = new MongoAction(defaultWriteConcern, MongoActionOperation.BULK, collectionName, entityType,
|
|
||||||
null, null);
|
|
||||||
WriteConcern writeConcern = writeConcernResolver.resolve(action);
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
return writeConcern == null ? bulk.execute() : bulk.execute(writeConcern);
|
|
||||||
|
|
||||||
} catch (BulkWriteException o_O) {
|
|
||||||
|
|
||||||
DataAccessException toThrow = exceptionTranslator.translateExceptionIfPossible(o_O);
|
|
||||||
throw toThrow == null ? o_O : toThrow;
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
this.bulk = initBulkOperation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs update and upsert bulk operations.
|
|
||||||
*
|
|
||||||
* @param query the {@link Query} to determine documents to update.
|
|
||||||
* @param update the {@link Update} to perform, must not be {@literal null}.
|
|
||||||
* @param upsert whether to upsert.
|
|
||||||
* @param multi whether to issue a multi-update.
|
|
||||||
* @return the {@link BulkOperations} with the update registered.
|
|
||||||
*/
|
|
||||||
private BulkOperations update(Query query, Update update, boolean upsert, boolean multi) {
|
|
||||||
|
|
||||||
Assert.notNull(query, "Query must not be null!");
|
|
||||||
Assert.notNull(update, "Update must not be null!");
|
|
||||||
|
|
||||||
BulkWriteRequestBuilder builder = bulk.find(query.getQueryObject());
|
|
||||||
|
|
||||||
if (upsert) {
|
|
||||||
|
|
||||||
if (multi) {
|
|
||||||
builder.upsert().update(update.getUpdateObject());
|
|
||||||
} else {
|
|
||||||
builder.upsert().updateOne(update.getUpdateObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (multi) {
|
|
||||||
builder.update(update.getUpdateObject());
|
|
||||||
} else {
|
|
||||||
builder.updateOne(update.getUpdateObject());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final BulkWriteOperation initBulkOperation() {
|
|
||||||
|
|
||||||
DBCollection collection = mongoOperations.getCollection(collectionName);
|
|
||||||
|
|
||||||
switch (bulkMode) {
|
|
||||||
case ORDERED:
|
|
||||||
return collection.initializeOrderedBulkOperation();
|
|
||||||
case UNORDERED:
|
|
||||||
return collection.initializeUnorderedBulkOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalStateException("BulkMode was null!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2015 the original author or authors.
|
* Copyright 2011-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -73,9 +73,9 @@ public class DefaultIndexOperations implements IndexOperations {
|
|||||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
DBObject indexOptions = indexDefinition.getIndexOptions();
|
DBObject indexOptions = indexDefinition.getIndexOptions();
|
||||||
if (indexOptions != null) {
|
if (indexOptions != null) {
|
||||||
collection.createIndex(indexDefinition.getIndexKeys(), indexOptions);
|
collection.ensureIndex(indexDefinition.getIndexKeys(), indexOptions);
|
||||||
} else {
|
} else {
|
||||||
collection.createIndex(indexDefinition.getIndexKeys());
|
collection.ensureIndex(indexDefinition.getIndexKeys());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -108,12 +108,10 @@ public class DefaultIndexOperations implements IndexOperations {
|
|||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.mongodb.core.IndexOperations#resetIndexCache()
|
* @see org.springframework.data.mongodb.core.IndexOperations#resetIndexCache()
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public void resetIndexCache() {
|
public void resetIndexCache() {
|
||||||
mongoOperations.execute(collectionName, new CollectionCallback<Void>() {
|
mongoOperations.execute(collectionName, new CollectionCallback<Void>() {
|
||||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
|
collection.resetIndexCache();
|
||||||
ReflectiveDBCollectionInvoker.resetIndexCache(collection);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,188 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014-2015 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;
|
|
||||||
|
|
||||||
import static java.util.UUID.*;
|
|
||||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
|
||||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.bson.types.ObjectId;
|
|
||||||
import org.springframework.dao.DataAccessException;
|
|
||||||
import org.springframework.data.mongodb.core.script.ExecutableMongoScript;
|
|
||||||
import org.springframework.data.mongodb.core.script.NamedMongoScript;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import com.mongodb.DB;
|
|
||||||
import com.mongodb.MongoException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default implementation of {@link ScriptOperations} capable of saving and executing {@link ServerSideJavaScript}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
class DefaultScriptOperations implements ScriptOperations {
|
|
||||||
|
|
||||||
private static final String SCRIPT_COLLECTION_NAME = "system.js";
|
|
||||||
private static final String SCRIPT_NAME_PREFIX = "func_";
|
|
||||||
|
|
||||||
private final MongoOperations mongoOperations;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new {@link DefaultScriptOperations} using given {@link MongoOperations}.
|
|
||||||
*
|
|
||||||
* @param mongoOperations must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public DefaultScriptOperations(MongoOperations mongoOperations) {
|
|
||||||
|
|
||||||
Assert.notNull(mongoOperations, "MongoOperations must not be null!");
|
|
||||||
|
|
||||||
this.mongoOperations = mongoOperations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.ScriptOperations#register(org.springframework.data.mongodb.core.script.ExecutableMongoScript)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public NamedMongoScript register(ExecutableMongoScript script) {
|
|
||||||
return register(new NamedMongoScript(generateScriptName(), script));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.ScriptOperations#register(org.springframework.data.mongodb.core.script.NamedMongoScript)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public NamedMongoScript register(NamedMongoScript script) {
|
|
||||||
|
|
||||||
Assert.notNull(script, "Script must not be null!");
|
|
||||||
|
|
||||||
mongoOperations.save(script, SCRIPT_COLLECTION_NAME);
|
|
||||||
return script;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.ScriptOperations#execute(org.springframework.data.mongodb.core.script.ExecutableMongoScript, java.lang.Object[])
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object execute(final ExecutableMongoScript script, final Object... args) {
|
|
||||||
|
|
||||||
Assert.notNull(script, "Script must not be null!");
|
|
||||||
|
|
||||||
return mongoOperations.execute(new DbCallback<Object>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object doInDB(DB db) throws MongoException, DataAccessException {
|
|
||||||
return db.eval(script.getCode(), convertScriptArgs(args));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.ScriptOperations#call(java.lang.String, java.lang.Object[])
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object call(final String scriptName, final Object... args) {
|
|
||||||
|
|
||||||
Assert.hasText(scriptName, "ScriptName must not be null or empty!");
|
|
||||||
|
|
||||||
return mongoOperations.execute(new DbCallback<Object>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object doInDB(DB db) throws MongoException, DataAccessException {
|
|
||||||
return db.eval(String.format("%s(%s)", scriptName, convertAndJoinScriptArgs(args)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.ScriptOperations#exists(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean exists(String scriptName) {
|
|
||||||
|
|
||||||
Assert.hasText(scriptName, "ScriptName must not be null or empty!");
|
|
||||||
|
|
||||||
return mongoOperations.exists(query(where("name").is(scriptName)), NamedMongoScript.class, SCRIPT_COLLECTION_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.ScriptOperations#getScriptNames()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Set<String> getScriptNames() {
|
|
||||||
|
|
||||||
List<NamedMongoScript> scripts = mongoOperations.findAll(NamedMongoScript.class, SCRIPT_COLLECTION_NAME);
|
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(scripts)) {
|
|
||||||
return Collections.emptySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<String> scriptNames = new HashSet<String>();
|
|
||||||
|
|
||||||
for (NamedMongoScript script : scripts) {
|
|
||||||
scriptNames.add(script.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return scriptNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object[] convertScriptArgs(Object... args) {
|
|
||||||
|
|
||||||
if (ObjectUtils.isEmpty(args)) {
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Object> convertedValues = new ArrayList<Object>(args.length);
|
|
||||||
|
|
||||||
for (Object arg : args) {
|
|
||||||
convertedValues.add(arg instanceof String ? String.format("'%s'", arg) : this.mongoOperations.getConverter()
|
|
||||||
.convertToMongoType(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
return convertedValues.toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String convertAndJoinScriptArgs(Object... args) {
|
|
||||||
return ObjectUtils.isEmpty(args) ? "" : StringUtils.arrayToCommaDelimitedString(convertScriptArgs(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a valid name for the {@literal JavaScript}. MongoDB requires an id of type String for scripts. Calling
|
|
||||||
* scripts having {@link ObjectId} as id fails. Therefore we create a random UUID without {@code -} (as this won't
|
|
||||||
* work) an prefix the result with {@link #SCRIPT_NAME_PREFIX}.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static String generateScriptName() {
|
|
||||||
return SCRIPT_NAME_PREFIX + randomUUID().toString().replaceAll("-", "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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;
|
|
||||||
|
|
||||||
import com.mongodb.WriteConcern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default {@link WriteConcernResolver} resolving the {@link WriteConcern} from the given {@link MongoAction}.
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
enum DefaultWriteConcernResolver implements WriteConcernResolver {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
public WriteConcern resolve(MongoAction action) {
|
|
||||||
return action.getDefaultWriteConcern();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 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;
|
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Value object to mitigate different representations of geo command execution results in MongoDB.
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @soundtrack Fruitcake - Jeff Coffin (The Inside of the Outside)
|
|
||||||
*/
|
|
||||||
class GeoCommandStatistics {
|
|
||||||
|
|
||||||
private static final GeoCommandStatistics NONE = new GeoCommandStatistics(new BasicDBObject());
|
|
||||||
|
|
||||||
private final DBObject source;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link GeoCommandStatistics} instance with the given source document.
|
|
||||||
*
|
|
||||||
* @param source must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
private GeoCommandStatistics(DBObject source) {
|
|
||||||
|
|
||||||
Assert.notNull(source, "Source document must not be null!");
|
|
||||||
this.source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link GeoCommandStatistics} from the given command result extracting the statistics.
|
|
||||||
*
|
|
||||||
* @param commandResult must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static GeoCommandStatistics from(DBObject commandResult) {
|
|
||||||
|
|
||||||
Assert.notNull(commandResult, "Command result must not be null!");
|
|
||||||
|
|
||||||
Object stats = commandResult.get("stats");
|
|
||||||
return stats == null ? NONE : new GeoCommandStatistics((DBObject) stats);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the average distance reported by the command result. Mitigating a removal of the field in case the command
|
|
||||||
* didn't return any result introduced in MongoDB 3.2 RC1.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @see https://jira.mongodb.org/browse/SERVER-21024
|
|
||||||
*/
|
|
||||||
public double getAverageDistance() {
|
|
||||||
|
|
||||||
Object averageDistance = source.get("avgDistance");
|
|
||||||
return averageDistance == null ? Double.NaN : (Double) averageDistance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.data.mongodb.core.geo.GeoJsonModule;
|
|
||||||
import org.springframework.data.web.config.SpringDataWebConfigurationMixin;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration class to expose {@link GeoJsonModule} as a Spring bean.
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
@SpringDataWebConfigurationMixin
|
|
||||||
public class GeoJsonConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public GeoJsonModule geoJsonModule() {
|
|
||||||
return new GeoJsonModule();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2015 the original author or authors.
|
* Copyright 2011 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,12 +20,12 @@ import java.util.List;
|
|||||||
import org.springframework.data.mongodb.core.index.IndexDefinition;
|
import org.springframework.data.mongodb.core.index.IndexDefinition;
|
||||||
import org.springframework.data.mongodb.core.index.IndexInfo;
|
import org.springframework.data.mongodb.core.index.IndexInfo;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Index operations on a collection.
|
* Index operations on a collection.
|
||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public interface IndexOperations {
|
public interface IndexOperations {
|
||||||
|
|
||||||
@@ -51,11 +51,7 @@ public interface IndexOperations {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all indices that have not yet been applied to this collection.
|
* Clears all indices that have not yet been applied to this collection.
|
||||||
*
|
|
||||||
* @deprecated since 1.7. The MongoDB Java driver version 3.0 does no longer support reseting the index cache.
|
|
||||||
* @throws {@link UnsupportedOperationException} when used with MongoDB Java driver version 3.0.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
void resetIndexCache();
|
void resetIndexCache();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2015 the original author or authors.
|
* Copyright 2011-2012 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -25,5 +25,5 @@ package org.springframework.data.mongodb.core;
|
|||||||
*/
|
*/
|
||||||
public enum MongoActionOperation {
|
public enum MongoActionOperation {
|
||||||
|
|
||||||
REMOVE, UPDATE, INSERT, INSERT_LIST, SAVE, BULK;
|
REMOVE, UPDATE, INSERT, INSERT_LIST, SAVE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,189 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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;
|
|
||||||
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
|
||||||
import org.springframework.dao.DataAccessException;
|
|
||||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import com.mongodb.Mongo;
|
|
||||||
import com.mongodb.MongoClient;
|
|
||||||
import com.mongodb.MongoClientOptions;
|
|
||||||
import com.mongodb.MongoCredential;
|
|
||||||
import com.mongodb.ServerAddress;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenient factory for configuring MongoDB.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public class MongoClientFactoryBean extends AbstractFactoryBean<Mongo> implements PersistenceExceptionTranslator {
|
|
||||||
|
|
||||||
private static final PersistenceExceptionTranslator DEFAULT_EXCEPTION_TRANSLATOR = new MongoExceptionTranslator();
|
|
||||||
|
|
||||||
private MongoClientOptions mongoClientOptions;
|
|
||||||
private String host;
|
|
||||||
private Integer port;
|
|
||||||
private List<ServerAddress> replicaSetSeeds;
|
|
||||||
private List<MongoCredential> credentials;
|
|
||||||
|
|
||||||
private PersistenceExceptionTranslator exceptionTranslator = DEFAULT_EXCEPTION_TRANSLATOR;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the {@link MongoClientOptions} to be used when creating {@link MongoClient}.
|
|
||||||
*
|
|
||||||
* @param mongoClientOptions
|
|
||||||
*/
|
|
||||||
public void setMongoClientOptions(MongoClientOptions mongoClientOptions) {
|
|
||||||
this.mongoClientOptions = mongoClientOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the list of credentials to be used when creating {@link MongoClient}.
|
|
||||||
*
|
|
||||||
* @param credentials can be {@literal null}.
|
|
||||||
*/
|
|
||||||
public void setCredentials(MongoCredential[] credentials) {
|
|
||||||
this.credentials = filterNonNullElementsAsList(credentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the list of {@link ServerAddress} to build up a replica set for.
|
|
||||||
*
|
|
||||||
* @param replicaSetSeeds can be {@literal null}.
|
|
||||||
*/
|
|
||||||
public void setReplicaSetSeeds(ServerAddress[] replicaSetSeeds) {
|
|
||||||
this.replicaSetSeeds = filterNonNullElementsAsList(replicaSetSeeds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the host to connect to.
|
|
||||||
*
|
|
||||||
* @param host
|
|
||||||
*/
|
|
||||||
public void setHost(String host) {
|
|
||||||
this.host = host;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the port to connect to.
|
|
||||||
*
|
|
||||||
* @param port
|
|
||||||
*/
|
|
||||||
public void setPort(int port) {
|
|
||||||
this.port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the {@link PersistenceExceptionTranslator} to use.
|
|
||||||
*
|
|
||||||
* @param exceptionTranslator
|
|
||||||
*/
|
|
||||||
public void setExceptionTranslator(PersistenceExceptionTranslator exceptionTranslator) {
|
|
||||||
this.exceptionTranslator = exceptionTranslator == null ? DEFAULT_EXCEPTION_TRANSLATOR : exceptionTranslator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
|
||||||
*/
|
|
||||||
public Class<? extends Mongo> getObjectType() {
|
|
||||||
return Mongo.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
|
||||||
*/
|
|
||||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
|
||||||
return exceptionTranslator.translateExceptionIfPossible(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Mongo createInstance() throws Exception {
|
|
||||||
|
|
||||||
if (mongoClientOptions == null) {
|
|
||||||
mongoClientOptions = MongoClientOptions.builder().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (credentials == null) {
|
|
||||||
credentials = Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return createMongoClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.config.AbstractFactoryBean#destroyInstance(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void destroyInstance(Mongo instance) throws Exception {
|
|
||||||
instance.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private MongoClient createMongoClient() throws UnknownHostException {
|
|
||||||
|
|
||||||
if (!CollectionUtils.isEmpty(replicaSetSeeds)) {
|
|
||||||
return new MongoClient(replicaSetSeeds, credentials, mongoClientOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new MongoClient(createConfiguredOrDefaultServerAddress(), credentials, mongoClientOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ServerAddress createConfiguredOrDefaultServerAddress() throws UnknownHostException {
|
|
||||||
|
|
||||||
ServerAddress defaultAddress = new ServerAddress();
|
|
||||||
|
|
||||||
return new ServerAddress(StringUtils.hasText(host) ? host : defaultAddress.getHost(),
|
|
||||||
port != null ? port.intValue() : defaultAddress.getPort());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the given array as {@link List} with all {@literal null} elements removed.
|
|
||||||
*
|
|
||||||
* @param elements the elements to filter <T>, can be {@literal null}.
|
|
||||||
* @return a new unmodifiable {@link List#} from the given elements without {@literal null}s.
|
|
||||||
*/
|
|
||||||
private static <T> List<T> filterNonNullElementsAsList(T[] elements) {
|
|
||||||
|
|
||||||
if (elements == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<T> candidateElements = new ArrayList<T>();
|
|
||||||
|
|
||||||
for (T element : elements) {
|
|
||||||
if (element != null) {
|
|
||||||
candidateElements.add(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.unmodifiableList(candidateElements);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,295 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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;
|
|
||||||
|
|
||||||
import javax.net.SocketFactory;
|
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
|
||||||
import org.springframework.data.mongodb.MongoDbFactory;
|
|
||||||
|
|
||||||
import com.mongodb.DBDecoderFactory;
|
|
||||||
import com.mongodb.DBEncoderFactory;
|
|
||||||
import com.mongodb.MongoClient;
|
|
||||||
import com.mongodb.MongoClientOptions;
|
|
||||||
import com.mongodb.ReadPreference;
|
|
||||||
import com.mongodb.WriteConcern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A factory bean for construction of a {@link MongoClientOptions} instance.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClientOptions> {
|
|
||||||
|
|
||||||
private static final MongoClientOptions DEFAULT_MONGO_OPTIONS = MongoClientOptions.builder().build();
|
|
||||||
|
|
||||||
private String description = DEFAULT_MONGO_OPTIONS.getDescription();
|
|
||||||
private int minConnectionsPerHost = DEFAULT_MONGO_OPTIONS.getMinConnectionsPerHost();
|
|
||||||
private int connectionsPerHost = DEFAULT_MONGO_OPTIONS.getConnectionsPerHost();
|
|
||||||
private int threadsAllowedToBlockForConnectionMultiplier = DEFAULT_MONGO_OPTIONS
|
|
||||||
.getThreadsAllowedToBlockForConnectionMultiplier();
|
|
||||||
private int maxWaitTime = DEFAULT_MONGO_OPTIONS.getMaxWaitTime();
|
|
||||||
private int maxConnectionIdleTime = DEFAULT_MONGO_OPTIONS.getMaxConnectionIdleTime();
|
|
||||||
private int maxConnectionLifeTime = DEFAULT_MONGO_OPTIONS.getMaxConnectionLifeTime();
|
|
||||||
private int connectTimeout = DEFAULT_MONGO_OPTIONS.getConnectTimeout();
|
|
||||||
private int socketTimeout = DEFAULT_MONGO_OPTIONS.getSocketTimeout();
|
|
||||||
private boolean socketKeepAlive = DEFAULT_MONGO_OPTIONS.isSocketKeepAlive();
|
|
||||||
private ReadPreference readPreference = DEFAULT_MONGO_OPTIONS.getReadPreference();
|
|
||||||
private DBDecoderFactory dbDecoderFactory = DEFAULT_MONGO_OPTIONS.getDbDecoderFactory();
|
|
||||||
private DBEncoderFactory dbEncoderFactory = DEFAULT_MONGO_OPTIONS.getDbEncoderFactory();
|
|
||||||
private WriteConcern writeConcern = DEFAULT_MONGO_OPTIONS.getWriteConcern();
|
|
||||||
private SocketFactory socketFactory = DEFAULT_MONGO_OPTIONS.getSocketFactory();
|
|
||||||
private boolean cursorFinalizerEnabled = DEFAULT_MONGO_OPTIONS.isCursorFinalizerEnabled();
|
|
||||||
private boolean alwaysUseMBeans = DEFAULT_MONGO_OPTIONS.isAlwaysUseMBeans();
|
|
||||||
private int heartbeatFrequency = DEFAULT_MONGO_OPTIONS.getHeartbeatFrequency();
|
|
||||||
private int minHeartbeatFrequency = DEFAULT_MONGO_OPTIONS.getMinHeartbeatFrequency();
|
|
||||||
private int heartbeatConnectTimeout = DEFAULT_MONGO_OPTIONS.getHeartbeatConnectTimeout();
|
|
||||||
private int heartbeatSocketTimeout = DEFAULT_MONGO_OPTIONS.getHeartbeatSocketTimeout();
|
|
||||||
private String requiredReplicaSetName = DEFAULT_MONGO_OPTIONS.getRequiredReplicaSetName();
|
|
||||||
|
|
||||||
private boolean ssl;
|
|
||||||
private SSLSocketFactory sslSocketFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the {@link MongoClient} description.
|
|
||||||
*
|
|
||||||
* @param description
|
|
||||||
*/
|
|
||||||
public void setDescription(String description) {
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the minimum number of connections per host.
|
|
||||||
*
|
|
||||||
* @param minConnectionsPerHost
|
|
||||||
*/
|
|
||||||
public void setMinConnectionsPerHost(int minConnectionsPerHost) {
|
|
||||||
this.minConnectionsPerHost = minConnectionsPerHost;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the number of connections allowed per host. Will block if run out. Default is 10. System property
|
|
||||||
* {@code MONGO.POOLSIZE} can override
|
|
||||||
*
|
|
||||||
* @param connectionsPerHost
|
|
||||||
*/
|
|
||||||
public void setConnectionsPerHost(int connectionsPerHost) {
|
|
||||||
this.connectionsPerHost = connectionsPerHost;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the multiplier for connectionsPerHost for # of threads that can block. Default is 5. If connectionsPerHost is
|
|
||||||
* 10, and threadsAllowedToBlockForConnectionMultiplier is 5, then 50 threads can block more than that and an
|
|
||||||
* exception will be thrown.
|
|
||||||
*
|
|
||||||
* @param threadsAllowedToBlockForConnectionMultiplier
|
|
||||||
*/
|
|
||||||
public void setThreadsAllowedToBlockForConnectionMultiplier(int threadsAllowedToBlockForConnectionMultiplier) {
|
|
||||||
this.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the max wait time of a blocking thread for a connection. Default is 12000 ms (2 minutes)
|
|
||||||
*
|
|
||||||
* @param maxWaitTime
|
|
||||||
*/
|
|
||||||
public void setMaxWaitTime(int maxWaitTime) {
|
|
||||||
this.maxWaitTime = maxWaitTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum idle time for a pooled connection.
|
|
||||||
*
|
|
||||||
* @param maxConnectionIdleTime
|
|
||||||
*/
|
|
||||||
public void setMaxConnectionIdleTime(int maxConnectionIdleTime) {
|
|
||||||
this.maxConnectionIdleTime = maxConnectionIdleTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the maximum life time for a pooled connection.
|
|
||||||
*
|
|
||||||
* @param maxConnectionLifeTime
|
|
||||||
*/
|
|
||||||
public void setMaxConnectionLifeTime(int maxConnectionLifeTime) {
|
|
||||||
this.maxConnectionLifeTime = maxConnectionLifeTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the connect timeout in milliseconds. 0 is default and infinite.
|
|
||||||
*
|
|
||||||
* @param connectTimeout
|
|
||||||
*/
|
|
||||||
public void setConnectTimeout(int connectTimeout) {
|
|
||||||
this.connectTimeout = connectTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the socket timeout. 0 is default and infinite.
|
|
||||||
*
|
|
||||||
* @param socketTimeout
|
|
||||||
*/
|
|
||||||
public void setSocketTimeout(int socketTimeout) {
|
|
||||||
this.socketTimeout = socketTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false.
|
|
||||||
*
|
|
||||||
* @param socketKeepAlive
|
|
||||||
*/
|
|
||||||
public void setSocketKeepAlive(boolean socketKeepAlive) {
|
|
||||||
this.socketKeepAlive = socketKeepAlive;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the {@link ReadPreference}.
|
|
||||||
*
|
|
||||||
* @param readPreference
|
|
||||||
*/
|
|
||||||
public void setReadPreference(ReadPreference readPreference) {
|
|
||||||
this.readPreference = readPreference;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the {@link WriteConcern} that will be the default value used when asking the {@link MongoDbFactory} for a DB
|
|
||||||
* object.
|
|
||||||
*
|
|
||||||
* @param writeConcern
|
|
||||||
*/
|
|
||||||
public void setWriteConcern(WriteConcern writeConcern) {
|
|
||||||
this.writeConcern = writeConcern;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param socketFactory
|
|
||||||
*/
|
|
||||||
public void setSocketFactory(SocketFactory socketFactory) {
|
|
||||||
this.socketFactory = socketFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the frequency that the driver will attempt to determine the current state of each server in the cluster.
|
|
||||||
*
|
|
||||||
* @param heartbeatFrequency
|
|
||||||
*/
|
|
||||||
public void setHeartbeatFrequency(int heartbeatFrequency) {
|
|
||||||
this.heartbeatFrequency = heartbeatFrequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In the event that the driver has to frequently re-check a server's availability, it will wait at least this long
|
|
||||||
* since the previous check to avoid wasted effort.
|
|
||||||
*
|
|
||||||
* @param minHeartbeatFrequency
|
|
||||||
*/
|
|
||||||
public void setMinHeartbeatFrequency(int minHeartbeatFrequency) {
|
|
||||||
this.minHeartbeatFrequency = minHeartbeatFrequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the connect timeout for connections used for the cluster heartbeat.
|
|
||||||
*
|
|
||||||
* @param heartbeatConnectTimeout
|
|
||||||
*/
|
|
||||||
public void setHeartbeatConnectTimeout(int heartbeatConnectTimeout) {
|
|
||||||
this.heartbeatConnectTimeout = heartbeatConnectTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the socket timeout for connections used for the cluster heartbeat.
|
|
||||||
*
|
|
||||||
* @param heartbeatSocketTimeout
|
|
||||||
*/
|
|
||||||
public void setHeartbeatSocketTimeout(int heartbeatSocketTimeout) {
|
|
||||||
this.heartbeatSocketTimeout = heartbeatSocketTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the name of the replica set.
|
|
||||||
*
|
|
||||||
* @param requiredReplicaSetName
|
|
||||||
*/
|
|
||||||
public void setRequiredReplicaSetName(String requiredReplicaSetName) {
|
|
||||||
this.requiredReplicaSetName = requiredReplicaSetName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This controls if the driver should us an SSL connection. Defaults to |@literal false}.
|
|
||||||
*
|
|
||||||
* @param ssl
|
|
||||||
*/
|
|
||||||
public void setSsl(boolean ssl) {
|
|
||||||
this.ssl = ssl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the {@link SSLSocketFactory} to use for the {@literal SSL} connection. If none is configured here,
|
|
||||||
* {@link SSLSocketFactory#getDefault()} will be used.
|
|
||||||
*
|
|
||||||
* @param sslSocketFactory
|
|
||||||
*/
|
|
||||||
public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
|
|
||||||
this.sslSocketFactory = sslSocketFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected MongoClientOptions createInstance() throws Exception {
|
|
||||||
|
|
||||||
SocketFactory socketFactoryToUse = ssl ? (sslSocketFactory != null ? sslSocketFactory : SSLSocketFactory
|
|
||||||
.getDefault()) : this.socketFactory;
|
|
||||||
|
|
||||||
return MongoClientOptions.builder() //
|
|
||||||
.alwaysUseMBeans(this.alwaysUseMBeans) //
|
|
||||||
.connectionsPerHost(this.connectionsPerHost) //
|
|
||||||
.connectTimeout(connectTimeout) //
|
|
||||||
.cursorFinalizerEnabled(cursorFinalizerEnabled) //
|
|
||||||
.dbDecoderFactory(dbDecoderFactory) //
|
|
||||||
.dbEncoderFactory(dbEncoderFactory) //
|
|
||||||
.description(description) //
|
|
||||||
.heartbeatConnectTimeout(heartbeatConnectTimeout) //
|
|
||||||
.heartbeatFrequency(heartbeatFrequency) //
|
|
||||||
.heartbeatSocketTimeout(heartbeatSocketTimeout) //
|
|
||||||
.maxConnectionIdleTime(maxConnectionIdleTime) //
|
|
||||||
.maxConnectionLifeTime(maxConnectionLifeTime) //
|
|
||||||
.maxWaitTime(maxWaitTime) //
|
|
||||||
.minConnectionsPerHost(minConnectionsPerHost) //
|
|
||||||
.minHeartbeatFrequency(minHeartbeatFrequency) //
|
|
||||||
.readPreference(readPreference) //
|
|
||||||
.requiredReplicaSetName(requiredReplicaSetName) //
|
|
||||||
.socketFactory(socketFactoryToUse) //
|
|
||||||
.socketKeepAlive(socketKeepAlive) //
|
|
||||||
.socketTimeout(socketTimeout) //
|
|
||||||
.threadsAllowedToBlockForConnectionMultiplier(threadsAllowedToBlockForConnectionMultiplier) //
|
|
||||||
.writeConcern(writeConcern).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
|
||||||
*/
|
|
||||||
public Class<?> getObjectType() {
|
|
||||||
return MongoClientOptions.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 the original author or authors.
|
* Copyright 2010-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -18,13 +18,12 @@ package org.springframework.data.mongodb.core;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.data.authentication.UserCredentials;
|
import org.springframework.data.authentication.UserCredentials;
|
||||||
import org.springframework.data.mongodb.util.MongoClientVersion;
|
import org.springframework.data.mongodb.CannotGetMongoDbConnectionException;
|
||||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import com.mongodb.DB;
|
import com.mongodb.DB;
|
||||||
import com.mongodb.Mongo;
|
import com.mongodb.Mongo;
|
||||||
import com.mongodb.MongoClient;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class featuring helper methods for internal MongoDb classes. Mainly intended for internal use within the
|
* Helper class featuring helper methods for internal MongoDb classes. Mainly intended for internal use within the
|
||||||
@@ -35,7 +34,6 @@ import com.mongodb.MongoClient;
|
|||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Randy Watler
|
* @author Randy Watler
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
public abstract class MongoDbUtils {
|
public abstract class MongoDbUtils {
|
||||||
@@ -45,7 +43,9 @@ public abstract class MongoDbUtils {
|
|||||||
/**
|
/**
|
||||||
* Private constructor to prevent instantiation.
|
* Private constructor to prevent instantiation.
|
||||||
*/
|
*/
|
||||||
private MongoDbUtils() {}
|
private MongoDbUtils() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains a {@link DB} connection for the given {@link Mongo} instance and database name
|
* Obtains a {@link DB} connection for the given {@link Mongo} instance and database name
|
||||||
@@ -65,24 +65,11 @@ public abstract class MongoDbUtils {
|
|||||||
* @param databaseName the database name, must not be {@literal null} or empty.
|
* @param databaseName the database name, must not be {@literal null} or empty.
|
||||||
* @param credentials the credentials to use, must not be {@literal null}.
|
* @param credentials the credentials to use, must not be {@literal null}.
|
||||||
* @return the {@link DB} connection
|
* @return the {@link DB} connection
|
||||||
* @deprecated since 1.7. The {@link MongoClient} itself should hold credentials within
|
|
||||||
* {@link MongoClient#getCredentialsList()}.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public static DB getDB(Mongo mongo, String databaseName, UserCredentials credentials) {
|
public static DB getDB(Mongo mongo, String databaseName, UserCredentials credentials) {
|
||||||
return getDB(mongo, databaseName, credentials, databaseName);
|
return getDB(mongo, databaseName, credentials, databaseName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mongo
|
|
||||||
* @param databaseName
|
|
||||||
* @param credentials
|
|
||||||
* @param authenticationDatabaseName
|
|
||||||
* @return
|
|
||||||
* @deprecated since 1.7. The {@link MongoClient} itself should hold credentials within
|
|
||||||
* {@link MongoClient#getCredentialsList()}.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static DB getDB(Mongo mongo, String databaseName, UserCredentials credentials,
|
public static DB getDB(Mongo mongo, String databaseName, UserCredentials credentials,
|
||||||
String authenticationDatabaseName) {
|
String authenticationDatabaseName) {
|
||||||
|
|
||||||
@@ -122,9 +109,22 @@ public abstract class MongoDbUtils {
|
|||||||
LOGGER.debug("Getting Mongo Database name=[{}]", databaseName);
|
LOGGER.debug("Getting Mongo Database name=[{}]", databaseName);
|
||||||
|
|
||||||
DB db = mongo.getDB(databaseName);
|
DB db = mongo.getDB(databaseName);
|
||||||
|
boolean credentialsGiven = credentials.hasUsername() && credentials.hasPassword();
|
||||||
|
|
||||||
if (!(mongo instanceof MongoClient) && requiresAuthDbAuthentication(credentials)) {
|
DB authDb = databaseName.equals(authenticationDatabaseName) ? db : mongo.getDB(authenticationDatabaseName);
|
||||||
ReflectiveDbInvoker.authenticate(mongo, db, credentials, authenticationDatabaseName);
|
|
||||||
|
synchronized (authDb) {
|
||||||
|
|
||||||
|
if (credentialsGiven && !authDb.isAuthenticated()) {
|
||||||
|
|
||||||
|
String username = credentials.getUsername();
|
||||||
|
String password = credentials.hasPassword() ? credentials.getPassword() : null;
|
||||||
|
|
||||||
|
if (!authDb.authenticate(username, password == null ? null : password.toCharArray())) {
|
||||||
|
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName + "], "
|
||||||
|
+ credentials.toString(), databaseName, credentials);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TX sync active, bind new database to thread
|
// TX sync active, bind new database to thread
|
||||||
@@ -181,36 +181,16 @@ public abstract class MongoDbUtils {
|
|||||||
* Perform actual closing of the Mongo DB object, catching and logging any cleanup exceptions thrown.
|
* Perform actual closing of the Mongo DB object, catching and logging any cleanup exceptions thrown.
|
||||||
*
|
*
|
||||||
* @param db the DB to close (may be <code>null</code>)
|
* @param db the DB to close (may be <code>null</code>)
|
||||||
* @deprecated since 1.7. The main use case for this method is to ensure that applications can read their own
|
|
||||||
* unacknowledged writes, but this is no longer so prevalent since the MongoDB Java driver version 3
|
|
||||||
* started defaulting to acknowledged writes.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public static void closeDB(DB db) {
|
public static void closeDB(DB db) {
|
||||||
|
|
||||||
if (db != null) {
|
if (db != null) {
|
||||||
LOGGER.debug("Closing Mongo DB object");
|
LOGGER.debug("Closing Mongo DB object");
|
||||||
try {
|
try {
|
||||||
ReflectiveDbInvoker.requestDone(db);
|
db.requestDone();
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
LOGGER.debug("Unexpected exception on closing Mongo DB object", ex);
|
LOGGER.debug("Unexpected exception on closing Mongo DB object", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if credentials present. In case we're using a mongo-java-driver version 3 or above we do not have the need
|
|
||||||
* for authentication as the auth data has to be provided within the MongoClient
|
|
||||||
*
|
|
||||||
* @param credentials
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static boolean requiresAuthDbAuthentication(UserCredentials credentials) {
|
|
||||||
|
|
||||||
if (credentials == null || !credentials.hasUsername()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !MongoClientVersion.isMongo3Driver();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 the original author or authors.
|
* Copyright 2010-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -15,25 +15,23 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.DataAccessResourceFailureException;
|
import org.springframework.dao.DataAccessResourceFailureException;
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
|
||||||
import org.springframework.dao.DuplicateKeyException;
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||||
import org.springframework.dao.PermissionDeniedDataAccessException;
|
|
||||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||||
import org.springframework.data.mongodb.BulkOperationException;
|
|
||||||
import org.springframework.data.mongodb.UncategorizedMongoDbException;
|
import org.springframework.data.mongodb.UncategorizedMongoDbException;
|
||||||
import org.springframework.data.mongodb.util.MongoDbErrorCodes;
|
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
|
|
||||||
import com.mongodb.BulkWriteException;
|
import com.mongodb.MongoCursorNotFoundException;
|
||||||
import com.mongodb.MongoException;
|
import com.mongodb.MongoException;
|
||||||
|
import com.mongodb.MongoException.CursorNotFound;
|
||||||
|
import com.mongodb.MongoException.DuplicateKey;
|
||||||
|
import com.mongodb.MongoException.Network;
|
||||||
|
import com.mongodb.MongoInternalException;
|
||||||
|
import com.mongodb.MongoServerSelectionException;
|
||||||
|
import com.mongodb.MongoSocketException;
|
||||||
|
import com.mongodb.MongoTimeoutException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple {@link PersistenceExceptionTranslator} for Mongo. Convert the given runtime exception to an appropriate
|
* Simple {@link PersistenceExceptionTranslator} for Mongo. Convert the given runtime exception to an appropriate
|
||||||
@@ -42,23 +40,9 @@ import com.mongodb.MongoException;
|
|||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Michal Vich
|
* @author Michal Vich
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public class MongoExceptionTranslator implements PersistenceExceptionTranslator {
|
public class MongoExceptionTranslator implements PersistenceExceptionTranslator {
|
||||||
|
|
||||||
private static final Set<String> DULICATE_KEY_EXCEPTIONS = new HashSet<String>(
|
|
||||||
Arrays.asList("MongoException.DuplicateKey", "DuplicateKeyException"));
|
|
||||||
|
|
||||||
private static final Set<String> RESOURCE_FAILURE_EXCEPTIONS = new HashSet<String>(
|
|
||||||
Arrays.asList("MongoException.Network", "MongoSocketException", "MongoException.CursorNotFound",
|
|
||||||
"MongoCursorNotFoundException", "MongoServerSelectionException", "MongoTimeoutException"));
|
|
||||||
|
|
||||||
private static final Set<String> RESOURCE_USAGE_EXCEPTIONS = new HashSet<String>(
|
|
||||||
Arrays.asList("MongoInternalException"));
|
|
||||||
|
|
||||||
private static final Set<String> DATA_INTEGRETY_EXCEPTIONS = new HashSet<String>(
|
|
||||||
Arrays.asList("WriteConcernException"));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
||||||
@@ -67,42 +51,41 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator
|
|||||||
|
|
||||||
// Check for well-known MongoException subclasses.
|
// Check for well-known MongoException subclasses.
|
||||||
|
|
||||||
String exception = ClassUtils.getShortName(ClassUtils.getUserClass(ex.getClass()));
|
if (ex instanceof DuplicateKey || ex instanceof DuplicateKeyException) {
|
||||||
|
|
||||||
if (DULICATE_KEY_EXCEPTIONS.contains(exception)) {
|
|
||||||
return new DuplicateKeyException(ex.getMessage(), ex);
|
return new DuplicateKeyException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RESOURCE_FAILURE_EXCEPTIONS.contains(exception)) {
|
if (ex instanceof Network || ex instanceof MongoSocketException) {
|
||||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RESOURCE_USAGE_EXCEPTIONS.contains(exception)) {
|
if (ex instanceof CursorNotFound || ex instanceof MongoCursorNotFoundException) {
|
||||||
|
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ex instanceof MongoServerSelectionException) {
|
||||||
|
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ex instanceof MongoTimeoutException) {
|
||||||
|
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ex instanceof MongoInternalException) {
|
||||||
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DATA_INTEGRETY_EXCEPTIONS.contains(exception)) {
|
|
||||||
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ex instanceof BulkWriteException) {
|
|
||||||
return new BulkOperationException(ex.getMessage(), (BulkWriteException) ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// All other MongoExceptions
|
// All other MongoExceptions
|
||||||
if (ex instanceof MongoException) {
|
if (ex instanceof MongoException) {
|
||||||
|
|
||||||
int code = ((MongoException) ex).getCode();
|
int code = ((MongoException) ex).getCode();
|
||||||
|
|
||||||
if (MongoDbErrorCodes.isDuplicateKeyCode(code)) {
|
if (code == 11000 || code == 11001) {
|
||||||
throw new DuplicateKeyException(ex.getMessage(), ex);
|
throw new DuplicateKeyException(ex.getMessage(), ex);
|
||||||
} else if (MongoDbErrorCodes.isDataAccessResourceFailureCode(code)) {
|
} else if (code == 12000 || code == 13440) {
|
||||||
throw new DataAccessResourceFailureException(ex.getMessage(), ex);
|
throw new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||||
} else if (MongoDbErrorCodes.isInvalidDataAccessApiUsageCode(code) || code == 10003 || code == 12001
|
} else if (code == 10003 || code == 12001 || code == 12010 || code == 12011 || code == 12012) {
|
||||||
|| code == 12010 || code == 12011 || code == 12012) {
|
|
||||||
throw new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
throw new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||||
} else if (MongoDbErrorCodes.isPermissionDeniedCode(code)) {
|
|
||||||
throw new PermissionDeniedDataAccessException(ex.getMessage(), ex);
|
|
||||||
}
|
}
|
||||||
return new UncategorizedMongoDbException(ex.getMessage(), ex);
|
return new UncategorizedMongoDbException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 the original author or authors.
|
* Copyright 2010-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,7 +20,9 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||||
import org.springframework.data.mongodb.CannotGetMongoDbConnectionException;
|
import org.springframework.data.mongodb.CannotGetMongoDbConnectionException;
|
||||||
@@ -38,14 +40,12 @@ import com.mongodb.WriteConcern;
|
|||||||
* @author Graeme Rocher
|
* @author Graeme Rocher
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
* @deprecated since 1.7. Please use {@link MongoClientFactoryBean} instead.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, DisposableBean,
|
||||||
public class MongoFactoryBean extends AbstractFactoryBean<Mongo> implements PersistenceExceptionTranslator {
|
PersistenceExceptionTranslator {
|
||||||
|
|
||||||
private static final PersistenceExceptionTranslator DEFAULT_EXCEPTION_TRANSLATOR = new MongoExceptionTranslator();
|
private Mongo mongo;
|
||||||
|
|
||||||
private MongoOptions mongoOptions;
|
private MongoOptions mongoOptions;
|
||||||
private String host;
|
private String host;
|
||||||
@@ -53,11 +53,9 @@ public class MongoFactoryBean extends AbstractFactoryBean<Mongo> implements Pers
|
|||||||
private WriteConcern writeConcern;
|
private WriteConcern writeConcern;
|
||||||
private List<ServerAddress> replicaSetSeeds;
|
private List<ServerAddress> replicaSetSeeds;
|
||||||
private List<ServerAddress> replicaPair;
|
private List<ServerAddress> replicaPair;
|
||||||
private PersistenceExceptionTranslator exceptionTranslator = DEFAULT_EXCEPTION_TRANSLATOR;
|
|
||||||
|
|
||||||
/**
|
private PersistenceExceptionTranslator exceptionTranslator = new MongoExceptionTranslator();
|
||||||
* @param mongoOptions
|
|
||||||
*/
|
|
||||||
public void setMongoOptions(MongoOptions mongoOptions) {
|
public void setMongoOptions(MongoOptions mongoOptions) {
|
||||||
this.mongoOptions = mongoOptions;
|
this.mongoOptions = mongoOptions;
|
||||||
}
|
}
|
||||||
@@ -68,6 +66,7 @@ public class MongoFactoryBean extends AbstractFactoryBean<Mongo> implements Pers
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use {@link #setReplicaSetSeeds(ServerAddress[])} instead
|
* @deprecated use {@link #setReplicaSetSeeds(ServerAddress[])} instead
|
||||||
|
*
|
||||||
* @param replicaPair
|
* @param replicaPair
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@@ -76,19 +75,30 @@ public class MongoFactoryBean extends AbstractFactoryBean<Mongo> implements Pers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the host to connect to.
|
* @param elements the elements to filter <T>
|
||||||
*
|
* @return a new unmodifiable {@link List#} from the given elements without nulls
|
||||||
* @param host
|
|
||||||
*/
|
*/
|
||||||
|
private <T> List<T> filterNonNullElementsAsList(T[] elements) {
|
||||||
|
|
||||||
|
if (elements == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<T> candidateElements = new ArrayList<T>();
|
||||||
|
|
||||||
|
for (T element : elements) {
|
||||||
|
if (element != null) {
|
||||||
|
candidateElements.add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableList(candidateElements);
|
||||||
|
}
|
||||||
|
|
||||||
public void setHost(String host) {
|
public void setHost(String host) {
|
||||||
this.host = host;
|
this.host = host;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the port to connect to.
|
|
||||||
*
|
|
||||||
* @param port
|
|
||||||
*/
|
|
||||||
public void setPort(int port) {
|
public void setPort(int port) {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
@@ -102,13 +112,12 @@ public class MongoFactoryBean extends AbstractFactoryBean<Mongo> implements Pers
|
|||||||
this.writeConcern = writeConcern;
|
this.writeConcern = writeConcern;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the {@link PersistenceExceptionTranslator} to use.
|
|
||||||
*
|
|
||||||
* @param exceptionTranslator can be {@literal null}.
|
|
||||||
*/
|
|
||||||
public void setExceptionTranslator(PersistenceExceptionTranslator exceptionTranslator) {
|
public void setExceptionTranslator(PersistenceExceptionTranslator exceptionTranslator) {
|
||||||
this.exceptionTranslator = exceptionTranslator == null ? DEFAULT_EXCEPTION_TRANSLATOR : exceptionTranslator;
|
this.exceptionTranslator = exceptionTranslator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mongo getObject() throws Exception {
|
||||||
|
return mongo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -119,6 +128,14 @@ public class MongoFactoryBean extends AbstractFactoryBean<Mongo> implements Pers
|
|||||||
return Mongo.class;
|
return Mongo.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||||
|
*/
|
||||||
|
public boolean isSingleton() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
||||||
@@ -129,10 +146,10 @@ public class MongoFactoryBean extends AbstractFactoryBean<Mongo> implements Pers
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
|
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||||
*/
|
*/
|
||||||
@Override
|
@SuppressWarnings("deprecation")
|
||||||
protected Mongo createInstance() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
|
||||||
Mongo mongo;
|
Mongo mongo;
|
||||||
ServerAddress defaultOptions = new ServerAddress();
|
ServerAddress defaultOptions = new ServerAddress();
|
||||||
@@ -158,42 +175,18 @@ public class MongoFactoryBean extends AbstractFactoryBean<Mongo> implements Pers
|
|||||||
mongo.setWriteConcern(writeConcern);
|
mongo.setWriteConcern(writeConcern);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mongo;
|
this.mongo = mongo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isNullOrEmpty(Collection<?> elements) {
|
||||||
|
return elements == null || elements.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.config.AbstractFactoryBean#destroyInstance(java.lang.Object)
|
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||||
*/
|
*/
|
||||||
@Override
|
public void destroy() throws Exception {
|
||||||
protected void destroyInstance(Mongo mongo) throws Exception {
|
this.mongo.close();
|
||||||
mongo.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isNullOrEmpty(Collection<?> elements) {
|
|
||||||
return elements == null || elements.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the given array as {@link List} with all {@literal null} elements removed.
|
|
||||||
*
|
|
||||||
* @param elements the elements to filter <T>
|
|
||||||
* @return a new unmodifiable {@link List#} from the given elements without nulls
|
|
||||||
*/
|
|
||||||
private static <T> List<T> filterNonNullElementsAsList(T[] elements) {
|
|
||||||
|
|
||||||
if (elements == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<T> candidateElements = new ArrayList<T>();
|
|
||||||
|
|
||||||
for (T element : elements) {
|
|
||||||
if (element != null) {
|
|
||||||
candidateElements.add(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.unmodifiableList(candidateElements);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.data.geo.GeoResults;
|
import org.springframework.data.geo.GeoResults;
|
||||||
import org.springframework.data.mongodb.core.BulkOperations.BulkMode;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||||
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
|
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
|
||||||
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
|
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
|
||||||
@@ -34,14 +33,10 @@ import org.springframework.data.mongodb.core.query.Criteria;
|
|||||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
import org.springframework.data.mongodb.core.query.Query;
|
||||||
import org.springframework.data.mongodb.core.query.Update;
|
import org.springframework.data.mongodb.core.query.Update;
|
||||||
import org.springframework.data.util.CloseableIterator;
|
|
||||||
|
|
||||||
import com.mongodb.CommandResult;
|
import com.mongodb.CommandResult;
|
||||||
import com.mongodb.Cursor;
|
|
||||||
import com.mongodb.DB;
|
|
||||||
import com.mongodb.DBCollection;
|
import com.mongodb.DBCollection;
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
import com.mongodb.ReadPreference;
|
|
||||||
import com.mongodb.WriteResult;
|
import com.mongodb.WriteResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,23 +85,9 @@ public interface MongoOperations {
|
|||||||
*
|
*
|
||||||
* @param command a MongoDB command
|
* @param command a MongoDB command
|
||||||
* @param options query options to use
|
* @param options query options to use
|
||||||
* @deprecated since 1.7. Please use {@link #executeCommand(DBObject, ReadPreference)}, as the MongoDB Java driver
|
|
||||||
* version 3 no longer supports this operation.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
CommandResult executeCommand(DBObject command, int options);
|
CommandResult executeCommand(DBObject command, int options);
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a MongoDB command. Any errors that result from executing this command will be converted into Spring's data
|
|
||||||
* access exception hierarchy.
|
|
||||||
*
|
|
||||||
* @param command a MongoDB command, must not be {@literal null}.
|
|
||||||
* @param readPreference read preferences to use, can be {@literal null}.
|
|
||||||
* @return
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
CommandResult executeCommand(DBObject command, ReadPreference readPreference);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a MongoDB query and iterate over the query results on a per-document basis with a DocumentCallbackHandler.
|
* Execute a MongoDB query and iterate over the query results on a per-document basis with a DocumentCallbackHandler.
|
||||||
*
|
*
|
||||||
@@ -162,41 +143,9 @@ public interface MongoOperations {
|
|||||||
* @param <T> return type
|
* @param <T> return type
|
||||||
* @param action callback that specified the MongoDB actions to perform on the DB instance
|
* @param action callback that specified the MongoDB actions to perform on the DB instance
|
||||||
* @return a result object returned by the action or <tt>null</tt>
|
* @return a result object returned by the action or <tt>null</tt>
|
||||||
* @deprecated since 1.7 as the MongoDB Java driver version 3 does not longer support request boundaries via
|
|
||||||
* {@link DB#requestStart()} and {@link DB#requestDone()}.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
<T> T executeInSession(DbCallback<T> action);
|
<T> T executeInSession(DbCallback<T> action);
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the given {@link Query} on the entity collection of the specified {@code entityType} backed by a Mongo DB
|
|
||||||
* {@link Cursor}.
|
|
||||||
* <p>
|
|
||||||
* Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed.
|
|
||||||
*
|
|
||||||
* @param <T> element return type
|
|
||||||
* @param query must not be {@literal null}.
|
|
||||||
* @param entityType must not be {@literal null}.
|
|
||||||
* @return will never be {@literal null}.
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
<T> CloseableIterator<T> stream(Query query, Class<T> entityType);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the given {@link Query} on the entity collection of the specified {@code entityType} and collection backed
|
|
||||||
* by a Mongo DB {@link Cursor}.
|
|
||||||
* <p>
|
|
||||||
* Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed.
|
|
||||||
*
|
|
||||||
* @param <T> element return type
|
|
||||||
* @param query must not be {@literal null}.
|
|
||||||
* @param entityType must not be {@literal null}.
|
|
||||||
* @param collectionName must not be {@literal null} or empty.
|
|
||||||
* @return will never be {@literal null}.
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
<T> CloseableIterator<T> stream(Query query, Class<T> entityType, String collectionName);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an uncapped collection with a name based on the provided entity class.
|
* Create an uncapped collection with a name based on the provided entity class.
|
||||||
*
|
*
|
||||||
@@ -206,7 +155,7 @@ public interface MongoOperations {
|
|||||||
<T> DBCollection createCollection(Class<T> entityClass);
|
<T> DBCollection createCollection(Class<T> entityClass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a collection with a name based on the provided entity class using the options.
|
* Create a collect with a name based on the provided entity class using the options.
|
||||||
*
|
*
|
||||||
* @param entityClass class that determines the collection to create
|
* @param entityClass class that determines the collection to create
|
||||||
* @param collectionOptions options to use when creating the collection.
|
* @param collectionOptions options to use when creating the collection.
|
||||||
@@ -223,7 +172,7 @@ public interface MongoOperations {
|
|||||||
DBCollection createCollection(String collectionName);
|
DBCollection createCollection(String collectionName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a collection with the provided name and options.
|
* Create a collect with the provided name and options.
|
||||||
*
|
*
|
||||||
* @param collectionName name of the collection
|
* @param collectionName name of the collection
|
||||||
* @param collectionOptions options to use when creating the collection.
|
* @param collectionOptions options to use when creating the collection.
|
||||||
@@ -300,42 +249,6 @@ public interface MongoOperations {
|
|||||||
*/
|
*/
|
||||||
IndexOperations indexOps(Class<?> entityClass);
|
IndexOperations indexOps(Class<?> entityClass);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link ScriptOperations} that can be performed on {@link com.mongodb.DB} level.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
ScriptOperations scriptOps();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new {@link BulkOperations} for the given collection.
|
|
||||||
*
|
|
||||||
* @param mode the {@link BulkMode} to use for bulk operations, must not be {@literal null}.
|
|
||||||
* @param collectionName the name of the collection to work on, must not be {@literal null} or empty.
|
|
||||||
* @return {@link BulkOperations} on the named collection
|
|
||||||
*/
|
|
||||||
BulkOperations bulkOps(BulkMode mode, String collectionName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new {@link BulkOperations} for the given entity type.
|
|
||||||
*
|
|
||||||
* @param mode the {@link BulkMode} to use for bulk operations, must not be {@literal null}.
|
|
||||||
* @param entityType the name of the entity class, must not be {@literal null}.
|
|
||||||
* @return {@link BulkOperations} on the named collection associated of the given entity class.
|
|
||||||
*/
|
|
||||||
BulkOperations bulkOps(BulkMode mode, Class<?> entityType);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new {@link BulkOperations} for the given entity type and collection name.
|
|
||||||
*
|
|
||||||
* @param mode the {@link BulkMode} to use for bulk operations, must not be {@literal null}.
|
|
||||||
* @param entityClass the name of the entity class, must not be {@literal null}.
|
|
||||||
* @param collectionName the name of the collection to work on, must not be {@literal null} or empty.
|
|
||||||
* @return {@link BulkOperations} on the named collection associated with the given entity class.
|
|
||||||
*/
|
|
||||||
BulkOperations bulkOps(BulkMode mode, Class<?> entityType, String collectionName);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query for a list of objects of type T from the collection used by the entity class.
|
* Query for a list of objects of type T from the collection used by the entity class.
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -644,8 +557,8 @@ public interface MongoOperations {
|
|||||||
<T> T findById(Object id, Class<T> entityClass, String collectionName);
|
<T> T findById(Object id, Class<T> entityClass, String collectionName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify
|
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
|
||||||
* <a/> to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
|
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
|
||||||
*
|
*
|
||||||
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
|
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
|
||||||
* fields specification.
|
* fields specification.
|
||||||
@@ -656,8 +569,8 @@ public interface MongoOperations {
|
|||||||
<T> T findAndModify(Query query, Update update, Class<T> entityClass);
|
<T> T findAndModify(Query query, Update update, Class<T> entityClass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify
|
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
|
||||||
* <a/> to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
|
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
|
||||||
*
|
*
|
||||||
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
|
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
|
||||||
* fields specification.
|
* fields specification.
|
||||||
@@ -669,8 +582,8 @@ public interface MongoOperations {
|
|||||||
<T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName);
|
<T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify
|
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
|
||||||
* <a/> to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
|
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
|
||||||
* {@link FindAndModifyOptions} into account.
|
* {@link FindAndModifyOptions} into account.
|
||||||
*
|
*
|
||||||
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
|
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
|
||||||
@@ -683,8 +596,8 @@ public interface MongoOperations {
|
|||||||
<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass);
|
<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify
|
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
|
||||||
* <a/> to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
|
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
|
||||||
* {@link FindAndModifyOptions} into account.
|
* {@link FindAndModifyOptions} into account.
|
||||||
*
|
*
|
||||||
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
|
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
|
||||||
@@ -772,9 +685,9 @@ public interface MongoOperations {
|
|||||||
* <p/>
|
* <p/>
|
||||||
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
|
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
|
||||||
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
|
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
|
||||||
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
|
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See <a
|
||||||
* <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert" >
|
* href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert"
|
||||||
* Spring's Type Conversion"</a> for more details.
|
* >Spring's Type Conversion"</a> for more details.
|
||||||
* <p/>
|
* <p/>
|
||||||
* <p/>
|
* <p/>
|
||||||
* Insert is used to initially store the object into the database. To update an existing object use the save method.
|
* Insert is used to initially store the object into the database. To update an existing object use the save method.
|
||||||
@@ -829,9 +742,9 @@ public interface MongoOperations {
|
|||||||
* <p/>
|
* <p/>
|
||||||
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
|
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
|
||||||
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
|
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
|
||||||
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
|
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See <a
|
||||||
* <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert" >
|
* href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert"
|
||||||
* Spring's Type Conversion"</a> for more details.
|
* >Spring's Type Conversion"</a> for more details.
|
||||||
*
|
*
|
||||||
* @param objectToSave the object to store in the collection
|
* @param objectToSave the object to store in the collection
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 the original author or authors.
|
* Copyright 2010-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,48 +17,41 @@ package org.springframework.data.mongodb.core;
|
|||||||
|
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.data.mongodb.util.MongoClientVersion;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
import com.mongodb.MongoOptions;
|
import com.mongodb.MongoOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A factory bean for construction of a {@link MongoOptions} instance. In case used with MongoDB Java driver version 3
|
* A factory bean for construction of a {@link MongoOptions} instance.
|
||||||
* porperties not suppprted by the driver will be ignored.
|
*
|
||||||
*
|
|
||||||
* @author Graeme Rocher
|
* @author Graeme Rocher
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Mike Saavedra
|
* @author Mike Saavedra
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
|
||||||
* @deprecated since 1.7. Please use {@link MongoClientOptionsFactoryBean} instead.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@SuppressWarnings("deprecation")
|
||||||
public class MongoOptionsFactoryBean extends AbstractFactoryBean<MongoOptions> {
|
public class MongoOptionsFactoryBean implements FactoryBean<MongoOptions>, InitializingBean {
|
||||||
|
|
||||||
private static final MongoOptions DEFAULT_MONGO_OPTIONS = new MongoOptions();
|
private static final MongoOptions DEFAULT_MONGO_OPTIONS = new MongoOptions();
|
||||||
|
|
||||||
private int connectionsPerHost = DEFAULT_MONGO_OPTIONS.getConnectionsPerHost();
|
private int connectionsPerHost = DEFAULT_MONGO_OPTIONS.connectionsPerHost;
|
||||||
private int threadsAllowedToBlockForConnectionMultiplier = DEFAULT_MONGO_OPTIONS
|
private int threadsAllowedToBlockForConnectionMultiplier = DEFAULT_MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier;
|
||||||
.getThreadsAllowedToBlockForConnectionMultiplier();
|
private int maxWaitTime = DEFAULT_MONGO_OPTIONS.maxWaitTime;
|
||||||
private int maxWaitTime = DEFAULT_MONGO_OPTIONS.getMaxWaitTime();
|
private int connectTimeout = DEFAULT_MONGO_OPTIONS.connectTimeout;
|
||||||
private int connectTimeout = DEFAULT_MONGO_OPTIONS.getConnectTimeout();
|
private int socketTimeout = DEFAULT_MONGO_OPTIONS.socketTimeout;
|
||||||
private int socketTimeout = DEFAULT_MONGO_OPTIONS.getSocketTimeout();
|
private boolean socketKeepAlive = DEFAULT_MONGO_OPTIONS.socketKeepAlive;
|
||||||
private boolean socketKeepAlive = DEFAULT_MONGO_OPTIONS.isSocketKeepAlive();
|
private boolean autoConnectRetry = DEFAULT_MONGO_OPTIONS.autoConnectRetry;
|
||||||
private int writeNumber = DEFAULT_MONGO_OPTIONS.getW();
|
private long maxAutoConnectRetryTime = DEFAULT_MONGO_OPTIONS.maxAutoConnectRetryTime;
|
||||||
private int writeTimeout = DEFAULT_MONGO_OPTIONS.getWtimeout();
|
private int writeNumber = DEFAULT_MONGO_OPTIONS.w;
|
||||||
private boolean writeFsync = DEFAULT_MONGO_OPTIONS.isFsync();
|
private int writeTimeout = DEFAULT_MONGO_OPTIONS.wtimeout;
|
||||||
|
private boolean writeFsync = DEFAULT_MONGO_OPTIONS.fsync;
|
||||||
private boolean autoConnectRetry = !MongoClientVersion.isMongo3Driver() ? ReflectiveMongoOptionsInvoker
|
private boolean slaveOk = DEFAULT_MONGO_OPTIONS.slaveOk;
|
||||||
.getAutoConnectRetry(DEFAULT_MONGO_OPTIONS) : false;
|
|
||||||
private long maxAutoConnectRetryTime = !MongoClientVersion.isMongo3Driver() ? ReflectiveMongoOptionsInvoker
|
|
||||||
.getMaxAutoConnectRetryTime(DEFAULT_MONGO_OPTIONS) : -1;
|
|
||||||
private boolean slaveOk = !MongoClientVersion.isMongo3Driver() ? ReflectiveMongoOptionsInvoker
|
|
||||||
.getSlaveOk(DEFAULT_MONGO_OPTIONS) : false;
|
|
||||||
|
|
||||||
private boolean ssl;
|
private boolean ssl;
|
||||||
private SSLSocketFactory sslSocketFactory;
|
private SSLSocketFactory sslSocketFactory;
|
||||||
|
|
||||||
|
private MongoOptions options;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the maximum number of connections allowed per host until we will block.
|
* Configures the maximum number of connections allowed per host until we will block.
|
||||||
*
|
*
|
||||||
@@ -151,10 +144,7 @@ public class MongoOptionsFactoryBean extends AbstractFactoryBean<MongoOptions> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures whether or not the system retries automatically on a failed connect. This defaults to {@literal false}.
|
* Configures whether or not the system retries automatically on a failed connect. This defaults to {@literal false}.
|
||||||
*
|
|
||||||
* @deprecated since 1.7.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public void setAutoConnectRetry(boolean autoConnectRetry) {
|
public void setAutoConnectRetry(boolean autoConnectRetry) {
|
||||||
this.autoConnectRetry = autoConnectRetry;
|
this.autoConnectRetry = autoConnectRetry;
|
||||||
}
|
}
|
||||||
@@ -164,9 +154,7 @@ public class MongoOptionsFactoryBean extends AbstractFactoryBean<MongoOptions> {
|
|||||||
* defaults to {@literal 0}, which means to use the default {@literal 15s} if {@link #autoConnectRetry} is on.
|
* defaults to {@literal 0}, which means to use the default {@literal 15s} if {@link #autoConnectRetry} is on.
|
||||||
*
|
*
|
||||||
* @param maxAutoConnectRetryTime the maxAutoConnectRetryTime to set
|
* @param maxAutoConnectRetryTime the maxAutoConnectRetryTime to set
|
||||||
* @deprecated since 1.7
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public void setMaxAutoConnectRetryTime(long maxAutoConnectRetryTime) {
|
public void setMaxAutoConnectRetryTime(long maxAutoConnectRetryTime) {
|
||||||
this.maxAutoConnectRetryTime = maxAutoConnectRetryTime;
|
this.maxAutoConnectRetryTime = maxAutoConnectRetryTime;
|
||||||
}
|
}
|
||||||
@@ -175,9 +163,7 @@ public class MongoOptionsFactoryBean extends AbstractFactoryBean<MongoOptions> {
|
|||||||
* Specifies if the driver is allowed to read from secondaries or slaves. Defaults to {@literal false}.
|
* Specifies if the driver is allowed to read from secondaries or slaves. Defaults to {@literal false}.
|
||||||
*
|
*
|
||||||
* @param slaveOk true if the driver should read from secondaries or slaves.
|
* @param slaveOk true if the driver should read from secondaries or slaves.
|
||||||
* @deprecated since 1.7
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public void setSlaveOk(boolean slaveOk) {
|
public void setSlaveOk(boolean slaveOk) {
|
||||||
this.slaveOk = slaveOk;
|
this.slaveOk = slaveOk;
|
||||||
}
|
}
|
||||||
@@ -208,41 +194,40 @@ public class MongoOptionsFactoryBean extends AbstractFactoryBean<MongoOptions> {
|
|||||||
this.sslSocketFactory = sslSocketFactory;
|
this.sslSocketFactory = sslSocketFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
|
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||||
*/
|
*/
|
||||||
@Override
|
public void afterPropertiesSet() {
|
||||||
protected MongoOptions createInstance() throws Exception {
|
|
||||||
|
|
||||||
if (MongoClientVersion.isMongo3Driver()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
String
|
|
||||||
.format("Usage of 'mongo-options' is no longer supported for MongoDB Java driver version 3 and above. Please use 'mongo-client-options' and refer to chapter 'MongoDB 3.0 Support' for details."));
|
|
||||||
}
|
|
||||||
|
|
||||||
MongoOptions options = new MongoOptions();
|
MongoOptions options = new MongoOptions();
|
||||||
|
|
||||||
options.setConnectionsPerHost(connectionsPerHost);
|
options.connectionsPerHost = connectionsPerHost;
|
||||||
options.setThreadsAllowedToBlockForConnectionMultiplier(threadsAllowedToBlockForConnectionMultiplier);
|
options.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
|
||||||
options.setMaxWaitTime(maxWaitTime);
|
options.maxWaitTime = maxWaitTime;
|
||||||
options.setConnectTimeout(connectTimeout);
|
options.connectTimeout = connectTimeout;
|
||||||
options.setSocketTimeout(socketTimeout);
|
options.socketTimeout = socketTimeout;
|
||||||
options.setSocketKeepAlive(socketKeepAlive);
|
options.socketKeepAlive = socketKeepAlive;
|
||||||
|
options.autoConnectRetry = autoConnectRetry;
|
||||||
options.setW(writeNumber);
|
options.maxAutoConnectRetryTime = maxAutoConnectRetryTime;
|
||||||
options.setWtimeout(writeTimeout);
|
options.slaveOk = slaveOk;
|
||||||
options.setFsync(writeFsync);
|
options.w = writeNumber;
|
||||||
|
options.wtimeout = writeTimeout;
|
||||||
|
options.fsync = writeFsync;
|
||||||
|
|
||||||
if (ssl) {
|
if (ssl) {
|
||||||
options.setSocketFactory(sslSocketFactory != null ? sslSocketFactory : SSLSocketFactory.getDefault());
|
options.setSocketFactory(sslSocketFactory != null ? sslSocketFactory : SSLSocketFactory.getDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
ReflectiveMongoOptionsInvoker.setAutoConnectRetry(options, autoConnectRetry);
|
this.options = options;
|
||||||
ReflectiveMongoOptionsInvoker.setMaxAutoConnectRetryTime(options, maxAutoConnectRetryTime);
|
}
|
||||||
ReflectiveMongoOptionsInvoker.setSlaveOk(options, slaveOk);
|
|
||||||
|
|
||||||
return options;
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
||||||
|
*/
|
||||||
|
public MongoOptions getObject() {
|
||||||
|
return this.options;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -252,4 +237,12 @@ public class MongoOptionsFactoryBean extends AbstractFactoryBean<MongoOptions> {
|
|||||||
public Class<?> getObjectType() {
|
public Class<?> getObjectType() {
|
||||||
return MongoOptions.class;
|
return MongoOptions.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
|
||||||
|
*/
|
||||||
|
public boolean isSingleton() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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;
|
|
||||||
|
|
||||||
import static org.springframework.data.mongodb.util.MongoClientVersion.*;
|
|
||||||
import static org.springframework.util.ReflectionUtils.*;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import org.springframework.data.mongodb.util.MongoClientVersion;
|
|
||||||
|
|
||||||
import com.mongodb.DBCollection;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ReflectiveDBCollectionInvoker} provides reflective access to {@link DBCollection} API that is not consistently
|
|
||||||
* available for various driver versions.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
class ReflectiveDBCollectionInvoker {
|
|
||||||
|
|
||||||
private static final Method GEN_INDEX_NAME_METHOD;
|
|
||||||
private static final Method RESET_INDEX_CHACHE_METHOD;
|
|
||||||
|
|
||||||
static {
|
|
||||||
|
|
||||||
GEN_INDEX_NAME_METHOD = findMethod(DBCollection.class, "genIndexName", DBObject.class);
|
|
||||||
RESET_INDEX_CHACHE_METHOD = findMethod(DBCollection.class, "resetIndexCache");
|
|
||||||
}
|
|
||||||
|
|
||||||
private ReflectiveDBCollectionInvoker() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience method to generate an index name from the set of fields it is over. Will fall back to a MongoDB Java
|
|
||||||
* driver version 2 compatible way of generating index name in case of {@link MongoClientVersion#isMongo3Driver()}.
|
|
||||||
*
|
|
||||||
* @param keys the names of the fields used in this index
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String generateIndexName(DBObject keys) {
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
return genIndexName(keys);
|
|
||||||
}
|
|
||||||
return (String) invokeMethod(GEN_INDEX_NAME_METHOD, null, keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In case of MongoDB Java driver version 2 all indices that have not yet been applied to this collection will be
|
|
||||||
* cleared. Since this method is not available for the MongoDB Java driver version 3 the operation will throw
|
|
||||||
* {@link UnsupportedOperationException}.
|
|
||||||
*
|
|
||||||
* @param dbCollection
|
|
||||||
* @throws UnsupportedOperationException
|
|
||||||
*/
|
|
||||||
public static void resetIndexCache(DBCollection dbCollection) {
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
throw new UnsupportedOperationException("The mongo java driver 3 does no loger support resetIndexCache!");
|
|
||||||
}
|
|
||||||
|
|
||||||
invokeMethod(RESET_INDEX_CHACHE_METHOD, dbCollection);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Borrowed from MongoDB Java driver version 2. See <a
|
|
||||||
* href="http://github.com/mongodb/mongo-java-driver/blob/r2.13.0/src/main/com/mongodb/DBCollection.java#L754"
|
|
||||||
* >http://github.com/mongodb/mongo-java-driver/blob/r2.13.0/src/main/com/mongodb/DBCollection.java#L754</a>
|
|
||||||
*
|
|
||||||
* @param keys
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static String genIndexName(DBObject keys) {
|
|
||||||
|
|
||||||
StringBuilder name = new StringBuilder();
|
|
||||||
|
|
||||||
for (String s : keys.keySet()) {
|
|
||||||
|
|
||||||
if (name.length() > 0) {
|
|
||||||
name.append('_');
|
|
||||||
}
|
|
||||||
|
|
||||||
name.append(s).append('_');
|
|
||||||
Object val = keys.get(s);
|
|
||||||
|
|
||||||
if (val instanceof Number || val instanceof String) {
|
|
||||||
name.append(val.toString().replace(' ', '_'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return name.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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;
|
|
||||||
|
|
||||||
import static org.springframework.data.mongodb.util.MongoClientVersion.*;
|
|
||||||
import static org.springframework.util.ReflectionUtils.*;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import org.springframework.data.authentication.UserCredentials;
|
|
||||||
import org.springframework.data.mongodb.CannotGetMongoDbConnectionException;
|
|
||||||
import org.springframework.data.mongodb.util.MongoClientVersion;
|
|
||||||
|
|
||||||
import com.mongodb.DB;
|
|
||||||
import com.mongodb.Mongo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ReflectiveDbInvoker} provides reflective access to {@link DB} API that is not consistently available for
|
|
||||||
* various driver versions.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
final class ReflectiveDbInvoker {
|
|
||||||
|
|
||||||
private static final Method DB_IS_AUTHENTICATED_METHOD;
|
|
||||||
private static final Method DB_AUTHENTICATE_METHOD;
|
|
||||||
private static final Method DB_REQUEST_DONE_METHOD;
|
|
||||||
private static final Method DB_ADD_USER_METHOD;
|
|
||||||
private static final Method DB_REQUEST_START_METHOD;
|
|
||||||
|
|
||||||
static {
|
|
||||||
|
|
||||||
DB_IS_AUTHENTICATED_METHOD = findMethod(DB.class, "isAuthenticated");
|
|
||||||
DB_AUTHENTICATE_METHOD = findMethod(DB.class, "authenticate", String.class, char[].class);
|
|
||||||
DB_REQUEST_DONE_METHOD = findMethod(DB.class, "requestDone");
|
|
||||||
DB_ADD_USER_METHOD = findMethod(DB.class, "addUser", String.class, char[].class);
|
|
||||||
DB_REQUEST_START_METHOD = findMethod(DB.class, "requestStart");
|
|
||||||
}
|
|
||||||
|
|
||||||
private ReflectiveDbInvoker() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authenticate against database using provided credentials in case of a MongoDB Java driver version 2.
|
|
||||||
*
|
|
||||||
* @param mongo must not be {@literal null}.
|
|
||||||
* @param db must not be {@literal null}.
|
|
||||||
* @param credentials must not be {@literal null}.
|
|
||||||
* @param authenticationDatabaseName
|
|
||||||
*/
|
|
||||||
public static void authenticate(Mongo mongo, DB db, UserCredentials credentials, String authenticationDatabaseName) {
|
|
||||||
|
|
||||||
String databaseName = db.getName();
|
|
||||||
|
|
||||||
DB authDb = databaseName.equals(authenticationDatabaseName) ? db : mongo.getDB(authenticationDatabaseName);
|
|
||||||
|
|
||||||
synchronized (authDb) {
|
|
||||||
|
|
||||||
Boolean isAuthenticated = (Boolean) invokeMethod(DB_IS_AUTHENTICATED_METHOD, authDb);
|
|
||||||
if (!isAuthenticated) {
|
|
||||||
|
|
||||||
String username = credentials.getUsername();
|
|
||||||
String password = credentials.hasPassword() ? credentials.getPassword() : null;
|
|
||||||
|
|
||||||
Boolean authenticated = (Boolean) invokeMethod(DB_AUTHENTICATE_METHOD, authDb, username,
|
|
||||||
password == null ? null : password.toCharArray());
|
|
||||||
if (!authenticated) {
|
|
||||||
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName + "], "
|
|
||||||
+ credentials.toString(), databaseName, credentials);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a new 'consistent request' in case of MongoDB Java driver version 2. Will do nothing for MongoDB Java driver
|
|
||||||
* version 3 since the operation is no longer available.
|
|
||||||
*
|
|
||||||
* @param db
|
|
||||||
*/
|
|
||||||
public static void requestStart(DB db) {
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
invokeMethod(DB_REQUEST_START_METHOD, db);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ends the current 'consistent request'. a new 'consistent request' in case of MongoDB Java driver version 2. Will do
|
|
||||||
* nothing for MongoDB Java driver version 3 since the operation is no longer available
|
|
||||||
*
|
|
||||||
* @param db
|
|
||||||
*/
|
|
||||||
public static void requestDone(DB db) {
|
|
||||||
|
|
||||||
if (MongoClientVersion.isMongo3Driver()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
invokeMethod(DB_REQUEST_DONE_METHOD, db);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param db
|
|
||||||
* @param username
|
|
||||||
* @param password
|
|
||||||
* @throws UnsupportedOperationException
|
|
||||||
*/
|
|
||||||
public static void addUser(DB db, String username, char[] password) {
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Please use DB.command(…) to call either the createUser or updateUser command!");
|
|
||||||
}
|
|
||||||
|
|
||||||
invokeMethod(DB_ADD_USER_METHOD, db, username, password);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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;
|
|
||||||
|
|
||||||
import static org.springframework.data.mongodb.util.MongoClientVersion.*;
|
|
||||||
import static org.springframework.util.ReflectionUtils.*;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import com.mongodb.MapReduceCommand;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ReflectiveMapReduceInvoker} provides reflective access to {@link MapReduceCommand} API that is not
|
|
||||||
* consistently available for various driver versions.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
final class ReflectiveMapReduceInvoker {
|
|
||||||
|
|
||||||
private static final Method ADD_EXTRA_OPTION_METHOD;
|
|
||||||
|
|
||||||
static {
|
|
||||||
|
|
||||||
ADD_EXTRA_OPTION_METHOD = findMethod(MapReduceCommand.class, "addExtraOption", String.class, Object.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ReflectiveMapReduceInvoker() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the extra option for MongoDB Java driver version 2. Will do nothing for MongoDB Java driver version 2.
|
|
||||||
*
|
|
||||||
* @param cmd can be {@literal null} for MongoDB Java driver version 2.
|
|
||||||
* @param key
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
public static void addExtraOption(MapReduceCommand cmd, String key, Object value) {
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.notNull(cmd, "MapReduceCommand must not be null!");
|
|
||||||
invokeMethod(ADD_EXTRA_OPTION_METHOD, cmd, key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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;
|
|
||||||
|
|
||||||
import static org.springframework.data.mongodb.util.MongoClientVersion.*;
|
|
||||||
import static org.springframework.util.ReflectionUtils.*;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import org.springframework.beans.DirectFieldAccessor;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
|
|
||||||
import com.mongodb.MongoOptions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ReflectiveMongoOptionsInvoker} provides reflective access to {@link MongoOptions} API that is not consistently
|
|
||||||
* available for various driver versions.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
class ReflectiveMongoOptionsInvoker {
|
|
||||||
|
|
||||||
private static final Method GET_AUTO_CONNECT_RETRY_METHOD;
|
|
||||||
private static final Method SET_AUTO_CONNECT_RETRY_METHOD;
|
|
||||||
private static final Method GET_MAX_AUTO_CONNECT_RETRY_TIME_METHOD;
|
|
||||||
private static final Method SET_MAX_AUTO_CONNECT_RETRY_TIME_METHOD;
|
|
||||||
|
|
||||||
static {
|
|
||||||
|
|
||||||
SET_AUTO_CONNECT_RETRY_METHOD = ReflectionUtils
|
|
||||||
.findMethod(MongoOptions.class, "setAutoConnectRetry", boolean.class);
|
|
||||||
GET_AUTO_CONNECT_RETRY_METHOD = ReflectionUtils.findMethod(MongoOptions.class, "isAutoConnectRetry");
|
|
||||||
SET_MAX_AUTO_CONNECT_RETRY_TIME_METHOD = ReflectionUtils.findMethod(MongoOptions.class,
|
|
||||||
"setMaxAutoConnectRetryTime", long.class);
|
|
||||||
GET_MAX_AUTO_CONNECT_RETRY_TIME_METHOD = ReflectionUtils.findMethod(MongoOptions.class,
|
|
||||||
"getMaxAutoConnectRetryTime");
|
|
||||||
}
|
|
||||||
|
|
||||||
private ReflectiveMongoOptionsInvoker() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the retry connection flag for MongoDB Java driver version 2. Will do nothing for MongoDB Java driver version 3
|
|
||||||
* since the method has been removed.
|
|
||||||
*
|
|
||||||
* @param options can be {@literal null} for MongoDB Java driver version 3.
|
|
||||||
* @param autoConnectRetry
|
|
||||||
*/
|
|
||||||
public static void setAutoConnectRetry(MongoOptions options, boolean autoConnectRetry) {
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
invokeMethod(SET_AUTO_CONNECT_RETRY_METHOD, options, autoConnectRetry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the maxAutoConnectRetryTime attribute for MongoDB Java driver version 2. Will do nothing for MongoDB Java
|
|
||||||
* driver version 3 since the method has been removed.
|
|
||||||
*
|
|
||||||
* @param options can be {@literal null} for MongoDB Java driver version 3.
|
|
||||||
* @param maxAutoConnectRetryTime
|
|
||||||
*/
|
|
||||||
public static void setMaxAutoConnectRetryTime(MongoOptions options, long maxAutoConnectRetryTime) {
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
invokeMethod(SET_MAX_AUTO_CONNECT_RETRY_TIME_METHOD, options, maxAutoConnectRetryTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the slaveOk attribute for MongoDB Java driver version 2. Will do nothing for MongoDB Java driver version 3
|
|
||||||
* since the method has been removed.
|
|
||||||
*
|
|
||||||
* @param options can be {@literal null} for MongoDB Java driver version 3.
|
|
||||||
* @param slaveOk
|
|
||||||
*/
|
|
||||||
public static void setSlaveOk(MongoOptions options, boolean slaveOk) {
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new DirectFieldAccessor(options).setPropertyValue("slaveOk", slaveOk);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the slaveOk attribute for MongoDB Java driver version 2. Throws {@link UnsupportedOperationException} for
|
|
||||||
* MongoDB Java driver version 3 since the method has been removed.
|
|
||||||
*
|
|
||||||
* @param options can be {@literal null} for MongoDB Java driver version 3.
|
|
||||||
* @return
|
|
||||||
* @throws UnsupportedOperationException
|
|
||||||
*/
|
|
||||||
public static boolean getSlaveOk(MongoOptions options) {
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Cannot get value for autoConnectRetry which has been removed in MongoDB Java driver version 3.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((Boolean) new DirectFieldAccessor(options).getPropertyValue("slaveOk")).booleanValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the autoConnectRetry attribute for MongoDB Java driver version 2. Throws {@link UnsupportedOperationException}
|
|
||||||
* for MongoDB Java driver version 3 since the method has been removed.
|
|
||||||
*
|
|
||||||
* @param options can be {@literal null} for MongoDB Java driver version 3.
|
|
||||||
* @return
|
|
||||||
* @throws UnsupportedOperationException
|
|
||||||
*/
|
|
||||||
public static boolean getAutoConnectRetry(MongoOptions options) {
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Cannot get value for autoConnectRetry which has been removed in MongoDB Java driver version 3.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((Boolean) invokeMethod(GET_AUTO_CONNECT_RETRY_METHOD, options)).booleanValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the maxAutoConnectRetryTime attribute for MongoDB Java driver version 2. Throws
|
|
||||||
* {@link UnsupportedOperationException} for MongoDB Java driver version 3 since the method has been removed.
|
|
||||||
*
|
|
||||||
* @param options can be {@literal null} for MongoDB Java driver version 3.
|
|
||||||
* @return
|
|
||||||
* @throws UnsupportedOperationException
|
|
||||||
*/
|
|
||||||
public static long getMaxAutoConnectRetryTime(MongoOptions options) {
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"Cannot get value for maxAutoConnectRetryTime which has been removed in MongoDB Java driver version 3.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((Long) invokeMethod(GET_MAX_AUTO_CONNECT_RETRY_TIME_METHOD, options)).longValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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;
|
|
||||||
|
|
||||||
import static org.springframework.data.mongodb.util.MongoClientVersion.*;
|
|
||||||
|
|
||||||
import org.springframework.beans.DirectFieldAccessor;
|
|
||||||
|
|
||||||
import com.mongodb.WriteConcern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ReflectiveWriteConcernInvoker} provides reflective access to {@link WriteConcern} API that is not consistently
|
|
||||||
* available for various driver versions.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
class ReflectiveWriteConcernInvoker {
|
|
||||||
|
|
||||||
private static final WriteConcern NONE_OR_UNACKNOWLEDGED;
|
|
||||||
|
|
||||||
static {
|
|
||||||
|
|
||||||
NONE_OR_UNACKNOWLEDGED = isMongo3Driver() ? WriteConcern.UNACKNOWLEDGED : (WriteConcern) new DirectFieldAccessor(
|
|
||||||
new WriteConcern()).getPropertyValue("NONE");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@link WriteConcern#NONE} for MongoDB Java driver version 2, otherwise {@link WriteConcern#UNACKNOWLEDGED}.
|
|
||||||
*/
|
|
||||||
public static WriteConcern noneOrUnacknowledged() {
|
|
||||||
return NONE_OR_UNACKNOWLEDGED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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;
|
|
||||||
|
|
||||||
import static org.springframework.data.mongodb.util.MongoClientVersion.*;
|
|
||||||
import static org.springframework.util.ReflectionUtils.*;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import com.mongodb.MongoException;
|
|
||||||
import com.mongodb.WriteResult;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ReflectiveWriteResultInvoker} provides reflective access to {@link WriteResult} API that is not consistently
|
|
||||||
* available for various driver versions.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
final class ReflectiveWriteResultInvoker {
|
|
||||||
|
|
||||||
private static final Method GET_ERROR_METHOD;
|
|
||||||
private static final Method WAS_ACKNOWLEDGED_METHOD;
|
|
||||||
|
|
||||||
private ReflectiveWriteResultInvoker() {}
|
|
||||||
|
|
||||||
static {
|
|
||||||
|
|
||||||
GET_ERROR_METHOD = findMethod(WriteResult.class, "getError");
|
|
||||||
WAS_ACKNOWLEDGED_METHOD = findMethod(WriteResult.class, "wasAcknowledged");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param writeResult can be {@literal null} for MongoDB Java driver version 3.
|
|
||||||
* @return null in case of MongoDB Java driver version 3 since errors are thrown as {@link MongoException}.
|
|
||||||
*/
|
|
||||||
public static String getError(WriteResult writeResult) {
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (String) invokeMethod(GET_ERROR_METHOD, writeResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param writeResult
|
|
||||||
* @return return in case of MongoDB Java driver version 2.
|
|
||||||
*/
|
|
||||||
public static boolean wasAcknowledged(WriteResult writeResult) {
|
|
||||||
return isMongo3Driver() ? ((Boolean) invokeMethod(WAS_ACKNOWLEDGED_METHOD, writeResult)).booleanValue() : true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014-2015 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;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.data.mongodb.core.script.ExecutableMongoScript;
|
|
||||||
import org.springframework.data.mongodb.core.script.NamedMongoScript;
|
|
||||||
|
|
||||||
import com.mongodb.DB;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Script operations on {@link com.mongodb.DB} level. Allows interaction with server side JavaScript functions.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public interface ScriptOperations {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store given {@link ExecutableMongoScript} generating a syntheitcal name so that it can be called by it
|
|
||||||
* subsequently.
|
|
||||||
*
|
|
||||||
* @param script must not be {@literal null}.
|
|
||||||
* @return {@link NamedMongoScript} with name under which the {@code JavaScript} function can be called.
|
|
||||||
*/
|
|
||||||
NamedMongoScript register(ExecutableMongoScript script);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers the given {@link NamedMongoScript} in the database.
|
|
||||||
*
|
|
||||||
* @param script the {@link NamedMongoScript} to be registered.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
NamedMongoScript register(NamedMongoScript script);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the {@literal script} by either calling it via its {@literal name} or directly sending it.
|
|
||||||
*
|
|
||||||
* @param script must not be {@literal null}.
|
|
||||||
* @param args arguments to pass on for script execution.
|
|
||||||
* @return the script evaluation result.
|
|
||||||
* @throws org.springframework.dao.DataAccessException
|
|
||||||
*/
|
|
||||||
Object execute(ExecutableMongoScript script, Object... args);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call the {@literal JavaScript} by its name.
|
|
||||||
*
|
|
||||||
* @param scriptName must not be {@literal null} or empty.
|
|
||||||
* @param args
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Object call(String scriptName, Object... args);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks {@link DB} for existence of {@link ServerSideJavaScript} with given name.
|
|
||||||
*
|
|
||||||
* @param scriptName must not be {@literal null} or empty.
|
|
||||||
* @return false if no {@link ServerSideJavaScript} with given name exists.
|
|
||||||
*/
|
|
||||||
boolean exists(String scriptName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns names of {@literal JavaScript} functions that can be called.
|
|
||||||
*
|
|
||||||
* @return empty {@link Set} if no scripts found.
|
|
||||||
*/
|
|
||||||
Set<String> getScriptNames();
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2015 the original author or authors.
|
* Copyright 2011-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -19,7 +19,6 @@ import java.net.UnknownHostException;
|
|||||||
|
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
|
||||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||||
import org.springframework.data.authentication.UserCredentials;
|
import org.springframework.data.authentication.UserCredentials;
|
||||||
import org.springframework.data.mongodb.MongoDbFactory;
|
import org.springframework.data.mongodb.MongoDbFactory;
|
||||||
@@ -28,8 +27,6 @@ import org.springframework.util.StringUtils;
|
|||||||
|
|
||||||
import com.mongodb.DB;
|
import com.mongodb.DB;
|
||||||
import com.mongodb.Mongo;
|
import com.mongodb.Mongo;
|
||||||
import com.mongodb.MongoClient;
|
|
||||||
import com.mongodb.MongoClientURI;
|
|
||||||
import com.mongodb.MongoException;
|
import com.mongodb.MongoException;
|
||||||
import com.mongodb.MongoURI;
|
import com.mongodb.MongoURI;
|
||||||
import com.mongodb.WriteConcern;
|
import com.mongodb.WriteConcern;
|
||||||
@@ -40,7 +37,6 @@ import com.mongodb.WriteConcern;
|
|||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||||
|
|
||||||
@@ -58,9 +54,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
|||||||
*
|
*
|
||||||
* @param mongo Mongo instance, must not be {@literal null}.
|
* @param mongo Mongo instance, must not be {@literal null}.
|
||||||
* @param databaseName database name, not be {@literal null} or empty.
|
* @param databaseName database name, not be {@literal null} or empty.
|
||||||
* @deprecated since 1.7. Please use {@link #SimpleMongoDbFactory(MongoClient, String)}.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName) {
|
public SimpleMongoDbFactory(Mongo mongo, String databaseName) {
|
||||||
this(mongo, databaseName, null);
|
this(mongo, databaseName, null);
|
||||||
}
|
}
|
||||||
@@ -71,9 +65,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
|||||||
* @param mongo Mongo instance, must not be {@literal null}.
|
* @param mongo Mongo instance, must not be {@literal null}.
|
||||||
* @param databaseName Database name, must not be {@literal null} or empty.
|
* @param databaseName Database name, must not be {@literal null} or empty.
|
||||||
* @param credentials username and password.
|
* @param credentials username and password.
|
||||||
* @deprecated since 1.7. The credentials used should be provided by {@link MongoClient#getCredentialsList()}.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials) {
|
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials) {
|
||||||
this(mongo, databaseName, credentials, false, null);
|
this(mongo, databaseName, credentials, false, null);
|
||||||
}
|
}
|
||||||
@@ -85,9 +77,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
|||||||
* @param databaseName Database name, must not be {@literal null} or empty.
|
* @param databaseName Database name, must not be {@literal null} or empty.
|
||||||
* @param credentials username and password.
|
* @param credentials username and password.
|
||||||
* @param authenticationDatabaseName the database name to use for authentication
|
* @param authenticationDatabaseName the database name to use for authentication
|
||||||
* @deprecated since 1.7. The credentials used should be provided by {@link MongoClient#getCredentialsList()}.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials,
|
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials,
|
||||||
String authenticationDatabaseName) {
|
String authenticationDatabaseName) {
|
||||||
this(mongo, databaseName, credentials, false, authenticationDatabaseName);
|
this(mongo, databaseName, credentials, false, authenticationDatabaseName);
|
||||||
@@ -100,44 +90,16 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
|||||||
* @throws MongoException
|
* @throws MongoException
|
||||||
* @throws UnknownHostException
|
* @throws UnknownHostException
|
||||||
* @see MongoURI
|
* @see MongoURI
|
||||||
* @deprecated since 1.7. Please use {@link #SimpleMongoDbFactory(MongoClientURI)} instead.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@SuppressWarnings("deprecation")
|
||||||
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())), true,
|
this(new Mongo(uri), uri.getDatabase(), new UserCredentials(uri.getUsername(), parseChars(uri.getPassword())),
|
||||||
uri.getDatabase());
|
true, uri.getDatabase());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoClientURI}.
|
|
||||||
*
|
|
||||||
* @param uri must not be {@literal null}.
|
|
||||||
* @throws UnknownHostException
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public SimpleMongoDbFactory(MongoClientURI uri) throws UnknownHostException {
|
|
||||||
this(new MongoClient(uri), uri.getDatabase(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoClient}.
|
|
||||||
*
|
|
||||||
* @param mongoClient must not be {@literal null}.
|
|
||||||
* @param databaseName must not be {@literal null}.
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public SimpleMongoDbFactory(MongoClient mongoClient, String databaseName) {
|
|
||||||
this(mongoClient, databaseName, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials,
|
private SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials,
|
||||||
boolean mongoInstanceCreated, String authenticationDatabaseName) {
|
boolean mongoInstanceCreated, String authenticationDatabaseName) {
|
||||||
|
|
||||||
if (mongo instanceof MongoClient && (credentials != null && !UserCredentials.NO_CREDENTIALS.equals(credentials))) {
|
|
||||||
throw new InvalidDataAccessApiUsageException(
|
|
||||||
"Usage of 'UserCredentials' with 'MongoClient' is no longer supported. Please use 'MongoCredential' for 'MongoClient' or just 'Mongo'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.notNull(mongo, "Mongo must not be null");
|
Assert.notNull(mongo, "Mongo must not be null");
|
||||||
Assert.hasText(databaseName, "Database name must not be empty");
|
Assert.hasText(databaseName, "Database name must not be empty");
|
||||||
Assert.isTrue(databaseName.matches("[\\w-]+"),
|
Assert.isTrue(databaseName.matches("[\\w-]+"),
|
||||||
@@ -155,25 +117,6 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
|||||||
"Authentication database name must only contain letters, numbers, underscores and dashes!");
|
"Authentication database name must only contain letters, numbers, underscores and dashes!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param client
|
|
||||||
* @param databaseName
|
|
||||||
* @param mongoInstanceCreated
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
private SimpleMongoDbFactory(MongoClient client, String databaseName, boolean mongoInstanceCreated) {
|
|
||||||
|
|
||||||
Assert.notNull(client, "MongoClient must not be null!");
|
|
||||||
Assert.hasText(databaseName, "Database name must not be empty!");
|
|
||||||
|
|
||||||
this.mongo = client;
|
|
||||||
this.databaseName = databaseName;
|
|
||||||
this.mongoInstanceCreated = mongoInstanceCreated;
|
|
||||||
this.exceptionTranslator = new MongoExceptionTranslator();
|
|
||||||
this.credentials = UserCredentials.NO_CREDENTIALS;
|
|
||||||
this.authenticationDatabaseName = databaseName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the {@link WriteConcern} to be used on the {@link DB} instance being created.
|
* Configures the {@link WriteConcern} to be used on the {@link DB} instance being created.
|
||||||
*
|
*
|
||||||
@@ -195,7 +138,6 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
|||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.mongodb.MongoDbFactory#getDb(java.lang.String)
|
* @see org.springframework.data.mongodb.MongoDbFactory#getDb(java.lang.String)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public DB getDb(String dbName) throws DataAccessException {
|
public DB getDb(String dbName) throws DataAccessException {
|
||||||
|
|
||||||
Assert.hasText(dbName, "Database name must not be empty.");
|
Assert.hasText(dbName, "Database name must not be empty.");
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2016 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -25,8 +25,7 @@ import org.springframework.data.domain.Sort;
|
|||||||
import org.springframework.data.domain.Sort.Direction;
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
||||||
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
|
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
|
||||||
import org.springframework.data.mongodb.core.aggregation.Fields.*;
|
import org.springframework.data.mongodb.core.aggregation.Fields.AggregationField;
|
||||||
import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation;
|
|
||||||
import org.springframework.data.mongodb.core.query.Criteria;
|
import org.springframework.data.mongodb.core.query.Criteria;
|
||||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||||
import org.springframework.data.mongodb.core.query.SerializationUtils;
|
import org.springframework.data.mongodb.core.query.SerializationUtils;
|
||||||
@@ -38,14 +37,10 @@ import com.mongodb.DBObject;
|
|||||||
/**
|
/**
|
||||||
* An {@code Aggregation} is a representation of a list of aggregation steps to be performed by the MongoDB Aggregation
|
* An {@code Aggregation} is a representation of a list of aggregation steps to be performed by the MongoDB Aggregation
|
||||||
* Framework.
|
* Framework.
|
||||||
*
|
*
|
||||||
* @author Tobias Trelle
|
* @author Tobias Trelle
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Mark Paluch
|
|
||||||
* @author Alessio Fachechi
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Nikolay Bogdanov
|
|
||||||
* @since 1.3
|
* @since 1.3
|
||||||
*/
|
*/
|
||||||
public class Aggregation {
|
public class Aggregation {
|
||||||
@@ -70,7 +65,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
||||||
*
|
*
|
||||||
* @param operations must not be {@literal null} or empty.
|
* @param operations must not be {@literal null} or empty.
|
||||||
*/
|
*/
|
||||||
public static Aggregation newAggregation(List<? extends AggregationOperation> operations) {
|
public static Aggregation newAggregation(List<? extends AggregationOperation> operations) {
|
||||||
@@ -79,7 +74,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
||||||
*
|
*
|
||||||
* @param operations must not be {@literal null} or empty.
|
* @param operations must not be {@literal null} or empty.
|
||||||
*/
|
*/
|
||||||
public static Aggregation newAggregation(AggregationOperation... operations) {
|
public static Aggregation newAggregation(AggregationOperation... operations) {
|
||||||
@@ -89,7 +84,7 @@ public class Aggregation {
|
|||||||
/**
|
/**
|
||||||
* Returns a copy of this {@link Aggregation} with the given {@link AggregationOptions} set. Note that options are
|
* Returns a copy of this {@link Aggregation} with the given {@link AggregationOptions} set. Note that options are
|
||||||
* supported in MongoDB version 2.6+.
|
* supported in MongoDB version 2.6+.
|
||||||
*
|
*
|
||||||
* @param options must not be {@literal null}.
|
* @param options must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
* @since 1.6
|
* @since 1.6
|
||||||
@@ -102,7 +97,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link TypedAggregation} for the given type and {@link AggregationOperation}s.
|
* Creates a new {@link TypedAggregation} for the given type and {@link AggregationOperation}s.
|
||||||
*
|
*
|
||||||
* @param type must not be {@literal null}.
|
* @param type must not be {@literal null}.
|
||||||
* @param operations must not be {@literal null} or empty.
|
* @param operations must not be {@literal null} or empty.
|
||||||
*/
|
*/
|
||||||
@@ -112,7 +107,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link TypedAggregation} for the given type and {@link AggregationOperation}s.
|
* Creates a new {@link TypedAggregation} for the given type and {@link AggregationOperation}s.
|
||||||
*
|
*
|
||||||
* @param type must not be {@literal null}.
|
* @param type must not be {@literal null}.
|
||||||
* @param operations must not be {@literal null} or empty.
|
* @param operations must not be {@literal null} or empty.
|
||||||
*/
|
*/
|
||||||
@@ -122,7 +117,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
||||||
*
|
*
|
||||||
* @param aggregationOperations must not be {@literal null} or empty.
|
* @param aggregationOperations must not be {@literal null} or empty.
|
||||||
*/
|
*/
|
||||||
protected Aggregation(AggregationOperation... aggregationOperations) {
|
protected Aggregation(AggregationOperation... aggregationOperations) {
|
||||||
@@ -142,7 +137,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
||||||
*
|
*
|
||||||
* @param aggregationOperations must not be {@literal null} or empty.
|
* @param aggregationOperations must not be {@literal null} or empty.
|
||||||
*/
|
*/
|
||||||
protected Aggregation(List<AggregationOperation> aggregationOperations) {
|
protected Aggregation(List<AggregationOperation> aggregationOperations) {
|
||||||
@@ -151,34 +146,23 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
||||||
*
|
*
|
||||||
* @param aggregationOperations must not be {@literal null} or empty.
|
* @param aggregationOperations must not be {@literal null} or empty.
|
||||||
* @param options must not be {@literal null} or empty.
|
* @param options must not be {@literal null} or empty.
|
||||||
*/
|
*/
|
||||||
protected Aggregation(List<AggregationOperation> aggregationOperations, AggregationOptions options) {
|
protected Aggregation(List<AggregationOperation> aggregationOperations, AggregationOptions options) {
|
||||||
|
|
||||||
Assert.notNull(aggregationOperations, "AggregationOperations must not be null!");
|
Assert.notNull(aggregationOperations, "AggregationOperations must not be null!");
|
||||||
Assert.isTrue(!aggregationOperations.isEmpty(), "At least one AggregationOperation has to be provided");
|
Assert.isTrue(aggregationOperations.size() > 0, "At least one AggregationOperation has to be provided");
|
||||||
Assert.notNull(options, "AggregationOptions must not be null!");
|
Assert.notNull(options, "AggregationOptions must not be null!");
|
||||||
|
|
||||||
// check $out is the last operation if it exists
|
|
||||||
for (AggregationOperation aggregationOperation : aggregationOperations) {
|
|
||||||
if (aggregationOperation instanceof OutOperation && !isLast(aggregationOperation, aggregationOperations)) {
|
|
||||||
throw new IllegalArgumentException("The $out operator must be the last stage in the pipeline.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.operations = aggregationOperations;
|
this.operations = aggregationOperations;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLast(AggregationOperation aggregationOperation, List<AggregationOperation> aggregationOperations) {
|
|
||||||
return aggregationOperations.indexOf(aggregationOperation) == aggregationOperations.size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A pointer to the previous {@link AggregationOperation}.
|
* A pointer to the previous {@link AggregationOperation}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String previousOperation() {
|
public static String previousOperation() {
|
||||||
@@ -187,7 +171,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link ProjectionOperation} including the given fields.
|
* Creates a new {@link ProjectionOperation} including the given fields.
|
||||||
*
|
*
|
||||||
* @param fields must not be {@literal null}.
|
* @param fields must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -197,7 +181,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link ProjectionOperation} includeing the given {@link Fields}.
|
* Creates a new {@link ProjectionOperation} includeing the given {@link Fields}.
|
||||||
*
|
*
|
||||||
* @param fields must not be {@literal null}.
|
* @param fields must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -207,61 +191,17 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method to create a new {@link UnwindOperation} for the field with the given name.
|
* Factory method to create a new {@link UnwindOperation} for the field with the given name.
|
||||||
*
|
*
|
||||||
* @param field must not be {@literal null} or empty.
|
* @param fieldName must not be {@literal null} or empty.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static UnwindOperation unwind(String field) {
|
public static UnwindOperation unwind(String field) {
|
||||||
return new UnwindOperation(field(field));
|
return new UnwindOperation(field(field));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to create a new {@link UnwindOperation} for the field with the given name and
|
|
||||||
* {@code preserveNullAndEmptyArrays}. Note that extended unwind is supported in MongoDB version 3.2+.
|
|
||||||
*
|
|
||||||
* @param field must not be {@literal null} or empty.
|
|
||||||
* @param preserveNullAndEmptyArrays {@literal true} to output the document if path is {@literal null}, missing or
|
|
||||||
* array is empty.
|
|
||||||
* @return new {@link UnwindOperation}
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public static UnwindOperation unwind(String field, boolean preserveNullAndEmptyArrays) {
|
|
||||||
return new UnwindOperation(field(field), preserveNullAndEmptyArrays);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to create a new {@link UnwindOperation} for the field with the given name including the name of a
|
|
||||||
* new field to hold the array index of the element as {@code arrayIndex}. Note that extended unwind is supported in
|
|
||||||
* MongoDB version 3.2+.
|
|
||||||
*
|
|
||||||
* @param field must not be {@literal null} or empty.
|
|
||||||
* @param arrayIndex must not be {@literal null} or empty.
|
|
||||||
* @return new {@link UnwindOperation}
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public static UnwindOperation unwind(String field, String arrayIndex) {
|
|
||||||
return new UnwindOperation(field(field), field(arrayIndex), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to create a new {@link UnwindOperation} for the field with the given nameincluding the name of a new
|
|
||||||
* field to hold the array index of the element as {@code arrayIndex} using {@code preserveNullAndEmptyArrays}. Note
|
|
||||||
* that extended unwind is supported in MongoDB version 3.2+.
|
|
||||||
*
|
|
||||||
* @param field must not be {@literal null} or empty.
|
|
||||||
* @param arrayIndex must not be {@literal null} or empty.
|
|
||||||
* @param preserveNullAndEmptyArrays {@literal true} to output the document if path is {@literal null}, missing or
|
|
||||||
* array is empty.
|
|
||||||
* @return new {@link UnwindOperation}
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public static UnwindOperation unwind(String field, String arrayIndex, boolean preserveNullAndEmptyArrays) {
|
|
||||||
return new UnwindOperation(field(field), field(arrayIndex), preserveNullAndEmptyArrays);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link GroupOperation} for the given fields.
|
* Creates a new {@link GroupOperation} for the given fields.
|
||||||
*
|
*
|
||||||
* @param fields must not be {@literal null}.
|
* @param fields must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -271,7 +211,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link GroupOperation} for the given {@link Fields}.
|
* Creates a new {@link GroupOperation} for the given {@link Fields}.
|
||||||
*
|
*
|
||||||
* @param fields must not be {@literal null}.
|
* @param fields must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -281,7 +221,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method to create a new {@link SortOperation} for the given {@link Sort}.
|
* Factory method to create a new {@link SortOperation} for the given {@link Sort}.
|
||||||
*
|
*
|
||||||
* @param sort must not be {@literal null}.
|
* @param sort must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -291,7 +231,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method to create a new {@link SortOperation} for the given sort {@link Direction} and {@code fields}.
|
* Factory method to create a new {@link SortOperation} for the given sort {@link Direction} and {@code fields}.
|
||||||
*
|
*
|
||||||
* @param direction must not be {@literal null}.
|
* @param direction must not be {@literal null}.
|
||||||
* @param fields must not be {@literal null}.
|
* @param fields must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
@@ -302,7 +242,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link SkipOperation} skipping the given number of elements.
|
* Creates a new {@link SkipOperation} skipping the given number of elements.
|
||||||
*
|
*
|
||||||
* @param elementsToSkip must not be less than zero.
|
* @param elementsToSkip must not be less than zero.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -312,7 +252,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link LimitOperation} limiting the result to the given number of elements.
|
* Creates a new {@link LimitOperation} limiting the result to the given number of elements.
|
||||||
*
|
*
|
||||||
* @param maxElements must not be less than zero.
|
* @param maxElements must not be less than zero.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -322,7 +262,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link MatchOperation} using the given {@link Criteria}.
|
* Creates a new {@link MatchOperation} using the given {@link Criteria}.
|
||||||
*
|
*
|
||||||
* @param criteria must not be {@literal null}.
|
* @param criteria must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -330,54 +270,12 @@ public class Aggregation {
|
|||||||
return new MatchOperation(criteria);
|
return new MatchOperation(criteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link OutOperation} using the given collection name. This operation must be the last operation
|
|
||||||
* in the pipeline.
|
|
||||||
*
|
|
||||||
* @param outCollectionName collection name to export aggregation results. The {@link OutOperation} creates a new
|
|
||||||
* collection in the current database if one does not already exist. The collection is
|
|
||||||
* not visible until the aggregation completes. If the aggregation fails, MongoDB does
|
|
||||||
* not create the collection. Must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static OutOperation out(String outCollectionName) {
|
|
||||||
return new OutOperation(outCollectionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link LookupOperation}.
|
|
||||||
*
|
|
||||||
* @param from must not be {@literal null}.
|
|
||||||
* @param localField must not be {@literal null}.
|
|
||||||
* @param foreignField must not be {@literal null}.
|
|
||||||
* @param as must not be {@literal null}.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @since 1.9
|
|
||||||
*/
|
|
||||||
public static LookupOperation lookup(String from, String localField, String foreignField, String as) {
|
|
||||||
return lookup(field(from), field(localField), field(foreignField), field(as));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link LookupOperation} for the given {@link Fields}.
|
|
||||||
*
|
|
||||||
* @param from must not be {@literal null}.
|
|
||||||
* @param localField must not be {@literal null}.
|
|
||||||
* @param foreignField must not be {@literal null}.
|
|
||||||
* @param as must not be {@literal null}.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @since 1.9
|
|
||||||
*/
|
|
||||||
public static LookupOperation lookup(Field from, Field localField, Field foreignField, Field as) {
|
|
||||||
return new LookupOperation(from, localField, foreignField, as);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Fields} instance for the given field names.
|
* Creates a new {@link Fields} instance for the given field names.
|
||||||
*
|
*
|
||||||
|
* @see Fields#fields(String...)
|
||||||
* @param fields must not be {@literal null}.
|
* @param fields must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
* @see Fields#fields(String...)
|
|
||||||
*/
|
*/
|
||||||
public static Fields fields(String... fields) {
|
public static Fields fields(String... fields) {
|
||||||
return Fields.fields(fields);
|
return Fields.fields(fields);
|
||||||
@@ -385,7 +283,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Fields} instance from the given field name and target reference.
|
* Creates a new {@link Fields} instance from the given field name and target reference.
|
||||||
*
|
*
|
||||||
* @param name must not be {@literal null} or empty.
|
* @param name must not be {@literal null} or empty.
|
||||||
* @param target must not be {@literal null} or empty.
|
* @param target must not be {@literal null} or empty.
|
||||||
* @return
|
* @return
|
||||||
@@ -397,7 +295,7 @@ public class Aggregation {
|
|||||||
/**
|
/**
|
||||||
* Creates a new {@link GeoNearOperation} instance from the given {@link NearQuery} and the{@code distanceField}. The
|
* Creates a new {@link GeoNearOperation} instance from the given {@link NearQuery} and the{@code distanceField}. The
|
||||||
* {@code distanceField} defines output field that contains the calculated distance.
|
* {@code distanceField} defines output field that contains the calculated distance.
|
||||||
*
|
*
|
||||||
* @param query must not be {@literal null}.
|
* @param query must not be {@literal null}.
|
||||||
* @param distanceField must not be {@literal null} or empty.
|
* @param distanceField must not be {@literal null} or empty.
|
||||||
* @return
|
* @return
|
||||||
@@ -409,7 +307,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new {@link AggregationOptions.Builder}.
|
* Returns a new {@link AggregationOptions.Builder}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* @since 1.6
|
* @since 1.6
|
||||||
*/
|
*/
|
||||||
@@ -419,7 +317,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts this {@link Aggregation} specification to a {@link DBObject}.
|
* Converts this {@link Aggregation} specification to a {@link DBObject}.
|
||||||
*
|
*
|
||||||
* @param inputCollectionName the name of the input collection
|
* @param inputCollectionName the name of the input collection
|
||||||
* @return the {@code DBObject} representing this aggregation
|
* @return the {@code DBObject} representing this aggregation
|
||||||
*/
|
*/
|
||||||
@@ -433,14 +331,8 @@ public class Aggregation {
|
|||||||
operationDocuments.add(operation.toDBObject(context));
|
operationDocuments.add(operation.toDBObject(context));
|
||||||
|
|
||||||
if (operation instanceof FieldsExposingAggregationOperation) {
|
if (operation instanceof FieldsExposingAggregationOperation) {
|
||||||
|
|
||||||
FieldsExposingAggregationOperation exposedFieldsOperation = (FieldsExposingAggregationOperation) operation;
|
FieldsExposingAggregationOperation exposedFieldsOperation = (FieldsExposingAggregationOperation) operation;
|
||||||
|
context = new ExposedFieldsAggregationOperationContext(exposedFieldsOperation.getFields(), rootContext);
|
||||||
if (operation instanceof InheritsFieldsAggregationOperation) {
|
|
||||||
context = new InheritingExposedFieldsAggregationOperationContext(exposedFieldsOperation.getFields(), context);
|
|
||||||
} else {
|
|
||||||
context = new ExposedFieldsAggregationOperationContext(exposedFieldsOperation.getFields(), context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,7 +356,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple {@link AggregationOperationContext} that just returns {@link FieldReference}s as is.
|
* Simple {@link AggregationOperationContext} that just returns {@link FieldReference}s as is.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
private static class NoOpAggregationOperationContext implements AggregationOperationContext {
|
private static class NoOpAggregationOperationContext implements AggregationOperationContext {
|
||||||
@@ -499,7 +391,7 @@ public class Aggregation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes the system variables available in MongoDB aggregation framework pipeline expressions.
|
* Describes the system variables available in MongoDB aggregation framework pipeline expressions.
|
||||||
*
|
*
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @see http://docs.mongodb.org/manual/reference/aggregation-variables
|
* @see http://docs.mongodb.org/manual/reference/aggregation-variables
|
||||||
*/
|
*/
|
||||||
@@ -512,7 +404,7 @@ public class Aggregation {
|
|||||||
/**
|
/**
|
||||||
* Return {@literal true} if the given {@code fieldRef} denotes a well-known system variable, {@literal false}
|
* Return {@literal true} if the given {@code fieldRef} denotes a well-known system variable, {@literal false}
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*
|
*
|
||||||
* @param fieldRef may be {@literal null}.
|
* @param fieldRef may be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.aggregation;
|
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An {@link AggregationExpression} can be used with field expressions in aggregation pipeline stages like
|
|
||||||
* {@code project} and {@code group}.
|
|
||||||
*
|
|
||||||
* @author Thomas Darimont
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
interface AggregationExpression {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turns the {@link AggregationExpression} into a {@link DBObject} within the given
|
|
||||||
* {@link AggregationOperationContext}.
|
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
DBObject toDbObject(AggregationOperationContext context);
|
|
||||||
}
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.aggregation;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An enum of supported {@link AggregationExpression}s in aggregation pipeline stages.
|
|
||||||
*
|
|
||||||
* @author Thomas Darimont
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public enum AggregationFunctionExpressions {
|
|
||||||
|
|
||||||
SIZE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an {@link AggregationExpression} build from the current {@link Enum} name and the given parameters.
|
|
||||||
*
|
|
||||||
* @param parameters must not be {@literal null}
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public AggregationExpression of(Object... parameters) {
|
|
||||||
|
|
||||||
Assert.notNull(parameters, "Parameters must not be null!");
|
|
||||||
return new FunctionExpression(name().toLowerCase(), parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An {@link AggregationExpression} representing a function call.
|
|
||||||
*
|
|
||||||
* @author Thomas Darimont
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
static class FunctionExpression implements AggregationExpression {
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
private final List<Object> values;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link FunctionExpression} for the given name and values.
|
|
||||||
*
|
|
||||||
* @param name must not be {@literal null} or empty.
|
|
||||||
* @param values must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public FunctionExpression(String name, Object[] values) {
|
|
||||||
|
|
||||||
Assert.hasText(name, "Name must not be null!");
|
|
||||||
Assert.notNull(values, "Values must not be null!");
|
|
||||||
|
|
||||||
this.name = name;
|
|
||||||
this.values = Arrays.asList(values);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.Expression#toDbObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DBObject toDbObject(AggregationOperationContext context) {
|
|
||||||
|
|
||||||
List<Object> args = new ArrayList<Object>(values.size());
|
|
||||||
|
|
||||||
for (Object value : values) {
|
|
||||||
args.add(unpack(value, context));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BasicDBObject("$" + name, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object unpack(Object value, AggregationOperationContext context) {
|
|
||||||
|
|
||||||
if (value instanceof AggregationExpression) {
|
|
||||||
return ((AggregationExpression) value).toDbObject(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value instanceof Field) {
|
|
||||||
return context.getReference((Field) value).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2016 the original author or authors.
|
* Copyright 2013-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -30,7 +30,6 @@ import org.springframework.util.CompositeIterator;
|
|||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 1.3
|
* @since 1.3
|
||||||
*/
|
*/
|
||||||
public final class ExposedFields implements Iterable<ExposedField> {
|
public final class ExposedFields implements Iterable<ExposedField> {
|
||||||
@@ -204,13 +203,8 @@ public final class ExposedFields implements Iterable<ExposedField> {
|
|||||||
public Iterator<ExposedField> iterator() {
|
public Iterator<ExposedField> iterator() {
|
||||||
|
|
||||||
CompositeIterator<ExposedField> iterator = new CompositeIterator<ExposedField>();
|
CompositeIterator<ExposedField> iterator = new CompositeIterator<ExposedField>();
|
||||||
if (!syntheticFields.isEmpty()) {
|
iterator.add(syntheticFields.iterator());
|
||||||
iterator.add(syntheticFields.iterator());
|
iterator.add(originalFields.iterator());
|
||||||
}
|
|
||||||
|
|
||||||
if (!originalFields.isEmpty()) {
|
|
||||||
iterator.add(originalFields.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
return iterator;
|
return iterator;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2016 the original author or authors.
|
* Copyright 2013-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -24,10 +24,9 @@ import com.mongodb.DBObject;
|
|||||||
/**
|
/**
|
||||||
* {@link AggregationOperationContext} that combines the available field references from a given
|
* {@link AggregationOperationContext} that combines the available field references from a given
|
||||||
* {@code AggregationOperationContext} and an {@link FieldsExposingAggregationOperation}.
|
* {@code AggregationOperationContext} and an {@link FieldsExposingAggregationOperation}.
|
||||||
*
|
*
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
class ExposedFieldsAggregationOperationContext implements AggregationOperationContext {
|
class ExposedFieldsAggregationOperationContext implements AggregationOperationContext {
|
||||||
@@ -38,12 +37,11 @@ class ExposedFieldsAggregationOperationContext implements AggregationOperationCo
|
|||||||
/**
|
/**
|
||||||
* Creates a new {@link ExposedFieldsAggregationOperationContext} from the given {@link ExposedFields}. Uses the given
|
* Creates a new {@link ExposedFieldsAggregationOperationContext} from the given {@link ExposedFields}. Uses the given
|
||||||
* {@link AggregationOperationContext} to perform a mapping to mongo types if necessary.
|
* {@link AggregationOperationContext} to perform a mapping to mongo types if necessary.
|
||||||
*
|
*
|
||||||
* @param exposedFields must not be {@literal null}.
|
* @param exposedFields must not be {@literal null}.
|
||||||
* @param rootContext must not be {@literal null}.
|
* @param rootContext must not be {@literal null}.
|
||||||
*/
|
*/
|
||||||
public ExposedFieldsAggregationOperationContext(ExposedFields exposedFields,
|
public ExposedFieldsAggregationOperationContext(ExposedFields exposedFields, AggregationOperationContext rootContext) {
|
||||||
AggregationOperationContext rootContext) {
|
|
||||||
|
|
||||||
Assert.notNull(exposedFields, "ExposedFields must not be null!");
|
Assert.notNull(exposedFields, "ExposedFields must not be null!");
|
||||||
Assert.notNull(rootContext, "RootContext must not be null!");
|
Assert.notNull(rootContext, "RootContext must not be null!");
|
||||||
@@ -81,7 +79,7 @@ class ExposedFieldsAggregationOperationContext implements AggregationOperationCo
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link FieldReference} to the given {@link Field} with the given {@code name}.
|
* Returns a {@link FieldReference} to the given {@link Field} with the given {@code name}.
|
||||||
*
|
*
|
||||||
* @param field may be {@literal null}
|
* @param field may be {@literal null}
|
||||||
* @param name must not be {@literal null}
|
* @param name must not be {@literal null}
|
||||||
* @return
|
* @return
|
||||||
@@ -90,22 +88,6 @@ class ExposedFieldsAggregationOperationContext implements AggregationOperationCo
|
|||||||
|
|
||||||
Assert.notNull(name, "Name must not be null!");
|
Assert.notNull(name, "Name must not be null!");
|
||||||
|
|
||||||
FieldReference exposedField = resolveExposedField(field, name);
|
|
||||||
if (exposedField != null) {
|
|
||||||
return exposedField;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException(String.format("Invalid reference '%s'!", name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves a {@link field}/{@link name} for a {@link FieldReference} if possible.
|
|
||||||
*
|
|
||||||
* @param field may be {@literal null}
|
|
||||||
* @param name must not be {@literal null}
|
|
||||||
* @return the resolved reference or {@literal null}
|
|
||||||
*/
|
|
||||||
protected FieldReference resolveExposedField(Field field, String name) {
|
|
||||||
ExposedField exposedField = exposedFields.getField(name);
|
ExposedField exposedField = exposedFields.getField(name);
|
||||||
|
|
||||||
if (exposedField != null) {
|
if (exposedField != null) {
|
||||||
@@ -129,6 +111,7 @@ class ExposedFieldsAggregationOperationContext implements AggregationOperationCo
|
|||||||
return new FieldReference(new ExposedField(name, true));
|
return new FieldReference(new ExposedField(name, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
throw new IllegalArgumentException(String.format("Invalid reference '%s'!", name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2016 the original author or authors.
|
* Copyright 2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,28 +16,17 @@
|
|||||||
package org.springframework.data.mongodb.core.aggregation;
|
package org.springframework.data.mongodb.core.aggregation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link AggregationOperation} that exposes {@link ExposedFields} that can be used for later aggregation pipeline
|
* {@link AggregationOperation} that exposes new {@link ExposedFields} that can be used for later aggregation pipeline
|
||||||
* {@code AggregationOperation}s. A {@link FieldsExposingAggregationOperation} implementing the
|
* {@code AggregationOperation}s.
|
||||||
* {@link InheritsFieldsAggregationOperation} will expose fields from its parent operations. Not implementing
|
*
|
||||||
* {@link InheritsFieldsAggregationOperation} will replace existing exposed fields.
|
|
||||||
*
|
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Mark Paluch
|
|
||||||
*/
|
*/
|
||||||
public interface FieldsExposingAggregationOperation extends AggregationOperation {
|
public interface FieldsExposingAggregationOperation extends AggregationOperation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the fields exposed by the {@link AggregationOperation}.
|
* Returns the fields exposed by the {@link AggregationOperation}.
|
||||||
*
|
*
|
||||||
* @return will never be {@literal null}.
|
* @return will never be {@literal null}.
|
||||||
*/
|
*/
|
||||||
ExposedFields getFields();
|
ExposedFields getFields();
|
||||||
|
|
||||||
/**
|
|
||||||
* Marker interface for {@link AggregationOperation} that inherits fields from previous operations.
|
|
||||||
*/
|
|
||||||
static interface InheritsFieldsAggregationOperation extends FieldsExposingAggregationOperation {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,16 +193,6 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
|
|||||||
return newBuilder(GroupOps.LAST, reference, null);
|
return newBuilder(GroupOps.LAST, reference, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates an {@link GroupOperationBuilder} for an {@code $last}-expression for the given {@link AggregationExpression}.
|
|
||||||
*
|
|
||||||
* @param expr
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public GroupOperationBuilder last(AggregationExpression expr) {
|
|
||||||
return newBuilder(GroupOps.LAST, null, expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an {@link GroupOperationBuilder} for a {@code $first}-expression for the given field-reference.
|
* Generates an {@link GroupOperationBuilder} for a {@code $first}-expression for the given field-reference.
|
||||||
*
|
*
|
||||||
@@ -213,16 +203,6 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
|
|||||||
return newBuilder(GroupOps.FIRST, reference, null);
|
return newBuilder(GroupOps.FIRST, reference, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates an {@link GroupOperationBuilder} for a {@code $first}-expression for the given {@link AggregationExpression}.
|
|
||||||
*
|
|
||||||
* @param expr
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public GroupOperationBuilder first(AggregationExpression expr) {
|
|
||||||
return newBuilder(GroupOps.FIRST, null, expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an {@link GroupOperationBuilder} for an {@code $avg}-expression for the given field-reference.
|
* Generates an {@link GroupOperationBuilder} for an {@code $avg}-expression for the given field-reference.
|
||||||
*
|
*
|
||||||
@@ -233,16 +213,6 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
|
|||||||
return newBuilder(GroupOps.AVG, reference, null);
|
return newBuilder(GroupOps.AVG, reference, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates an {@link GroupOperationBuilder} for an {@code $avg}-expression for the given {@link AggregationExpression}.
|
|
||||||
*
|
|
||||||
* @param expr
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public GroupOperationBuilder avg(AggregationExpression expr) {
|
|
||||||
return newBuilder(GroupOps.AVG, null, expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an {@link GroupOperationBuilder} for an {@code $push}-expression for the given field-reference.
|
* Generates an {@link GroupOperationBuilder} for an {@code $push}-expression for the given field-reference.
|
||||||
*
|
*
|
||||||
@@ -277,16 +247,6 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
|
|||||||
return newBuilder(GroupOps.MIN, reference, null);
|
return newBuilder(GroupOps.MIN, reference, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates an {@link GroupOperationBuilder} for an {@code $min}-expression that for the given {@link AggregationExpression}.
|
|
||||||
*
|
|
||||||
* @param expr
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public GroupOperationBuilder min(AggregationExpression expr) {
|
|
||||||
return newBuilder(GroupOps.MIN, null, expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an {@link GroupOperationBuilder} for an {@code $max}-expression that for the given field-reference.
|
* Generates an {@link GroupOperationBuilder} for an {@code $max}-expression that for the given field-reference.
|
||||||
*
|
*
|
||||||
@@ -297,16 +257,6 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
|
|||||||
return newBuilder(GroupOps.MAX, reference, null);
|
return newBuilder(GroupOps.MAX, reference, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates an {@link GroupOperationBuilder} for an {@code $max}-expression that for the given {@link AggregationExpression}.
|
|
||||||
*
|
|
||||||
* @param expr
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public GroupOperationBuilder max(AggregationExpression expr) {
|
|
||||||
return newBuilder(GroupOps.MAX, null, expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GroupOperationBuilder newBuilder(Keyword keyword, String reference, Object value) {
|
private GroupOperationBuilder newBuilder(Keyword keyword, String reference, Object value) {
|
||||||
return new GroupOperationBuilder(this, new Operation(keyword, null, reference, value));
|
return new GroupOperationBuilder(this, new Operation(keyword, null, reference, value));
|
||||||
}
|
}
|
||||||
@@ -419,11 +369,6 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
|
|||||||
public Object getValue(AggregationOperationContext context) {
|
public Object getValue(AggregationOperationContext context) {
|
||||||
|
|
||||||
if (reference == null) {
|
if (reference == null) {
|
||||||
|
|
||||||
if (value instanceof AggregationExpression) {
|
|
||||||
return ((AggregationExpression) value).toDbObject(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 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.aggregation;
|
|
||||||
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ExposedFieldsAggregationOperationContext} that inherits fields from its parent
|
|
||||||
* {@link AggregationOperationContext}.
|
|
||||||
*
|
|
||||||
* @author Mark Paluch
|
|
||||||
*/
|
|
||||||
class InheritingExposedFieldsAggregationOperationContext extends ExposedFieldsAggregationOperationContext {
|
|
||||||
|
|
||||||
private final AggregationOperationContext previousContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link ExposedFieldsAggregationOperationContext} from the given {@link ExposedFields}. Uses the given
|
|
||||||
* {@link AggregationOperationContext} to perform a mapping to mongo types if necessary.
|
|
||||||
*
|
|
||||||
* @param exposedFields must not be {@literal null}.
|
|
||||||
* @param previousContext must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public InheritingExposedFieldsAggregationOperationContext(ExposedFields exposedFields,
|
|
||||||
AggregationOperationContext previousContext) {
|
|
||||||
|
|
||||||
super(exposedFields, previousContext);
|
|
||||||
Assert.notNull(previousContext, "PreviousContext must not be null!");
|
|
||||||
this.previousContext = previousContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.ExposedFieldsAggregationOperationContext#resolveExposedField(org.springframework.data.mongodb.core.aggregation.Field, java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected FieldReference resolveExposedField(Field field, String name) {
|
|
||||||
|
|
||||||
FieldReference fieldReference = super.resolveExposedField(field, name);
|
|
||||||
if (fieldReference != null) {
|
|
||||||
return fieldReference;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (field != null) {
|
|
||||||
return previousContext.getReference(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
return previousContext.getReference(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 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.aggregation;
|
|
||||||
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encapsulates the aggregation framework {@code $lookup}-operation. We recommend to use the static factory method
|
|
||||||
* {@link Aggregation#lookup(String, String, String, String)} instead of creating instances of this class directly.
|
|
||||||
*
|
|
||||||
* @author Alessio Fachechi
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @see http://docs.mongodb.org/manual/reference/aggregation/lookup/#stage._S_lookup
|
|
||||||
* @since 1.9
|
|
||||||
*/
|
|
||||||
public class LookupOperation implements FieldsExposingAggregationOperation, InheritsFieldsAggregationOperation {
|
|
||||||
|
|
||||||
private Field from;
|
|
||||||
private Field localField;
|
|
||||||
private Field foreignField;
|
|
||||||
private ExposedField as;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link LookupOperation} for the given {@link Field}s.
|
|
||||||
*
|
|
||||||
* @param from must not be {@literal null}.
|
|
||||||
* @param localField must not be {@literal null}.
|
|
||||||
* @param foreignField must not be {@literal null}.
|
|
||||||
* @param as must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public LookupOperation(Field from, Field localField, Field foreignField, Field as) {
|
|
||||||
|
|
||||||
Assert.notNull(from, "From must not be null!");
|
|
||||||
Assert.notNull(localField, "LocalField must not be null!");
|
|
||||||
Assert.notNull(foreignField, "ForeignField must not be null!");
|
|
||||||
Assert.notNull(as, "As must not be null!");
|
|
||||||
|
|
||||||
this.from = from;
|
|
||||||
this.localField = localField;
|
|
||||||
this.foreignField = foreignField;
|
|
||||||
this.as = new ExposedField(as, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private LookupOperation() {
|
|
||||||
// used by builder
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation#getFields()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public ExposedFields getFields() {
|
|
||||||
return ExposedFields.from(as);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DBObject toDBObject(AggregationOperationContext context) {
|
|
||||||
|
|
||||||
BasicDBObject lookupObject = new BasicDBObject();
|
|
||||||
|
|
||||||
lookupObject.append("from", from.getTarget());
|
|
||||||
lookupObject.append("localField", localField.getTarget());
|
|
||||||
lookupObject.append("foreignField", foreignField.getTarget());
|
|
||||||
lookupObject.append("as", as.getTarget());
|
|
||||||
|
|
||||||
return new BasicDBObject("$lookup", lookupObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a builder that allows creation of {@link LookupOperation}.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static FromBuilder newLookup() {
|
|
||||||
return new LookupOperationBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface FromBuilder {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name the collection in the same database to perform the join with, must not be {@literal null} or empty.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
LocalFieldBuilder from(String name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface LocalFieldBuilder {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name the field from the documents input to the {@code $lookup} stage, must not be {@literal null} or
|
|
||||||
* empty.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
ForeignFieldBuilder localField(String name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface ForeignFieldBuilder {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name the field from the documents in the {@code from} collection, must not be {@literal null} or empty.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
AsBuilder foreignField(String name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface AsBuilder {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name the name of the new array field to add to the input documents, must not be {@literal null} or empty.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
LookupOperation as(String name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builder for fluent {@link LookupOperation} creation.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.9
|
|
||||||
*/
|
|
||||||
public static final class LookupOperationBuilder
|
|
||||||
implements FromBuilder, LocalFieldBuilder, ForeignFieldBuilder, AsBuilder {
|
|
||||||
|
|
||||||
private final LookupOperation lookupOperation;
|
|
||||||
|
|
||||||
private LookupOperationBuilder() {
|
|
||||||
this.lookupOperation = new LookupOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new builder for {@link LookupOperation}.
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
*/
|
|
||||||
public static FromBuilder newBuilder() {
|
|
||||||
return new LookupOperationBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocalFieldBuilder from(String name) {
|
|
||||||
|
|
||||||
Assert.hasText(name, "'From' must not be null or empty!");
|
|
||||||
lookupOperation.from = Fields.field(name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LookupOperation as(String name) {
|
|
||||||
|
|
||||||
Assert.hasText(name, "'As' must not be null or empty!");
|
|
||||||
lookupOperation.as = new ExposedField(Fields.field(name), true);
|
|
||||||
return new LookupOperation(lookupOperation.from, lookupOperation.localField, lookupOperation.foreignField,
|
|
||||||
lookupOperation.as);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AsBuilder foreignField(String name) {
|
|
||||||
|
|
||||||
Assert.hasText(name, "'ForeignField' must not be null or empty!");
|
|
||||||
lookupOperation.foreignField = Fields.field(name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ForeignFieldBuilder localField(String name) {
|
|
||||||
|
|
||||||
Assert.hasText(name, "'LocalField' must not be null or empty!");
|
|
||||||
lookupOperation.localField = Fields.field(name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 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.aggregation;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encapsulates the {@code $out}-operation.
|
|
||||||
* <p>
|
|
||||||
* We recommend to use the static factory method {@link Aggregation#out(String)} instead of creating instances of this
|
|
||||||
* class directly.
|
|
||||||
*
|
|
||||||
* @see http://docs.mongodb.org/manual/reference/aggregation/out/
|
|
||||||
* @author Nikolay Bogdanov
|
|
||||||
*/
|
|
||||||
public class OutOperation implements AggregationOperation {
|
|
||||||
|
|
||||||
private final String collectionName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param outCollectionName Collection name to export the results. Must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public OutOperation(String outCollectionName) {
|
|
||||||
Assert.notNull(outCollectionName, "Collection name must not be null!");
|
|
||||||
this.collectionName = outCollectionName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DBObject toDBObject(AggregationOperationContext context) {
|
|
||||||
return new BasicDBObject("$out", collectionName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2016 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -21,7 +21,6 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
||||||
import org.springframework.data.mongodb.core.aggregation.Fields.AggregationField;
|
|
||||||
import org.springframework.data.mongodb.core.aggregation.ProjectionOperation.ProjectionOperationBuilder.FieldProjection;
|
import org.springframework.data.mongodb.core.aggregation.ProjectionOperation.ProjectionOperationBuilder.FieldProjection;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@@ -41,7 +40,6 @@ import com.mongodb.DBObject;
|
|||||||
* @author Tobias Trelle
|
* @author Tobias Trelle
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.3
|
* @since 1.3
|
||||||
*/
|
*/
|
||||||
public class ProjectionOperation implements FieldsExposingAggregationOperation {
|
public class ProjectionOperation implements FieldsExposingAggregationOperation {
|
||||||
@@ -123,10 +121,6 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
|
|||||||
return new ExpressionProjectionOperationBuilder(expression, this, params);
|
return new ExpressionProjectionOperationBuilder(expression, this, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProjectionOperationBuilder and(AggregationExpression expression) {
|
|
||||||
return new ProjectionOperationBuilder(expression, this, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excludes the given fields from the projection.
|
* Excludes the given fields from the projection.
|
||||||
*
|
*
|
||||||
@@ -352,7 +346,6 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
|
|||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public static class ProjectionOperationBuilder extends AbstractProjectionOperationBuilder {
|
public static class ProjectionOperationBuilder extends AbstractProjectionOperationBuilder {
|
||||||
|
|
||||||
@@ -427,13 +420,9 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
|
|||||||
|
|
||||||
if (this.previousProjection != null) {
|
if (this.previousProjection != null) {
|
||||||
return this.operation.andReplaceLastOneWith(this.previousProjection.withAlias(alias));
|
return this.operation.andReplaceLastOneWith(this.previousProjection.withAlias(alias));
|
||||||
|
} else {
|
||||||
|
return this.operation.and(new FieldProjection(Fields.field(alias, name), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value instanceof AggregationExpression) {
|
|
||||||
return this.operation.and(new ExpressionProjection(Fields.field(alias), (AggregationExpression) value));
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.operation.and(new FieldProjection(Fields.field(alias, name), null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -563,41 +552,6 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
|
|||||||
return project("mod", Fields.field(fieldReference));
|
return project("mod", Fields.field(fieldReference));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a {@code $size} expression that returns the size of the array held by the given field. <br />
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public ProjectionOperationBuilder size() {
|
|
||||||
return project("size");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a {@code $slice} expression that returns a subset of the array held by the given field. <br />
|
|
||||||
* If {@literal n} is positive, $slice returns up to the first n elements in the array. <br />
|
|
||||||
* If {@literal n} is negative, $slice returns up to the last n elements in the array.
|
|
||||||
*
|
|
||||||
* @param count max number of elements.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public ProjectionOperationBuilder slice(int count) {
|
|
||||||
return project("slice", count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a {@code $slice} expression that returns a subset of the array held by the given field. <br />
|
|
||||||
*
|
|
||||||
* @param count max number of elements. Must not be negative.
|
|
||||||
* @param offset the offset within the array to start from.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public ProjectionOperationBuilder slice(int count, int offset) {
|
|
||||||
return project("slice", offset, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||||
@@ -797,20 +751,6 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
|
|||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#getExposedField()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public ExposedField getExposedField() {
|
|
||||||
|
|
||||||
if (!getField().isAliased()) {
|
|
||||||
return super.getExposedField();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ExposedField(new AggregationField(getField().getName()), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of this {@link OperationProjection} with the given alias.
|
* Creates a new instance of this {@link OperationProjection} with the given alias.
|
||||||
*
|
*
|
||||||
@@ -1000,31 +940,4 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
|
|||||||
*/
|
*/
|
||||||
public abstract DBObject toDBObject(AggregationOperationContext context);
|
public abstract DBObject toDBObject(AggregationOperationContext context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Thomas Darimont
|
|
||||||
*/
|
|
||||||
static class ExpressionProjection extends Projection {
|
|
||||||
|
|
||||||
private final AggregationExpression expression;
|
|
||||||
private final Field field;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link ExpressionProjection}.
|
|
||||||
*
|
|
||||||
* @param field
|
|
||||||
* @param expression
|
|
||||||
*/
|
|
||||||
public ExpressionProjection(Field field, AggregationExpression expression) {
|
|
||||||
|
|
||||||
super(field);
|
|
||||||
this.field = field;
|
|
||||||
this.expression = expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DBObject toDBObject(AggregationOperationContext context) {
|
|
||||||
return new BasicDBObject(field.getName(), expression.toDbObject(context));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2016 the original author or authors.
|
* Copyright 2013-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -30,238 +30,29 @@ import com.mongodb.DBObject;
|
|||||||
* @see http://docs.mongodb.org/manual/reference/aggregation/unwind/#pipe._S_unwind
|
* @see http://docs.mongodb.org/manual/reference/aggregation/unwind/#pipe._S_unwind
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Mark Paluch
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.3
|
* @since 1.3
|
||||||
*/
|
*/
|
||||||
public class UnwindOperation
|
public class UnwindOperation implements AggregationOperation {
|
||||||
implements AggregationOperation, FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation {
|
|
||||||
|
|
||||||
private final ExposedField field;
|
private final ExposedField field;
|
||||||
private final ExposedField arrayIndex;
|
|
||||||
private final boolean preserveNullAndEmptyArrays;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link UnwindOperation} for the given {@link Field}.
|
* Creates a new {@link UnwindOperation} for the given {@link Field}.
|
||||||
*
|
*
|
||||||
* @param field must not be {@literal null}.
|
* @param field must not be {@literal null}.
|
||||||
*/
|
*/
|
||||||
public UnwindOperation(Field field) {
|
public UnwindOperation(Field field) {
|
||||||
this(new ExposedField(field, true), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link UnwindOperation} using Mongo 3.2 syntax.
|
|
||||||
*
|
|
||||||
* @param field must not be {@literal null}.
|
|
||||||
* @param preserveNullAndEmptyArrays {@literal true} to output the document if path is {@literal null}, missing or
|
|
||||||
* array is empty.
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public UnwindOperation(Field field, boolean preserveNullAndEmptyArrays) {
|
|
||||||
Assert.notNull(field, "Field must not be null!");
|
|
||||||
|
|
||||||
|
Assert.notNull(field);
|
||||||
this.field = new ExposedField(field, true);
|
this.field = new ExposedField(field, true);
|
||||||
this.arrayIndex = null;
|
|
||||||
this.preserveNullAndEmptyArrays = preserveNullAndEmptyArrays;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Creates a new {@link UnwindOperation} using Mongo 3.2 syntax.
|
|
||||||
*
|
|
||||||
* @param field must not be {@literal null}.
|
|
||||||
* @param arrayIndex optional field name to expose the field array index, must not be {@literal null}.
|
|
||||||
* @param preserveNullAndEmptyArrays {@literal true} to output the document if path is {@literal null}, missing or
|
|
||||||
* array is empty.
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public UnwindOperation(Field field, Field arrayIndex, boolean preserveNullAndEmptyArrays) {
|
|
||||||
|
|
||||||
Assert.notNull(field, "Field must not be null!");
|
|
||||||
Assert.notNull(arrayIndex, "ArrayIndex must not be null!");
|
|
||||||
|
|
||||||
this.field = new ExposedField(field, true);
|
|
||||||
this.arrayIndex = new ExposedField(arrayIndex, true);
|
|
||||||
this.preserveNullAndEmptyArrays = preserveNullAndEmptyArrays;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public DBObject toDBObject(AggregationOperationContext context) {
|
public DBObject toDBObject(AggregationOperationContext context) {
|
||||||
|
return new BasicDBObject("$unwind", context.getReference(field).toString());
|
||||||
String path = context.getReference(field).toString();
|
|
||||||
|
|
||||||
if (!preserveNullAndEmptyArrays && arrayIndex == null) {
|
|
||||||
return new BasicDBObject("$unwind", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
DBObject unwindArgs = new BasicDBObject();
|
|
||||||
unwindArgs.put("path", path);
|
|
||||||
if (arrayIndex != null) {
|
|
||||||
unwindArgs.put("includeArrayIndex", arrayIndex.getName());
|
|
||||||
}
|
|
||||||
unwindArgs.put("preserveNullAndEmptyArrays", preserveNullAndEmptyArrays);
|
|
||||||
|
|
||||||
return new BasicDBObject("$unwind", unwindArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation#getFields()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public ExposedFields getFields() {
|
|
||||||
return arrayIndex != null ? ExposedFields.from(arrayIndex) : ExposedFields.from();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a builder that allows creation of {@link LookupOperation}.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public static PathBuilder newUnwind() {
|
|
||||||
return UnwindOperationBuilder.newBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public static interface PathBuilder {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param path the path to unwind, must not be {@literal null} or empty.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
IndexBuilder path(String path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public static interface IndexBuilder {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exposes the array index as {@code field}.
|
|
||||||
*
|
|
||||||
* @param field field name to expose the field array index, must not be {@literal null} or empty.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
EmptyArraysBuilder arrayIndex(String field);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do not expose the array index.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
EmptyArraysBuilder noArrayIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface EmptyArraysBuilder {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output documents if the array is null or empty.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
UnwindOperation preserveNullAndEmptyArrays();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do not output documents if the array is null or empty.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
UnwindOperation skipNullAndEmptyArrays();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builder for fluent {@link UnwindOperation} creation.
|
|
||||||
*
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public static final class UnwindOperationBuilder implements PathBuilder, IndexBuilder, EmptyArraysBuilder {
|
|
||||||
|
|
||||||
private Field field;
|
|
||||||
private Field arrayIndex;
|
|
||||||
|
|
||||||
private UnwindOperationBuilder() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new builder for {@link UnwindOperation}.
|
|
||||||
*
|
|
||||||
* @return never {@literal null}.
|
|
||||||
*/
|
|
||||||
public static PathBuilder newBuilder() {
|
|
||||||
return new UnwindOperationBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.UnwindOperation.EmptyArraysBuilder#preserveNullAndEmptyArrays()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public UnwindOperation preserveNullAndEmptyArrays() {
|
|
||||||
|
|
||||||
if (arrayIndex != null) {
|
|
||||||
return new UnwindOperation(field, arrayIndex, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new UnwindOperation(field, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.UnwindOperation.EmptyArraysBuilder#skipNullAndEmptyArrays()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public UnwindOperation skipNullAndEmptyArrays() {
|
|
||||||
|
|
||||||
if (arrayIndex != null) {
|
|
||||||
return new UnwindOperation(field, arrayIndex, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new UnwindOperation(field, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.UnwindOperation.IndexBuilder#arrayIndex(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public EmptyArraysBuilder arrayIndex(String field) {
|
|
||||||
|
|
||||||
Assert.hasText(field, "'ArrayIndex' must not be null or empty!");
|
|
||||||
arrayIndex = Fields.field(field);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.UnwindOperation.IndexBuilder#noArrayIndex()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public EmptyArraysBuilder noArrayIndex() {
|
|
||||||
|
|
||||||
arrayIndex = null;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.aggregation.UnwindOperation.PathBuilder#path(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public UnwindOperationBuilder path(String path) {
|
|
||||||
|
|
||||||
Assert.hasText(path, "'Path' must not be null or empty!");
|
|
||||||
field = Fields.field(path);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,13 +75,15 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
|
|||||||
*/
|
*/
|
||||||
private void initializeConverters() {
|
private void initializeConverters() {
|
||||||
|
|
||||||
conversionService.addConverter(ObjectIdToStringConverter.INSTANCE);
|
if (!conversionService.canConvert(ObjectId.class, String.class)) {
|
||||||
conversionService.addConverter(StringToObjectIdConverter.INSTANCE);
|
conversionService.addConverter(ObjectIdToStringConverter.INSTANCE);
|
||||||
|
}
|
||||||
|
if (!conversionService.canConvert(String.class, ObjectId.class)) {
|
||||||
|
conversionService.addConverter(StringToObjectIdConverter.INSTANCE);
|
||||||
|
}
|
||||||
if (!conversionService.canConvert(ObjectId.class, BigInteger.class)) {
|
if (!conversionService.canConvert(ObjectId.class, BigInteger.class)) {
|
||||||
conversionService.addConverter(ObjectIdToBigIntegerConverter.INSTANCE);
|
conversionService.addConverter(ObjectIdToBigIntegerConverter.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!conversionService.canConvert(BigInteger.class, ObjectId.class)) {
|
if (!conversionService.canConvert(BigInteger.class, ObjectId.class)) {
|
||||||
conversionService.addConverter(BigIntegerToObjectIdConverter.INSTANCE);
|
conversionService.addConverter(BigIntegerToObjectIdConverter.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2016 the original author or authors.
|
* Copyright 2011-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -37,13 +37,18 @@ import org.springframework.core.convert.converter.GenericConverter;
|
|||||||
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
|
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
|
||||||
import org.springframework.core.convert.support.GenericConversionService;
|
import org.springframework.core.convert.support.GenericConversionService;
|
||||||
import org.springframework.data.convert.JodaTimeConverters;
|
import org.springframework.data.convert.JodaTimeConverters;
|
||||||
import org.springframework.data.convert.Jsr310Converters;
|
|
||||||
import org.springframework.data.convert.ReadingConverter;
|
import org.springframework.data.convert.ReadingConverter;
|
||||||
import org.springframework.data.convert.ThreeTenBackPortConverters;
|
|
||||||
import org.springframework.data.convert.WritingConverter;
|
import org.springframework.data.convert.WritingConverter;
|
||||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
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.DBObjectToStringConverter;
|
||||||
|
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.StringToURLConverter;
|
||||||
|
import org.springframework.data.mongodb.core.convert.MongoConverters.TermToStringConverter;
|
||||||
|
import org.springframework.data.mongodb.core.convert.MongoConverters.URLToStringConverter;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
||||||
import org.springframework.data.util.CacheValue;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,9 +75,9 @@ public class CustomConversions {
|
|||||||
|
|
||||||
private final List<Object> converters;
|
private final List<Object> converters;
|
||||||
|
|
||||||
private final Map<ConvertiblePair, CacheValue<Class<?>>> customReadTargetTypes;
|
private final Map<ConvertiblePair, CacheValue> customReadTargetTypes;
|
||||||
private final Map<ConvertiblePair, CacheValue<Class<?>>> customWriteTargetTypes;
|
private final Map<ConvertiblePair, CacheValue> customWriteTargetTypes;
|
||||||
private final Map<Class<?>, CacheValue<Class<?>>> rawWriteTargetTypes;
|
private final Map<Class<?>, CacheValue> rawWriteTargetTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty {@link CustomConversions} object.
|
* Creates an empty {@link CustomConversions} object.
|
||||||
@@ -93,20 +98,26 @@ public class CustomConversions {
|
|||||||
this.readingPairs = new LinkedHashSet<ConvertiblePair>();
|
this.readingPairs = new LinkedHashSet<ConvertiblePair>();
|
||||||
this.writingPairs = new LinkedHashSet<ConvertiblePair>();
|
this.writingPairs = new LinkedHashSet<ConvertiblePair>();
|
||||||
this.customSimpleTypes = new HashSet<Class<?>>();
|
this.customSimpleTypes = new HashSet<Class<?>>();
|
||||||
this.customReadTargetTypes = new ConcurrentHashMap<ConvertiblePair, CacheValue<Class<?>>>();
|
this.customReadTargetTypes = new ConcurrentHashMap<ConvertiblePair, CacheValue>();
|
||||||
this.customWriteTargetTypes = new ConcurrentHashMap<ConvertiblePair, CacheValue<Class<?>>>();
|
this.customWriteTargetTypes = new ConcurrentHashMap<ConvertiblePair, CacheValue>();
|
||||||
this.rawWriteTargetTypes = new ConcurrentHashMap<Class<?>, CacheValue<Class<?>>>();
|
this.rawWriteTargetTypes = new ConcurrentHashMap<Class<?>, CacheValue>();
|
||||||
|
|
||||||
List<Object> toRegister = new ArrayList<Object>();
|
List<Object> toRegister = new ArrayList<Object>();
|
||||||
|
|
||||||
// Add user provided converters to make sure they can override the defaults
|
// Add user provided converters to make sure they can override the defaults
|
||||||
toRegister.addAll(converters);
|
toRegister.addAll(converters);
|
||||||
toRegister.add(CustomToStringConverter.INSTANCE);
|
toRegister.add(CustomToStringConverter.INSTANCE);
|
||||||
toRegister.addAll(MongoConverters.getConvertersToRegister());
|
toRegister.add(BigDecimalToStringConverter.INSTANCE);
|
||||||
|
toRegister.add(StringToBigDecimalConverter.INSTANCE);
|
||||||
|
toRegister.add(BigIntegerToStringConverter.INSTANCE);
|
||||||
|
toRegister.add(StringToBigIntegerConverter.INSTANCE);
|
||||||
|
toRegister.add(URLToStringConverter.INSTANCE);
|
||||||
|
toRegister.add(StringToURLConverter.INSTANCE);
|
||||||
|
toRegister.add(DBObjectToStringConverter.INSTANCE);
|
||||||
|
toRegister.add(TermToStringConverter.INSTANCE);
|
||||||
|
|
||||||
toRegister.addAll(JodaTimeConverters.getConvertersToRegister());
|
toRegister.addAll(JodaTimeConverters.getConvertersToRegister());
|
||||||
toRegister.addAll(GeoConverters.getConvertersToRegister());
|
toRegister.addAll(GeoConverters.getConvertersToRegister());
|
||||||
toRegister.addAll(Jsr310Converters.getConvertersToRegister());
|
|
||||||
toRegister.addAll(ThreeTenBackPortConverters.getConvertersToRegister());
|
|
||||||
|
|
||||||
for (Object c : toRegister) {
|
for (Object c : toRegister) {
|
||||||
registerConversion(c);
|
registerConversion(c);
|
||||||
@@ -166,15 +177,14 @@ public class CustomConversions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!added) {
|
if (!added) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException("Given set contains element that is neither Converter nor ConverterFactory!");
|
||||||
"Given set contains element that is neither Converter nor ConverterFactory!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a conversion for the given converter. Inspects either generics of {@link Converter} and
|
* Registers a conversion for the given converter. Inspects either generics or the {@link ConvertiblePair}s returned
|
||||||
* {@link ConverterFactory} or the {@link ConvertiblePair}s returned by a {@link GenericConverter}.
|
* by a {@link GenericConverter}.
|
||||||
*
|
*
|
||||||
* @param converter
|
* @param converter
|
||||||
*/
|
*/
|
||||||
@@ -189,10 +199,6 @@ public class CustomConversions {
|
|||||||
for (ConvertiblePair pair : genericConverter.getConvertibleTypes()) {
|
for (ConvertiblePair pair : genericConverter.getConvertibleTypes()) {
|
||||||
register(new ConverterRegistration(pair, isReading, isWriting));
|
register(new ConverterRegistration(pair, isReading, isWriting));
|
||||||
}
|
}
|
||||||
} else if (converter instanceof ConverterFactory) {
|
|
||||||
|
|
||||||
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), ConverterFactory.class);
|
|
||||||
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
|
|
||||||
} else if (converter instanceof Converter) {
|
} else if (converter instanceof Converter) {
|
||||||
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), Converter.class);
|
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), Converter.class);
|
||||||
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
|
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
|
||||||
@@ -373,16 +379,16 @@ public class CustomConversions {
|
|||||||
* @param producer the {@link Producer} to create values to cache, must not be {@literal null}.
|
* @param producer the {@link Producer} to create values to cache, must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static <T> Class<?> getOrCreateAndCache(T key, Map<T, CacheValue<Class<?>>> cache, Producer producer) {
|
private static <T> Class<?> getOrCreateAndCache(T key, Map<T, CacheValue> cache, Producer producer) {
|
||||||
|
|
||||||
CacheValue<Class<?>> cacheValue = cache.get(key);
|
CacheValue cacheValue = cache.get(key);
|
||||||
|
|
||||||
if (cacheValue != null) {
|
if (cacheValue != null) {
|
||||||
return cacheValue.getValue();
|
return cacheValue.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> type = producer.get();
|
Class<?> type = producer.get();
|
||||||
cache.put(key, CacheValue.<Class<?>> ofNullable(type));
|
cache.put(key, CacheValue.of(type));
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@@ -397,10 +403,6 @@ public class CustomConversions {
|
|||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.GenericConverter#getConvertibleTypes()
|
|
||||||
*/
|
|
||||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||||
|
|
||||||
ConvertiblePair localeToString = new ConvertiblePair(Locale.class, String.class);
|
ConvertiblePair localeToString = new ConvertiblePair(Locale.class, String.class);
|
||||||
@@ -409,12 +411,34 @@ public class CustomConversions {
|
|||||||
return new HashSet<ConvertiblePair>(Arrays.asList(localeToString, booleanToString));
|
return new HashSet<ConvertiblePair>(Arrays.asList(localeToString, booleanToString));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.GenericConverter#convert(java.lang.Object, org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
|
|
||||||
*/
|
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
return source.toString();
|
return source.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper to safely store {@literal null} values in the type cache.
|
||||||
|
*
|
||||||
|
* @author Patryk Wasik
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @author Thomas Darimont
|
||||||
|
*/
|
||||||
|
private static class CacheValue {
|
||||||
|
|
||||||
|
private static final CacheValue ABSENT = new CacheValue(null);
|
||||||
|
|
||||||
|
private final Class<?> type;
|
||||||
|
|
||||||
|
public CacheValue(Class<?> type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CacheValue of(Class<?> type) {
|
||||||
|
return type == null ? ABSENT : new CacheValue(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,9 @@ class DBObjectAccessor {
|
|||||||
String part = parts.next();
|
String part = parts.next();
|
||||||
|
|
||||||
if (parts.hasNext()) {
|
if (parts.hasNext()) {
|
||||||
dbObject = getOrCreateNestedDbObject(part, dbObject);
|
BasicDBObject nestedDbObject = new BasicDBObject();
|
||||||
|
dbObject.put(part, nestedDbObject);
|
||||||
|
dbObject = nestedDbObject;
|
||||||
} else {
|
} else {
|
||||||
dbObject.put(part, value);
|
dbObject.put(part, value);
|
||||||
}
|
}
|
||||||
@@ -114,14 +116,8 @@ class DBObjectAccessor {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the given source object as map, i.e. {@link BasicDBObject}s and maps as is or {@literal null} otherwise.
|
|
||||||
*
|
|
||||||
* @param source can be {@literal null}.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static Map<String, Object> getAsMap(Object source) {
|
private Map<String, Object> getAsMap(Object source) {
|
||||||
|
|
||||||
if (source instanceof BasicDBObject) {
|
if (source instanceof BasicDBObject) {
|
||||||
return (BasicDBObject) source;
|
return (BasicDBObject) source;
|
||||||
@@ -133,26 +129,4 @@ class DBObjectAccessor {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link DBObject} which either already exists in the given source under the given key, or creates a new
|
|
||||||
* nested one, registers it with the source and returns it.
|
|
||||||
*
|
|
||||||
* @param key must not be {@literal null} or empty.
|
|
||||||
* @param source must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static DBObject getOrCreateNestedDbObject(String key, DBObject source) {
|
|
||||||
|
|
||||||
Object existing = source.get(key);
|
|
||||||
|
|
||||||
if (existing instanceof BasicDBObject) {
|
|
||||||
return (BasicDBObject) existing;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBObject nested = new BasicDBObject();
|
|
||||||
source.put(key, nested);
|
|
||||||
|
|
||||||
return nested;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2016 the original author or authors.
|
* Copyright 2013-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -15,13 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core.convert;
|
package org.springframework.data.mongodb.core.convert;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import com.mongodb.DBRef;
|
import com.mongodb.DBRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,7 +25,6 @@ import com.mongodb.DBRef;
|
|||||||
*
|
*
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public interface DbRefResolver {
|
public interface DbRefResolver {
|
||||||
@@ -58,25 +53,4 @@ public interface DbRefResolver {
|
|||||||
*/
|
*/
|
||||||
DBRef createDbRef(org.springframework.data.mongodb.core.mapping.DBRef annotation, MongoPersistentEntity<?> entity,
|
DBRef createDbRef(org.springframework.data.mongodb.core.mapping.DBRef annotation, MongoPersistentEntity<?> entity,
|
||||||
Object id);
|
Object id);
|
||||||
|
|
||||||
/**
|
|
||||||
* Actually loads the {@link DBRef} from the datasource.
|
|
||||||
*
|
|
||||||
* @param dbRef must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
DBObject fetch(DBRef dbRef);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a given {@link List} of {@link DBRef}s from the datasource in one batch. The resulting {@link List} of
|
|
||||||
* {@link DBObject} will reflect the ordering of the {@link DBRef} passed in.<br />
|
|
||||||
* The {@link DBRef} elements in the list must not reference different collections.
|
|
||||||
*
|
|
||||||
* @param dbRefs must not be {@literal null}.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @throws InvalidDataAccessApiUsageException in case not all {@link DBRef} target the same collection.
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
List<DBObject> bulkFetch(List<DBRef> dbRefs);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core.convert;
|
package org.springframework.data.mongodb.core.convert;
|
||||||
|
|
||||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
|
import org.springframework.data.mapping.model.BeanWrapper;
|
||||||
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
|
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
|
||||||
import org.springframework.data.mapping.model.SpELContext;
|
import org.springframework.data.mapping.model.SpELContext;
|
||||||
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||||
@@ -60,19 +60,19 @@ class DefaultDbRefProxyHandler implements DbRefProxyHandler {
|
|||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(property);
|
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(property);
|
||||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
MongoPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||||
|
|
||||||
if (idProperty.usePropertyAccess()) {
|
if(idProperty.usePropertyAccess()) {
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(proxy, spELContext);
|
SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(proxy, spELContext);
|
||||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(proxy);
|
BeanWrapper<Object> proxyWrapper = BeanWrapper.create(proxy, null);
|
||||||
|
|
||||||
DBObject object = new BasicDBObject(idProperty.getFieldName(), source.getId());
|
DBObject object = new BasicDBObject(idProperty.getFieldName(), source.getId());
|
||||||
ObjectPath objectPath = ObjectPath.ROOT.push(proxy, entity, null);
|
ObjectPath objectPath = ObjectPath.ROOT.push(proxy, persistentEntity, null);
|
||||||
accessor.setProperty(idProperty, resolver.getValueInternal(idProperty, object, evaluator, objectPath));
|
proxyWrapper.setProperty(idProperty, resolver.getValueInternal(idProperty, object, evaluator, objectPath));
|
||||||
|
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2016 the original author or authors.
|
* Copyright 2013-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -22,10 +22,6 @@ import java.io.ObjectInputStream;
|
|||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
import org.aopalliance.intercept.MethodInterceptor;
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
@@ -35,7 +31,6 @@ import org.springframework.cglib.proxy.Enhancer;
|
|||||||
import org.springframework.cglib.proxy.Factory;
|
import org.springframework.cglib.proxy.Factory;
|
||||||
import org.springframework.cglib.proxy.MethodProxy;
|
import org.springframework.cglib.proxy.MethodProxy;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
|
||||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||||
import org.springframework.data.mongodb.LazyLoadingException;
|
import org.springframework.data.mongodb.LazyLoadingException;
|
||||||
import org.springframework.data.mongodb.MongoDbFactory;
|
import org.springframework.data.mongodb.MongoDbFactory;
|
||||||
@@ -44,11 +39,9 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
|||||||
import org.springframework.objenesis.ObjenesisStd;
|
import org.springframework.objenesis.ObjenesisStd;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.BasicDBObjectBuilder;
|
|
||||||
import com.mongodb.DB;
|
import com.mongodb.DB;
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import com.mongodb.DBRef;
|
import com.mongodb.DBRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,7 +50,6 @@ import com.mongodb.DBRef;
|
|||||||
*
|
*
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public class DefaultDbRefResolver implements DbRefResolver {
|
public class DefaultDbRefResolver implements DbRefResolver {
|
||||||
@@ -105,50 +97,11 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
|||||||
@Override
|
@Override
|
||||||
public DBRef createDbRef(org.springframework.data.mongodb.core.mapping.DBRef annotation,
|
public DBRef createDbRef(org.springframework.data.mongodb.core.mapping.DBRef annotation,
|
||||||
MongoPersistentEntity<?> entity, Object id) {
|
MongoPersistentEntity<?> entity, Object id) {
|
||||||
return new DBRef(entity.getCollection(), id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.convert.DbRefResolver#fetch(com.mongodb.DBRef)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DBObject fetch(DBRef dbRef) {
|
|
||||||
return ReflectiveDBRefResolver.fetch(mongoDbFactory, dbRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.convert.DbRefResolver#bulkFetch(java.util.List)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List<DBObject> bulkFetch(List<DBRef> refs) {
|
|
||||||
|
|
||||||
Assert.notNull(mongoDbFactory, "Factory must not be null!");
|
|
||||||
Assert.notNull(refs, "DBRef to fetch must not be null!");
|
|
||||||
|
|
||||||
if (refs.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
String collection = refs.iterator().next().getCollectionName();
|
|
||||||
|
|
||||||
List<Object> ids = new ArrayList<Object>(refs.size());
|
|
||||||
for (DBRef ref : refs) {
|
|
||||||
|
|
||||||
if (!collection.equals(ref.getCollectionName())) {
|
|
||||||
throw new InvalidDataAccessApiUsageException(
|
|
||||||
"DBRefs must all target the same collection for bulk fetch operation.");
|
|
||||||
}
|
|
||||||
|
|
||||||
ids.add(ref.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
DB db = mongoDbFactory.getDb();
|
DB db = mongoDbFactory.getDb();
|
||||||
List<DBObject> result = db.getCollection(collection)
|
db = annotation != null && StringUtils.hasText(annotation.db()) ? mongoDbFactory.getDb(annotation.db()) : db;
|
||||||
.find(new BasicDBObjectBuilder().add("_id", new BasicDBObject("$in", ids)).get()).toArray();
|
|
||||||
Collections.sort(result, new DbRefByReferencePositionComparator(ids));
|
return new DBRef(db, entity.getCollection(), id);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,8 +175,8 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
|||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
*/
|
*/
|
||||||
static class LazyLoadingInterceptor
|
static class LazyLoadingInterceptor implements MethodInterceptor, org.springframework.cglib.proxy.MethodInterceptor,
|
||||||
implements MethodInterceptor, org.springframework.cglib.proxy.MethodInterceptor, Serializable {
|
Serializable {
|
||||||
|
|
||||||
private static final Method INITIALIZE_METHOD, TO_DBREF_METHOD, FINALIZE_METHOD;
|
private static final Method INITIALIZE_METHOD, TO_DBREF_METHOD, FINALIZE_METHOD;
|
||||||
|
|
||||||
@@ -329,7 +282,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
|||||||
|
|
||||||
StringBuilder description = new StringBuilder();
|
StringBuilder description = new StringBuilder();
|
||||||
if (dbref != null) {
|
if (dbref != null) {
|
||||||
description.append(dbref.getCollectionName());
|
description.append(dbref.getRef());
|
||||||
description.append(":");
|
description.append(":");
|
||||||
description.append(dbref.getId());
|
description.append(dbref.getId());
|
||||||
} else {
|
} else {
|
||||||
@@ -429,45 +382,11 @@ public class DefaultDbRefResolver implements DbRefResolver {
|
|||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
|
|
||||||
DataAccessException translatedException = this.exceptionTranslator.translateExceptionIfPossible(ex);
|
DataAccessException translatedException = this.exceptionTranslator.translateExceptionIfPossible(ex);
|
||||||
throw new LazyLoadingException("Unable to lazily resolve DBRef!",
|
throw new LazyLoadingException("Unable to lazily resolve DBRef!", translatedException);
|
||||||
translatedException != null ? translatedException : ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link Comparator} for sorting {@link DBObject} that have been loaded in random order by a predefined list of
|
|
||||||
* reference identifiers.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
private static class DbRefByReferencePositionComparator implements Comparator<DBObject> {
|
|
||||||
|
|
||||||
private final List<Object> reference;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link DbRefByReferencePositionComparator} for the given list of reference identifiers.
|
|
||||||
*
|
|
||||||
* @param referenceIds must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public DbRefByReferencePositionComparator(List<Object> referenceIds) {
|
|
||||||
|
|
||||||
Assert.notNull(referenceIds, "Reference identifiers must not be null!");
|
|
||||||
this.reference = new ArrayList<Object>(referenceIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int compare(DBObject o1, DBObject o2) {
|
|
||||||
return Integer.compare(reference.indexOf(o1.get("_id")), reference.indexOf(o2.get("_id")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2016 the original author or authors.
|
* Copyright 2011-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -45,9 +45,9 @@ import com.mongodb.DBObject;
|
|||||||
public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implements MongoTypeMapper {
|
public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implements MongoTypeMapper {
|
||||||
|
|
||||||
public static final String DEFAULT_TYPE_KEY = "_class";
|
public static final String DEFAULT_TYPE_KEY = "_class";
|
||||||
@SuppressWarnings("rawtypes") //
|
@SuppressWarnings("rawtypes")//
|
||||||
private static final TypeInformation<List> LIST_TYPE_INFO = ClassTypeInformation.from(List.class);
|
private static final TypeInformation<List> LIST_TYPE_INFO = ClassTypeInformation.from(List.class);
|
||||||
@SuppressWarnings("rawtypes") //
|
@SuppressWarnings("rawtypes")//
|
||||||
private static final TypeInformation<Map> MAP_TYPE_INFO = ClassTypeInformation.from(Map.class);
|
private static final TypeInformation<Map> MAP_TYPE_INFO = ClassTypeInformation.from(Map.class);
|
||||||
|
|
||||||
private final TypeAliasAccessor<DBObject> accessor;
|
private final TypeAliasAccessor<DBObject> accessor;
|
||||||
@@ -58,12 +58,12 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DefaultMongoTypeMapper(String typeKey) {
|
public DefaultMongoTypeMapper(String typeKey) {
|
||||||
this(typeKey, Arrays.asList(new SimpleTypeInformationMapper()));
|
this(typeKey, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultMongoTypeMapper(String typeKey, MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext) {
|
public DefaultMongoTypeMapper(String typeKey, MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext) {
|
||||||
this(typeKey, new DBObjectTypeAliasAccessor(typeKey), mappingContext,
|
this(typeKey, new DBObjectTypeAliasAccessor(typeKey), mappingContext, Arrays
|
||||||
Arrays.asList(new SimpleTypeInformationMapper()));
|
.asList(SimpleTypeInformationMapper.INSTANCE));
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultMongoTypeMapper(String typeKey, List<? extends TypeInformationMapper> mappers) {
|
public DefaultMongoTypeMapper(String typeKey, List<? extends TypeInformationMapper> mappers) {
|
||||||
@@ -71,8 +71,7 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private DefaultMongoTypeMapper(String typeKey, TypeAliasAccessor<DBObject> accessor,
|
private DefaultMongoTypeMapper(String typeKey, TypeAliasAccessor<DBObject> accessor,
|
||||||
MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext,
|
MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext, List<? extends TypeInformationMapper> mappers) {
|
||||||
List<? extends TypeInformationMapper> mappers) {
|
|
||||||
|
|
||||||
super(accessor, mappingContext, mappers);
|
super(accessor, mappingContext, mappers);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2016 the original author or authors.
|
* Copyright 2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -30,18 +30,9 @@ import org.springframework.data.geo.Metrics;
|
|||||||
import org.springframework.data.geo.Point;
|
import org.springframework.data.geo.Point;
|
||||||
import org.springframework.data.geo.Polygon;
|
import org.springframework.data.geo.Polygon;
|
||||||
import org.springframework.data.geo.Shape;
|
import org.springframework.data.geo.Shape;
|
||||||
import org.springframework.data.mongodb.core.geo.GeoJson;
|
|
||||||
import org.springframework.data.mongodb.core.geo.GeoJsonGeometryCollection;
|
|
||||||
import org.springframework.data.mongodb.core.geo.GeoJsonLineString;
|
|
||||||
import org.springframework.data.mongodb.core.geo.GeoJsonMultiLineString;
|
|
||||||
import org.springframework.data.mongodb.core.geo.GeoJsonMultiPoint;
|
|
||||||
import org.springframework.data.mongodb.core.geo.GeoJsonMultiPolygon;
|
|
||||||
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
|
|
||||||
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
|
|
||||||
import org.springframework.data.mongodb.core.geo.Sphere;
|
import org.springframework.data.mongodb.core.geo.Sphere;
|
||||||
import org.springframework.data.mongodb.core.query.GeoCommand;
|
import org.springframework.data.mongodb.core.query.GeoCommand;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBList;
|
import com.mongodb.BasicDBList;
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
@@ -52,7 +43,6 @@ import com.mongodb.DBObject;
|
|||||||
*
|
*
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
abstract class GeoConverters {
|
abstract class GeoConverters {
|
||||||
@@ -67,7 +57,6 @@ abstract class GeoConverters {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static Collection<? extends Object> getConvertersToRegister() {
|
public static Collection<? extends Object> getConvertersToRegister() {
|
||||||
return Arrays.asList( //
|
return Arrays.asList( //
|
||||||
BoxToDbObjectConverter.INSTANCE //
|
BoxToDbObjectConverter.INSTANCE //
|
||||||
@@ -80,17 +69,7 @@ abstract class GeoConverters {
|
|||||||
, DbObjectToSphereConverter.INSTANCE //
|
, DbObjectToSphereConverter.INSTANCE //
|
||||||
, DbObjectToPointConverter.INSTANCE //
|
, DbObjectToPointConverter.INSTANCE //
|
||||||
, PointToDbObjectConverter.INSTANCE //
|
, PointToDbObjectConverter.INSTANCE //
|
||||||
, GeoCommandToDbObjectConverter.INSTANCE //
|
, GeoCommandToDbObjectConverter.INSTANCE);
|
||||||
, GeoJsonToDbObjectConverter.INSTANCE //
|
|
||||||
, GeoJsonPointToDbObjectConverter.INSTANCE //
|
|
||||||
, GeoJsonPolygonToDbObjectConverter.INSTANCE //
|
|
||||||
, DbObjectToGeoJsonPointConverter.INSTANCE //
|
|
||||||
, DbObjectToGeoJsonPolygonConverter.INSTANCE //
|
|
||||||
, DbObjectToGeoJsonLineStringConverter.INSTANCE //
|
|
||||||
, DbObjectToGeoJsonMultiLineStringConverter.INSTANCE //
|
|
||||||
, DbObjectToGeoJsonMultiPointConverter.INSTANCE //
|
|
||||||
, DbObjectToGeoJsonMultiPolygonConverter.INSTANCE //
|
|
||||||
, DbObjectToGeoJsonGeometryCollectionConverter.INSTANCE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,7 +79,7 @@ abstract class GeoConverters {
|
|||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
@ReadingConverter
|
@ReadingConverter
|
||||||
static enum DbObjectToPointConverter implements Converter<DBObject, Point> {
|
public static enum DbObjectToPointConverter implements Converter<DBObject, Point> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
@@ -111,17 +90,9 @@ abstract class GeoConverters {
|
|||||||
@Override
|
@Override
|
||||||
public Point convert(DBObject source) {
|
public Point convert(DBObject source) {
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.isTrue(source.keySet().size() == 2, "Source must contain 2 elements");
|
Assert.isTrue(source.keySet().size() == 2, "Source must contain 2 elements");
|
||||||
|
|
||||||
if (source.containsField("type")) {
|
return source == null ? null : new Point((Double) source.get("x"), (Double) source.get("y"));
|
||||||
return DbObjectToGeoJsonPointConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Point((Double) source.get("x"), (Double) source.get("y"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +102,7 @@ abstract class GeoConverters {
|
|||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
static enum PointToDbObjectConverter implements Converter<Point, DBObject> {
|
public static enum PointToDbObjectConverter implements Converter<Point, DBObject> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
@@ -152,7 +123,7 @@ abstract class GeoConverters {
|
|||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
@WritingConverter
|
@WritingConverter
|
||||||
static enum BoxToDbObjectConverter implements Converter<Box, DBObject> {
|
public static enum BoxToDbObjectConverter implements Converter<Box, DBObject> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
@@ -181,7 +152,7 @@ abstract class GeoConverters {
|
|||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
@ReadingConverter
|
@ReadingConverter
|
||||||
static enum DbObjectToBoxConverter implements Converter<DBObject, Box> {
|
public static enum DbObjectToBoxConverter implements Converter<DBObject, Box> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
@@ -209,7 +180,7 @@ abstract class GeoConverters {
|
|||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
static enum CircleToDbObjectConverter implements Converter<Circle, DBObject> {
|
public static enum CircleToDbObjectConverter implements Converter<Circle, DBObject> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
@@ -239,7 +210,7 @@ abstract class GeoConverters {
|
|||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
@ReadingConverter
|
@ReadingConverter
|
||||||
static enum DbObjectToCircleConverter implements Converter<DBObject, Circle> {
|
public static enum DbObjectToCircleConverter implements Converter<DBObject, Circle> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
@@ -280,7 +251,7 @@ abstract class GeoConverters {
|
|||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
static enum SphereToDbObjectConverter implements Converter<Sphere, DBObject> {
|
public static enum SphereToDbObjectConverter implements Converter<Sphere, DBObject> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
@@ -310,7 +281,7 @@ abstract class GeoConverters {
|
|||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
@ReadingConverter
|
@ReadingConverter
|
||||||
static enum DbObjectToSphereConverter implements Converter<DBObject, Sphere> {
|
public static enum DbObjectToSphereConverter implements Converter<DBObject, Sphere> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
@@ -351,7 +322,7 @@ abstract class GeoConverters {
|
|||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
static enum PolygonToDbObjectConverter implements Converter<Polygon, DBObject> {
|
public static enum PolygonToDbObjectConverter implements Converter<Polygon, DBObject> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
@@ -386,7 +357,7 @@ abstract class GeoConverters {
|
|||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
@ReadingConverter
|
@ReadingConverter
|
||||||
static enum DbObjectToPolygonConverter implements Converter<DBObject, Polygon> {
|
public static enum DbObjectToPolygonConverter implements Converter<DBObject, Polygon> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
@@ -421,7 +392,7 @@ abstract class GeoConverters {
|
|||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
static enum GeoCommandToDbObjectConverter implements Converter<GeoCommand, DBObject> {
|
public static enum GeoCommandToDbObjectConverter implements Converter<GeoCommand, DBObject> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
@@ -430,7 +401,6 @@ abstract class GeoConverters {
|
|||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public DBObject convert(GeoCommand source) {
|
public DBObject convert(GeoCommand source) {
|
||||||
|
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
@@ -441,10 +411,6 @@ abstract class GeoConverters {
|
|||||||
|
|
||||||
Shape shape = source.getShape();
|
Shape shape = source.getShape();
|
||||||
|
|
||||||
if (shape instanceof GeoJson) {
|
|
||||||
return GeoJsonToDbObjectConverter.INSTANCE.convert((GeoJson) shape);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shape instanceof Box) {
|
if (shape instanceof Box) {
|
||||||
|
|
||||||
argument.add(toList(((Box) shape).getFirst()));
|
argument.add(toList(((Box) shape).getFirst()));
|
||||||
@@ -476,377 +442,7 @@ abstract class GeoConverters {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
static enum GeoJsonToDbObjectConverter implements Converter<GeoJson, DBObject> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DBObject convert(GeoJson source) {
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBObject dbo = new BasicDBObject("type", source.getType());
|
|
||||||
|
|
||||||
if (source instanceof GeoJsonGeometryCollection) {
|
|
||||||
|
|
||||||
BasicDBList dbl = new BasicDBList();
|
|
||||||
|
|
||||||
for (GeoJson geometry : ((GeoJsonGeometryCollection) source).getCoordinates()) {
|
|
||||||
dbl.add(convert(geometry));
|
|
||||||
}
|
|
||||||
|
|
||||||
dbo.put("geometries", dbl);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
dbo.put("coordinates", convertIfNecessarry(source.getCoordinates()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbo;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object convertIfNecessarry(Object candidate) {
|
|
||||||
|
|
||||||
if (candidate instanceof GeoJson) {
|
|
||||||
return convertIfNecessarry(((GeoJson) candidate).getCoordinates());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (candidate instanceof Iterable) {
|
|
||||||
|
|
||||||
BasicDBList dbl = new BasicDBList();
|
|
||||||
|
|
||||||
for (Object element : (Iterable) candidate) {
|
|
||||||
dbl.add(convertIfNecessarry(element));
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (candidate instanceof Point) {
|
|
||||||
return toList((Point) candidate);
|
|
||||||
}
|
|
||||||
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
static enum GeoJsonPointToDbObjectConverter implements Converter<GeoJsonPoint, DBObject> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DBObject convert(GeoJsonPoint source) {
|
|
||||||
return GeoJsonToDbObjectConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
static enum GeoJsonPolygonToDbObjectConverter implements Converter<GeoJsonPolygon, DBObject> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DBObject convert(GeoJsonPolygon source) {
|
|
||||||
return GeoJsonToDbObjectConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
static enum DbObjectToGeoJsonPointConverter implements Converter<DBObject, GeoJsonPoint> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public GeoJsonPoint convert(DBObject source) {
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "Point"),
|
|
||||||
String.format("Cannot convert type '%s' to Point.", source.get("type")));
|
|
||||||
|
|
||||||
List<Number> dbl = (List<Number>) source.get("coordinates");
|
|
||||||
return new GeoJsonPoint(dbl.get(0).doubleValue(), dbl.get(1).doubleValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
static enum DbObjectToGeoJsonPolygonConverter implements Converter<DBObject, GeoJsonPolygon> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public GeoJsonPolygon convert(DBObject source) {
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "Polygon"),
|
|
||||||
String.format("Cannot convert type '%s' to Polygon.", source.get("type")));
|
|
||||||
|
|
||||||
return toGeoJsonPolygon((BasicDBList) source.get("coordinates"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
static enum DbObjectToGeoJsonMultiPolygonConverter implements Converter<DBObject, GeoJsonMultiPolygon> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public GeoJsonMultiPolygon convert(DBObject source) {
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "MultiPolygon"),
|
|
||||||
String.format("Cannot convert type '%s' to MultiPolygon.", source.get("type")));
|
|
||||||
|
|
||||||
BasicDBList dbl = (BasicDBList) source.get("coordinates");
|
|
||||||
List<GeoJsonPolygon> polygones = new ArrayList<GeoJsonPolygon>();
|
|
||||||
|
|
||||||
for (Object polygon : dbl) {
|
|
||||||
polygones.add(toGeoJsonPolygon((BasicDBList) polygon));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GeoJsonMultiPolygon(polygones);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
static enum DbObjectToGeoJsonLineStringConverter implements Converter<DBObject, GeoJsonLineString> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public GeoJsonLineString convert(DBObject source) {
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "LineString"),
|
|
||||||
String.format("Cannot convert type '%s' to LineString.", source.get("type")));
|
|
||||||
|
|
||||||
BasicDBList cords = (BasicDBList) source.get("coordinates");
|
|
||||||
|
|
||||||
return new GeoJsonLineString(toListOfPoint(cords));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
static enum DbObjectToGeoJsonMultiPointConverter implements Converter<DBObject, GeoJsonMultiPoint> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public GeoJsonMultiPoint convert(DBObject source) {
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "MultiPoint"),
|
|
||||||
String.format("Cannot convert type '%s' to MultiPoint.", source.get("type")));
|
|
||||||
|
|
||||||
BasicDBList cords = (BasicDBList) source.get("coordinates");
|
|
||||||
|
|
||||||
return new GeoJsonMultiPoint(toListOfPoint(cords));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
static enum DbObjectToGeoJsonMultiLineStringConverter implements Converter<DBObject, GeoJsonMultiLineString> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public GeoJsonMultiLineString convert(DBObject source) {
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "MultiLineString"),
|
|
||||||
String.format("Cannot convert type '%s' to MultiLineString.", source.get("type")));
|
|
||||||
|
|
||||||
List<GeoJsonLineString> lines = new ArrayList<GeoJsonLineString>();
|
|
||||||
BasicDBList cords = (BasicDBList) source.get("coordinates");
|
|
||||||
|
|
||||||
for (Object line : cords) {
|
|
||||||
lines.add(new GeoJsonLineString(toListOfPoint((BasicDBList) line)));
|
|
||||||
}
|
|
||||||
return new GeoJsonMultiLineString(lines);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
static enum DbObjectToGeoJsonGeometryCollectionConverter implements Converter<DBObject, GeoJsonGeometryCollection> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@Override
|
|
||||||
public GeoJsonGeometryCollection convert(DBObject source) {
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "GeometryCollection"),
|
|
||||||
String.format("Cannot convert type '%s' to GeometryCollection.", source.get("type")));
|
|
||||||
|
|
||||||
List<GeoJson<?>> geometries = new ArrayList<GeoJson<?>>();
|
|
||||||
for (Object o : (List) source.get("geometries")) {
|
|
||||||
geometries.add(convertGeometries((DBObject) o));
|
|
||||||
}
|
|
||||||
return new GeoJsonGeometryCollection(geometries);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static GeoJson<?> convertGeometries(DBObject source) {
|
|
||||||
|
|
||||||
Object type = source.get("type");
|
|
||||||
if (ObjectUtils.nullSafeEquals(type, "Point")) {
|
|
||||||
return DbObjectToGeoJsonPointConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ObjectUtils.nullSafeEquals(type, "MultiPoint")) {
|
|
||||||
return DbObjectToGeoJsonMultiPointConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ObjectUtils.nullSafeEquals(type, "LineString")) {
|
|
||||||
return DbObjectToGeoJsonLineStringConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ObjectUtils.nullSafeEquals(type, "MultiLineString")) {
|
|
||||||
return DbObjectToGeoJsonMultiLineStringConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ObjectUtils.nullSafeEquals(type, "Polygon")) {
|
|
||||||
return DbObjectToGeoJsonPolygonConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
if (ObjectUtils.nullSafeEquals(type, "MultiPolygon")) {
|
|
||||||
return DbObjectToGeoJsonMultiPolygonConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException(String.format("Cannot convert unknown GeoJson type %s", type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static List<Double> toList(Point point) {
|
static List<Double> toList(Point point) {
|
||||||
return Arrays.asList(point.getX(), point.getY());
|
return Arrays.asList(point.getX(), point.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a coordinate pairs nested in in {@link BasicDBList} into {@link GeoJsonPoint}s.
|
|
||||||
*
|
|
||||||
* @param listOfCoordinatePairs
|
|
||||||
* @return
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
static List<Point> toListOfPoint(BasicDBList listOfCoordinatePairs) {
|
|
||||||
|
|
||||||
List<Point> points = new ArrayList<Point>();
|
|
||||||
|
|
||||||
for (Object point : listOfCoordinatePairs) {
|
|
||||||
|
|
||||||
Assert.isInstanceOf(List.class, point);
|
|
||||||
|
|
||||||
List<Number> coordinatesList = (List<Number>) point;
|
|
||||||
|
|
||||||
points.add(new GeoJsonPoint(coordinatesList.get(0).doubleValue(), coordinatesList.get(1).doubleValue()));
|
|
||||||
}
|
|
||||||
return points;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a coordinate pairs nested in in {@link BasicDBList} into {@link GeoJsonPolygon}.
|
|
||||||
*
|
|
||||||
* @param dbList
|
|
||||||
* @return
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
static GeoJsonPolygon toGeoJsonPolygon(BasicDBList dbList) {
|
|
||||||
return new GeoJsonPolygon(toListOfPoint((BasicDBList) dbList.get(0)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2016 by the original author(s).
|
* Copyright 2011-2014 by the original author(s).
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,30 +20,27 @@ import java.util.Arrays;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.core.CollectionFactory;
|
|
||||||
import org.springframework.core.convert.ConversionException;
|
import org.springframework.core.convert.ConversionException;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.support.DefaultConversionService;
|
import org.springframework.core.convert.support.DefaultConversionService;
|
||||||
|
import org.springframework.data.convert.CollectionFactory;
|
||||||
import org.springframework.data.convert.EntityInstantiator;
|
import org.springframework.data.convert.EntityInstantiator;
|
||||||
import org.springframework.data.convert.TypeMapper;
|
import org.springframework.data.convert.TypeMapper;
|
||||||
import org.springframework.data.mapping.Association;
|
import org.springframework.data.mapping.Association;
|
||||||
import org.springframework.data.mapping.AssociationHandler;
|
import org.springframework.data.mapping.AssociationHandler;
|
||||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
|
||||||
import org.springframework.data.mapping.PreferredConstructor.Parameter;
|
import org.springframework.data.mapping.PreferredConstructor.Parameter;
|
||||||
import org.springframework.data.mapping.PropertyHandler;
|
import org.springframework.data.mapping.PropertyHandler;
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
import org.springframework.data.mapping.model.BeanWrapper;
|
||||||
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
|
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
|
||||||
import org.springframework.data.mapping.model.MappingException;
|
import org.springframework.data.mapping.model.MappingException;
|
||||||
import org.springframework.data.mapping.model.ParameterValueProvider;
|
import org.springframework.data.mapping.model.ParameterValueProvider;
|
||||||
@@ -55,9 +52,6 @@ import org.springframework.data.mapping.model.SpELExpressionParameterValueProvid
|
|||||||
import org.springframework.data.mongodb.MongoDbFactory;
|
import org.springframework.data.mongodb.MongoDbFactory;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||||
import org.springframework.data.mongodb.core.mapping.event.AfterConvertEvent;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.event.AfterLoadEvent;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent;
|
|
||||||
import org.springframework.data.util.ClassTypeInformation;
|
import org.springframework.data.util.ClassTypeInformation;
|
||||||
import org.springframework.data.util.TypeInformation;
|
import org.springframework.data.util.TypeInformation;
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
@@ -79,7 +73,6 @@ import com.mongodb.DBRef;
|
|||||||
* @author Patrik Wasik
|
* @author Patrik Wasik
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Jordi Llach
|
|
||||||
*/
|
*/
|
||||||
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware, ValueResolver {
|
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware, ValueResolver {
|
||||||
|
|
||||||
@@ -256,22 +249,19 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
|
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
|
||||||
S instance = instantiator.createInstance(entity, provider);
|
S instance = instantiator.createInstance(entity, provider);
|
||||||
|
|
||||||
final PersistentPropertyAccessor accessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(instance),
|
final BeanWrapper<S> wrapper = BeanWrapper.create(instance, conversionService);
|
||||||
conversionService);
|
|
||||||
|
|
||||||
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||||
final S result = instance;
|
final S result = wrapper.getBean();
|
||||||
|
|
||||||
// make sure id property is set before all other properties
|
// make sure id property is set before all other properties
|
||||||
Object idValue = null;
|
Object idValue = null;
|
||||||
|
|
||||||
if (idProperty != null) {
|
if (idProperty != null) {
|
||||||
idValue = getValueInternal(idProperty, dbo, evaluator, path);
|
idValue = getValueInternal(idProperty, dbo, evaluator, path);
|
||||||
accessor.setProperty(idProperty, idValue);
|
wrapper.setProperty(idProperty, idValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
final ObjectPath currentPath = path.push(result, entity,
|
final ObjectPath currentPath = path.push(result, entity, idValue);
|
||||||
idValue != null ? dbo.get(idProperty.getFieldName()) : null);
|
|
||||||
|
|
||||||
// Set properties not already set in the constructor
|
// Set properties not already set in the constructor
|
||||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||||
@@ -286,7 +276,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
accessor.setProperty(prop, getValueInternal(prop, dbo, evaluator, currentPath));
|
wrapper.setProperty(prop, getValueInternal(prop, dbo, evaluator, currentPath));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -297,7 +287,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
final MongoPersistentProperty property = association.getInverse();
|
final MongoPersistentProperty property = association.getInverse();
|
||||||
Object value = dbo.get(property.getFieldName());
|
Object value = dbo.get(property.getFieldName());
|
||||||
|
|
||||||
if (value == null || entity.isConstructorArgument(property)) {
|
if (value == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +298,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
DbRefResolverCallback callback = new DefaultDbRefResolverCallback(dbo, currentPath, evaluator,
|
DbRefResolverCallback callback = new DefaultDbRefResolverCallback(dbo, currentPath, evaluator,
|
||||||
MappingMongoConverter.this);
|
MappingMongoConverter.this);
|
||||||
|
|
||||||
accessor.setProperty(property, dbRefResolver.resolveDbRef(property, dbref, callback, handler));
|
wrapper.setProperty(property, dbRefResolver.resolveDbRef(property, dbref, callback, handler));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -408,13 +398,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
throw new MappingException("No mapping metadata found for entity of type " + obj.getClass().getName());
|
throw new MappingException("No mapping metadata found for entity of type " + obj.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
final PersistentPropertyAccessor accessor = entity.getPropertyAccessor(obj);
|
final BeanWrapper<Object> wrapper = BeanWrapper.create(obj, conversionService);
|
||||||
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||||
|
|
||||||
if (!dbo.containsField("_id") && null != idProperty) {
|
if (!dbo.containsField("_id") && null != idProperty) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Object id = accessor.getProperty(idProperty);
|
Object id = wrapper.getProperty(idProperty, Object.class);
|
||||||
dbo.put("_id", idMapper.convertId(id));
|
dbo.put("_id", idMapper.convertId(id));
|
||||||
} catch (ConversionException ignored) {}
|
} catch (ConversionException ignored) {}
|
||||||
}
|
}
|
||||||
@@ -427,7 +417,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object propertyObj = accessor.getProperty(prop);
|
Object propertyObj = wrapper.getProperty(prop);
|
||||||
|
|
||||||
if (null != propertyObj) {
|
if (null != propertyObj) {
|
||||||
|
|
||||||
@@ -441,12 +431,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
});
|
});
|
||||||
|
|
||||||
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
|
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
|
||||||
|
|
||||||
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
||||||
|
|
||||||
MongoPersistentProperty inverseProp = association.getInverse();
|
MongoPersistentProperty inverseProp = association.getInverse();
|
||||||
Object propertyObj = accessor.getProperty(inverseProp);
|
Class<?> type = inverseProp.getType();
|
||||||
|
Object propertyObj = wrapper.getProperty(inverseProp, type);
|
||||||
if (null != propertyObj) {
|
if (null != propertyObj) {
|
||||||
writePropertyInternal(propertyObj, dbo, inverseProp);
|
writePropertyInternal(propertyObj, dbo, inverseProp);
|
||||||
}
|
}
|
||||||
@@ -516,7 +504,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
Object existingValue = accessor.get(prop);
|
Object existingValue = accessor.get(prop);
|
||||||
BasicDBObject propDbObj = existingValue instanceof BasicDBObject ? (BasicDBObject) existingValue
|
BasicDBObject propDbObj = existingValue instanceof BasicDBObject ? (BasicDBObject) existingValue
|
||||||
: new BasicDBObject();
|
: new BasicDBObject();
|
||||||
addCustomTypeKeyIfNecessary(ClassTypeInformation.from(prop.getRawType()), obj, propDbObj);
|
addCustomTypeKeyIfNecessary(type, obj, propDbObj);
|
||||||
|
|
||||||
MongoPersistentEntity<?> entity = isSubtype(prop.getType(), obj.getClass())
|
MongoPersistentEntity<?> entity = isSubtype(prop.getType(), obj.getClass())
|
||||||
? mappingContext.getPersistentEntity(obj.getClass()) : mappingContext.getPersistentEntity(type);
|
? mappingContext.getPersistentEntity(obj.getClass()) : mappingContext.getPersistentEntity(type);
|
||||||
@@ -747,7 +735,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
/**
|
/**
|
||||||
* Adds custom type information to the given {@link DBObject} if necessary. That is if the value is not the same as
|
* 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.
|
* the one given. This is usually the case if you store a subtype of the actual declared type of the property.
|
||||||
*
|
*
|
||||||
* @param type
|
* @param type
|
||||||
* @param value must not be {@literal null}.
|
* @param value must not be {@literal null}.
|
||||||
* @param dbObject must not be {@literal null}.
|
* @param dbObject must not be {@literal null}.
|
||||||
@@ -854,8 +842,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
if (target.getClass().equals(idProperty.getType())) {
|
if (target.getClass().equals(idProperty.getType())) {
|
||||||
id = target;
|
id = target;
|
||||||
} else {
|
} else {
|
||||||
PersistentPropertyAccessor accessor = targetEntity.getPropertyAccessor(target);
|
BeanWrapper<Object> wrapper = BeanWrapper.create(target, conversionService);
|
||||||
id = accessor.getProperty(idProperty);
|
id = wrapper.getProperty(idProperty, Object.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null == id) {
|
if (null == id) {
|
||||||
@@ -884,7 +872,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
* @param path must not be {@literal null}.
|
* @param path must not be {@literal null}.
|
||||||
* @return the converted {@link Collection} or array, will never be {@literal null}.
|
* @return the converted {@link Collection} or array, will never be {@literal null}.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
|
||||||
private Object readCollectionOrArray(TypeInformation<?> targetType, BasicDBList sourceValue, ObjectPath path) {
|
private Object readCollectionOrArray(TypeInformation<?> targetType, BasicDBList sourceValue, ObjectPath path) {
|
||||||
|
|
||||||
Assert.notNull(targetType, "Target type must not be null!");
|
Assert.notNull(targetType, "Target type must not be null!");
|
||||||
@@ -903,16 +890,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>()
|
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>()
|
||||||
: CollectionFactory.createCollection(collectionType, rawComponentType, sourceValue.size());
|
: CollectionFactory.createCollection(collectionType, rawComponentType, sourceValue.size());
|
||||||
|
|
||||||
if (!DBRef.class.equals(rawComponentType) && isCollectionOfDbRefWhereBulkFetchIsPossible(sourceValue)) {
|
for (int i = 0; i < sourceValue.size(); i++) {
|
||||||
return bulkReadAndConvertDBRefs((List<DBRef>) (List) (sourceValue), componentType, path, rawComponentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Object dbObjItem : sourceValue) {
|
Object dbObjItem = sourceValue.get(i);
|
||||||
|
|
||||||
if (dbObjItem instanceof DBRef) {
|
if (dbObjItem instanceof DBRef) {
|
||||||
|
items.add(
|
||||||
items.add(DBRef.class.equals(rawComponentType) ? dbObjItem
|
DBRef.class.equals(rawComponentType) ? dbObjItem : read(componentType, readRef((DBRef) dbObjItem), path));
|
||||||
: readAndConvertDBRef((DBRef) dbObjItem, componentType, path, rawComponentType));
|
|
||||||
} else if (dbObjItem instanceof DBObject) {
|
} else if (dbObjItem instanceof DBObject) {
|
||||||
items.add(read(componentType, (DBObject) dbObjItem, path));
|
items.add(read(componentType, (DBObject) dbObjItem, path));
|
||||||
} else {
|
} else {
|
||||||
@@ -948,11 +932,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
Map<Object, Object> map = CollectionFactory.createMap(mapType, rawKeyType, dbObject.keySet().size());
|
Map<Object, Object> map = CollectionFactory.createMap(mapType, rawKeyType, dbObject.keySet().size());
|
||||||
Map<String, Object> sourceMap = dbObject.toMap();
|
Map<String, Object> sourceMap = dbObject.toMap();
|
||||||
|
|
||||||
if (!DBRef.class.equals(rawValueType) && isCollectionOfDbRefWhereBulkFetchIsPossible(sourceMap.values())) {
|
|
||||||
bulkReadAndConvertDBRefMapIntoTarget(valueType, rawValueType, sourceMap, map);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Entry<String, Object> entry : sourceMap.entrySet()) {
|
for (Entry<String, Object> entry : sourceMap.entrySet()) {
|
||||||
if (typeMapper.isTypeKey(entry.getKey())) {
|
if (typeMapper.isTypeKey(entry.getKey())) {
|
||||||
continue;
|
continue;
|
||||||
@@ -969,8 +948,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
if (value instanceof DBObject) {
|
if (value instanceof DBObject) {
|
||||||
map.put(key, read(valueType, (DBObject) value, path));
|
map.put(key, read(valueType, (DBObject) value, path));
|
||||||
} else if (value instanceof DBRef) {
|
} else if (value instanceof DBRef) {
|
||||||
map.put(key, DBRef.class.equals(rawValueType) ? value
|
map.put(key, DBRef.class.equals(rawValueType) ? value : read(valueType, readRef((DBRef) value)));
|
||||||
: readAndConvertDBRef((DBRef) value, valueType, ObjectPath.ROOT, rawValueType));
|
|
||||||
} else {
|
} else {
|
||||||
Class<?> valueClass = valueType == null ? null : valueType.getType();
|
Class<?> valueClass = valueType == null ? null : valueType.getType();
|
||||||
map.put(key, getPotentiallyConvertedSimpleRead(value, valueClass));
|
map.put(key, getPotentiallyConvertedSimpleRead(value, valueClass));
|
||||||
@@ -1008,31 +986,20 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (obj instanceof DBObject) {
|
if (obj instanceof DBObject) {
|
||||||
|
|
||||||
DBObject newValueDbo = new BasicDBObject();
|
DBObject newValueDbo = new BasicDBObject();
|
||||||
|
|
||||||
for (String vk : ((DBObject) obj).keySet()) {
|
for (String vk : ((DBObject) obj).keySet()) {
|
||||||
|
|
||||||
Object o = ((DBObject) obj).get(vk);
|
Object o = ((DBObject) obj).get(vk);
|
||||||
newValueDbo.put(vk, convertToMongoType(o, typeHint));
|
newValueDbo.put(vk, convertToMongoType(o, typeHint));
|
||||||
}
|
}
|
||||||
|
|
||||||
return newValueDbo;
|
return newValueDbo;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj instanceof Map) {
|
if (obj instanceof Map) {
|
||||||
|
DBObject result = new BasicDBObject();
|
||||||
Map<Object, Object> converted = new LinkedHashMap<Object, Object>();
|
for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) obj).entrySet()) {
|
||||||
|
result.put(entry.getKey().toString(), convertToMongoType(entry.getValue(), typeHint));
|
||||||
for (Entry<Object, Object> entry : ((Map<Object, Object>) obj).entrySet()) {
|
|
||||||
|
|
||||||
TypeInformation<? extends Object> valueTypeHint = typeHint != null && typeHint.getMapValueType() != null
|
|
||||||
? typeHint.getMapValueType() : typeHint;
|
|
||||||
|
|
||||||
converted.put(convertToMongoType(entry.getKey()), convertToMongoType(entry.getValue(), valueTypeHint));
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
return new BasicDBObject(converted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj.getClass().isArray()) {
|
if (obj.getClass().isArray()) {
|
||||||
@@ -1223,71 +1190,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
return (T) dbref;
|
return (T) dbref;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object object = dbref == null ? null : path.getPathItem(dbref.getId(), dbref.getCollectionName());
|
Object object = dbref == null ? null : path.getPathItem(dbref.getId(), dbref.getRef());
|
||||||
return (T) (object != null ? object : readAndConvertDBRef(dbref, type, path, rawType));
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> T readAndConvertDBRef(DBRef dbref, TypeInformation<?> type, ObjectPath path, final Class<?> rawType) {
|
if (object != null) {
|
||||||
|
return (T) object;
|
||||||
List<T> result = bulkReadAndConvertDBRefs(Collections.singletonList(dbref), type, path, rawType);
|
|
||||||
return CollectionUtils.isEmpty(result) ? null : result.iterator().next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
private void bulkReadAndConvertDBRefMapIntoTarget(TypeInformation<?> valueType, Class<?> rawValueType,
|
|
||||||
Map<String, Object> sourceMap, Map<Object, Object> targetMap) {
|
|
||||||
|
|
||||||
LinkedHashMap<String, Object> referenceMap = new LinkedHashMap<String, Object>(sourceMap);
|
|
||||||
List<Object> convertedObjects = bulkReadAndConvertDBRefs((List<DBRef>) new ArrayList(referenceMap.values()),
|
|
||||||
valueType, ObjectPath.ROOT, rawValueType);
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
for (String key : referenceMap.keySet()) {
|
|
||||||
targetMap.put(key, convertedObjects.get(index));
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private <T> List<T> bulkReadAndConvertDBRefs(List<DBRef> dbrefs, TypeInformation<?> type, ObjectPath path,
|
|
||||||
final Class<?> rawType) {
|
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(dbrefs)) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DBObject> referencedRawDocuments = dbrefs.size() == 1
|
return (T) (object != null ? object : read(type, readRef(dbref), path));
|
||||||
? Collections.singletonList(readRef(dbrefs.iterator().next())) : bulkReadRefs(dbrefs);
|
|
||||||
String collectionName = dbrefs.iterator().next().getCollectionName();
|
|
||||||
|
|
||||||
List<T> targeList = new ArrayList<T>(dbrefs.size());
|
|
||||||
|
|
||||||
for (DBObject document : referencedRawDocuments) {
|
|
||||||
|
|
||||||
if (document != null) {
|
|
||||||
maybeEmitEvent(new AfterLoadEvent<T>(document, (Class<T>) rawType, collectionName));
|
|
||||||
}
|
|
||||||
|
|
||||||
final T target = (T) read(type, document, path);
|
|
||||||
targeList.add(target);
|
|
||||||
|
|
||||||
if (target != null) {
|
|
||||||
maybeEmitEvent(new AfterConvertEvent<T>(document, target, collectionName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return targeList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void maybeEmitEvent(MongoMappingEvent<?> event) {
|
|
||||||
|
|
||||||
if (canPublishEvent()) {
|
|
||||||
this.applicationContext.publishEvent(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canPublishEvent() {
|
|
||||||
return this.applicationContext != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1297,46 +1206,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
DBObject readRef(DBRef ref) {
|
DBObject readRef(DBRef ref) {
|
||||||
return dbRefResolver.fetch(ref);
|
return ref.fetch();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs a bulk fetch operation for the given {@link DBRef}s.
|
|
||||||
*
|
|
||||||
* @param references must not be {@literal null}.
|
|
||||||
* @return never {@literal null}.
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
List<DBObject> bulkReadRefs(List<DBRef> references) {
|
|
||||||
return dbRefResolver.bulkFetch(references);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the given {@link Iterable} contains {@link DBRef} instances all pointing to the same collection.
|
|
||||||
*
|
|
||||||
* @param source must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static boolean isCollectionOfDbRefWhereBulkFetchIsPossible(Iterable<Object> source) {
|
|
||||||
|
|
||||||
Assert.notNull(source, "Iterable of DBRefs must not be null!");
|
|
||||||
|
|
||||||
Set<String> collectionsFound = new HashSet<String>();
|
|
||||||
|
|
||||||
for (Object dbObjItem : source) {
|
|
||||||
|
|
||||||
if (!(dbObjItem instanceof DBRef)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
collectionsFound.add(((DBRef) dbObjItem).getCollectionName());
|
|
||||||
|
|
||||||
if (collectionsFound.size() > 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2016 the original author or authors.
|
* Copyright 2011-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -19,30 +19,16 @@ import java.math.BigDecimal;
|
|||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Currency;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
import org.bson.types.Code;
|
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.springframework.core.convert.ConversionFailedException;
|
import org.springframework.core.convert.ConversionFailedException;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.ConditionalConverter;
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.core.convert.converter.ConverterFactory;
|
|
||||||
import org.springframework.data.convert.ReadingConverter;
|
import org.springframework.data.convert.ReadingConverter;
|
||||||
import org.springframework.data.convert.WritingConverter;
|
import org.springframework.data.convert.WritingConverter;
|
||||||
import org.springframework.data.mongodb.core.query.Term;
|
import org.springframework.data.mongodb.core.query.Term;
|
||||||
import org.springframework.data.mongodb.core.script.NamedMongoScript;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.NumberUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.BasicDBObjectBuilder;
|
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,36 +45,6 @@ abstract class MongoConverters {
|
|||||||
*/
|
*/
|
||||||
private MongoConverters() {}
|
private MongoConverters() {}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the converters to be registered.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @since 1.9
|
|
||||||
*/
|
|
||||||
public static Collection<Object> getConvertersToRegister() {
|
|
||||||
|
|
||||||
List<Object> converters = new ArrayList<Object>();
|
|
||||||
|
|
||||||
converters.add(BigDecimalToStringConverter.INSTANCE);
|
|
||||||
converters.add(StringToBigDecimalConverter.INSTANCE);
|
|
||||||
converters.add(BigIntegerToStringConverter.INSTANCE);
|
|
||||||
converters.add(StringToBigIntegerConverter.INSTANCE);
|
|
||||||
converters.add(URLToStringConverter.INSTANCE);
|
|
||||||
converters.add(StringToURLConverter.INSTANCE);
|
|
||||||
converters.add(DBObjectToStringConverter.INSTANCE);
|
|
||||||
converters.add(TermToStringConverter.INSTANCE);
|
|
||||||
converters.add(NamedMongoScriptToDBObjectConverter.INSTANCE);
|
|
||||||
converters.add(DBObjectToNamedMongoScriptCoverter.INSTANCE);
|
|
||||||
converters.add(CurrencyToStringConverter.INSTANCE);
|
|
||||||
converters.add(StringToCurrencyConverter.INSTANCE);
|
|
||||||
converters.add(AtomicIntegerToIntegerConverter.INSTANCE);
|
|
||||||
converters.add(AtomicLongToLongConverter.INSTANCE);
|
|
||||||
converters.add(LongToAtomicLongConverter.INSTANCE);
|
|
||||||
converters.add(IntegerToAtomicIntegerConverter.INSTANCE);
|
|
||||||
|
|
||||||
return converters;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple singleton to convert {@link ObjectId}s to their {@link String} representation.
|
* Simple singleton to convert {@link ObjectId}s to their {@link String} representation.
|
||||||
*
|
*
|
||||||
@@ -222,223 +178,4 @@ abstract class MongoConverters {
|
|||||||
return source == null ? null : source.getFormatted();
|
return source == null ? null : source.getFormatted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public static enum DBObjectToNamedMongoScriptCoverter implements Converter<DBObject, NamedMongoScript> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NamedMongoScript convert(DBObject source) {
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String id = source.get("_id").toString();
|
|
||||||
Object rawValue = source.get("value");
|
|
||||||
|
|
||||||
return new NamedMongoScript(id, ((Code) rawValue).getCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public static enum NamedMongoScriptToDBObjectConverter implements Converter<NamedMongoScript, DBObject> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DBObject convert(NamedMongoScript source) {
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return new BasicDBObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicDBObjectBuilder builder = new BasicDBObjectBuilder();
|
|
||||||
|
|
||||||
builder.append("_id", source.getName());
|
|
||||||
builder.append("value", new Code(source.getCode()));
|
|
||||||
|
|
||||||
return builder.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link Converter} implementation converting {@link Currency} into its ISO 4217 {@link String} representation.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.9
|
|
||||||
*/
|
|
||||||
@WritingConverter
|
|
||||||
public static enum CurrencyToStringConverter implements Converter<Currency, String> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String convert(Currency source) {
|
|
||||||
return source == null ? null : source.getCurrencyCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link Converter} implementation converting ISO 4217 {@link String} into {@link Currency}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.9
|
|
||||||
*/
|
|
||||||
@ReadingConverter
|
|
||||||
public static enum StringToCurrencyConverter implements Converter<String, Currency> {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Currency convert(String source) {
|
|
||||||
return StringUtils.hasText(source) ? Currency.getInstance(source) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ConverterFactory} implementation using {@link NumberUtils} for number conversion and parsing. Additionally
|
|
||||||
* deals with {@link AtomicInteger} and {@link AtomicLong} by calling {@code get()} before performing the actual
|
|
||||||
* conversion.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.9
|
|
||||||
*/
|
|
||||||
@WritingConverter
|
|
||||||
public static enum NumberToNumberConverterFactory implements ConverterFactory<Number, Number>,ConditionalConverter {
|
|
||||||
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.ConverterFactory#getConverter(java.lang.Class)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T extends Number> Converter<Number, T> getConverter(Class<T> targetType) {
|
|
||||||
return new NumberToNumberConverter<T>(targetType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.ConditionalConverter#matches(org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
|
||||||
return !sourceType.equals(targetType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final static class NumberToNumberConverter<T extends Number> implements Converter<Number, T> {
|
|
||||||
|
|
||||||
private final Class<T> targetType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link NumberToNumberConverter} for the given target type.
|
|
||||||
*
|
|
||||||
* @param targetType must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public NumberToNumberConverter(Class<T> targetType) {
|
|
||||||
|
|
||||||
Assert.notNull(targetType, "Target type must not be null!");
|
|
||||||
|
|
||||||
this.targetType = targetType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public T convert(Number source) {
|
|
||||||
|
|
||||||
if (source instanceof AtomicInteger) {
|
|
||||||
return NumberUtils.convertNumberToTargetClass(((AtomicInteger) source).get(), this.targetType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (source instanceof AtomicLong) {
|
|
||||||
return NumberUtils.convertNumberToTargetClass(((AtomicLong) source).get(), this.targetType);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NumberUtils.convertNumberToTargetClass(source, this.targetType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ConverterFactory} implementation converting {@link AtomicLong} into {@link Long}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
@WritingConverter
|
|
||||||
public static enum AtomicLongToLongConverter implements Converter<AtomicLong, Long> {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long convert(AtomicLong source) {
|
|
||||||
return NumberUtils.convertNumberToTargetClass(source, Long.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ConverterFactory} implementation converting {@link AtomicInteger} into {@link Integer}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
@WritingConverter
|
|
||||||
public static enum AtomicIntegerToIntegerConverter implements Converter<AtomicInteger, Integer> {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer convert(AtomicInteger source) {
|
|
||||||
return NumberUtils.convertNumberToTargetClass(source, Integer.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ConverterFactory} implementation converting {@link Long} into {@link AtomicLong}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
@ReadingConverter
|
|
||||||
public static enum LongToAtomicLongConverter implements Converter<Long, AtomicLong> {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AtomicLong convert(Long source) {
|
|
||||||
return source != null ? new AtomicLong(source) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ConverterFactory} implementation converting {@link Integer} into {@link AtomicInteger}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
@ReadingConverter
|
|
||||||
public static enum IntegerToAtomicIntegerConverter implements Converter<Integer, AtomicInteger> {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AtomicInteger convert(Integer source) {
|
|
||||||
return source != null ? new AtomicInteger(source) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,275 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015-2016 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.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Stack;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.springframework.data.domain.Example;
|
|
||||||
import org.springframework.data.domain.ExampleMatcher.NullHandler;
|
|
||||||
import org.springframework.data.domain.ExampleMatcher.PropertyValueTransformer;
|
|
||||||
import org.springframework.data.domain.ExampleMatcher.StringMatcher;
|
|
||||||
import org.springframework.data.mapping.PropertyHandler;
|
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
|
||||||
import org.springframework.data.mongodb.core.query.MongoRegexCreator;
|
|
||||||
import org.springframework.data.mongodb.core.query.SerializationUtils;
|
|
||||||
import org.springframework.data.repository.core.support.ExampleMatcherAccessor;
|
|
||||||
import org.springframework.data.repository.query.parser.Part.Type;
|
|
||||||
import org.springframework.data.util.TypeInformation;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public class MongoExampleMapper {
|
|
||||||
|
|
||||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
|
||||||
private final MongoConverter converter;
|
|
||||||
private final Map<StringMatcher, Type> stringMatcherPartMapping = new HashMap<StringMatcher, Type>();
|
|
||||||
|
|
||||||
public MongoExampleMapper(MongoConverter converter) {
|
|
||||||
|
|
||||||
this.converter = converter;
|
|
||||||
this.mappingContext = converter.getMappingContext();
|
|
||||||
|
|
||||||
stringMatcherPartMapping.put(StringMatcher.EXACT, Type.SIMPLE_PROPERTY);
|
|
||||||
stringMatcherPartMapping.put(StringMatcher.CONTAINING, Type.CONTAINING);
|
|
||||||
stringMatcherPartMapping.put(StringMatcher.STARTING, Type.STARTING_WITH);
|
|
||||||
stringMatcherPartMapping.put(StringMatcher.ENDING, Type.ENDING_WITH);
|
|
||||||
stringMatcherPartMapping.put(StringMatcher.REGEX, Type.REGEX);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the given {@link Example} as {@link DBObject} holding matching values extracted from
|
|
||||||
* {@link Example#getProbe()}.
|
|
||||||
*
|
|
||||||
* @param example must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public DBObject getMappedExample(Example<?> example) {
|
|
||||||
|
|
||||||
Assert.notNull(example, "Example must not be null!");
|
|
||||||
|
|
||||||
return getMappedExample(example, mappingContext.getPersistentEntity(example.getProbeType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the given {@link Example} as {@link DBObject} holding matching values extracted from
|
|
||||||
* {@link Example#getProbe()}.
|
|
||||||
*
|
|
||||||
* @param example must not be {@literal null}.
|
|
||||||
* @param entity must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public DBObject getMappedExample(Example<?> example, MongoPersistentEntity<?> entity) {
|
|
||||||
|
|
||||||
Assert.notNull(example, "Example must not be null!");
|
|
||||||
Assert.notNull(entity, "MongoPersistentEntity must not be null!");
|
|
||||||
|
|
||||||
DBObject reference = (DBObject) converter.convertToMongoType(example.getProbe());
|
|
||||||
|
|
||||||
if (entity.hasIdProperty() && entity.getIdentifierAccessor(example.getProbe()).getIdentifier() == null) {
|
|
||||||
reference.removeField(entity.getIdProperty().getFieldName());
|
|
||||||
}
|
|
||||||
|
|
||||||
ExampleMatcherAccessor matcherAccessor = new ExampleMatcherAccessor(example.getMatcher());
|
|
||||||
|
|
||||||
applyPropertySpecs("", reference, example.getProbeType(), matcherAccessor);
|
|
||||||
|
|
||||||
DBObject flattened = ObjectUtils.nullSafeEquals(NullHandler.INCLUDE, matcherAccessor.getNullHandler()) ? reference
|
|
||||||
: new BasicDBObject(SerializationUtils.flattenMap(reference));
|
|
||||||
DBObject result = example.getMatcher().isAllMatching() ? flattened : orConcatenate(flattened);
|
|
||||||
|
|
||||||
this.converter.getTypeMapper().writeTypeRestrictions(result, getTypesToMatch(example));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static DBObject orConcatenate(DBObject source) {
|
|
||||||
|
|
||||||
List<DBObject> foo = new ArrayList<DBObject>(source.keySet().size());
|
|
||||||
|
|
||||||
for (String key : source.keySet()) {
|
|
||||||
foo.add(new BasicDBObject(key, source.get(key)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BasicDBObject("$or", foo);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<Class<?>> getTypesToMatch(Example<?> example) {
|
|
||||||
|
|
||||||
Set<Class<?>> types = new HashSet<Class<?>>();
|
|
||||||
|
|
||||||
for (TypeInformation<?> reference : mappingContext.getManagedTypes()) {
|
|
||||||
if (example.getProbeType().isAssignableFrom(reference.getType())) {
|
|
||||||
types.add(reference.getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return types;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getMappedPropertyPath(String path, Class<?> probeType) {
|
|
||||||
|
|
||||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(probeType);
|
|
||||||
|
|
||||||
Iterator<String> parts = Arrays.asList(path.split("\\.")).iterator();
|
|
||||||
|
|
||||||
final Stack<MongoPersistentProperty> stack = new Stack<MongoPersistentProperty>();
|
|
||||||
|
|
||||||
List<String> resultParts = new ArrayList<String>();
|
|
||||||
|
|
||||||
while (parts.hasNext()) {
|
|
||||||
|
|
||||||
final String part = parts.next();
|
|
||||||
MongoPersistentProperty prop = entity.getPersistentProperty(part);
|
|
||||||
|
|
||||||
if (prop == null) {
|
|
||||||
|
|
||||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doWithPersistentProperty(MongoPersistentProperty property) {
|
|
||||||
|
|
||||||
if (property.getFieldName().equals(part)) {
|
|
||||||
stack.push(property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (stack.isEmpty()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
prop = stack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
resultParts.add(prop.getName());
|
|
||||||
|
|
||||||
if (prop.isEntity() && mappingContext.hasPersistentEntityFor(prop.getActualType())) {
|
|
||||||
entity = mappingContext.getPersistentEntity(prop.getActualType());
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return StringUtils.collectionToDelimitedString(resultParts, ".");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyPropertySpecs(String path, DBObject source, Class<?> probeType,
|
|
||||||
ExampleMatcherAccessor exampleSpecAccessor) {
|
|
||||||
|
|
||||||
if (!(source instanceof BasicDBObject)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator<Map.Entry<String, Object>> iter = ((BasicDBObject) source).entrySet().iterator();
|
|
||||||
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
|
|
||||||
Map.Entry<String, Object> entry = iter.next();
|
|
||||||
String propertyPath = StringUtils.hasText(path) ? path + "." + entry.getKey() : entry.getKey();
|
|
||||||
String mappedPropertyPath = getMappedPropertyPath(propertyPath, probeType);
|
|
||||||
|
|
||||||
if (isEmptyIdProperty(entry)) {
|
|
||||||
iter.remove();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exampleSpecAccessor.isIgnoredPath(propertyPath) || exampleSpecAccessor.isIgnoredPath(mappedPropertyPath)) {
|
|
||||||
iter.remove();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringMatcher stringMatcher = exampleSpecAccessor.getDefaultStringMatcher();
|
|
||||||
Object value = entry.getValue();
|
|
||||||
boolean ignoreCase = exampleSpecAccessor.isIgnoreCaseEnabled();
|
|
||||||
|
|
||||||
if (exampleSpecAccessor.hasPropertySpecifiers()) {
|
|
||||||
|
|
||||||
mappedPropertyPath = exampleSpecAccessor.hasPropertySpecifier(propertyPath) ? propertyPath
|
|
||||||
: getMappedPropertyPath(propertyPath, probeType);
|
|
||||||
|
|
||||||
stringMatcher = exampleSpecAccessor.getStringMatcherForPath(mappedPropertyPath);
|
|
||||||
ignoreCase = exampleSpecAccessor.isIgnoreCaseForPath(mappedPropertyPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: should a PropertySpecifier outrule the later on string matching?
|
|
||||||
if (exampleSpecAccessor.hasPropertySpecifier(mappedPropertyPath)) {
|
|
||||||
|
|
||||||
PropertyValueTransformer valueTransformer = exampleSpecAccessor.getValueTransformerForPath(mappedPropertyPath);
|
|
||||||
value = valueTransformer.convert(value);
|
|
||||||
if (value == null) {
|
|
||||||
iter.remove();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry.setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.getValue() instanceof String) {
|
|
||||||
applyStringMatcher(entry, stringMatcher, ignoreCase);
|
|
||||||
} else if (entry.getValue() instanceof BasicDBObject) {
|
|
||||||
applyPropertySpecs(propertyPath, (BasicDBObject) entry.getValue(), probeType, exampleSpecAccessor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isEmptyIdProperty(Entry<String, Object> entry) {
|
|
||||||
return entry.getKey().equals("_id") && entry.getValue() == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyStringMatcher(Map.Entry<String, Object> entry, StringMatcher stringMatcher, boolean ignoreCase) {
|
|
||||||
|
|
||||||
BasicDBObject dbo = new BasicDBObject();
|
|
||||||
|
|
||||||
if (ObjectUtils.nullSafeEquals(StringMatcher.DEFAULT, stringMatcher)) {
|
|
||||||
|
|
||||||
if (ignoreCase) {
|
|
||||||
dbo.put("$regex", Pattern.quote((String) entry.getValue()));
|
|
||||||
entry.setValue(dbo);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
Type type = stringMatcherPartMapping.get(stringMatcher);
|
|
||||||
String expression = MongoRegexCreator.INSTANCE.toRegularExpression((String) entry.getValue(), type);
|
|
||||||
dbo.put("$regex", expression);
|
|
||||||
entry.setValue(dbo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ignoreCase) {
|
|
||||||
dbo.put("$options", "i");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2016 the original author or authors.
|
* Copyright 2011-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -27,12 +27,10 @@ import org.bson.types.ObjectId;
|
|||||||
import org.springframework.core.convert.ConversionException;
|
import org.springframework.core.convert.ConversionException;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.data.domain.Example;
|
|
||||||
import org.springframework.data.mapping.Association;
|
import org.springframework.data.mapping.Association;
|
||||||
import org.springframework.data.mapping.PersistentEntity;
|
import org.springframework.data.mapping.PersistentEntity;
|
||||||
import org.springframework.data.mapping.PropertyPath;
|
import org.springframework.data.mapping.PropertyPath;
|
||||||
import org.springframework.data.mapping.PropertyReferenceException;
|
import org.springframework.data.mapping.PropertyReferenceException;
|
||||||
import org.springframework.data.mapping.context.InvalidPersistentPropertyPath;
|
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
import org.springframework.data.mapping.context.PersistentPropertyPath;
|
import org.springframework.data.mapping.context.PersistentPropertyPath;
|
||||||
import org.springframework.data.mapping.model.MappingException;
|
import org.springframework.data.mapping.model.MappingException;
|
||||||
@@ -72,7 +70,6 @@ public class QueryMapper {
|
|||||||
private final ConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
private final MongoConverter converter;
|
private final MongoConverter converter;
|
||||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||||
private final MongoExampleMapper exampleMapper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link QueryMapper} with the given {@link MongoConverter}.
|
* Creates a new {@link QueryMapper} with the given {@link MongoConverter}.
|
||||||
@@ -86,7 +83,6 @@ public class QueryMapper {
|
|||||||
this.conversionService = converter.getConversionService();
|
this.conversionService = converter.getConversionService();
|
||||||
this.converter = converter;
|
this.converter = converter;
|
||||||
this.mappingContext = converter.getMappingContext();
|
this.mappingContext = converter.getMappingContext();
|
||||||
this.exampleMapper = new MongoExampleMapper(converter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,20 +119,10 @@ public class QueryMapper {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
Field field = createPropertyField(entity, key, mappingContext);
|
||||||
|
Entry<String, Object> entry = getMappedObjectForField(field, query.get(key));
|
||||||
|
|
||||||
Field field = createPropertyField(entity, key, mappingContext);
|
result.put(entry.getKey(), entry.getValue());
|
||||||
Entry<String, Object> entry = getMappedObjectForField(field, query.get(key));
|
|
||||||
result.put(entry.getKey(), entry.getValue());
|
|
||||||
} catch (InvalidPersistentPropertyPath invalidPathException) {
|
|
||||||
|
|
||||||
// in case the object has not already been mapped
|
|
||||||
if (!(query.get(key) instanceof DBObject)) {
|
|
||||||
throw invalidPathException;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.put(key, query.get(key));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -240,7 +226,7 @@ public class QueryMapper {
|
|||||||
protected DBObject getMappedKeyword(Keyword keyword, MongoPersistentEntity<?> entity) {
|
protected DBObject getMappedKeyword(Keyword keyword, MongoPersistentEntity<?> entity) {
|
||||||
|
|
||||||
// $or/$nor
|
// $or/$nor
|
||||||
if (keyword.isOrOrNor() || (keyword.hasIterableValue() && !keyword.isGeometry())) {
|
if (keyword.isOrOrNor() || keyword.hasIterableValue()) {
|
||||||
|
|
||||||
Iterable<?> conditions = keyword.getValue();
|
Iterable<?> conditions = keyword.getValue();
|
||||||
BasicDBList newConditions = new BasicDBList();
|
BasicDBList newConditions = new BasicDBList();
|
||||||
@@ -253,10 +239,6 @@ public class QueryMapper {
|
|||||||
return new BasicDBObject(keyword.getKey(), newConditions);
|
return new BasicDBObject(keyword.getKey(), newConditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyword.isSample()) {
|
|
||||||
return exampleMapper.getMappedExample(keyword.<Example<?>> getValue(), entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BasicDBObject(keyword.getKey(), convertSimpleOrDBObject(keyword.getValue(), entity));
|
return new BasicDBObject(keyword.getKey(), convertSimpleOrDBObject(keyword.getValue(), entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,7 +394,7 @@ public class QueryMapper {
|
|||||||
if (source instanceof DBRef) {
|
if (source instanceof DBRef) {
|
||||||
|
|
||||||
DBRef ref = (DBRef) source;
|
DBRef ref = (DBRef) source;
|
||||||
return new DBRef(ref.getCollectionName(), convertId(ref.getId()));
|
return new DBRef(ref.getDB(), ref.getRef(), convertId(ref.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source instanceof Iterable) {
|
if (source instanceof Iterable) {
|
||||||
@@ -574,26 +556,6 @@ public class QueryMapper {
|
|||||||
return key.matches(N_OR_PATTERN);
|
return key.matches(N_OR_PATTERN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the current keyword is the {@code $geometry} keyword.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public boolean isGeometry() {
|
|
||||||
return "$geometry".equalsIgnoreCase(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns wheter the current keyword indicates a sample object.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public boolean isSample() {
|
|
||||||
return "$sample".equalsIgnoreCase(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasIterableValue() {
|
public boolean hasIterableValue() {
|
||||||
return value instanceof Iterable;
|
return value instanceof Iterable;
|
||||||
}
|
}
|
||||||
@@ -895,7 +857,7 @@ public class QueryMapper {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
|
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
|
||||||
return new PositionParameterRetainingPropertyKeyConverter(name);
|
return PropertyToFieldNameConverter.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -909,28 +871,6 @@ public class QueryMapper {
|
|||||||
return new AssociationConverter(getAssociation());
|
return new AssociationConverter(getAssociation());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
static class PositionParameterRetainingPropertyKeyConverter implements Converter<MongoPersistentProperty, String> {
|
|
||||||
|
|
||||||
private final KeyMapper keyMapper;
|
|
||||||
|
|
||||||
public PositionParameterRetainingPropertyKeyConverter(String rawKey) {
|
|
||||||
this.keyMapper = new KeyMapper(rawKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String convert(MongoPersistentProperty source) {
|
|
||||||
return keyMapper.mapPropertyName(source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#getTypeHint()
|
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#getTypeHint()
|
||||||
@@ -951,61 +891,6 @@ public class QueryMapper {
|
|||||||
|
|
||||||
return NESTED_DOCUMENT;
|
return NESTED_DOCUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
static class KeyMapper {
|
|
||||||
|
|
||||||
private final Iterator<String> iterator;
|
|
||||||
|
|
||||||
public KeyMapper(String key) {
|
|
||||||
|
|
||||||
this.iterator = Arrays.asList(key.split("\\.")).iterator();
|
|
||||||
this.iterator.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps the property name while retaining potential positional operator {@literal $}.
|
|
||||||
*
|
|
||||||
* @param property
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected String mapPropertyName(MongoPersistentProperty property) {
|
|
||||||
|
|
||||||
StringBuilder mappedName = new StringBuilder(PropertyToFieldNameConverter.INSTANCE.convert(property));
|
|
||||||
boolean inspect = iterator.hasNext();
|
|
||||||
|
|
||||||
while (inspect) {
|
|
||||||
|
|
||||||
String partial = iterator.next();
|
|
||||||
boolean isPositional = (isPositionalParameter(partial) && (property.isMap() || property.isCollectionLike()));
|
|
||||||
|
|
||||||
if (isPositional) {
|
|
||||||
mappedName.append(".").append(partial);
|
|
||||||
}
|
|
||||||
|
|
||||||
inspect = isPositional && iterator.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
return mappedName.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isPositionalParameter(String partial) {
|
|
||||||
|
|
||||||
if ("$".equals(partial)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Long.valueOf(partial);
|
|
||||||
return true;
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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 static org.springframework.data.mongodb.util.MongoClientVersion.*;
|
|
||||||
import static org.springframework.util.ReflectionUtils.*;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import org.springframework.data.mongodb.MongoDbFactory;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import com.mongodb.DBCollection;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import com.mongodb.DBRef;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link ReflectiveDBRefResolver} provides reflective access to {@link DBRef} API that is not consistently available
|
|
||||||
* for various driver versions.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
class ReflectiveDBRefResolver {
|
|
||||||
|
|
||||||
private static final Method FETCH_METHOD;
|
|
||||||
|
|
||||||
static {
|
|
||||||
FETCH_METHOD = findMethod(DBRef.class, "fetch");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the object referenced from the database either be directly calling {@link DBRef#fetch()} or
|
|
||||||
* {@link DBCollection#findOne(Object)}.
|
|
||||||
*
|
|
||||||
* @param db can be {@literal null} when using MongoDB Java driver in version 2.x.
|
|
||||||
* @param ref must not be {@literal null}.
|
|
||||||
* @return the document that this references.
|
|
||||||
*/
|
|
||||||
public static DBObject fetch(MongoDbFactory factory, DBRef ref) {
|
|
||||||
|
|
||||||
Assert.notNull(ref, "DBRef to fetch must not be null!");
|
|
||||||
|
|
||||||
if (isMongo3Driver()) {
|
|
||||||
|
|
||||||
Assert.notNull(factory, "DbFactory to fetch DB from must not be null!");
|
|
||||||
return factory.getDb().getCollection(ref.getCollectionName()).findOne(ref.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
return (DBObject) invokeMethod(FETCH_METHOD, ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core.convert;
|
package org.springframework.data.mongodb.core.convert;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
@@ -22,11 +24,13 @@ import org.springframework.data.mapping.Association;
|
|||||||
import org.springframework.data.mapping.context.MappingContext;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty.PropertyToFieldNameConverter;
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
import org.springframework.data.mongodb.core.query.Query;
|
||||||
import org.springframework.data.mongodb.core.query.Update.Modifier;
|
import org.springframework.data.mongodb.core.query.Update.Modifier;
|
||||||
import org.springframework.data.mongodb.core.query.Update.Modifiers;
|
import org.springframework.data.mongodb.core.query.Update.Modifiers;
|
||||||
import org.springframework.data.util.ClassTypeInformation;
|
import org.springframework.data.util.ClassTypeInformation;
|
||||||
import org.springframework.data.util.TypeInformation;
|
import org.springframework.data.util.TypeInformation;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
@@ -138,18 +142,19 @@ public class UpdateMapper extends QueryMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TypeInformation<?> getTypeHintForEntity(Object source, MongoPersistentEntity<?> entity) {
|
private TypeInformation<?> getTypeHintForEntity(Object source, MongoPersistentEntity<?> entity) {
|
||||||
|
return processTypeHintForNestedDocuments(source, entity.getTypeInformation());
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeInformation<?> processTypeHintForNestedDocuments(Object source, TypeInformation<?> info) {
|
||||||
|
|
||||||
TypeInformation<?> info = entity.getTypeInformation();
|
|
||||||
Class<?> type = info.getActualType().getType();
|
Class<?> type = info.getActualType().getType();
|
||||||
|
if (type.isInterface() || java.lang.reflect.Modifier.isAbstract(type.getModifiers())) {
|
||||||
if (source == null || type.isInterface() || java.lang.reflect.Modifier.isAbstract(type.getModifiers())) {
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!type.equals(source.getClass())) {
|
if (!type.equals(source.getClass())) {
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NESTED_DOCUMENT;
|
return NESTED_DOCUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +214,7 @@ public class UpdateMapper extends QueryMapper {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
|
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
|
||||||
return new PositionParameterRetainingPropertyKeyConverter(key);
|
return new UpdatePropertyConverter(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -221,6 +226,99 @@ public class UpdateMapper extends QueryMapper {
|
|||||||
return new UpdateAssociationConverter(getAssociation(), key);
|
return new UpdateAssociationConverter(getAssociation(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special mapper handling positional parameter {@literal $} within property names.
|
||||||
|
*
|
||||||
|
* @author Christoph Strobl
|
||||||
|
* @since 1.7
|
||||||
|
*/
|
||||||
|
private static class UpdateKeyMapper {
|
||||||
|
|
||||||
|
private final Iterator<String> iterator;
|
||||||
|
|
||||||
|
protected UpdateKeyMapper(String rawKey) {
|
||||||
|
|
||||||
|
Assert.hasText(rawKey, "Key must not be null or empty!");
|
||||||
|
|
||||||
|
this.iterator = Arrays.asList(rawKey.split("\\.")).iterator();
|
||||||
|
this.iterator.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps the property name while retaining potential positional operator {@literal $}.
|
||||||
|
*
|
||||||
|
* @param property
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected String mapPropertyName(MongoPersistentProperty property) {
|
||||||
|
|
||||||
|
String mappedName = PropertyToFieldNameConverter.INSTANCE.convert(property);
|
||||||
|
|
||||||
|
boolean inspect = iterator.hasNext();
|
||||||
|
while (inspect) {
|
||||||
|
|
||||||
|
String partial = iterator.next();
|
||||||
|
|
||||||
|
boolean isPositional = isPositionalParameter(partial);
|
||||||
|
if (isPositional) {
|
||||||
|
mappedName += "." + partial;
|
||||||
|
}
|
||||||
|
|
||||||
|
inspect = isPositional && iterator.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mappedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isPositionalParameter(String partial) {
|
||||||
|
|
||||||
|
if (partial.equals("$")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Long.valueOf(partial);
|
||||||
|
return true;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special {@link Converter} for {@link MongoPersistentProperty} instances that will concatenate the {@literal $}
|
||||||
|
* contained in the source update key.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @author Christoph Strobl
|
||||||
|
*/
|
||||||
|
private static class UpdatePropertyConverter implements Converter<MongoPersistentProperty, String> {
|
||||||
|
|
||||||
|
private final UpdateKeyMapper mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link UpdatePropertyConverter} with the given update key.
|
||||||
|
*
|
||||||
|
* @param updateKey must not be {@literal null} or empty.
|
||||||
|
*/
|
||||||
|
public UpdatePropertyConverter(String updateKey) {
|
||||||
|
|
||||||
|
Assert.hasText(updateKey, "Update key must not be null or empty!");
|
||||||
|
|
||||||
|
this.mapper = new UpdateKeyMapper(updateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String convert(MongoPersistentProperty property) {
|
||||||
|
return mapper.mapPropertyName(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Converter} retaining positional parameter {@literal $} for {@link Association}s.
|
* {@link Converter} retaining positional parameter {@literal $} for {@link Association}s.
|
||||||
*
|
*
|
||||||
@@ -228,7 +326,7 @@ public class UpdateMapper extends QueryMapper {
|
|||||||
*/
|
*/
|
||||||
protected static class UpdateAssociationConverter extends AssociationConverter {
|
protected static class UpdateAssociationConverter extends AssociationConverter {
|
||||||
|
|
||||||
private final KeyMapper mapper;
|
private final UpdateKeyMapper mapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link AssociationConverter} for the given {@link Association}.
|
* Creates a new {@link AssociationConverter} for the given {@link Association}.
|
||||||
@@ -238,7 +336,7 @@ public class UpdateMapper extends QueryMapper {
|
|||||||
public UpdateAssociationConverter(Association<MongoPersistentProperty> association, String key) {
|
public UpdateAssociationConverter(Association<MongoPersistentProperty> association, String key) {
|
||||||
|
|
||||||
super(association);
|
super(association);
|
||||||
this.mapper = new KeyMapper(key);
|
this.mapper = new UpdateKeyMapper(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.geo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface definition for structures defined in GeoJSON ({@link http://geojson.org/}) format.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public interface GeoJson<T extends Iterable<?>> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* String value representing the type of the {@link GeoJson} object.
|
|
||||||
*
|
|
||||||
* @return will never be {@literal null}.
|
|
||||||
* @see http://geojson.org/geojson-spec.html#geojson-objects
|
|
||||||
*/
|
|
||||||
String getType();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The value of the coordinates member is always an {@link Iterable}. The structure for the elements within is
|
|
||||||
* determined by {@link #getType()} of geometry.
|
|
||||||
*
|
|
||||||
* @return will never be {@literal null}.
|
|
||||||
* @see http://geojson.org/geojson-spec.html#geometry-objects
|
|
||||||
*/
|
|
||||||
T getCoordinates();
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.geo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a {@link GeoJsonGeometryCollection} that consists of a {@link List} of {@link GeoJson} objects.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
* @see http://geojson.org/geojson-spec.html#geometry-collection
|
|
||||||
*/
|
|
||||||
public class GeoJsonGeometryCollection implements GeoJson<Iterable<GeoJson<?>>> {
|
|
||||||
|
|
||||||
private static final String TYPE = "GeometryCollection";
|
|
||||||
|
|
||||||
private final List<GeoJson<?>> geometries = new ArrayList<GeoJson<?>>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link GeoJsonGeometryCollection} for the given {@link GeoJson} instances.
|
|
||||||
*
|
|
||||||
* @param geometries
|
|
||||||
*/
|
|
||||||
public GeoJsonGeometryCollection(List<GeoJson<?>> geometries) {
|
|
||||||
|
|
||||||
Assert.notNull(geometries, "Geometries must not be null!");
|
|
||||||
|
|
||||||
this.geometries.addAll(geometries);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJson#getType()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJson#getCoordinates()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Iterable<GeoJson<?>> getCoordinates() {
|
|
||||||
return Collections.unmodifiableList(this.geometries);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.lang.Object#hashCode()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return ObjectUtils.nullSafeHashCode(this.geometries);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.lang.Object#equals(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(obj instanceof GeoJsonGeometryCollection)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GeoJsonGeometryCollection other = (GeoJsonGeometryCollection) obj;
|
|
||||||
|
|
||||||
return ObjectUtils.nullSafeEquals(this.geometries, other.geometries);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.geo;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.data.geo.Point;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link GeoJsonLineString} is defined as list of at least 2 {@link Point}s.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
* @see http://geojson.org/geojson-spec.html#linestring
|
|
||||||
*/
|
|
||||||
public class GeoJsonLineString extends GeoJsonMultiPoint {
|
|
||||||
|
|
||||||
private static final String TYPE = "LineString";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link GeoJsonLineString} for the given {@link Point}s.
|
|
||||||
*
|
|
||||||
* @param points must not be {@literal null} and have at least 2 entries.
|
|
||||||
*/
|
|
||||||
public GeoJsonLineString(List<Point> points) {
|
|
||||||
super(points);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link GeoJsonLineString} for the given {@link Point}s.
|
|
||||||
*
|
|
||||||
* @param first must not be {@literal null}
|
|
||||||
* @param second must not be {@literal null}
|
|
||||||
* @param others can be {@literal null}
|
|
||||||
*/
|
|
||||||
public GeoJsonLineString(Point first, Point second, Point... others) {
|
|
||||||
super(first, second, others);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJsonMultiPoint#getType()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return TYPE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,341 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.geo;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.data.geo.Point;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
|
||||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
|
||||||
import com.fasterxml.jackson.databind.Module;
|
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Jackson {@link Module} to register custom {@link JsonSerializer} and {@link JsonDeserializer}s for GeoJSON types.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Oliver Gierke
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public class GeoJsonModule extends SimpleModule {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -8723016728655643720L;
|
|
||||||
|
|
||||||
public GeoJsonModule() {
|
|
||||||
|
|
||||||
addDeserializer(GeoJsonPoint.class, new GeoJsonPointDeserializer());
|
|
||||||
addDeserializer(GeoJsonMultiPoint.class, new GeoJsonMultiPointDeserializer());
|
|
||||||
addDeserializer(GeoJsonLineString.class, new GeoJsonLineStringDeserializer());
|
|
||||||
addDeserializer(GeoJsonMultiLineString.class, new GeoJsonMultiLineStringDeserializer());
|
|
||||||
addDeserializer(GeoJsonPolygon.class, new GeoJsonPolygonDeserializer());
|
|
||||||
addDeserializer(GeoJsonMultiPolygon.class, new GeoJsonMultiPolygonDeserializer());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
private static abstract class GeoJsonDeserializer<T extends GeoJson<?>> extends JsonDeserializer<T> {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see com.fasterxml.jackson.databind.JsonDeserializer#deserialize(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.DeserializationContext)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
|
|
||||||
|
|
||||||
JsonNode node = jp.readValueAsTree();
|
|
||||||
JsonNode coordinates = node.get("coordinates");
|
|
||||||
|
|
||||||
if (coordinates != null && coordinates.isArray()) {
|
|
||||||
return doDeserialize((ArrayNode) coordinates);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform the actual deserialization given the {@literal coordinates} as {@link ArrayNode}.
|
|
||||||
*
|
|
||||||
* @param coordinates
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected abstract T doDeserialize(ArrayNode coordinates);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link GeoJsonPoint} representation of given {@link ArrayNode} assuming {@code node.[0]} represents
|
|
||||||
* {@literal x - coordinate} and {@code node.[1]} is {@literal y}.
|
|
||||||
*
|
|
||||||
* @param node can be {@literal null}.
|
|
||||||
* @return {@literal null} when given a {@code null} value.
|
|
||||||
*/
|
|
||||||
protected GeoJsonPoint toGeoJsonPoint(ArrayNode node) {
|
|
||||||
|
|
||||||
if (node == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GeoJsonPoint(node.get(0).asDouble(), node.get(1).asDouble());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link Point} representation of given {@link ArrayNode} assuming {@code node.[0]} represents
|
|
||||||
* {@literal x - coordinate} and {@code node.[1]} is {@literal y}.
|
|
||||||
*
|
|
||||||
* @param node can be {@literal null}.
|
|
||||||
* @return {@literal null} when given a {@code null} value.
|
|
||||||
*/
|
|
||||||
protected Point toPoint(ArrayNode node) {
|
|
||||||
|
|
||||||
if (node == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Point(node.get(0).asDouble(), node.get(1).asDouble());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the points nested within given {@link ArrayNode}.
|
|
||||||
*
|
|
||||||
* @param node can be {@literal null}.
|
|
||||||
* @return {@literal empty list} when given a {@code null} value.
|
|
||||||
*/
|
|
||||||
protected List<Point> toPoints(ArrayNode node) {
|
|
||||||
|
|
||||||
if (node == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Point> points = new ArrayList<Point>(node.size());
|
|
||||||
|
|
||||||
for (JsonNode coordinatePair : node) {
|
|
||||||
if (coordinatePair.isArray()) {
|
|
||||||
points.add(toPoint((ArrayNode) coordinatePair));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return points;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected GeoJsonLineString toLineString(ArrayNode node) {
|
|
||||||
return new GeoJsonLineString(toPoints((ArrayNode) node));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link JsonDeserializer} converting GeoJSON representation of {@literal Point}.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <code>
|
|
||||||
* { "type": "Point", "coordinates": [10.0, 20.0] }
|
|
||||||
* </code>
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
private static class GeoJsonPointDeserializer extends GeoJsonDeserializer<GeoJsonPoint> {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJsonModule.GeoJsonDeserializer#doDeserialize(com.fasterxml.jackson.databind.node.ArrayNode)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected GeoJsonPoint doDeserialize(ArrayNode coordinates) {
|
|
||||||
return toGeoJsonPoint(coordinates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link JsonDeserializer} converting GeoJSON representation of {@literal LineString}.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <code>
|
|
||||||
* {
|
|
||||||
* "type": "LineString",
|
|
||||||
* "coordinates": [
|
|
||||||
* [10.0, 20.0], [30.0, 40.0], [50.0, 60.0]
|
|
||||||
* ]
|
|
||||||
* }
|
|
||||||
* </code>
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
private static class GeoJsonLineStringDeserializer extends GeoJsonDeserializer<GeoJsonLineString> {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJsonModule.GeoJsonDeserializer#doDeserialize(com.fasterxml.jackson.databind.node.ArrayNode)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected GeoJsonLineString doDeserialize(ArrayNode coordinates) {
|
|
||||||
return new GeoJsonLineString(toPoints(coordinates));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link JsonDeserializer} converting GeoJSON representation of {@literal MultiPoint}.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <code>
|
|
||||||
* {
|
|
||||||
* "type": "MultiPoint",
|
|
||||||
* "coordinates": [
|
|
||||||
* [10.0, 20.0], [30.0, 40.0], [50.0, 60.0]
|
|
||||||
* ]
|
|
||||||
* }
|
|
||||||
* </code>
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
private static class GeoJsonMultiPointDeserializer extends GeoJsonDeserializer<GeoJsonMultiPoint> {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJsonModule.GeoJsonDeserializer#doDeserialize(com.fasterxml.jackson.databind.node.ArrayNode)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected GeoJsonMultiPoint doDeserialize(ArrayNode coordinates) {
|
|
||||||
return new GeoJsonMultiPoint(toPoints(coordinates));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link JsonDeserializer} converting GeoJSON representation of {@literal MultiLineString}.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <code>
|
|
||||||
* {
|
|
||||||
* "type": "MultiLineString",
|
|
||||||
* "coordinates": [
|
|
||||||
* [ [10.0, 20.0], [30.0, 40.0] ],
|
|
||||||
* [ [50.0, 60.0] , [70.0, 80.0] ]
|
|
||||||
* ]
|
|
||||||
* }
|
|
||||||
* </code>
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
private static class GeoJsonMultiLineStringDeserializer extends GeoJsonDeserializer<GeoJsonMultiLineString> {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJsonModule.GeoJsonDeserializer#doDeserialize(com.fasterxml.jackson.databind.node.ArrayNode)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected GeoJsonMultiLineString doDeserialize(ArrayNode coordinates) {
|
|
||||||
|
|
||||||
List<GeoJsonLineString> lines = new ArrayList<GeoJsonLineString>(coordinates.size());
|
|
||||||
|
|
||||||
for (JsonNode lineString : coordinates) {
|
|
||||||
if (lineString.isArray()) {
|
|
||||||
lines.add(toLineString((ArrayNode) lineString));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GeoJsonMultiLineString(lines);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link JsonDeserializer} converting GeoJSON representation of {@literal Polygon}.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <code>
|
|
||||||
* {
|
|
||||||
* "type": "Polygon",
|
|
||||||
* "coordinates": [
|
|
||||||
* [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]
|
|
||||||
* ]
|
|
||||||
* }
|
|
||||||
* </code>
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
private static class GeoJsonPolygonDeserializer extends GeoJsonDeserializer<GeoJsonPolygon> {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJsonModule.GeoJsonDeserializer#doDeserialize(com.fasterxml.jackson.databind.node.ArrayNode)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected GeoJsonPolygon doDeserialize(ArrayNode coordinates) {
|
|
||||||
|
|
||||||
for (JsonNode ring : coordinates) {
|
|
||||||
|
|
||||||
// currently we do not support holes in polygons.
|
|
||||||
return new GeoJsonPolygon(toPoints((ArrayNode) ring));
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link JsonDeserializer} converting GeoJSON representation of {@literal MultiPolygon}.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <code>
|
|
||||||
* {
|
|
||||||
* "type": "MultiPolygon",
|
|
||||||
* "coordinates": [
|
|
||||||
* [[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]],
|
|
||||||
* [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],
|
|
||||||
* [[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]]]
|
|
||||||
* ]
|
|
||||||
* }
|
|
||||||
* </code>
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
private static class GeoJsonMultiPolygonDeserializer extends GeoJsonDeserializer<GeoJsonMultiPolygon> {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJsonModule.GeoJsonDeserializer#doDeserialize(com.fasterxml.jackson.databind.node.ArrayNode)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected GeoJsonMultiPolygon doDeserialize(ArrayNode coordinates) {
|
|
||||||
|
|
||||||
List<GeoJsonPolygon> polygones = new ArrayList<GeoJsonPolygon>(coordinates.size());
|
|
||||||
|
|
||||||
for (JsonNode polygon : coordinates) {
|
|
||||||
for (JsonNode ring : (ArrayNode) polygon) {
|
|
||||||
polygones.add(new GeoJsonPolygon(toPoints((ArrayNode) ring)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GeoJsonMultiPolygon(polygones);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.geo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.data.geo.Point;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link GeoJsonMultiLineString} is defined as list of {@link GeoJsonLineString}s.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
* @see http://geojson.org/geojson-spec.html#multilinestring
|
|
||||||
*/
|
|
||||||
public class GeoJsonMultiLineString implements GeoJson<Iterable<GeoJsonLineString>> {
|
|
||||||
|
|
||||||
private static final String TYPE = "MultiLineString";
|
|
||||||
|
|
||||||
private List<GeoJsonLineString> coordinates = new ArrayList<GeoJsonLineString>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new {@link GeoJsonMultiLineString} for the given {@link Point}s.
|
|
||||||
*
|
|
||||||
* @param lines must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public GeoJsonMultiLineString(List<Point>... lines) {
|
|
||||||
|
|
||||||
Assert.notEmpty(lines, "Points for MultiLineString must not be null!");
|
|
||||||
|
|
||||||
for (List<Point> line : lines) {
|
|
||||||
this.coordinates.add(new GeoJsonLineString(line));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new {@link GeoJsonMultiLineString} for the given {@link GeoJsonLineString}s.
|
|
||||||
*
|
|
||||||
* @param lines must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public GeoJsonMultiLineString(List<GeoJsonLineString> lines) {
|
|
||||||
|
|
||||||
Assert.notNull(lines, "Lines for MultiLineString must not be null!");
|
|
||||||
|
|
||||||
this.coordinates.addAll(lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJson#getType()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJson#getCoordinates()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Iterable<GeoJsonLineString> getCoordinates() {
|
|
||||||
return Collections.unmodifiableList(this.coordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.lang.Object#hashCode()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return ObjectUtils.nullSafeHashCode(this.coordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.lang.Object#equals(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(obj instanceof GeoJsonMultiLineString)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ObjectUtils.nullSafeEquals(this.coordinates, ((GeoJsonMultiLineString) obj).coordinates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.geo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.data.geo.Point;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link GeoJsonMultiPoint} is defined as list of {@link Point}s.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
* @see http://geojson.org/geojson-spec.html#multipoint
|
|
||||||
*/
|
|
||||||
public class GeoJsonMultiPoint implements GeoJson<Iterable<Point>> {
|
|
||||||
|
|
||||||
private static final String TYPE = "MultiPoint";
|
|
||||||
|
|
||||||
private final List<Point> points;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link GeoJsonMultiPoint} for the given {@link Point}s.
|
|
||||||
*
|
|
||||||
* @param points points must not be {@literal null} and have at least 2 entries.
|
|
||||||
*/
|
|
||||||
public GeoJsonMultiPoint(List<Point> points) {
|
|
||||||
|
|
||||||
Assert.notNull(points, "Points must not be null.");
|
|
||||||
Assert.isTrue(points.size() >= 2, "Minimum of 2 Points required.");
|
|
||||||
|
|
||||||
this.points = new ArrayList<Point>(points);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link GeoJsonMultiPoint} for the given {@link Point}s.
|
|
||||||
*
|
|
||||||
* @param first must not be {@literal null}.
|
|
||||||
* @param second must not be {@literal null}.
|
|
||||||
* @param others must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public GeoJsonMultiPoint(Point first, Point second, Point... others) {
|
|
||||||
|
|
||||||
Assert.notNull(first, "First point must not be null!");
|
|
||||||
Assert.notNull(second, "Second point must not be null!");
|
|
||||||
Assert.notNull(others, "Additional points must not be null!");
|
|
||||||
|
|
||||||
this.points = new ArrayList<Point>();
|
|
||||||
this.points.add(first);
|
|
||||||
this.points.add(second);
|
|
||||||
this.points.addAll(Arrays.asList(others));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJson#getType()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJson#getCoordinates()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List<Point> getCoordinates() {
|
|
||||||
return Collections.unmodifiableList(this.points);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.lang.Object#hashCode()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return ObjectUtils.nullSafeHashCode(this.points);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.lang.Object#equals(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(obj instanceof GeoJsonMultiPoint)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ObjectUtils.nullSafeEquals(this.points, ((GeoJsonMultiPoint) obj).points);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.geo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link GeoJsonMultiPolygon} is defined as a list of {@link GeoJsonPolygon}s.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
public class GeoJsonMultiPolygon implements GeoJson<Iterable<GeoJsonPolygon>> {
|
|
||||||
|
|
||||||
private static final String TYPE = "MultiPolygon";
|
|
||||||
|
|
||||||
private List<GeoJsonPolygon> coordinates = new ArrayList<GeoJsonPolygon>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link GeoJsonMultiPolygon} for the given {@link GeoJsonPolygon}s.
|
|
||||||
*
|
|
||||||
* @param polygons must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public GeoJsonMultiPolygon(List<GeoJsonPolygon> polygons) {
|
|
||||||
|
|
||||||
Assert.notNull(polygons, "Polygons for MultiPolygon must not be null!");
|
|
||||||
|
|
||||||
this.coordinates.addAll(polygons);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJson#getType()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJson#getCoordinates()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List<GeoJsonPolygon> getCoordinates() {
|
|
||||||
return Collections.unmodifiableList(this.coordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.lang.Object#hashCode()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return ObjectUtils.nullSafeHashCode(this.coordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.lang.Object#equals(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(obj instanceof GeoJsonMultiPolygon)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ObjectUtils.nullSafeEquals(this.coordinates, ((GeoJsonMultiPolygon) obj).coordinates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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.geo;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.data.geo.Point;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link GeoJson} representation of {@link Point}.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
* @see http://geojson.org/geojson-spec.html#point
|
|
||||||
*/
|
|
||||||
public class GeoJsonPoint extends Point implements GeoJson<List<Double>> {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -8026303425147474002L;
|
|
||||||
|
|
||||||
private static final String TYPE = "Point";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates {@link GeoJsonPoint} for given coordinates.
|
|
||||||
*
|
|
||||||
* @param x
|
|
||||||
* @param y
|
|
||||||
*/
|
|
||||||
public GeoJsonPoint(double x, double y) {
|
|
||||||
super(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates {@link GeoJsonPoint} for given {@link Point}.
|
|
||||||
*
|
|
||||||
* @param point must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public GeoJsonPoint(Point point) {
|
|
||||||
super(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJson#getType()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJson#getCoordinates()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List<Double> getCoordinates() {
|
|
||||||
return Arrays.asList(Double.valueOf(getX()), Double.valueOf(getY()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015-2016 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.geo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.data.geo.Point;
|
|
||||||
import org.springframework.data.geo.Polygon;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link GeoJson} representation of {@link Polygon}. Unlike {@link Polygon} the {@link GeoJsonPolygon} requires a
|
|
||||||
* closed border. Which means that the first and last {@link Point} have to have same coordinate pairs.
|
|
||||||
*
|
|
||||||
* @author Christoph Strobl
|
|
||||||
* @since 1.7
|
|
||||||
* @see http://geojson.org/geojson-spec.html#polygon
|
|
||||||
*/
|
|
||||||
public class GeoJsonPolygon extends Polygon implements GeoJson<List<GeoJsonLineString>> {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 3936163018187247185L;
|
|
||||||
private static final String TYPE = "Polygon";
|
|
||||||
|
|
||||||
private List<GeoJsonLineString> coordinates = new ArrayList<GeoJsonLineString>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new {@link GeoJsonPolygon} from the given {@link Point}s.
|
|
||||||
*
|
|
||||||
* @param first must not be {@literal null}.
|
|
||||||
* @param second must not be {@literal null}.
|
|
||||||
* @param third must not be {@literal null}.
|
|
||||||
* @param fourth must not be {@literal null}.
|
|
||||||
* @param others can be {@literal null}.
|
|
||||||
*/
|
|
||||||
public GeoJsonPolygon(Point first, Point second, Point third, Point fourth, final Point... others) {
|
|
||||||
this(asList(first, second, third, fourth, others));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new {@link GeoJsonPolygon} from the given {@link Point}s.
|
|
||||||
*
|
|
||||||
* @param points must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
public GeoJsonPolygon(List<Point> points) {
|
|
||||||
|
|
||||||
super(points);
|
|
||||||
this.coordinates.add(new GeoJsonLineString(points));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link GeoJsonPolygon} with an inner ring defined be the given {@link Point}s.
|
|
||||||
*
|
|
||||||
* @param first must not be {@literal null}.
|
|
||||||
* @param second must not be {@literal null}.
|
|
||||||
* @param third must not be {@literal null}.
|
|
||||||
* @param fourth must not be {@literal null}.
|
|
||||||
* @param others can be {@literal null}.
|
|
||||||
* @return new {@link GeoJsonPolygon}.
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public GeoJsonPolygon withInnerRing(Point first, Point second, Point third, Point fourth, final Point... others) {
|
|
||||||
return withInnerRing(asList(first, second, third, fourth, others));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link GeoJsonPolygon} with an inner ring defined be the given {@link List} of {@link Point}s.
|
|
||||||
*
|
|
||||||
* @param points must not be {@literal null}.
|
|
||||||
* @return new {@link GeoJsonPolygon}.
|
|
||||||
*/
|
|
||||||
public GeoJsonPolygon withInnerRing(List<Point> points) {
|
|
||||||
return withInnerRing(new GeoJsonLineString(points));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link GeoJsonPolygon} with an inner ring defined be the given {@link GeoJsonLineString}.
|
|
||||||
*
|
|
||||||
* @param lineString must not be {@literal null}.
|
|
||||||
* @return new {@link GeoJsonPolygon}.
|
|
||||||
* @since 1.10
|
|
||||||
*/
|
|
||||||
public GeoJsonPolygon withInnerRing(GeoJsonLineString lineString) {
|
|
||||||
|
|
||||||
Assert.notNull(lineString, "LineString must not be null!");
|
|
||||||
|
|
||||||
Iterator<GeoJsonLineString> it = this.coordinates.iterator();
|
|
||||||
GeoJsonPolygon polygon = new GeoJsonPolygon(it.next().getCoordinates());
|
|
||||||
|
|
||||||
while (it.hasNext()) {
|
|
||||||
polygon.coordinates.add(it.next());
|
|
||||||
}
|
|
||||||
|
|
||||||
polygon.coordinates.add(lineString);
|
|
||||||
return polygon;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJson#getType()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.geo.GeoJson#getCoordinates()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List<GeoJsonLineString> getCoordinates() {
|
|
||||||
return Collections.unmodifiableList(this.coordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Point> asList(Point first, Point second, Point third, Point fourth, final Point... others) {
|
|
||||||
|
|
||||||
ArrayList<Point> result = new ArrayList<Point>(3 + others.length);
|
|
||||||
|
|
||||||
result.add(first);
|
|
||||||
result.add(second);
|
|
||||||
result.add(third);
|
|
||||||
result.add(fourth);
|
|
||||||
result.addAll(Arrays.asList(others));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2015 the original author or authors.
|
* Copyright 2011-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -28,7 +28,6 @@ import java.lang.annotation.Target;
|
|||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Philipp Schneider
|
* @author Philipp Schneider
|
||||||
* @author Johno Crawford
|
* @author Johno Crawford
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
@Target({ ElementType.TYPE })
|
@Target({ ElementType.TYPE })
|
||||||
@Documented
|
@Documented
|
||||||
@@ -106,9 +105,9 @@ public @interface CompoundIndex {
|
|||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* <code>
|
* <code>
|
||||||
* db.root.createIndex( { hybrid.h1: 1, hybrid.h2: 1 } , { name: "hybrid.compound_index" } )
|
* db.root.ensureIndex( { hybrid.h1: 1, hybrid.h2: 1 } , { name: "hybrid.compound_index" } )
|
||||||
* db.root.createIndex( { nested.n1: 1, nested.n2: 1 } , { name: "nested.compound_index" } )
|
* db.root.ensureIndex( { nested.n1: 1, nested.n2: 1 } , { name: "nested.compound_index" } )
|
||||||
* db.hybrid.createIndex( { h1: 1, h2: 1 } , { name: "compound_index" } )
|
* db.hybrid.ensureIndex( { h1: 1, h2: 1 } , { name: "compound_index" } )
|
||||||
* </code>
|
* </code>
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2016 the original author or authors.
|
* Copyright 2010-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,10 +26,8 @@ import java.lang.annotation.Target;
|
|||||||
* @author Jon Brisbin
|
* @author Jon Brisbin
|
||||||
* @author Laurent Canet
|
* @author Laurent Canet
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Mark Paluch
|
|
||||||
*/
|
*/
|
||||||
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
|
@Target(ElementType.FIELD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface GeoSpatialIndexed {
|
public @interface GeoSpatialIndexed {
|
||||||
|
|
||||||
@@ -64,9 +62,9 @@ public @interface GeoSpatialIndexed {
|
|||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* <code>
|
* <code>
|
||||||
* db.root.createIndex( { hybrid.h1: "2d" } , { name: "hybrid.index" } )
|
* db.root.ensureIndex( { hybrid.h1: "2d" } , { name: "hybrid.index" } )
|
||||||
* db.root.createIndex( { nested.n1: "2d" } , { name: "nested.index" } )
|
* db.root.ensureIndex( { nested.n1: "2d" } , { name: "nested.index" } )
|
||||||
* db.hybrid.createIndex( { h1: "2d" } , { name: "index" } )
|
* db.hybrid.ensureIndex( { h1: "2d" } , { name: "index" } )
|
||||||
* </code>
|
* </code>
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 the original author or authors.
|
* Copyright 2010-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,7 +17,6 @@ package org.springframework.data.mongodb.core.index;
|
|||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.springframework.data.domain.Sort.Direction;
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
@@ -36,17 +35,7 @@ import com.mongodb.DBObject;
|
|||||||
public class Index implements IndexDefinition {
|
public class Index implements IndexDefinition {
|
||||||
|
|
||||||
public enum Duplicates {
|
public enum Duplicates {
|
||||||
RETAIN, //
|
RETAIN, DROP
|
||||||
|
|
||||||
/**
|
|
||||||
* Dropping Duplicates was removed in MongoDB Server 2.8.0-rc0.
|
|
||||||
* <p>
|
|
||||||
* See https://jira.mongodb.org/browse/SERVER-14710
|
|
||||||
*
|
|
||||||
* @deprecated since 1.7.
|
|
||||||
*/
|
|
||||||
@Deprecated //
|
|
||||||
DROP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<String, Direction> fieldSpec = new LinkedHashMap<String, Direction>();
|
private final Map<String, Direction> fieldSpec = new LinkedHashMap<String, Direction>();
|
||||||
@@ -176,18 +165,11 @@ public class Index implements IndexDefinition {
|
|||||||
return unique();
|
return unique();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.index.IndexDefinition#getIndexKeys()
|
|
||||||
*/
|
|
||||||
public DBObject getIndexKeys() {
|
public DBObject getIndexKeys() {
|
||||||
|
|
||||||
DBObject dbo = new BasicDBObject();
|
DBObject dbo = new BasicDBObject();
|
||||||
|
for (String k : fieldSpec.keySet()) {
|
||||||
for (Entry<String, Direction> entry : fieldSpec.entrySet()) {
|
dbo.put(k, fieldSpec.get(k).equals(Direction.ASC) ? 1 : -1);
|
||||||
dbo.put(entry.getKey(), Direction.ASC.equals(entry.getValue()) ? 1 : -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dbo;
|
return dbo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2015 the original author or authors.
|
* Copyright 2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,24 +16,22 @@
|
|||||||
package org.springframework.data.mongodb.core.index;
|
package org.springframework.data.mongodb.core.index;
|
||||||
|
|
||||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.IndexDefinitionHolder;
|
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.IndexDefinitionHolder;
|
||||||
import org.springframework.data.util.TypeInformation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link IndexResolver} finds those {@link IndexDefinition}s to be created for a given class.
|
* {@link IndexResolver} finds those {@link IndexDefinition}s to be created for a given class.
|
||||||
*
|
*
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Thomas Darimont
|
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
interface IndexResolver {
|
interface IndexResolver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find and create {@link IndexDefinition}s for properties of given {@link TypeInformation}. {@link IndexDefinition}s are created
|
* Find and create {@link IndexDefinition}s for properties of given {@code type}. {@link IndexDefinition}s are created
|
||||||
* for properties and types with {@link Indexed}, {@link CompoundIndexes} or {@link GeoSpatialIndexed}.
|
* for properties and types with {@link Indexed}, {@link CompoundIndexes} or {@link GeoSpatialIndexed}.
|
||||||
*
|
*
|
||||||
* @param typeInformation
|
* @param type
|
||||||
* @return Empty {@link Iterable} in case no {@link IndexDefinition} could be resolved for type.
|
* @return Empty {@link Iterable} in case no {@link IndexDefinition} could be resolved for type.
|
||||||
*/
|
*/
|
||||||
Iterable<? extends IndexDefinitionHolder> resolveIndexFor(TypeInformation<?> typeInformation);
|
Iterable<? extends IndexDefinitionHolder> resolveIndexForClass(Class<?> type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2015 the original author or authors.
|
* Copyright 2011-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -28,10 +28,8 @@ import java.lang.annotation.Target;
|
|||||||
* @author Philipp Schneider
|
* @author Philipp Schneider
|
||||||
* @author Johno Crawford
|
* @author Johno Crawford
|
||||||
* @author Thomas Darimont
|
* @author Thomas Darimont
|
||||||
* @author Christoph Strobl
|
|
||||||
* @author Jordi Llach
|
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD})
|
@Target(ElementType.FIELD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Indexed {
|
public @interface Indexed {
|
||||||
|
|
||||||
@@ -90,9 +88,9 @@ public @interface Indexed {
|
|||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* <code>
|
* <code>
|
||||||
* db.root.createIndex( { hybrid.h1: 1 } , { name: "hybrid.index" } )
|
* db.root.ensureIndex( { hybrid.h1: 1 } , { name: "hybrid.index" } )
|
||||||
* db.root.createIndex( { nested.n1: 1 } , { name: "nested.index" } )
|
* db.root.ensureIndex( { nested.n1: 1 } , { name: "nested.index" } )
|
||||||
* db.hybrid.createIndex( { h1: 1} , { name: "index" } )
|
* db.hybrid.ensureIndex( { h1: 1} , { name: "index" } )
|
||||||
* </code>
|
* </code>
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
|
||||||
import org.springframework.data.mapping.PersistentEntity;
|
import org.springframework.data.mapping.PersistentEntity;
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
import org.springframework.data.mapping.context.MappingContextEvent;
|
import org.springframework.data.mapping.context.MappingContextEvent;
|
||||||
@@ -30,12 +29,7 @@ import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexRes
|
|||||||
import org.springframework.data.mongodb.core.mapping.Document;
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||||
import org.springframework.data.mongodb.util.MongoDbErrorCodes;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import com.mongodb.MongoException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that inspects {@link MongoPersistentEntity} instances contained in the given {@link MongoMappingContext}
|
* Component that inspects {@link MongoPersistentEntity} instances contained in the given {@link MongoMappingContext}
|
||||||
@@ -129,40 +123,15 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener<Ma
|
|||||||
private void checkForAndCreateIndexes(MongoPersistentEntity<?> entity) {
|
private void checkForAndCreateIndexes(MongoPersistentEntity<?> entity) {
|
||||||
|
|
||||||
if (entity.findAnnotation(Document.class) != null) {
|
if (entity.findAnnotation(Document.class) != null) {
|
||||||
for (IndexDefinitionHolder indexToCreate : indexResolver.resolveIndexFor(entity.getTypeInformation())) {
|
for (IndexDefinitionHolder indexToCreate : indexResolver.resolveIndexForClass(entity.getType())) {
|
||||||
createIndex(indexToCreate);
|
createIndex(indexToCreate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void createIndex(IndexDefinitionHolder indexDefinition) {
|
private void createIndex(IndexDefinitionHolder indexDefinition) {
|
||||||
|
mongoDbFactory.getDb().getCollection(indexDefinition.getCollection()).createIndex(indexDefinition.getIndexKeys(),
|
||||||
try {
|
indexDefinition.getIndexOptions());
|
||||||
|
|
||||||
mongoDbFactory.getDb().getCollection(indexDefinition.getCollection()).createIndex(indexDefinition.getIndexKeys(),
|
|
||||||
indexDefinition.getIndexOptions());
|
|
||||||
|
|
||||||
} catch (MongoException ex) {
|
|
||||||
|
|
||||||
if (MongoDbErrorCodes.isDataIntegrityViolationCode(ex.getCode())) {
|
|
||||||
|
|
||||||
DBObject existingIndex = fetchIndexInformation(indexDefinition);
|
|
||||||
String message = "Cannot create index for '%s' in collection '%s' with keys '%s' and options '%s'.";
|
|
||||||
|
|
||||||
if (existingIndex != null) {
|
|
||||||
message += " Index already defined as '%s'.";
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new DataIntegrityViolationException(
|
|
||||||
String.format(message, indexDefinition.getPath(), indexDefinition.getCollection(),
|
|
||||||
indexDefinition.getIndexKeys(), indexDefinition.getIndexOptions(), existingIndex),
|
|
||||||
ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
RuntimeException exceptionToThrow = mongoDbFactory.getExceptionTranslator().translateExceptionIfPossible(ex);
|
|
||||||
|
|
||||||
throw exceptionToThrow != null ? exceptionToThrow : ex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -174,28 +143,4 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener<Ma
|
|||||||
public boolean isIndexCreatorFor(MappingContext<?, ?> context) {
|
public boolean isIndexCreatorFor(MappingContext<?, ?> context) {
|
||||||
return this.mappingContext.equals(context);
|
return this.mappingContext.equals(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DBObject fetchIndexInformation(IndexDefinitionHolder indexDefinition) {
|
|
||||||
|
|
||||||
if (indexDefinition == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
Object indexNameToLookUp = indexDefinition.getIndexOptions().get("name");
|
|
||||||
|
|
||||||
for (DBObject index : mongoDbFactory.getDb().getCollection(indexDefinition.getCollection()).getIndexInfo()) {
|
|
||||||
if (ObjectUtils.nullSafeEquals(indexNameToLookUp, index.get("name"))) {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.debug(
|
|
||||||
String.format("Failed to load index information for collection '%s'.", indexDefinition.getCollection()), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,10 +27,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.mapping.Association;
|
|
||||||
import org.springframework.data.mapping.AssociationHandler;
|
|
||||||
import org.springframework.data.mapping.PropertyHandler;
|
import org.springframework.data.mapping.PropertyHandler;
|
||||||
import org.springframework.data.mapping.model.MappingException;
|
|
||||||
import org.springframework.data.mongodb.core.index.Index.Duplicates;
|
import org.springframework.data.mongodb.core.index.Index.Duplicates;
|
||||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.TextIndexIncludeOptions.IncludeStrategy;
|
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.TextIndexIncludeOptions.IncludeStrategy;
|
||||||
import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexDefinitionBuilder;
|
import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexDefinitionBuilder;
|
||||||
@@ -39,7 +36,6 @@ import org.springframework.data.mongodb.core.mapping.Document;
|
|||||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||||
import org.springframework.data.util.TypeInformation;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
@@ -55,7 +51,6 @@ import com.mongodb.util.JSON;
|
|||||||
* scanning related annotations.
|
* scanning related annotations.
|
||||||
*
|
*
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Thomas Darimont
|
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||||
@@ -75,12 +70,13 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
this.mappingContext = mappingContext;
|
this.mappingContext = mappingContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/*
|
||||||
* @see org.springframework.data.mongodb.core.index.IndexResolver#resolveIndexForClass(org.springframework.data.util.TypeInformation)
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.index.IndexResolver#resolveIndexForClass(java.lang.Class)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Iterable<? extends IndexDefinitionHolder> resolveIndexFor(TypeInformation<?> typeInformation) {
|
public List<IndexDefinitionHolder> resolveIndexForClass(Class<?> type) {
|
||||||
return resolveIndexForEntity(mappingContext.getPersistentEntity(typeInformation));
|
return resolveIndexForEntity(mappingContext.getPersistentEntity(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,7 +107,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (persistentProperty.isEntity()) {
|
if (persistentProperty.isEntity()) {
|
||||||
indexInformation.addAll(resolveIndexForClass(persistentProperty.getTypeInformation().getActualType(),
|
indexInformation.addAll(resolveIndexForClass(persistentProperty.getActualType(),
|
||||||
persistentProperty.getFieldName(), root.getCollection(), guard));
|
persistentProperty.getFieldName(), root.getCollection(), guard));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,8 +122,6 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
indexInformation.addAll(resolveIndexesForDbrefs("", root.getCollection(), root));
|
|
||||||
|
|
||||||
return indexInformation;
|
return indexInformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +134,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
* @return List of {@link IndexDefinitionHolder} representing indexes for given type and its referenced property
|
* @return List of {@link IndexDefinitionHolder} representing indexes for given type and its referenced property
|
||||||
* types. Will never be {@code null}.
|
* types. Will never be {@code null}.
|
||||||
*/
|
*/
|
||||||
private List<IndexDefinitionHolder> resolveIndexForClass(final TypeInformation<?> type, final String path,
|
private List<IndexDefinitionHolder> resolveIndexForClass(final Class<?> type, final String path,
|
||||||
final String collection, final CycleGuard guard) {
|
final String collection, final CycleGuard guard) {
|
||||||
|
|
||||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(type);
|
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(type);
|
||||||
@@ -158,8 +152,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
|
|
||||||
if (persistentProperty.isEntity()) {
|
if (persistentProperty.isEntity()) {
|
||||||
try {
|
try {
|
||||||
indexInformation.addAll(resolveIndexForClass(persistentProperty.getTypeInformation().getActualType(),
|
indexInformation.addAll(resolveIndexForClass(persistentProperty.getActualType(), propertyDotPath,
|
||||||
propertyDotPath, collection, guard));
|
collection, guard));
|
||||||
} catch (CyclicPropertyReferenceException e) {
|
} catch (CyclicPropertyReferenceException e) {
|
||||||
LOGGER.info(e.getMessage());
|
LOGGER.info(e.getMessage());
|
||||||
}
|
}
|
||||||
@@ -173,8 +167,6 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
indexInformation.addAll(resolveIndexesForDbrefs(path, collection, entity));
|
|
||||||
|
|
||||||
return indexInformation;
|
return indexInformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,19 +192,18 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
return createCompoundIndexDefinitions(dotPath, collection, entity);
|
return createCompoundIndexDefinitions(dotPath, collection, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<? extends IndexDefinitionHolder> potentiallyCreateTextIndexDefinition(
|
private Collection<? extends IndexDefinitionHolder> potentiallyCreateTextIndexDefinition(MongoPersistentEntity<?> root) {
|
||||||
MongoPersistentEntity<?> root) {
|
|
||||||
|
|
||||||
TextIndexDefinitionBuilder indexDefinitionBuilder = new TextIndexDefinitionBuilder()
|
TextIndexDefinitionBuilder indexDefinitionBuilder = new TextIndexDefinitionBuilder().named(root.getType()
|
||||||
.named(root.getType().getSimpleName() + "_TextIndex");
|
.getSimpleName() + "_TextIndex");
|
||||||
|
|
||||||
if (StringUtils.hasText(root.getLanguage())) {
|
if (StringUtils.hasText(root.getLanguage())) {
|
||||||
indexDefinitionBuilder.withDefaultLanguage(root.getLanguage());
|
indexDefinitionBuilder.withDefaultLanguage(root.getLanguage());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
appendTextIndexInformation("", indexDefinitionBuilder, root, new TextIndexIncludeOptions(IncludeStrategy.DEFAULT),
|
appendTextIndexInformation("", indexDefinitionBuilder, root,
|
||||||
new CycleGuard());
|
new TextIndexIncludeOptions(IncludeStrategy.DEFAULT), new CycleGuard());
|
||||||
} catch (CyclicPropertyReferenceException e) {
|
} catch (CyclicPropertyReferenceException e) {
|
||||||
LOGGER.info(e.getMessage());
|
LOGGER.info(e.getMessage());
|
||||||
}
|
}
|
||||||
@@ -228,8 +219,9 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendTextIndexInformation(final String dotPath, final TextIndexDefinitionBuilder indexDefinitionBuilder,
|
private void appendTextIndexInformation(final String dotPath,
|
||||||
final MongoPersistentEntity<?> entity, final TextIndexIncludeOptions includeOptions, final CycleGuard guard) {
|
final TextIndexDefinitionBuilder indexDefinitionBuilder, final MongoPersistentEntity<?> entity,
|
||||||
|
final TextIndexIncludeOptions includeOptions, final CycleGuard guard) {
|
||||||
|
|
||||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||||
|
|
||||||
@@ -256,8 +248,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
|
|
||||||
TextIndexIncludeOptions optionsForNestedType = includeOptions;
|
TextIndexIncludeOptions optionsForNestedType = includeOptions;
|
||||||
if (!IncludeStrategy.FORCE.equals(includeOptions.getStrategy()) && indexed != null) {
|
if (!IncludeStrategy.FORCE.equals(includeOptions.getStrategy()) && indexed != null) {
|
||||||
optionsForNestedType = new TextIndexIncludeOptions(IncludeStrategy.FORCE,
|
optionsForNestedType = new TextIndexIncludeOptions(IncludeStrategy.FORCE, new TextIndexedFieldSpec(
|
||||||
new TextIndexedFieldSpec(propertyDotPath, weight));
|
propertyDotPath, weight));
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -266,8 +258,9 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
} catch (CyclicPropertyReferenceException e) {
|
} catch (CyclicPropertyReferenceException e) {
|
||||||
LOGGER.info(e.getMessage(), e);
|
LOGGER.info(e.getMessage(), e);
|
||||||
} catch (InvalidDataAccessApiUsageException e) {
|
} catch (InvalidDataAccessApiUsageException e) {
|
||||||
LOGGER.info(String.format("Potentially invalid index structure discovered. Breaking operation for %s.",
|
LOGGER.info(
|
||||||
entity.getName()), e);
|
String.format("Potentially invalid index structure discovered. Breaking operation for %s.",
|
||||||
|
entity.getName()), e);
|
||||||
}
|
}
|
||||||
} else if (includeOptions.isForce() || indexed != null) {
|
} else if (includeOptions.isForce() || indexed != null) {
|
||||||
indexDefinitionBuilder.onField(propertyDotPath, weight);
|
indexDefinitionBuilder.onField(propertyDotPath, weight);
|
||||||
@@ -312,8 +305,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, String fallbackCollection,
|
protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, String fallbackCollection,
|
||||||
CompoundIndex index, MongoPersistentEntity<?> entity) {
|
CompoundIndex index, MongoPersistentEntity<?> entity) {
|
||||||
|
|
||||||
CompoundIndexDefinition indexDefinition = new CompoundIndexDefinition(
|
CompoundIndexDefinition indexDefinition = new CompoundIndexDefinition(resolveCompoundIndexKeyFromStringDefinition(
|
||||||
resolveCompoundIndexKeyFromStringDefinition(dotPath, index.def()));
|
dotPath, index.def()));
|
||||||
|
|
||||||
if (!index.useGeneratedName()) {
|
if (!index.useGeneratedName()) {
|
||||||
indexDefinition.named(pathAwareIndexName(index.name(), dotPath, null));
|
indexDefinition.named(pathAwareIndexName(index.name(), dotPath, null));
|
||||||
@@ -437,45 +430,13 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
|
|
||||||
if (StringUtils.hasText(dotPath)) {
|
if (StringUtils.hasText(dotPath)) {
|
||||||
|
|
||||||
nameToUse = StringUtils.hasText(nameToUse)
|
nameToUse = StringUtils.hasText(nameToUse) ? (property != null ? dotPath.replace("." + property.getFieldName(),
|
||||||
? (property != null ? dotPath.replace("." + property.getFieldName(), "") : dotPath) + "." + nameToUse
|
"") : dotPath) + "." + nameToUse : dotPath;
|
||||||
: dotPath;
|
|
||||||
}
|
}
|
||||||
return nameToUse;
|
return nameToUse;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<IndexDefinitionHolder> resolveIndexesForDbrefs(final String path, final String collection,
|
|
||||||
MongoPersistentEntity<?> entity) {
|
|
||||||
|
|
||||||
final List<IndexDefinitionHolder> indexes = new ArrayList<IndexDefinitionHolder>(0);
|
|
||||||
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
|
||||||
|
|
||||||
MongoPersistentProperty property = association.getInverse();
|
|
||||||
|
|
||||||
String propertyDotPath = (StringUtils.hasText(path) ? path + "." : "") + property.getFieldName();
|
|
||||||
|
|
||||||
if (property.isAnnotationPresent(GeoSpatialIndexed.class) || property.isAnnotationPresent(TextIndexed.class)) {
|
|
||||||
throw new MappingException(
|
|
||||||
String.format("Cannot create geospatial-/text- index on DBRef in collection '%s' for path '%s'.",
|
|
||||||
collection, propertyDotPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
IndexDefinitionHolder indexDefinitionHolder = createIndexDefinitionHolderForProperty(propertyDotPath,
|
|
||||||
collection, property);
|
|
||||||
|
|
||||||
if (indexDefinitionHolder != null) {
|
|
||||||
indexes.add(indexDefinitionHolder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return indexes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link CycleGuard} holds information about properties and the paths for accessing those. This information is used
|
* {@link CycleGuard} holds information about properties and the paths for accessing those. This information is used
|
||||||
* to detect potential cycles within the references.
|
* to detect potential cycles within the references.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2016 the original author or authors.
|
* Copyright 2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,11 +26,10 @@ import java.lang.annotation.Target;
|
|||||||
* all fields marked with {@link TextIndexed} are combined into one single index. <br />
|
* all fields marked with {@link TextIndexed} are combined into one single index. <br />
|
||||||
*
|
*
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Mark Paluch
|
|
||||||
* @since 1.6
|
* @since 1.6
|
||||||
*/
|
*/
|
||||||
@Documented
|
@Documented
|
||||||
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
|
@Target({ ElementType.FIELD })
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface TextIndexed {
|
public @interface TextIndexed {
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
|||||||
Class<?> rawType = typeInformation.getType();
|
Class<?> rawType = typeInformation.getType();
|
||||||
String fallback = MongoCollectionUtils.getPreferredCollectionName(rawType);
|
String fallback = MongoCollectionUtils.getPreferredCollectionName(rawType);
|
||||||
|
|
||||||
Document document = this.findAnnotation(Document.class);
|
Document document = rawType.getAnnotation(Document.class);
|
||||||
|
|
||||||
this.expression = detectExpression(document);
|
this.expression = detectExpression(document);
|
||||||
this.context = new StandardEvaluationContext();
|
this.context = new StandardEvaluationContext();
|
||||||
|
|||||||
@@ -100,8 +100,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We need to support a wider range of ID types than just the ones that can be converted to an ObjectId
|
// We need to support a wider range of ID types than just the ones that can be converted to an ObjectId
|
||||||
// but still we need to check if there happens to be an explicit name set
|
return SUPPORTED_ID_PROPERTY_NAMES.contains(getName());
|
||||||
return SUPPORTED_ID_PROPERTY_NAMES.contains(getName()) && !hasExplicitFieldName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -135,8 +134,10 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasExplicitFieldName()) {
|
org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation(org.springframework.data.mongodb.core.mapping.Field.class);
|
||||||
return getAnnotatedFieldName();
|
|
||||||
|
if (annotation != null && StringUtils.hasText(annotation.value())) {
|
||||||
|
return annotation.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
String fieldName = fieldNamingStrategy.getFieldName(this);
|
String fieldName = fieldNamingStrategy.getFieldName(this);
|
||||||
@@ -149,26 +150,6 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
|||||||
return fieldName;
|
return fieldName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if {@link org.springframework.data.mongodb.core.mapping.Field} having non blank
|
|
||||||
* {@link org.springframework.data.mongodb.core.mapping.Field#value()} present.
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
protected boolean hasExplicitFieldName() {
|
|
||||||
return StringUtils.hasText(getAnnotatedFieldName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getAnnotatedFieldName() {
|
|
||||||
|
|
||||||
org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation(org.springframework.data.mongodb.core.mapping.Field.class);
|
|
||||||
|
|
||||||
if (annotation != null && StringUtils.hasText(annotation.value())) {
|
|
||||||
return annotation.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#getFieldOrder()
|
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#getFieldOrder()
|
||||||
|
|||||||
@@ -1,25 +1,8 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011-2016 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.mapping;
|
package org.springframework.data.mongodb.core.mapping;
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation to define custom metadata for document fields.
|
* Annotation to define custom metadata for document fields.
|
||||||
@@ -28,7 +11,6 @@ import java.lang.annotation.Target;
|
|||||||
*/
|
*/
|
||||||
@Documented
|
@Documented
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
|
||||||
public @interface Field {
|
public @interface Field {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2015 by the original author(s).
|
* Copyright 2013 by the original author(s).
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -21,7 +21,6 @@ import com.mongodb.DBObject;
|
|||||||
* Base class for delete events.
|
* Base class for delete events.
|
||||||
*
|
*
|
||||||
* @author Martin Baumgartner
|
* @author Martin Baumgartner
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractDeleteEvent<T> extends MongoMappingEvent<DBObject> {
|
public abstract class AbstractDeleteEvent<T> extends MongoMappingEvent<DBObject> {
|
||||||
|
|
||||||
@@ -32,25 +31,11 @@ public abstract class AbstractDeleteEvent<T> extends MongoMappingEvent<DBObject>
|
|||||||
* Creates a new {@link AbstractDeleteEvent} for the given {@link DBObject} and type.
|
* Creates a new {@link AbstractDeleteEvent} for the given {@link DBObject} and type.
|
||||||
*
|
*
|
||||||
* @param dbo must not be {@literal null}.
|
* @param dbo must not be {@literal null}.
|
||||||
* @param type can be {@literal null}.
|
* @param type , possibly be {@literal null}.
|
||||||
* @deprecated since 1.8. Please use {@link #AbstractDeleteEvent(DBObject, Class, String)}.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public AbstractDeleteEvent(DBObject dbo, Class<T> type) {
|
public AbstractDeleteEvent(DBObject dbo, Class<T> type) {
|
||||||
this(dbo, type, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
super(dbo, dbo);
|
||||||
* Creates a new {@link AbstractDeleteEvent} for the given {@link DBObject} and type.
|
|
||||||
*
|
|
||||||
* @param dbo must not be {@literal null}.
|
|
||||||
* @param type can be {@literal null}.
|
|
||||||
* @param collectionName can be {@literal null}.
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public AbstractDeleteEvent(DBObject dbo, Class<T> type, String collectionName) {
|
|
||||||
|
|
||||||
super(dbo, dbo, collectionName);
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2016 by the original author(s).
|
* Copyright 2011-2013 by the original author(s).
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,13 +20,14 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.core.GenericTypeResolver;
|
import org.springframework.core.GenericTypeResolver;
|
||||||
|
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class to implement domain class specific {@link ApplicationListener}s.
|
* Base class to implement domain class specific {@link ApplicationListener}s.
|
||||||
*
|
*
|
||||||
* @author Jon Brisbin
|
* @author Jon Brisbin
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Martin Baumgartner
|
* @author Martin Baumgartner
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractMongoEventListener<E> implements ApplicationListener<MongoMappingEvent<?>> {
|
public abstract class AbstractMongoEventListener<E> implements ApplicationListener<MongoMappingEvent<?>> {
|
||||||
|
|
||||||
@@ -45,14 +46,14 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
|
|||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings("rawtypes")
|
||||||
public void onApplicationEvent(MongoMappingEvent<?> event) {
|
public void onApplicationEvent(MongoMappingEvent<?> event) {
|
||||||
|
|
||||||
if (event instanceof AfterLoadEvent) {
|
if (event instanceof AfterLoadEvent) {
|
||||||
AfterLoadEvent<?> afterLoadEvent = (AfterLoadEvent<?>) event;
|
AfterLoadEvent<?> afterLoadEvent = (AfterLoadEvent<?>) event;
|
||||||
|
|
||||||
if (domainClass.isAssignableFrom(afterLoadEvent.getType())) {
|
if (domainClass.isAssignableFrom(afterLoadEvent.getType())) {
|
||||||
onAfterLoad((AfterLoadEvent<E>) event);
|
onAfterLoad(event.getDBObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -64,18 +65,18 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
|
|||||||
|
|
||||||
if (eventDomainType != null && domainClass.isAssignableFrom(eventDomainType)) {
|
if (eventDomainType != null && domainClass.isAssignableFrom(eventDomainType)) {
|
||||||
if (event instanceof BeforeDeleteEvent) {
|
if (event instanceof BeforeDeleteEvent) {
|
||||||
onBeforeDelete((BeforeDeleteEvent<E>) event);
|
onBeforeDelete(event.getDBObject());
|
||||||
}
|
}
|
||||||
if (event instanceof AfterDeleteEvent) {
|
if (event instanceof AfterDeleteEvent) {
|
||||||
onAfterDelete((AfterDeleteEvent<E>) event);
|
onAfterDelete(event.getDBObject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object source = event.getSource();
|
@SuppressWarnings("unchecked")
|
||||||
|
E source = (E) event.getSource();
|
||||||
|
|
||||||
// Check for matching domain type and invoke callbacks
|
// Check for matching domain type and invoke callbacks
|
||||||
if (source != null && !domainClass.isAssignableFrom(source.getClass())) {
|
if (source != null && !domainClass.isAssignableFrom(source.getClass())) {
|
||||||
@@ -83,104 +84,55 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event instanceof BeforeConvertEvent) {
|
if (event instanceof BeforeConvertEvent) {
|
||||||
onBeforeConvert((BeforeConvertEvent<E>) event);
|
onBeforeConvert(source);
|
||||||
} else if (event instanceof BeforeSaveEvent) {
|
} else if (event instanceof BeforeSaveEvent) {
|
||||||
onBeforeSave((BeforeSaveEvent<E>) event);
|
onBeforeSave(source, event.getDBObject());
|
||||||
} else if (event instanceof AfterSaveEvent) {
|
} else if (event instanceof AfterSaveEvent) {
|
||||||
onAfterSave((AfterSaveEvent<E>) event);
|
onAfterSave(source, event.getDBObject());
|
||||||
} else if (event instanceof AfterConvertEvent) {
|
} else if (event instanceof AfterConvertEvent) {
|
||||||
onAfterConvert((AfterConvertEvent<E>) event);
|
onAfterConvert(event.getDBObject(), source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void onBeforeConvert(E source) {
|
||||||
* Captures {@link BeforeConvertEvent}.
|
|
||||||
*
|
|
||||||
* @param event never {@literal null}.
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public void onBeforeConvert(BeforeConvertEvent<E> event) {
|
|
||||||
|
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("onBeforeConvert({})", event.getSource());
|
LOG.debug("onBeforeConvert({})", source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void onBeforeSave(E source, DBObject dbo) {
|
||||||
* Captures {@link BeforeSaveEvent}.
|
|
||||||
*
|
|
||||||
* @param event will never be {@literal null}.
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public void onBeforeSave(BeforeSaveEvent<E> event) {
|
|
||||||
|
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("onBeforeSave({}, {})", event.getSource(), event.getDBObject());
|
LOG.debug("onBeforeSave({}, {})", source, dbo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void onAfterSave(E source, DBObject dbo) {
|
||||||
* Captures {@link AfterSaveEvent}.
|
|
||||||
*
|
|
||||||
* @param event will never be {@literal null}.
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public void onAfterSave(AfterSaveEvent<E> event) {
|
|
||||||
|
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("onAfterSave({}, {})", event.getSource(), event.getDBObject());
|
LOG.debug("onAfterSave({}, {})", source, dbo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void onAfterLoad(DBObject dbo) {
|
||||||
* Captures {@link AfterLoadEvent}.
|
|
||||||
*
|
|
||||||
* @param event will never be {@literal null}.
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public void onAfterLoad(AfterLoadEvent<E> event) {
|
|
||||||
|
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("onAfterLoad({})", event.getDBObject());
|
LOG.debug("onAfterLoad({})", dbo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void onAfterConvert(DBObject dbo, E source) {
|
||||||
* Captures {@link AfterConvertEvent}.
|
|
||||||
*
|
|
||||||
* @param event will never be {@literal null}.
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public void onAfterConvert(AfterConvertEvent<E> event) {
|
|
||||||
|
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("onAfterConvert({}, {})", event.getDBObject(), event.getSource());
|
LOG.debug("onAfterConvert({}, {})", dbo, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void onAfterDelete(DBObject dbo) {
|
||||||
* Captures {@link AfterDeleteEvent}.
|
|
||||||
*
|
|
||||||
* @param event will never be {@literal null}.
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public void onAfterDelete(AfterDeleteEvent<E> event) {
|
|
||||||
|
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("onAfterDelete({})", event.getDBObject());
|
LOG.debug("onAfterDelete({})", dbo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void onBeforeDelete(DBObject dbo) {
|
||||||
* Capture {@link BeforeDeleteEvent}.
|
|
||||||
*
|
|
||||||
* @param event will never be {@literal null}.
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public void onBeforeDelete(BeforeDeleteEvent<E> event) {
|
|
||||||
|
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("onBeforeDelete({})", event.getDBObject());
|
LOG.debug("onBeforeDelete({})", dbo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011-2015 by the original author(s).
|
* Copyright (c) 2011 by the original author(s).
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -13,42 +13,20 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.data.mongodb.core.mapping.event;
|
package org.springframework.data.mongodb.core.mapping.event;
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link MongoMappingEvent} thrown after convert of a document.
|
|
||||||
*
|
|
||||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public class AfterConvertEvent<E> extends MongoMappingEvent<E> {
|
public class AfterConvertEvent<E> extends MongoMappingEvent<E> {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new {@link AfterConvertEvent}.
|
|
||||||
*
|
|
||||||
* @param dbo can be {@literal null}.
|
|
||||||
* @param source must not be {@literal null}.
|
|
||||||
* @deprecated since 1.8. Please use {@link #AfterConvertEvent(DBObject, Object, String)}.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public AfterConvertEvent(DBObject dbo, E source) {
|
public AfterConvertEvent(DBObject dbo, E source) {
|
||||||
this(dbo, source, null);
|
super(source, dbo);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new {@link AfterConvertEvent}.
|
|
||||||
*
|
|
||||||
* @param dbo can be {@literal null}.
|
|
||||||
* @param source must not be {@literal null}.
|
|
||||||
* @param collectionName can be {@literal null}.
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public AfterConvertEvent(DBObject dbo, E source, String collectionName) {
|
|
||||||
super(source, dbo, collectionName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2015 by the original author(s).
|
* Copyright 2013 by the original author(s).
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -22,7 +22,6 @@ import com.mongodb.DBObject;
|
|||||||
* will be the query document <em>after</am> it has been mapped onto the domain type handled.
|
* will be the query document <em>after</am> it has been mapped onto the domain type handled.
|
||||||
*
|
*
|
||||||
* @author Martin Baumgartner
|
* @author Martin Baumgartner
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public class AfterDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
public class AfterDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
||||||
|
|
||||||
@@ -33,22 +32,8 @@ public class AfterDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
|||||||
*
|
*
|
||||||
* @param dbo must not be {@literal null}.
|
* @param dbo must not be {@literal null}.
|
||||||
* @param type can be {@literal null}.
|
* @param type can be {@literal null}.
|
||||||
* @deprecated since 1.8. Please use {@link #AfterDeleteEvent(DBObject, Class, String)}.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public AfterDeleteEvent(DBObject dbo, Class<T> type) {
|
public AfterDeleteEvent(DBObject dbo, Class<T> type) {
|
||||||
this(dbo, type, null);
|
super(dbo, type);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link AfterDeleteEvent} for the given {@link DBObject}, type and collectionName.
|
|
||||||
*
|
|
||||||
* @param dbo must not be {@literal null}.
|
|
||||||
* @param type can be {@literal null}.
|
|
||||||
* @param collectionName can be {@literal null}.
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
public AfterDeleteEvent(DBObject dbo, Class<T> type, String collectionName) {
|
|
||||||
super(dbo, type, collectionName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011-2015 by the original author(s).
|
* Copyright (c) 2011 by the original author(s).
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,7 +26,6 @@ import com.mongodb.DBObject;
|
|||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Jon Brisbin
|
* @author Jon Brisbin
|
||||||
* @author Christoph Leiter
|
* @author Christoph Leiter
|
||||||
* @author Christoph Strobl
|
|
||||||
*/
|
*/
|
||||||
public class AfterLoadEvent<T> extends MongoMappingEvent<DBObject> {
|
public class AfterLoadEvent<T> extends MongoMappingEvent<DBObject> {
|
||||||
|
|
||||||
@@ -37,25 +36,11 @@ public class AfterLoadEvent<T> extends MongoMappingEvent<DBObject> {
|
|||||||
* Creates a new {@link AfterLoadEvent} for the given {@link DBObject} and type.
|
* Creates a new {@link AfterLoadEvent} for the given {@link DBObject} and type.
|
||||||
*
|
*
|
||||||
* @param dbo must not be {@literal null}.
|
* @param dbo must not be {@literal null}.
|
||||||
* @param type can be {@literal null}.
|
|
||||||
* @deprecated since 1.8. Please use {@link #AfterLoadEvent(DBObject, Class, String)}.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public AfterLoadEvent(DBObject dbo, Class<T> type) {
|
|
||||||
this(dbo, type, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link AfterLoadEvent} for the given {@link DBObject}, type and collectionName.
|
|
||||||
*
|
|
||||||
* @param dbo must not be {@literal null}.
|
|
||||||
* @param type must not be {@literal null}.
|
* @param type must not be {@literal null}.
|
||||||
* @param collectionName can be {@literal null}.
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
*/
|
||||||
public AfterLoadEvent(DBObject dbo, Class<T> type, String collectionName) {
|
public AfterLoadEvent(DBObject dbo, Class<T> type) {
|
||||||
|
|
||||||
super(dbo, dbo, collectionName);
|
super(dbo, dbo);
|
||||||
|
|
||||||
Assert.notNull(type, "Type must not be null!");
|
Assert.notNull(type, "Type must not be null!");
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user