Compare commits
289 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f27f42976b | ||
|
|
752ea95fde | ||
|
|
3ea9dd9e73 | ||
|
|
c077ae8985 | ||
|
|
19e29c7e1d | ||
|
|
4f0b2d66a5 | ||
|
|
4b5c53e959 | ||
|
|
cb071ce05f | ||
|
|
e59911b42b | ||
|
|
61e87be306 | ||
|
|
1637f8d181 | ||
|
|
b9c8b7b234 | ||
|
|
741429a452 | ||
|
|
b75f4795ea | ||
|
|
a97980b04d | ||
|
|
2d8c666802 | ||
|
|
de0c4109d7 | ||
|
|
02abfced9c | ||
|
|
ec696618be | ||
|
|
ee43703100 | ||
|
|
cadc74932e | ||
|
|
fa4b4b97dd | ||
|
|
8392f4275f | ||
|
|
8ff1913ec7 | ||
|
|
57c7524c77 | ||
|
|
f79636240c | ||
|
|
f22bf106db | ||
|
|
ff72150518 | ||
|
|
099689c00d | ||
|
|
1d5df555f0 | ||
|
|
54e6a80ca9 | ||
|
|
f66d773a94 | ||
|
|
899afe1fe7 | ||
|
|
ee9a6993b1 | ||
|
|
5d7e12a4fa | ||
|
|
8b3da2d7f9 | ||
|
|
49af31bb6e | ||
|
|
c2aacc03ff | ||
|
|
1cf544a530 | ||
|
|
bbb097cafc | ||
|
|
feafd50b59 | ||
|
|
b51cf05f90 | ||
|
|
b8196ac9ed | ||
|
|
e643d39fa6 | ||
|
|
6abdb0aa46 | ||
|
|
34063ff647 | ||
|
|
857f366b56 | ||
|
|
f7540d45c6 | ||
|
|
3d2ae8117f | ||
|
|
6b3bd8f621 | ||
|
|
b17ec47003 | ||
|
|
8c7b558d39 | ||
|
|
a3faabf718 | ||
|
|
1a46abfbb9 | ||
|
|
61284228dd | ||
|
|
8cb92de1ee | ||
|
|
5d3cc3fa04 | ||
|
|
c0b99740dc | ||
|
|
595bbd3aa7 | ||
|
|
5d2fc31164 | ||
|
|
a9dc0fae69 | ||
|
|
0605c7b753 | ||
|
|
21352a8829 | ||
|
|
58e1d2dbd9 | ||
|
|
4f7821e3c2 | ||
|
|
9dd866e34a | ||
|
|
def6079795 | ||
|
|
f3f537c1a6 | ||
|
|
ad44db386b | ||
|
|
bcc3bf61b6 | ||
|
|
1a28a294d1 | ||
|
|
14623a3655 | ||
|
|
6dcaa31897 | ||
|
|
e57fe346c0 | ||
|
|
7dd94949d5 | ||
|
|
966f971bee | ||
|
|
aa23c579e8 | ||
|
|
6b634d08ce | ||
|
|
b7b61405f9 | ||
|
|
4d65aa7207 | ||
|
|
c129c706a3 | ||
|
|
7823385ac7 | ||
|
|
21fcfe11c2 | ||
|
|
bfe33a446c | ||
|
|
9be50316c3 | ||
|
|
30513267af | ||
|
|
d3d480e79b | ||
|
|
c39ad1bbc4 | ||
|
|
fcdc29df49 | ||
|
|
de7120d8dd | ||
|
|
84df02ae38 | ||
|
|
d6c5907940 | ||
|
|
b2fe54c0a1 | ||
|
|
47a198c688 | ||
|
|
5d9dbda03b | ||
|
|
36d52862bc | ||
|
|
0afbf6fe19 | ||
|
|
b0bf8cb718 | ||
|
|
567a8d9d5b | ||
|
|
ceef18d7a4 | ||
|
|
4f57712f12 | ||
|
|
478396c503 | ||
|
|
aa80d1ad0a | ||
|
|
fd28ab4d33 | ||
|
|
187c80dfcc | ||
|
|
389a3ac066 | ||
|
|
297bd3e3dd | ||
|
|
b11fba3321 | ||
|
|
3c68671d86 | ||
|
|
b171f4192d | ||
|
|
21a1ce985c | ||
|
|
97caba50bf | ||
|
|
818f739d5a | ||
|
|
a44c1fdd2d | ||
|
|
6b35ca80d4 | ||
|
|
23b276745c | ||
|
|
be0092d3f5 | ||
|
|
f36792d419 | ||
|
|
31393db6ff | ||
|
|
8b50af07ce | ||
|
|
0eb315a758 | ||
|
|
976f5dd0e3 | ||
|
|
f614364918 | ||
|
|
38a86033be | ||
|
|
d11c20d548 | ||
|
|
3e2387ae6b | ||
|
|
e8a1caec53 | ||
|
|
44c0b14018 | ||
|
|
3daf3fc95b | ||
|
|
bd3aac8342 | ||
|
|
94f697da10 | ||
|
|
0cdec56a27 | ||
|
|
9d83331f9f | ||
|
|
071cd1647f | ||
|
|
92af5aa345 | ||
|
|
c07ad0fdf6 | ||
|
|
04e0f5c4a7 | ||
|
|
133975fb44 | ||
|
|
9a372a57e0 | ||
|
|
e67644094a | ||
|
|
c5a99b5b5e | ||
|
|
9564bcb280 | ||
|
|
f1e961a1ee | ||
|
|
0c69c87787 | ||
|
|
48b4a88a6a | ||
|
|
d0c0866f88 | ||
|
|
ab18bb5b96 | ||
|
|
509be3d681 | ||
|
|
8e01f95b29 | ||
|
|
4dcec1f6e2 | ||
|
|
d3bf6c0a19 | ||
|
|
3410a0589c | ||
|
|
7a64766496 | ||
|
|
e56a8597b8 | ||
|
|
e13208b4b3 | ||
|
|
6139e83d8d | ||
|
|
f33790013f | ||
|
|
bf81d95d21 | ||
|
|
158e4f033c | ||
|
|
81097061ad | ||
|
|
2bc6ebc250 | ||
|
|
909110cf4e | ||
|
|
ba094da5a7 | ||
|
|
876b31bc52 | ||
|
|
dc8e8281eb | ||
|
|
48deb1a150 | ||
|
|
48625956b7 | ||
|
|
782cf6e10d | ||
|
|
c28e51cf86 | ||
|
|
4b1065cac5 | ||
|
|
c807b2abcf | ||
|
|
19ad2d3aac | ||
|
|
bd7fe5bfd3 | ||
|
|
a237999037 | ||
|
|
d8a9752724 | ||
|
|
4c8bf0dec2 | ||
|
|
cffc27d83a | ||
|
|
42ab4cb7b4 | ||
|
|
42df25434f | ||
|
|
4e16f7ebe2 | ||
|
|
04a87b373d | ||
|
|
c4eca7eadd | ||
|
|
3a9dc2b98c | ||
|
|
c568b7cbc2 | ||
|
|
9482350062 | ||
|
|
772a140def | ||
|
|
936259a766 | ||
|
|
533d21281e | ||
|
|
6977fa87e6 | ||
|
|
41dcebb010 | ||
|
|
ef077182f6 | ||
|
|
21e7c63766 | ||
|
|
4b018a9d7d | ||
|
|
ecf15b93e0 | ||
|
|
6323a86560 | ||
|
|
3b0b7315e1 | ||
|
|
4aeba6f92d | ||
|
|
342f9ae837 | ||
|
|
66d98b355e | ||
|
|
cabbe747f8 | ||
|
|
5ff3064acd | ||
|
|
3001e2941f | ||
|
|
9cf72fbdd4 | ||
|
|
cb5144de0f | ||
|
|
4be90e51ae | ||
|
|
6c368d557b | ||
|
|
a8432e13a1 | ||
|
|
05ac139554 | ||
|
|
3661b2981e | ||
|
|
69bd7acf74 | ||
|
|
d882af257f | ||
|
|
c92058a79a | ||
|
|
ed2b576261 | ||
|
|
6744446a48 | ||
|
|
fdecec48b2 | ||
|
|
f1289c46e6 | ||
|
|
aa0b87be57 | ||
|
|
2040f02d07 | ||
|
|
13a69ecdfd | ||
|
|
f0051deff0 | ||
|
|
05a8148084 | ||
|
|
aaa44b3369 | ||
|
|
7f35c4430d | ||
|
|
114489d19a | ||
|
|
eda8200d51 | ||
|
|
b078ea9ceb | ||
|
|
d90b1a0ddd | ||
|
|
737a42e07a | ||
|
|
22d5d4c019 | ||
|
|
7ac1e7b6e1 | ||
|
|
e86ab783f3 | ||
|
|
6fe3e67ecb | ||
|
|
3b78034c55 | ||
|
|
a06a69797f | ||
|
|
8b1557e38c | ||
|
|
fcdc6d0df2 | ||
|
|
83b6cd7f05 | ||
|
|
38a9a6d51d | ||
|
|
5e2f16c678 | ||
|
|
d7ae95a779 | ||
|
|
8fbdf9afbd | ||
|
|
f5a4d78e62 | ||
|
|
1f4264e6a7 | ||
|
|
05baa851d8 | ||
|
|
35e8ae1224 | ||
|
|
ceec0bcc4a | ||
|
|
0d87e7fa5f | ||
|
|
a530629d97 | ||
|
|
ba0232b187 | ||
|
|
04a17cacb7 | ||
|
|
761d725fce | ||
|
|
726b0b1bcc | ||
|
|
888e031452 | ||
|
|
91b818b8c1 | ||
|
|
7646a64770 | ||
|
|
94c057e89c | ||
|
|
190d7cefb0 | ||
|
|
669bc071b1 | ||
|
|
31b9b6b5c0 | ||
|
|
914ecd34fe | ||
|
|
74532ff199 | ||
|
|
c7bcb55bda | ||
|
|
afe560ca7d | ||
|
|
1380c49fd0 | ||
|
|
90240a8da5 | ||
|
|
ad587f63ed | ||
|
|
3c7cb592b3 | ||
|
|
5b15c9500a | ||
|
|
2d25f0d6e4 | ||
|
|
557fc869eb | ||
|
|
033f44e802 | ||
|
|
ee3c1bc007 | ||
|
|
f507fe2e4d | ||
|
|
4a27ba0a3f | ||
|
|
e2e5fd8b31 | ||
|
|
ba9abd1dd0 | ||
|
|
ab66614843 | ||
|
|
caa2f5f030 | ||
|
|
6e7c8f5771 | ||
|
|
44c4566c9d | ||
|
|
9a1e6226b1 | ||
|
|
cdb6d54d6a | ||
|
|
1fbfd3f0cb | ||
|
|
848e6f59c2 | ||
|
|
b3a891c69b | ||
|
|
54e105d19d | ||
|
|
4cfb62a413 | ||
|
|
7cdf9cedf3 | ||
|
|
fd198c172b |
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).
|
||||||
202
README.md
202
README.md
@@ -1,149 +1,141 @@
|
|||||||
Spring Data - Document
|
# Spring Data MongoDB
|
||||||
======================
|
|
||||||
|
|
||||||
The primary goal of the [Spring Data](http://www.springsource.org/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://www.springsource.org/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.
|
||||||
As the name implies, the **Document** modules provides integration with document databases such as [MongoDB](http://www.mongodb.org/) and [CouchDB](http://couchdb.apache.org/).
|
|
||||||
|
|
||||||
Getting Help
|
The Spring Data MongoDB project aims to provide a familiar and consistent Spring-based programming model for new datastores while retaining store-specific features and capabilities. The Spring Data MongoDB project provides integration with the MongoDB document database. Key functional areas of Spring Data MongoDB are a POJO centric model for interacting with a MongoDB DBCollection and easily writing a repository style data access layer.
|
||||||
------------
|
|
||||||
|
|
||||||
At this point your best bet is to look at the Look at the [JavaDocs](http://static.springsource.org/spring-data/data-document/docs/1.0.0.BUILD-SNAPSHOT/spring-data-mongodb/apidocs/) for MongoDB integration and corresponding and source code. For more detailed questions, use the [forum](http://forum.springsource.org/forumdisplay.php?f=80). If you are new to Spring as well as to Spring Data, look for information about [Spring projects](http://www.springsource.org/projects).
|
## Getting Help
|
||||||
|
|
||||||
The [User Guide](http://static.springsource.org/spring-data/data-document/docs/1.0.0.BUILD-SNAPSHOT/reference/html/) (A work in progress).
|
For a comprehensive treatment of all the Spring Data MongoDB features, please refer to:
|
||||||
|
|
||||||
|
* the [User Guide](http://static.springsource.org/spring-data/data-mongodb/docs/current/reference/html/)
|
||||||
|
* the [JavaDocs](http://static.springsource.org/spring-data/data-mongodb/docs/current/api/) have extensive comments in them as well.
|
||||||
|
* the home page of [Spring Data MongoDB](http://www.springsource.org/spring-data/mongodb) contains links to articles and other resources.
|
||||||
|
* for more detailed questions, use the [forum](http://forum.springsource.org/forumdisplay.php?f=80).
|
||||||
|
|
||||||
|
If you are new to Spring as well as to Spring Data, look for information about [Spring projects](http://www.springsource.org/projects).
|
||||||
|
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
Quick Start
|
### Maven configuration
|
||||||
-----------
|
|
||||||
|
|
||||||
## MongoDB
|
Add the Maven dependency:
|
||||||
|
|
||||||
For those in a hurry:
|
```xml
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.data</groupId>
|
||||||
|
<artifactId>spring-data-mongodb</artifactId>
|
||||||
|
<version>1.3.5.RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
|
|
||||||
|
If you'd rather like the latest snapshots of the upcoming major version, use our Maven snapshot repository and declare the appropriate dependency version.
|
||||||
|
|
||||||
* Download the jar through Maven:
|
```xml
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.data</groupId>
|
||||||
|
<artifactId>spring-data-mongodb</artifactId>
|
||||||
|
<version>1.4.0.BUILD-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<repository>
|
||||||
<groupId>org.springframework.data</groupId>
|
<id>spring-libs-snapshot</id>
|
||||||
<artifactId>spring-data-mongodb</artifactId>
|
<name>Spring Snapshot Repository</name>
|
||||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||||
</dependency>
|
</repository>
|
||||||
|
```
|
||||||
|
|
||||||
<repository>
|
|
||||||
<id>spring-maven-snapshot</id>
|
|
||||||
<snapshots><enabled>true</enabled></snapshots>
|
|
||||||
<name>Springframework Maven SNAPSHOT Repository</name>
|
|
||||||
<url>http://maven.springframework.org/snapshot</url>
|
|
||||||
</repository>
|
|
||||||
|
|
||||||
### MongoTemplate
|
### MongoTemplate
|
||||||
MongoTemplate is the central support class for Mongo database operations. It provides
|
|
||||||
|
MongoTemplate is the central support class for Mongo database operations. It provides:
|
||||||
|
|
||||||
* Basic POJO mapping support to and from BSON
|
* Basic POJO mapping support to and from BSON
|
||||||
* Connection Affinity callback
|
* Convenience methods to interact with the store (insert object, update objects) and MongoDB specific ones (geo-spatial operations, upserts, map-reduce etc.)
|
||||||
|
* Connection affinity callback
|
||||||
* Exception translation into Spring's [technology agnostic DAO exception hierarchy](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/dao.html#dao-exceptions).
|
* Exception translation into Spring's [technology agnostic DAO exception hierarchy](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/dao.html#dao-exceptions).
|
||||||
|
|
||||||
Future plans are to support optional logging and/or exception throwing based on WriteResult return value, common map-reduce operations, GridFS operations. A simple API for partial document updates is also planned.
|
### Spring Data repositories
|
||||||
|
|
||||||
### Easy Data Repository generation
|
To simplify the creation of data repositories Spring Data MongoDB provides a generic repository programming model. It will automatically create a repository proxy for you that adds implementations of finder methods you specify on an interface.
|
||||||
|
|
||||||
To simplify the creation of Data Repositories a generic Repository interface and default implementation is provided. Furthermore, Spring will automatically create a Repository implementation for you that adds implementations of finder methods you specify on an interface.
|
For example, given a `Person` class with first and last name properties, a `PersonRepository` interface that can query for `Person` by last name and when the first name matches a like expression is shown below:
|
||||||
|
|
||||||
The Repository interface is
|
```java
|
||||||
|
public interface PersonRepository extends CrudRepository<Person, Long> {
|
||||||
|
|
||||||
public interface Repository<T, ID extends Serializable> {
|
List<Person> findByLastname(String lastname);
|
||||||
|
|
||||||
T save(T entity);
|
List<Person> findByFirstnameLike(String firstname);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
List<T> save(Iterable<? extends T> entities);
|
The queries issued on execution will be derived from the method name. Extending `CrudRepository` causes CRUD methods being pulled into the interface so that you can easily save and find single entities and collections of them.
|
||||||
|
|
||||||
T findById(ID id);
|
You can have Spring automatically create a proxy for the interface by using the following JavaConfig:
|
||||||
|
|
||||||
boolean exists(ID id);
|
```java
|
||||||
|
@Configuration
|
||||||
|
@EnableMongoRepositories
|
||||||
|
class ApplicationConfig extends AbstractMongoConfiguration {
|
||||||
|
|
||||||
List<T> findAll();
|
@Override
|
||||||
|
public Mongo mongo() throws Exception {
|
||||||
|
return new Mongo();
|
||||||
|
}
|
||||||
|
|
||||||
Long count();
|
@Override
|
||||||
|
protected String getDatabaseName() {
|
||||||
|
return "springdata";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
void delete(T entity);
|
This sets up a connection to a local MongoDB instance and enables the detection of Spring Data repositories (through `@EnableMongoRepositories`). The same configuration would look like this in XML:
|
||||||
|
|
||||||
void delete(Iterable<? extends T> entities);
|
```xml
|
||||||
|
<bean id="template" class="org.springframework.data.document.mongodb.MongoTemplate">
|
||||||
|
<constructor-arg>
|
||||||
|
<bean class="com.mongodb.Mongo">
|
||||||
|
<constructor-arg value="localhost" />
|
||||||
|
<constructor-arg value="27017" />
|
||||||
|
</bean>
|
||||||
|
</constructor-arg>
|
||||||
|
<constructor-arg value="database" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
void deleteAll();
|
<mongo:repositories base-package="com.acme.repository" />
|
||||||
}
|
```
|
||||||
|
|
||||||
|
This will find the repository interface and register a proxy object in the container. You can use it as shown below:
|
||||||
|
|
||||||
The MongoRepository extends Repository and will in future add more Mongo specific methods.
|
```java
|
||||||
|
@Service
|
||||||
|
public class MyService {
|
||||||
|
|
||||||
public interface MongoRepository<T, ID extends Serializable> extends
|
private final PersonRepository repository;
|
||||||
Repository<T, ID> {
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleMongoRepository is the out of the box implementation of the MongoRepository you can use for basid CRUD operations.
|
@Autowired
|
||||||
|
public MyService(PersonRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
To go beyond basic CRUD, extend the MongoRepository interface and supply your own finder methods that follow simple naming conventions such that they can be easily converted into queries.
|
public void doWork() {
|
||||||
|
|
||||||
For example, given a Person class with first and last name properties, a PersonRepository interface that can query for Person by last name and when the first name matches a regular expression is shown below
|
repository.deleteAll();
|
||||||
|
|
||||||
public interface PersonRepository extends MongoRepository<Person, Long> {
|
Person person = new Person();
|
||||||
|
person.setFirstname("Oliver");
|
||||||
|
person.setLastname("Gierke");
|
||||||
|
person = repository.save(person);
|
||||||
|
|
||||||
List<Person> findByLastname(String lastname);
|
List<Person> lastNameResults = repository.findByLastname("Gierke");
|
||||||
|
List<Person> firstNameResults = repository.findByFirstnameLike("Oli*");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
List<Person> findByFirstnameLike(String firstname);
|
## Contributing to Spring Data
|
||||||
}
|
|
||||||
|
|
||||||
You can have Spring automatically generate the implemention as shown below
|
|
||||||
|
|
||||||
<bean id="template" class="org.springframework.data.document.mongodb.MongoTemplate">
|
|
||||||
<constructor-arg>
|
|
||||||
<bean class="com.mongodb.Mongo">
|
|
||||||
<constructor-arg value="localhost" />
|
|
||||||
<constructor-arg value="27017" />
|
|
||||||
</bean>
|
|
||||||
</constructor-arg>
|
|
||||||
<constructor-arg value="database" />
|
|
||||||
<property name="defaultCollectionName" value="springdata" />
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<bean class="org.springframework.data.document.mongodb.repository.MongoRepositoryFactoryBean">
|
|
||||||
<property name="template" ref="template" />
|
|
||||||
<property name="repositoryInterface" value="org.springframework.data.document.mongodb.repository.PersonRepository" />
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
This will register an object in the container named PersonRepository. You can use it as shown below
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class MyService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
PersonRepository repository;
|
|
||||||
|
|
||||||
|
|
||||||
public void doWork() {
|
|
||||||
|
|
||||||
repository.deleteAll();
|
|
||||||
|
|
||||||
Person person = new Person();
|
|
||||||
person.setFirstname("Oliver");
|
|
||||||
person.setLastname("Gierke");
|
|
||||||
person = repository.save(person);
|
|
||||||
|
|
||||||
List<Person> lastNameResults = repository.findByLastname("Gierke");
|
|
||||||
|
|
||||||
List<Person> firstNameResults = repository.findByFirstnameLike("Oli*");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## CouchDB
|
|
||||||
|
|
||||||
TBD
|
|
||||||
|
|
||||||
|
|
||||||
Contributing to Spring Data
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
Here are some ways for you to get involved in the community:
|
Here are some ways for you to get involved in the community:
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||||
@@ -135,9 +135,9 @@
|
|||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||||
@@ -150,12 +150,12 @@
|
|||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||||
@@ -182,11 +182,11 @@
|
|||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||||
@@ -237,7 +237,7 @@
|
|||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||||
@@ -251,12 +251,12 @@
|
|||||||
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
|
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
|||||||
403
pom.xml
403
pom.xml
@@ -1,291 +1,128 @@
|
|||||||
<?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/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>org.springframework.data</groupId>
|
|
||||||
<artifactId>spring-data-mongodb-dist</artifactId>
|
|
||||||
<name>Spring Data MongoDB Distribution</name>
|
|
||||||
<version>1.1.0.M1</version>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
<modules>
|
|
||||||
<module>spring-data-mongodb</module>
|
|
||||||
<module>spring-data-mongodb-cross-store</module>
|
|
||||||
<module>spring-data-mongodb-log4j</module>
|
|
||||||
<module>spring-data-mongodb-parent</module>
|
|
||||||
</modules>
|
|
||||||
|
|
||||||
<developers>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<developer>
|
|
||||||
<id>trisberg</id>
|
<groupId>org.springframework.data</groupId>
|
||||||
<name>Thomas Risberg</name>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
<email>trisberg at vmware.com</email>
|
<version>1.3.6.BUILD-SNAPSHOT</version>
|
||||||
<organization>SpringSource</organization>
|
<packaging>pom</packaging>
|
||||||
<organizationUrl>http://www.SpringSource.com</organizationUrl>
|
|
||||||
<roles>
|
|
||||||
<role>Project Admin</role>
|
|
||||||
<role>Developer</role>
|
|
||||||
</roles>
|
|
||||||
<timezone>-5</timezone>
|
|
||||||
</developer>
|
|
||||||
<developer>
|
|
||||||
<id>mpollack</id>
|
|
||||||
<name>Mark Pollack</name>
|
|
||||||
<email>mpollack at vmware.com</email>
|
|
||||||
<organization>SpringSource</organization>
|
|
||||||
<organizationUrl>http://www.SpringSource.com</organizationUrl>
|
|
||||||
<roles>
|
|
||||||
<role>Project Admin</role>
|
|
||||||
<role>Developer</role>
|
|
||||||
</roles>
|
|
||||||
<timezone>-5</timezone>
|
|
||||||
</developer>
|
|
||||||
<developer>
|
|
||||||
<id>ogierke</id>
|
|
||||||
<name>Oliver Gierke</name>
|
|
||||||
<email>ogierke at vmware.com</email>
|
|
||||||
<organization>SpringSource</organization>
|
|
||||||
<organizationUrl>http://www.springsource.com</organizationUrl>
|
|
||||||
<roles>
|
|
||||||
<role>Developer</role>
|
|
||||||
</roles>
|
|
||||||
<timezone>+1</timezone>
|
|
||||||
</developer>
|
|
||||||
<developer>
|
|
||||||
<id>jbrisbin</id>
|
|
||||||
<name>Jon Brisbin</name>
|
|
||||||
<email>jbrisbin at vmware.com</email>
|
|
||||||
<organization>SpringSource</organization>
|
|
||||||
<organizationUrl>http://www.springsource.com</organizationUrl>
|
|
||||||
<roles>
|
|
||||||
<role>Developer</role>
|
|
||||||
</roles>
|
|
||||||
<timezone>-6</timezone>
|
|
||||||
</developer>
|
|
||||||
</developers>
|
|
||||||
|
|
||||||
<licenses>
|
<name>Spring Data MongoDB</name>
|
||||||
<license>
|
<description>MongoDB support for Spring Data</description>
|
||||||
<name>Apache License, Version 2.0</name>
|
<url>http://projects.spring.io/spring-data-mongodb</url>
|
||||||
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
|
|
||||||
<comments>
|
|
||||||
Copyright 2010 the original author or authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
<parent>
|
||||||
you may not use this file except in compliance with the License.
|
<groupId>org.springframework.data.build</groupId>
|
||||||
You may obtain a copy of the License at
|
<artifactId>spring-data-parent</artifactId>
|
||||||
|
<version>1.2.2.RELEASE</version>
|
||||||
|
<relativePath>../spring-data-build/parent/pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>spring-data-mongodb</module>
|
||||||
|
<module>spring-data-mongodb-cross-store</module>
|
||||||
|
<module>spring-data-mongodb-log4j</module>
|
||||||
|
<module>spring-data-mongodb-distribution</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
<properties>
|
||||||
|
<project.type>multi</project.type>
|
||||||
|
<dist.id>spring-data-mongodb</dist.id>
|
||||||
|
<springdata.commons>1.6.5.RELEASE</springdata.commons>
|
||||||
|
<mongo>2.10.1</mongo>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<id>ogierke</id>
|
||||||
|
<name>Oliver Gierke</name>
|
||||||
|
<email>ogierke at gopivotal.com</email>
|
||||||
|
<organization>Pivotal Software, Inc.</organization>
|
||||||
|
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
||||||
|
<roles>
|
||||||
|
<role>Project Lean</role>
|
||||||
|
</roles>
|
||||||
|
<timezone>+1</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>trisberg</id>
|
||||||
|
<name>Thomas Risberg</name>
|
||||||
|
<email>trisberg at gopivotal.com</email>
|
||||||
|
<organization>Pivotal Software, Inc.</organization>
|
||||||
|
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
||||||
|
<roles>
|
||||||
|
<role>Developer</role>
|
||||||
|
</roles>
|
||||||
|
<timezone>-5</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>mpollack</id>
|
||||||
|
<name>Mark Pollack</name>
|
||||||
|
<email>mpollack at gopivotal.com</email>
|
||||||
|
<organization>Pivotal Software, Inc.</organization>
|
||||||
|
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
||||||
|
<roles>
|
||||||
|
<role>Developer</role>
|
||||||
|
</roles>
|
||||||
|
<timezone>-5</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>jbrisbin</id>
|
||||||
|
<name>Jon Brisbin</name>
|
||||||
|
<email>jbrisbin at gopivotal.com</email>
|
||||||
|
<organization>Pivotal Software, Inc.</organization>
|
||||||
|
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
||||||
|
<roles>
|
||||||
|
<role>Developer</role>
|
||||||
|
</roles>
|
||||||
|
<timezone>-6</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>tdarimont</id>
|
||||||
|
<name>Thomas Darimont</name>
|
||||||
|
<email>tdarimont at gopivotal.com</email>
|
||||||
|
<organization>Pivotal Software, Inc.</organization>
|
||||||
|
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
||||||
|
<roles>
|
||||||
|
<role>Developer</role>
|
||||||
|
</roles>
|
||||||
|
<timezone>+1</timezone>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>cstrobl</id>
|
||||||
|
<name>Christoph Strobl</name>
|
||||||
|
<email>cstrobl at gopivotal.com</email>
|
||||||
|
<organization>Pivotal Software, Inc.</organization>
|
||||||
|
<organizationUrl>http://www.gopivotal.com</organizationUrl>
|
||||||
|
<roles>
|
||||||
|
<role>Developer</role>
|
||||||
|
</roles>
|
||||||
|
<timezone>+1</timezone>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
<dependencies>
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
<!-- MongoDB -->
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
<dependency>
|
||||||
implied.
|
<groupId>org.mongodb</groupId>
|
||||||
See the License for the specific language governing permissions and
|
<artifactId>mongo-java-driver</artifactId>
|
||||||
limitations under the License.
|
<version>${mongo}</version>
|
||||||
</comments>
|
</dependency>
|
||||||
</license>
|
</dependencies>
|
||||||
</licenses>
|
|
||||||
|
<repositories>
|
||||||
<properties>
|
<repository>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<id>spring-lib-snapshot</id>
|
||||||
<!-- dist.* properties are used by the antrun tasks below -->
|
<url>http://repo.spring.io/libs-snapshot</url>
|
||||||
<dist.id>spring-data-mongo</dist.id>
|
</repository>
|
||||||
<dist.name>Spring Data Mongo</dist.name>
|
</repositories>
|
||||||
<dist.key>SDMONGO</dist.key>
|
|
||||||
<dist.version>${project.version}</dist.version>
|
<pluginRepositories>
|
||||||
<dist.releaseType>snapshot</dist.releaseType>
|
<pluginRepository>
|
||||||
<dist.finalName>${dist.id}-${dist.version}</dist.finalName>
|
<id>spring-plugins-release</id>
|
||||||
<dist.fileName>${dist.finalName}.zip</dist.fileName>
|
<url>http://repo.spring.io/plugins-release</url>
|
||||||
<dist.filePath>target/${dist.fileName}</dist.filePath>
|
</pluginRepository>
|
||||||
<dist.bucketName>dist.springframework.org</dist.bucketName>
|
</pluginRepositories>
|
||||||
<!-- these properties should be in ~/.m2/settings.xml
|
|
||||||
<dist.accessKey>s3 access key</dist.accessKey>
|
|
||||||
<dist.secretKey>s3 secret key</dist.secretKey>
|
|
||||||
-->
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<extensions>
|
|
||||||
<extension>
|
|
||||||
<groupId>org.springframework.build.aws</groupId>
|
|
||||||
<artifactId>org.springframework.build.aws.maven</artifactId>
|
|
||||||
<version>3.1.0.RELEASE</version>
|
|
||||||
</extension>
|
|
||||||
</extensions>
|
|
||||||
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>com.agilejava.docbkx</groupId>
|
|
||||||
<artifactId>docbkx-maven-plugin</artifactId>
|
|
||||||
<!-- yes it really needs to be this (2.0.7) otherwise pdf generation from a clean build doesn't work -->
|
|
||||||
<version>2.0.7</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>generate-html</goal>
|
|
||||||
<goal>generate-pdf</goal>
|
|
||||||
</goals>
|
|
||||||
<phase>pre-site</phase>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.docbook</groupId>
|
|
||||||
<artifactId>docbook-xml</artifactId>
|
|
||||||
<version>4.4</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
<configuration>
|
|
||||||
<includes>index.xml</includes>
|
|
||||||
<xincludeSupported>true</xincludeSupported>
|
|
||||||
<foCustomization>${project.basedir}/src/docbkx/resources/xsl/fopdf.xsl</foCustomization>
|
|
||||||
<htmlStylesheet>css/html.css</htmlStylesheet>
|
|
||||||
<chunkedOutput>false</chunkedOutput>
|
|
||||||
<htmlCustomization>${project.basedir}/src/docbkx/resources/xsl/html.xsl</htmlCustomization>
|
|
||||||
<useExtensions>1</useExtensions>
|
|
||||||
<highlightSource>1</highlightSource>
|
|
||||||
<highlightDefaultLanguage />
|
|
||||||
<!-- callouts -->
|
|
||||||
<entities>
|
|
||||||
<entity>
|
|
||||||
<name>version</name>
|
|
||||||
<value>${project.version}</value>
|
|
||||||
</entity>
|
|
||||||
</entities>
|
|
||||||
<postProcess>
|
|
||||||
<copy todir="${project.basedir}/target/site/reference">
|
|
||||||
<fileset dir="${project.basedir}/target/docbkx">
|
|
||||||
<include name="**/*.html" />
|
|
||||||
<include name="**/*.pdf" />
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="${project.basedir}/target/site/reference/html">
|
|
||||||
<fileset dir="${project.basedir}/src/docbkx/resources">
|
|
||||||
<include name="**/*.css" />
|
|
||||||
<include name="**/*.png" />
|
|
||||||
<include name="**/*.gif" />
|
|
||||||
<include name="**/*.jpg" />
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="${project.basedir}/target/site/reference/html">
|
|
||||||
<fileset dir="${project.basedir}/src/docbkx/resources/images">
|
|
||||||
<include name="*.png" />
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<move file="${project.basedir}/target/site/reference/pdf/index.pdf" tofile="${project.basedir}/target/site/reference/pdf/spring-data-mongo-reference.pdf" failonerror="false" />
|
|
||||||
</postProcess>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
|
||||||
<version>2.5</version>
|
|
||||||
<configuration>
|
|
||||||
<aggregate>true</aggregate>
|
|
||||||
<breakiterator>true</breakiterator>
|
|
||||||
<header>Spring Data Document</header>
|
|
||||||
<source>1.5</source>
|
|
||||||
<quiet>true</quiet>
|
|
||||||
<javadocDirectory>${project.basedir}/src/main/javadoc</javadocDirectory>
|
|
||||||
<overview>${project.basedir}/src/main/javadoc/overview.html</overview>
|
|
||||||
<stylesheetfile>${project.basedir}/src/main/javadoc/spring-javadoc.css</stylesheetfile>
|
|
||||||
<!-- copies doc-files subdirectory which contains image resources -->
|
|
||||||
<docfilessubdirs>true</docfilessubdirs>
|
|
||||||
<links>
|
|
||||||
<link>http://static.springframework.org/spring/docs/3.0.x/javadoc-api</link>
|
|
||||||
<link>http://download.oracle.com/javase/1.5.0/docs/api</link>
|
|
||||||
<link>http://api.mongodb.org/java/2.3</link>
|
|
||||||
</links>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin><!--
|
|
||||||
run `mvn package assembly:assembly` to trigger assembly creation.
|
|
||||||
see http://www.sonatype.com/books/mvnref-book/reference/assemblies-set-dist-assemblies.html -->
|
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
|
||||||
<version>2.2-beta-5</version>
|
|
||||||
<inherited>false</inherited>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>distribution</id>
|
|
||||||
<goals>
|
|
||||||
<goal>single</goal>
|
|
||||||
</goals>
|
|
||||||
<phase>package</phase>
|
|
||||||
<configuration>
|
|
||||||
<descriptors>
|
|
||||||
<descriptor>${project.basedir}/src/assembly/distribution.xml</descriptor>
|
|
||||||
</descriptors>
|
|
||||||
<appendAssemblyId>false</appendAssemblyId>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-antrun-plugin</artifactId>
|
|
||||||
<version>1.4</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>upload-dist</id>
|
|
||||||
<phase>deploy</phase>
|
|
||||||
<configuration>
|
|
||||||
<tasks>
|
|
||||||
<ant antfile="${basedir}/src/ant/upload-dist.xml">
|
|
||||||
<target name="upload-dist" />
|
|
||||||
</ant>
|
|
||||||
</tasks>
|
|
||||||
</configuration>
|
|
||||||
<goals>
|
|
||||||
<goal>run</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.build</groupId>
|
|
||||||
<artifactId>org.springframework.build.aws.ant</artifactId>
|
|
||||||
<version>3.0.5.RELEASE</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.java.dev.jets3t</groupId>
|
|
||||||
<artifactId>jets3t</artifactId>
|
|
||||||
<version>0.7.2</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
<!-- the name of this project is 'spring-data-mongo-dist';
|
|
||||||
make sure the zip file is just 'spring-data-mongo'. -->
|
|
||||||
<finalName>${dist.finalName}</finalName>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<pluginRepositories>
|
|
||||||
<!-- Necessary for the build extension -->
|
|
||||||
<pluginRepository>
|
|
||||||
<id>spring-plugins-release</id>
|
|
||||||
<url>http://repo.springsource.org/plugins-release</url>
|
|
||||||
</pluginRepository>
|
|
||||||
</pluginRepositories>
|
|
||||||
|
|
||||||
<distributionManagement>
|
|
||||||
<!-- see 'staging' profile for dry-run deployment settings -->
|
|
||||||
<downloadUrl>http://www.springsource.com/spring-data</downloadUrl>
|
|
||||||
<site>
|
|
||||||
<id>static.springframework.org</id>
|
|
||||||
<url>
|
|
||||||
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-mongodb/snapshot-site
|
|
||||||
</url>
|
|
||||||
</site>
|
|
||||||
<repository>
|
|
||||||
<id>spring-milestone</id>
|
|
||||||
<name>Spring Milestone Repository</name>
|
|
||||||
<url>s3://maven.springframework.org/milestone</url>
|
|
||||||
</repository>
|
|
||||||
<snapshotRepository>
|
|
||||||
<id>spring-snapshot</id>
|
|
||||||
<name>Spring Snapshot Repository</name>
|
|
||||||
<url>s3://maven.springframework.org/snapshot</url>
|
|
||||||
</snapshotRepository>
|
|
||||||
</distributionManagement>
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,139 +1,145 @@
|
|||||||
<?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>
|
|
||||||
<parent>
|
|
||||||
<groupId>org.springframework.data</groupId>
|
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
|
||||||
<version>1.1.0.M1</version>
|
|
||||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
<artifactId>spring-data-mongodb-cross-store</artifactId>
|
|
||||||
<name>Spring Data MongoDB Cross-store Persistence Support</name>
|
|
||||||
<dependencies>
|
|
||||||
|
|
||||||
<!-- Spring -->
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
<parent>
|
||||||
<artifactId>spring-beans</artifactId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<version>${org.springframework.version.range}</version>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
</dependency>
|
<version>1.3.6.BUILD-SNAPSHOT</version>
|
||||||
<dependency>
|
<relativePath>../pom.xml</relativePath>
|
||||||
<groupId>org.springframework</groupId>
|
</parent>
|
||||||
<artifactId>spring-tx</artifactId>
|
|
||||||
<version>${org.springframework.version.range}</version>
|
<artifactId>spring-data-mongodb-cross-store</artifactId>
|
||||||
</dependency>
|
<name>Spring Data MongoDB - Cross-Store Persistence Support</name>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
<properties>
|
||||||
<artifactId>spring-aspects</artifactId>
|
<jpa>1.0.0.Final</jpa>
|
||||||
<version>${org.springframework.version.range}</version>
|
<hibernate>3.6.10.Final</hibernate>
|
||||||
</dependency>
|
</properties>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
<dependencies>
|
||||||
<artifactId>spring-orm</artifactId>
|
|
||||||
<version>${org.springframework.version.range}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Spring Data -->
|
<!-- Spring -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-data-commons-core</artifactId>
|
<artifactId>spring-beans</artifactId>
|
||||||
<version>${data.commons.version}</version>
|
<version>${spring}</version>
|
||||||
</dependency>
|
<exclusions>
|
||||||
<dependency>
|
<exclusion>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>commons-logging</groupId>
|
||||||
<artifactId>spring-data-mongodb</artifactId>
|
<artifactId>commons-logging</artifactId>
|
||||||
<version>1.1.0.M1</version>
|
</exclusion>
|
||||||
</dependency>
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-tx</artifactId>
|
||||||
|
<version>${spring}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-aspects</artifactId>
|
||||||
|
<version>${spring}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-orm</artifactId>
|
||||||
|
<version>${spring}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<!-- Spring Data -->
|
||||||
<groupId>org.aspectj</groupId>
|
<dependency>
|
||||||
<artifactId>aspectjrt</artifactId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<version>${aspectj.version}</version>
|
<artifactId>spring-data-mongodb</artifactId>
|
||||||
</dependency>
|
<version>1.3.6.BUILD-SNAPSHOT</version>
|
||||||
<dependency>
|
</dependency>
|
||||||
<groupId>cglib</groupId>
|
|
||||||
<artifactId>cglib</artifactId>
|
|
||||||
<version>2.2</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- JPA -->
|
<dependency>
|
||||||
<dependency>
|
<groupId>org.aspectj</groupId>
|
||||||
<groupId>org.hibernate.javax.persistence</groupId>
|
<artifactId>aspectjrt</artifactId>
|
||||||
<artifactId>hibernate-jpa-2.0-api</artifactId>
|
<version>${aspectj}</version>
|
||||||
<version>1.0.0.Final</version>
|
</dependency>
|
||||||
</dependency>
|
<dependency>
|
||||||
|
<groupId>cglib</groupId>
|
||||||
|
<artifactId>cglib</artifactId>
|
||||||
|
<version>2.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- For Tests -->
|
<!-- JPA -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate</groupId>
|
<groupId>org.hibernate.javax.persistence</groupId>
|
||||||
<artifactId>hibernate-entitymanager</artifactId>
|
<artifactId>hibernate-jpa-2.0-api</artifactId>
|
||||||
<version>3.5.5-Final</version>
|
<version>${jpa}</version>
|
||||||
<scope>test</scope>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>hsqldb</groupId>
|
|
||||||
<artifactId>hsqldb</artifactId>
|
|
||||||
<version>1.8.0.10</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.validation</groupId>
|
|
||||||
<artifactId>validation-api</artifactId>
|
|
||||||
<version>1.0.0.GA</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hibernate</groupId>
|
|
||||||
<artifactId>hibernate-validator</artifactId>
|
|
||||||
<version>4.0.2.GA</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
<!-- For Tests -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-entitymanager</artifactId>
|
||||||
|
<version>${hibernate}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>hsqldb</groupId>
|
||||||
|
<artifactId>hsqldb</artifactId>
|
||||||
|
<version>1.8.0.10</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.validation</groupId>
|
||||||
|
<artifactId>validation-api</artifactId>
|
||||||
|
<version>1.0.0.GA</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-validator</artifactId>
|
||||||
|
<version>4.0.2.GA</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<build>
|
</dependencies>
|
||||||
<plugins>
|
|
||||||
<plugin>
|
<build>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<plugins>
|
||||||
<artifactId>aspectj-maven-plugin</artifactId>
|
<plugin>
|
||||||
<version>1.2</version>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<dependencies>
|
<artifactId>aspectj-maven-plugin</artifactId>
|
||||||
<dependency>
|
<version>1.4</version>
|
||||||
<groupId>org.aspectj</groupId>
|
<dependencies>
|
||||||
<artifactId>aspectjrt</artifactId>
|
<dependency>
|
||||||
<version>${aspectj.version}</version>
|
<groupId>org.aspectj</groupId>
|
||||||
</dependency>
|
<artifactId>aspectjrt</artifactId>
|
||||||
<dependency>
|
<version>${aspectj}</version>
|
||||||
<groupId>org.aspectj</groupId>
|
</dependency>
|
||||||
<artifactId>aspectjtools</artifactId>
|
<dependency>
|
||||||
<version>${aspectj.version}</version>
|
<groupId>org.aspectj</groupId>
|
||||||
</dependency>
|
<artifactId>aspectjtools</artifactId>
|
||||||
</dependencies>
|
<version>${aspectj}</version>
|
||||||
<executions>
|
</dependency>
|
||||||
<execution>
|
</dependencies>
|
||||||
<goals>
|
<executions>
|
||||||
<goal>compile</goal>
|
<execution>
|
||||||
<goal>test-compile</goal>
|
<goals>
|
||||||
</goals>
|
<goal>compile</goal>
|
||||||
</execution>
|
<goal>test-compile</goal>
|
||||||
</executions>
|
</goals>
|
||||||
<configuration>
|
</execution>
|
||||||
<outxml>true</outxml>
|
</executions>
|
||||||
<aspectLibraries>
|
<configuration>
|
||||||
<aspectLibrary>
|
<outxml>true</outxml>
|
||||||
<groupId>org.springframework</groupId>
|
<aspectLibraries>
|
||||||
<artifactId>spring-aspects</artifactId>
|
<aspectLibrary>
|
||||||
</aspectLibrary>
|
<groupId>org.springframework</groupId>
|
||||||
<!-- <aspectLibrary>
|
<artifactId>spring-aspects</artifactId>
|
||||||
<groupId>org.springframework.data</groupId>
|
</aspectLibrary>
|
||||||
<artifactId>spring-data-commons-aspects</artifactId>
|
</aspectLibraries>
|
||||||
</aspectLibrary> -->
|
<source>${source.level}</source>
|
||||||
</aspectLibraries>
|
<target>${source.level}</target>
|
||||||
<source>1.5</source>
|
</configuration>
|
||||||
<target>1.5</target>
|
</plugin>
|
||||||
</configuration>
|
</plugins>
|
||||||
</plugin>
|
</build>
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011 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.
|
||||||
@@ -17,8 +17,8 @@ package org.springframework.data.mongodb.crossstore;
|
|||||||
|
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.slf4j.Logger;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
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.DataIntegrityViolationException;
|
||||||
@@ -34,6 +34,10 @@ import com.mongodb.DBCollection;
|
|||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
import com.mongodb.MongoException;
|
import com.mongodb.MongoException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Thomas Risberg
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||||
|
|
||||||
private static final String ENTITY_CLASS = "_entity_class";
|
private static final String ENTITY_CLASS = "_entity_class";
|
||||||
@@ -44,7 +48,7 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
|
|
||||||
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
|
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
|
||||||
|
|
||||||
protected final Log log = LogFactory.getLog(getClass());
|
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
private MongoTemplate mongoTemplate;
|
private MongoTemplate mongoTemplate;
|
||||||
|
|
||||||
@@ -58,6 +62,10 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
this.entityManagerFactory = entityManagerFactory;
|
this.entityManagerFactory = entityManagerFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentState(java.lang.Class, java.lang.Object, org.springframework.data.crossstore.ChangeSet)
|
||||||
|
*/
|
||||||
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass, Object id, final ChangeSet changeSet)
|
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass, Object id, final ChangeSet changeSet)
|
||||||
throws DataAccessException, NotFoundException {
|
throws DataAccessException, NotFoundException {
|
||||||
|
|
||||||
@@ -100,6 +108,10 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @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 {
|
||||||
log.debug("getPersistentId called on " + entity);
|
log.debug("getPersistentId called on " + entity);
|
||||||
if (entityManagerFactory == null) {
|
if (entityManagerFactory == null) {
|
||||||
@@ -109,6 +121,10 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.crossstore.ChangeSetPersister#persistState(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
|
||||||
|
*/
|
||||||
public Object persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
public Object persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
||||||
if (cs == null) {
|
if (cs == null) {
|
||||||
log.debug("Flush: changeset was null, nothing to flush.");
|
log.debug("Flush: changeset was null, nothing to flush.");
|
||||||
@@ -169,8 +185,13 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
|||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the collection the given entity type shall be persisted to.
|
||||||
|
*
|
||||||
|
* @param entityClass must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private String getCollectionNameForEntity(Class<? extends ChangeSetBacked> entityClass) {
|
private String getCollectionNameForEntity(Class<? extends ChangeSetBacked> entityClass) {
|
||||||
return ClassUtils.getQualifiedName(entityClass);
|
return mongoTemplate.getCollectionName(entityClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,13 +21,12 @@ import javax.persistence.EntityManager;
|
|||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.aspectj.lang.reflect.FieldSignature;
|
import org.aspectj.lang.reflect.FieldSignature;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
|
|
||||||
import org.springframework.data.mongodb.crossstore.RelatedDocument;
|
import org.springframework.data.mongodb.crossstore.RelatedDocument;
|
||||||
import org.springframework.data.mongodb.crossstore.DocumentBacked;
|
import org.springframework.data.mongodb.crossstore.DocumentBacked;
|
||||||
import org.springframework.data.crossstore.ChangeSetBackedTransactionSynchronization;
|
import org.springframework.data.crossstore.ChangeSetBackedTransactionSynchronization;
|
||||||
@@ -44,7 +43,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
|
|||||||
*/
|
*/
|
||||||
public aspect MongoDocumentBacking {
|
public aspect MongoDocumentBacking {
|
||||||
|
|
||||||
private static final Log LOGGER = LogFactory.getLog(MongoDocumentBacking.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(MongoDocumentBacking.class);
|
||||||
|
|
||||||
// Aspect shared config
|
// Aspect shared config
|
||||||
private ChangeSetPersister<Object> changeSetPersister;
|
private ChangeSetPersister<Object> changeSetPersister;
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* Infrastructure for Spring Data's MongoDB cross store support.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.mongodb.crossstore;
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011 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.
|
||||||
@@ -18,7 +18,9 @@ package org.springframework.data.mongodb.crossstore;
|
|||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.PersistenceContext;
|
import javax.persistence.PersistenceContext;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -26,7 +28,6 @@ import org.springframework.data.mongodb.core.MongoTemplate;
|
|||||||
import org.springframework.data.mongodb.crossstore.test.Address;
|
import org.springframework.data.mongodb.crossstore.test.Address;
|
||||||
import org.springframework.data.mongodb.crossstore.test.Person;
|
import org.springframework.data.mongodb.crossstore.test.Person;
|
||||||
import org.springframework.data.mongodb.crossstore.test.Resume;
|
import org.springframework.data.mongodb.crossstore.test.Resume;
|
||||||
import org.springframework.test.annotation.Rollback;
|
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
@@ -35,55 +36,76 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.transaction.support.TransactionCallback;
|
import org.springframework.transaction.support.TransactionCallback;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
import com.mongodb.DBCollection;
|
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for MongoDB cross-store persistence (mainly {@link MongoChangeSetPersister}).
|
||||||
|
*
|
||||||
|
* @author Thomas Risberg
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration(locations = "classpath:/META-INF/spring/applicationContext.xml")
|
@ContextConfiguration("classpath:/META-INF/spring/applicationContext.xml")
|
||||||
public class CrossStoreMongoTests {
|
public class CrossStoreMongoTests {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MongoTemplate mongoTemplate;
|
MongoTemplate mongoTemplate;
|
||||||
|
|
||||||
private EntityManager entityManager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private PlatformTransactionManager transactionManager;
|
|
||||||
|
|
||||||
@PersistenceContext
|
@PersistenceContext
|
||||||
public void setEntityManager(EntityManager entityManager) {
|
EntityManager entityManager;
|
||||||
this.entityManager = entityManager;
|
|
||||||
|
@Autowired
|
||||||
|
PlatformTransactionManager transactionManager;
|
||||||
|
TransactionTemplate txTemplate;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
|
||||||
|
txTemplate = new TransactionTemplate(transactionManager);
|
||||||
|
|
||||||
|
clearData(Person.class);
|
||||||
|
|
||||||
|
Address address = new Address(12, "MAin St.", "Boston", "MA", "02101");
|
||||||
|
|
||||||
|
Resume resume = new Resume();
|
||||||
|
resume.addEducation("Skanstulls High School, 1975");
|
||||||
|
resume.addEducation("Univ. of Stockholm, 1980");
|
||||||
|
resume.addJob("DiMark, DBA, 1990-2000");
|
||||||
|
resume.addJob("VMware, Developer, 2007-");
|
||||||
|
|
||||||
|
final Person person = new Person("Thomas", 20);
|
||||||
|
person.setAddress(address);
|
||||||
|
person.setResume(resume);
|
||||||
|
person.setId(1L);
|
||||||
|
|
||||||
|
txTemplate.execute(new TransactionCallback<Void>() {
|
||||||
|
public Void doInTransaction(TransactionStatus status) {
|
||||||
|
entityManager.persist(person);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearData(String collectionName) {
|
@After
|
||||||
DBCollection col = this.mongoTemplate.getCollection(collectionName);
|
public void tearDown() {
|
||||||
if (col != null) {
|
txTemplate.execute(new TransactionCallback<Void>() {
|
||||||
this.mongoTemplate.dropCollection(collectionName);
|
public Void doInTransaction(TransactionStatus status) {
|
||||||
}
|
entityManager.remove(entityManager.find(Person.class, 1L));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearData(Class<?> domainType) {
|
||||||
|
|
||||||
|
String collectionName = mongoTemplate.getCollectionName(domainType);
|
||||||
|
mongoTemplate.dropCollection(collectionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
@Rollback(false)
|
|
||||||
public void testCreateJpaToMongoEntityRelationship() {
|
|
||||||
clearData(Person.class.getName());
|
|
||||||
Person p = new Person("Thomas", 20);
|
|
||||||
Address a = new Address(12, "MAin St.", "Boston", "MA", "02101");
|
|
||||||
p.setAddress(a);
|
|
||||||
Resume r = new Resume();
|
|
||||||
r.addEducation("Skanstulls High School, 1975");
|
|
||||||
r.addEducation("Univ. of Stockholm, 1980");
|
|
||||||
r.addJob("DiMark, DBA, 1990-2000");
|
|
||||||
r.addJob("VMware, Developer, 2007-");
|
|
||||||
p.setResume(r);
|
|
||||||
p.setId(1L);
|
|
||||||
entityManager.persist(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Transactional
|
|
||||||
@Rollback(false)
|
|
||||||
public void testReadJpaToMongoEntityRelationship() {
|
public void testReadJpaToMongoEntityRelationship() {
|
||||||
|
|
||||||
Person found = entityManager.find(Person.class, 1L);
|
Person found = entityManager.find(Person.class, 1L);
|
||||||
Assert.assertNotNull(found);
|
Assert.assertNotNull(found);
|
||||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||||
@@ -91,15 +113,18 @@ public class CrossStoreMongoTests {
|
|||||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||||
Assert.assertNotNull(found.getResume());
|
Assert.assertNotNull(found.getResume());
|
||||||
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; " + "VMware, Developer, 2007-", found.getResume().getJobs());
|
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; " + "VMware, Developer, 2007-", found.getResume().getJobs());
|
||||||
found.getResume().addJob("SpringDeveloper.com, Consultant, 2005-2006");
|
|
||||||
found.setAge(44);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Transactional
|
@Transactional
|
||||||
@Rollback(false)
|
|
||||||
public void testUpdatedJpaToMongoEntityRelationship() {
|
public void testUpdatedJpaToMongoEntityRelationship() {
|
||||||
|
|
||||||
Person found = entityManager.find(Person.class, 1L);
|
Person found = entityManager.find(Person.class, 1L);
|
||||||
|
found.setAge(44);
|
||||||
|
found.getResume().addJob("SpringDeveloper.com, Consultant, 2005-2006");
|
||||||
|
|
||||||
|
entityManager.merge(found);
|
||||||
|
|
||||||
Assert.assertNotNull(found);
|
Assert.assertNotNull(found);
|
||||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||||
Assert.assertNotNull(found);
|
Assert.assertNotNull(found);
|
||||||
@@ -111,14 +136,19 @@ public class CrossStoreMongoTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMergeJpaEntityWithMongoDocument() {
|
public void testMergeJpaEntityWithMongoDocument() {
|
||||||
TransactionTemplate txTemplate = new TransactionTemplate(transactionManager);
|
|
||||||
final Person detached = entityManager.find(Person.class, 1L);
|
final Person detached = entityManager.find(Person.class, 1L);
|
||||||
|
entityManager.detach(detached);
|
||||||
detached.getResume().addJob("TargetRx, Developer, 2000-2005");
|
detached.getResume().addJob("TargetRx, Developer, 2000-2005");
|
||||||
|
|
||||||
Person merged = txTemplate.execute(new TransactionCallback<Person>() {
|
Person merged = txTemplate.execute(new TransactionCallback<Person>() {
|
||||||
public Person doInTransaction(TransactionStatus status) {
|
public Person doInTransaction(TransactionStatus status) {
|
||||||
return entityManager.merge(detached);
|
Person result = entityManager.merge(detached);
|
||||||
|
entityManager.flush();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Assert.assertTrue(detached.getResume().getJobs().contains("TargetRx, Developer, 2000-2005"));
|
Assert.assertTrue(detached.getResume().getJobs().contains("TargetRx, Developer, 2000-2005"));
|
||||||
Assert.assertTrue(merged.getResume().getJobs().contains("TargetRx, Developer, 2000-2005"));
|
Assert.assertTrue(merged.getResume().getJobs().contains("TargetRx, Developer, 2000-2005"));
|
||||||
final Person updated = entityManager.find(Person.class, 1L);
|
final Person updated = entityManager.find(Person.class, 1L);
|
||||||
@@ -127,7 +157,7 @@ public class CrossStoreMongoTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveJpaEntityWithMongoDocument() {
|
public void testRemoveJpaEntityWithMongoDocument() {
|
||||||
TransactionTemplate txTemplate = new TransactionTemplate(transactionManager);
|
|
||||||
txTemplate.execute(new TransactionCallback<Person>() {
|
txTemplate.execute(new TransactionCallback<Person>() {
|
||||||
public Person doInTransaction(TransactionStatus status) {
|
public Person doInTransaction(TransactionStatus status) {
|
||||||
Person p2 = new Person("Thomas", 20);
|
Person p2 = new Person("Thomas", 20);
|
||||||
@@ -154,8 +184,10 @@ public class CrossStoreMongoTests {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
boolean weFound3 = false;
|
boolean weFound3 = false;
|
||||||
for (DBObject dbo : this.mongoTemplate.getCollection(Person.class.getName()).find()) {
|
|
||||||
|
for (DBObject dbo : this.mongoTemplate.getCollection(mongoTemplate.getCollectionName(Person.class)).find()) {
|
||||||
Assert.assertTrue(!dbo.get("_entity_id").equals(2L));
|
Assert.assertTrue(!dbo.get("_entity_id").equals(2L));
|
||||||
if (dbo.get("_entity_id").equals(3L)) {
|
if (dbo.get("_entity_id").equals(3L)) {
|
||||||
weFound3 = true;
|
weFound3 = true;
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
log4j.rootCategory=INFO, stdout
|
|
||||||
|
|
||||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
|
||||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
|
||||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %40.40c:%4L - %m%n
|
|
||||||
|
|
||||||
log4j.category.org.springframework=INFO
|
|
||||||
log4j.category.org.springframework.data=TRACE
|
|
||||||
|
|
||||||
log4j.category.org.hibernate.SQL=DEBUG
|
|
||||||
# for debugging datasource initialization
|
|
||||||
# log4j.category.test.jdbc=DEBUG
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<logger name="org.springframework" level="debug" />
|
||||||
|
-->
|
||||||
|
|
||||||
|
<root level="error">
|
||||||
|
<appender-ref ref="console" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
18
spring-data-mongodb-cross-store/template.mf
Normal file
18
spring-data-mongodb-cross-store/template.mf
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
Bundle-SymbolicName: org.springframework.data.mongodb.crossstore
|
||||||
|
Bundle-Name: Spring Data MongoDB Cross Store Support
|
||||||
|
Bundle-Vendor: SpringSource
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Import-Package:
|
||||||
|
sun.reflect;version="0";resolution:=optional
|
||||||
|
Export-Template:
|
||||||
|
org.springframework.data.mongodb.crossstore.*;version="${project.version}"
|
||||||
|
Import-Template:
|
||||||
|
com.mongodb.*;version="0",
|
||||||
|
javax.persistence.*;version="${jpa:[=.=.=,+1.0.0)}",
|
||||||
|
org.aspectj.*;version="${aspectj:[1.0.0, 2.0.0)}",
|
||||||
|
org.bson.*;version="0",
|
||||||
|
org.slf4j.*;version="${slf4j:[=.=.=,+1.0.0)}",
|
||||||
|
org.springframework.*;version="${spring30:[=.=.=.=,+1.0.0)}",
|
||||||
|
org.springframework.data.*;version="${springdata.commons:[=.=.=.=,+1.0.0)}",
|
||||||
|
org.springframework.data.mongodb.*;version="${project.version:[=.=.=.=,+1.0.0)}",
|
||||||
|
org.w3c.dom.*;version="0"
|
||||||
38
spring-data-mongodb-distribution/pom.xml
Normal file
38
spring-data-mongodb-distribution/pom.xml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?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/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>spring-data-mongodb-distribution</artifactId>
|
||||||
|
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<name>Spring Data MongoDB - Distribution</name>
|
||||||
|
<description>Distribution build for Spring Data MongoDB</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.data</groupId>
|
||||||
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
|
<version>1.3.6.BUILD-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.root>${basedir}/..</project.root>
|
||||||
|
<dist.key>SDMONGO</dist.key>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>wagon-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -32,7 +32,7 @@ An example log entry might look like:
|
|||||||
{
|
{
|
||||||
"_id" : ObjectId("4d89341a8ef397e06940d5cd"),
|
"_id" : ObjectId("4d89341a8ef397e06940d5cd"),
|
||||||
"applicationId" : "my.application",
|
"applicationId" : "my.application",
|
||||||
"name" : "org.springframework.data.mongodb.log4j.AppenderTest",
|
"name" : "org.springframework.data.mongodb.log4j.MongoLog4jAppenderIntegrationTests",
|
||||||
"level" : "DEBUG",
|
"level" : "DEBUG",
|
||||||
"timestamp" : ISODate("2011-03-23T16:53:46.778Z"),
|
"timestamp" : ISODate("2011-03-23T16:53:46.778Z"),
|
||||||
"properties" : {
|
"properties" : {
|
||||||
|
|||||||
@@ -1,44 +1,30 @@
|
|||||||
<?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>
|
|
||||||
<groupId>org.springframework.data</groupId>
|
<parent>
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<version>1.1.0.M1</version>
|
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
<version>1.3.6.BUILD-SNAPSHOT</version>
|
||||||
</parent>
|
<relativePath>../pom.xml</relativePath>
|
||||||
<artifactId>spring-data-mongodb-log4j</artifactId>
|
</parent>
|
||||||
<name>Spring Data MongoDB Log4J Appender</name>
|
|
||||||
|
|
||||||
<properties>
|
<artifactId>spring-data-mongodb-log4j</artifactId>
|
||||||
<mongo.version>2.3</mongo.version>
|
<name>Spring Data MongoDB - Log4J Appender</name>
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
<properties>
|
||||||
|
<log4j>1.2.16</log4j>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<!-- MongoDB -->
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.mongodb</groupId>
|
|
||||||
<artifactId>mongo-java-driver</artifactId>
|
|
||||||
<version>${mongo.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Logging -->
|
<!-- Logging -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>log4j</groupId>
|
<groupId>log4j</groupId>
|
||||||
<artifactId>log4j</artifactId>
|
<artifactId>log4j</artifactId>
|
||||||
<version>${log4j.version}</version>
|
<version>${log4j}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>com.springsource.bundlor</groupId>
|
|
||||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -13,7 +13,6 @@
|
|||||||
* 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.log4j;
|
package org.springframework.data.mongodb.log4j;
|
||||||
|
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
@@ -21,188 +20,207 @@ import java.util.Arrays;
|
|||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.mongodb.BasicDBList;
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DB;
|
|
||||||
import com.mongodb.Mongo;
|
|
||||||
import com.mongodb.WriteConcern;
|
|
||||||
import org.apache.log4j.AppenderSkeleton;
|
import org.apache.log4j.AppenderSkeleton;
|
||||||
import org.apache.log4j.Level;
|
import org.apache.log4j.Level;
|
||||||
import org.apache.log4j.MDC;
|
import org.apache.log4j.MDC;
|
||||||
import org.apache.log4j.PatternLayout;
|
import org.apache.log4j.PatternLayout;
|
||||||
import org.apache.log4j.spi.LoggingEvent;
|
import org.apache.log4j.spi.LoggingEvent;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBList;
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DB;
|
||||||
|
import com.mongodb.Mongo;
|
||||||
|
import com.mongodb.WriteConcern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
* Log4j appender writing log entries into a MongoDB instance.
|
||||||
|
*
|
||||||
|
* @author Jon Brisbin
|
||||||
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public class MongoLog4jAppender extends AppenderSkeleton {
|
public class MongoLog4jAppender extends AppenderSkeleton {
|
||||||
|
|
||||||
public static final String LEVEL = "level";
|
public static final String LEVEL = "level";
|
||||||
public static final String NAME = "name";
|
public static final String NAME = "name";
|
||||||
public static final String APP_ID = "applicationId";
|
public static final String APP_ID = "applicationId";
|
||||||
public static final String TIMESTAMP = "timestamp";
|
public static final String TIMESTAMP = "timestamp";
|
||||||
public static final String PROPERTIES = "properties";
|
public static final String PROPERTIES = "properties";
|
||||||
public static final String TRACEBACK = "traceback";
|
public static final String TRACEBACK = "traceback";
|
||||||
public static final String MESSAGE = "message";
|
public static final String MESSAGE = "message";
|
||||||
public static final String YEAR = "year";
|
public static final String YEAR = "year";
|
||||||
public static final String MONTH = "month";
|
public static final String MONTH = "month";
|
||||||
public static final String DAY = "day";
|
public static final String DAY = "day";
|
||||||
public static final String HOUR = "hour";
|
public static final String HOUR = "hour";
|
||||||
|
|
||||||
protected String host = "localhost";
|
protected String host = "localhost";
|
||||||
protected int port = 27017;
|
protected int port = 27017;
|
||||||
protected String database = "logs";
|
protected String database = "logs";
|
||||||
protected String collectionPattern = "%c";
|
protected String collectionPattern = "%c";
|
||||||
protected PatternLayout collectionLayout = new PatternLayout(collectionPattern);
|
protected PatternLayout collectionLayout = new PatternLayout(collectionPattern);
|
||||||
protected String applicationId = System.getProperty("APPLICATION_ID", null);
|
protected String applicationId = System.getProperty("APPLICATION_ID", null);
|
||||||
protected WriteConcern warnOrHigherWriteConcern = WriteConcern.SAFE;
|
protected WriteConcern warnOrHigherWriteConcern = WriteConcern.SAFE;
|
||||||
protected WriteConcern infoOrLowerWriteConcern = WriteConcern.NORMAL;
|
protected WriteConcern infoOrLowerWriteConcern = WriteConcern.NORMAL;
|
||||||
protected Mongo mongo;
|
protected Mongo mongo;
|
||||||
protected DB db;
|
protected DB db;
|
||||||
|
|
||||||
public MongoLog4jAppender() {
|
public MongoLog4jAppender() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MongoLog4jAppender(boolean isActive) {
|
public MongoLog4jAppender(boolean isActive) {
|
||||||
super(isActive);
|
super(isActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getHost() {
|
public String getHost() {
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHost(String host) {
|
public void setHost(String host) {
|
||||||
this.host = host;
|
this.host = host;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPort() {
|
public int getPort() {
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPort(int port) {
|
public void setPort(int port) {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDatabase() {
|
public String getDatabase() {
|
||||||
return database;
|
return database;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDatabase(String database) {
|
public void setDatabase(String database) {
|
||||||
this.database = database;
|
this.database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCollectionPattern() {
|
public String getCollectionPattern() {
|
||||||
return collectionPattern;
|
return collectionPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCollectionPattern(String collectionPattern) {
|
public void setCollectionPattern(String collectionPattern) {
|
||||||
this.collectionPattern = collectionPattern;
|
this.collectionPattern = collectionPattern;
|
||||||
this.collectionLayout = new PatternLayout(collectionPattern);
|
this.collectionLayout = new PatternLayout(collectionPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getApplicationId() {
|
public String getApplicationId() {
|
||||||
return applicationId;
|
return applicationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setApplicationId(String applicationId) {
|
public void setApplicationId(String applicationId) {
|
||||||
this.applicationId = applicationId;
|
this.applicationId = applicationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWarnOrHigherWriteConcern(String wc) {
|
public void setWarnOrHigherWriteConcern(String wc) {
|
||||||
this.warnOrHigherWriteConcern = WriteConcern.valueOf(wc);
|
this.warnOrHigherWriteConcern = WriteConcern.valueOf(wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWarnOrHigherWriteConcern() {
|
public String getWarnOrHigherWriteConcern() {
|
||||||
return warnOrHigherWriteConcern.toString();
|
return warnOrHigherWriteConcern.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getInfoOrLowerWriteConcern() {
|
public String getInfoOrLowerWriteConcern() {
|
||||||
return infoOrLowerWriteConcern.toString();
|
return infoOrLowerWriteConcern.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInfoOrLowerWriteConcern(String wc) {
|
public void setInfoOrLowerWriteConcern(String wc) {
|
||||||
this.infoOrLowerWriteConcern = WriteConcern.valueOf(wc);
|
this.infoOrLowerWriteConcern = WriteConcern.valueOf(wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void connectToMongo() throws UnknownHostException {
|
protected void connectToMongo() throws UnknownHostException {
|
||||||
this.mongo = new Mongo(host, port);
|
this.mongo = new Mongo(host, port);
|
||||||
this.db = mongo.getDB(database);
|
this.db = mongo.getDB(database);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked"})
|
/*
|
||||||
@Override
|
* (non-Javadoc)
|
||||||
protected void append(final LoggingEvent event) {
|
* @see org.apache.log4j.AppenderSkeleton#append(org.apache.log4j.spi.LoggingEvent)
|
||||||
if (null == db) {
|
*/
|
||||||
try {
|
@Override
|
||||||
connectToMongo();
|
@SuppressWarnings({ "unchecked" })
|
||||||
} catch (UnknownHostException e) {
|
protected void append(final LoggingEvent event) {
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
if (null == db) {
|
||||||
}
|
try {
|
||||||
}
|
connectToMongo();
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BasicDBObject dbo = new BasicDBObject();
|
BasicDBObject dbo = new BasicDBObject();
|
||||||
if (null != applicationId) {
|
if (null != applicationId) {
|
||||||
dbo.put(APP_ID, applicationId);
|
dbo.put(APP_ID, applicationId);
|
||||||
MDC.put(APP_ID, applicationId);
|
MDC.put(APP_ID, applicationId);
|
||||||
}
|
}
|
||||||
dbo.put(NAME, event.getLogger().getName());
|
dbo.put(NAME, event.getLogger().getName());
|
||||||
dbo.put(LEVEL, event.getLevel().toString());
|
dbo.put(LEVEL, event.getLevel().toString());
|
||||||
Calendar tstamp = Calendar.getInstance();
|
Calendar tstamp = Calendar.getInstance();
|
||||||
tstamp.setTimeInMillis(event.getTimeStamp());
|
tstamp.setTimeInMillis(event.getTimeStamp());
|
||||||
dbo.put(TIMESTAMP, tstamp.getTime());
|
dbo.put(TIMESTAMP, tstamp.getTime());
|
||||||
|
|
||||||
// Copy properties into document
|
// Copy properties into document
|
||||||
Map<Object, Object> props = event.getProperties();
|
Map<Object, Object> props = event.getProperties();
|
||||||
if (null != props && props.size() > 0) {
|
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());
|
||||||
}
|
}
|
||||||
dbo.put(PROPERTIES, propsDbo);
|
dbo.put(PROPERTIES, propsDbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy traceback info (if there is any) into the document
|
// Copy traceback info (if there is any) into the document
|
||||||
String[] traceback = event.getThrowableStrRep();
|
String[] traceback = event.getThrowableStrRep();
|
||||||
if (null != traceback && traceback.length > 0) {
|
if (null != traceback && traceback.length > 0) {
|
||||||
BasicDBList tbDbo = new BasicDBList();
|
BasicDBList tbDbo = new BasicDBList();
|
||||||
tbDbo.addAll(Arrays.asList(traceback));
|
tbDbo.addAll(Arrays.asList(traceback));
|
||||||
dbo.put(TRACEBACK, tbDbo);
|
dbo.put(TRACEBACK, tbDbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the rendered message into the document
|
// Put the rendered message into the document
|
||||||
dbo.put(MESSAGE, event.getRenderedMessage());
|
dbo.put(MESSAGE, event.getRenderedMessage());
|
||||||
|
|
||||||
// Insert the document
|
// Insert the document
|
||||||
Calendar now = Calendar.getInstance();
|
Calendar now = Calendar.getInstance();
|
||||||
MDC.put(YEAR, now.get(Calendar.YEAR));
|
MDC.put(YEAR, now.get(Calendar.YEAR));
|
||||||
MDC.put(MONTH, String.format("%1$02d", now.get(Calendar.MONTH) + 1));
|
MDC.put(MONTH, String.format("%1$02d", now.get(Calendar.MONTH) + 1));
|
||||||
MDC.put(DAY, String.format("%1$02d", now.get(Calendar.DAY_OF_MONTH)));
|
MDC.put(DAY, String.format("%1$02d", now.get(Calendar.DAY_OF_MONTH)));
|
||||||
MDC.put(HOUR, String.format("%1$02d", now.get(Calendar.HOUR_OF_DAY)));
|
MDC.put(HOUR, String.format("%1$02d", now.get(Calendar.HOUR_OF_DAY)));
|
||||||
|
|
||||||
String coll = collectionLayout.format(event);
|
String coll = collectionLayout.format(event);
|
||||||
|
|
||||||
MDC.remove(YEAR);
|
MDC.remove(YEAR);
|
||||||
MDC.remove(MONTH);
|
MDC.remove(MONTH);
|
||||||
MDC.remove(DAY);
|
MDC.remove(DAY);
|
||||||
MDC.remove(HOUR);
|
MDC.remove(HOUR);
|
||||||
if (null != applicationId) {
|
if (null != applicationId) {
|
||||||
MDC.remove(APP_ID);
|
MDC.remove(APP_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteConcern wc;
|
WriteConcern wc;
|
||||||
if (event.getLevel().isGreaterOrEqual(Level.WARN)) {
|
if (event.getLevel().isGreaterOrEqual(Level.WARN)) {
|
||||||
wc = warnOrHigherWriteConcern;
|
wc = warnOrHigherWriteConcern;
|
||||||
} else {
|
} else {
|
||||||
wc = infoOrLowerWriteConcern;
|
wc = infoOrLowerWriteConcern;
|
||||||
}
|
}
|
||||||
db.getCollection(coll).insert(dbo, wc);
|
db.getCollection(coll).insert(dbo, wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
/*
|
||||||
mongo.close();
|
* (non-Javadoc)
|
||||||
}
|
* @see org.apache.log4j.AppenderSkeleton#close()
|
||||||
|
*/
|
||||||
|
public void close() {
|
||||||
|
|
||||||
public boolean requiresLayout() {
|
if (mongo != null) {
|
||||||
return true;
|
mongo.close();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.apache.log4j.AppenderSkeleton#requiresLayout()
|
||||||
|
*/
|
||||||
|
public boolean requiresLayout() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* Infrastructure for to use MongoDB as a logging sink.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.mongodb.log4j;
|
||||||
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2011 by the original author(s).
|
|
||||||
*
|
|
||||||
* 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.log4j;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.Calendar;
|
|
||||||
|
|
||||||
import com.mongodb.DB;
|
|
||||||
import com.mongodb.DBCursor;
|
|
||||||
import com.mongodb.Mongo;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import org.apache.log4j.MDC;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
|
||||||
*/
|
|
||||||
public class AppenderTest {
|
|
||||||
|
|
||||||
private static final String NAME = AppenderTest.class.getName();
|
|
||||||
private Logger log = Logger.getLogger(NAME);
|
|
||||||
private Mongo mongo;
|
|
||||||
private DB db;
|
|
||||||
private String collection;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setup() {
|
|
||||||
try {
|
|
||||||
mongo = new Mongo("localhost", 27017);
|
|
||||||
db = mongo.getDB("logs");
|
|
||||||
Calendar now = Calendar.getInstance();
|
|
||||||
collection = String.valueOf(now.get(Calendar.YEAR)) + String.format("%1$02d", now.get(Calendar.MONTH) + 1);
|
|
||||||
db.getCollection(collection).drop();
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLogging() {
|
|
||||||
log.debug("DEBUG message");
|
|
||||||
log.info("INFO message");
|
|
||||||
log.warn("WARN message");
|
|
||||||
log.error("ERROR message");
|
|
||||||
|
|
||||||
DBCursor msgs = db.getCollection(collection).find();
|
|
||||||
assertThat(msgs.count(), is(4));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testProperties() {
|
|
||||||
MDC.put("property", "one");
|
|
||||||
log.debug("DEBUG message");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2013 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.log4j;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.apache.log4j.MDC;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.mongodb.DB;
|
||||||
|
import com.mongodb.DBCursor;
|
||||||
|
import com.mongodb.Mongo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for {@link MongoLog4jAppender}.
|
||||||
|
*
|
||||||
|
* @author Jon Brisbin
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public class MongoLog4jAppenderIntegrationTests {
|
||||||
|
|
||||||
|
static final String NAME = MongoLog4jAppenderIntegrationTests.class.getName();
|
||||||
|
|
||||||
|
Logger log = Logger.getLogger(NAME);
|
||||||
|
Mongo mongo;
|
||||||
|
DB db;
|
||||||
|
String collection;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
|
||||||
|
mongo = new Mongo("localhost", 27017);
|
||||||
|
db = mongo.getDB("logs");
|
||||||
|
|
||||||
|
Calendar now = Calendar.getInstance();
|
||||||
|
collection = String.valueOf(now.get(Calendar.YEAR)) + String.format("%1$02d", now.get(Calendar.MONTH) + 1);
|
||||||
|
db.getCollection(collection).drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLogging() {
|
||||||
|
|
||||||
|
log.debug("DEBUG message");
|
||||||
|
log.info("INFO message");
|
||||||
|
log.warn("WARN message");
|
||||||
|
log.error("ERROR message");
|
||||||
|
|
||||||
|
DBCursor msgs = db.getCollection(collection).find();
|
||||||
|
|
||||||
|
assertThat(msgs.count(), is(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProperties() {
|
||||||
|
|
||||||
|
MDC.put("property", "one");
|
||||||
|
log.debug("DEBUG message");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.log4j;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for {@link MongoLog4jAppender}.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public class MongoLog4jAppenderUnitTests {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DATAMONGO-641
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void closesWithoutMongoInstancePresent() {
|
||||||
|
new MongoLog4jAppender().close();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,11 +10,4 @@ log4j.appender.stdout.collectionPattern = %X{year}%X{month}
|
|||||||
log4j.appender.stdout.applicationId = my.application
|
log4j.appender.stdout.applicationId = my.application
|
||||||
log4j.appender.stdout.warnOrHigherWriteConcern = FSYNC_SAFE
|
log4j.appender.stdout.warnOrHigherWriteConcern = FSYNC_SAFE
|
||||||
|
|
||||||
log4j.category.org.apache.activemq=ERROR
|
log4j.category.org.springframework.data.mongodb=DEBUG
|
||||||
log4j.category.org.springframework.batch=DEBUG
|
|
||||||
log4j.category.org.springframework.data.document.mongodb=DEBUG
|
|
||||||
log4j.category.org.springframework.transaction=INFO
|
|
||||||
|
|
||||||
log4j.category.org.hibernate.SQL=DEBUG
|
|
||||||
# for debugging datasource initialization
|
|
||||||
# log4j.category.test.jdbc=DEBUG
|
|
||||||
|
|||||||
@@ -5,6 +5,5 @@ Bundle-ManifestVersion: 2
|
|||||||
Import-Package:
|
Import-Package:
|
||||||
sun.reflect;version="0";resolution:=optional
|
sun.reflect;version="0";resolution:=optional
|
||||||
Import-Template:
|
Import-Template:
|
||||||
com.mongodb.*;version="${mongo.version:[=.=,+1.0.0)}",
|
com.mongodb.*;version="${mongo:[=.=,+1.0.0)}",
|
||||||
org.apache.log4j.*;version="[1.2.15, 2.0.0)",
|
org.apache.log4j.*;version="${log4j:[=.=.=,+1.0.0)}"
|
||||||
org.apache.log4j.spi.*;version="[1.2.15, 2.0.0)"
|
|
||||||
|
|||||||
@@ -1,271 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>org.springframework.data</groupId>
|
|
||||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
|
||||||
<name>Spring Data MongoDB Parent</name>
|
|
||||||
<url>http://www.springsource.org/spring-data/mongodb</url>
|
|
||||||
<version>1.1.0.M1</version>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
<properties>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
<!-- versions for commonly-used dependencies -->
|
|
||||||
<junit.version>4.8.1</junit.version>
|
|
||||||
<log4j.version>1.2.16</log4j.version>
|
|
||||||
<org.mockito.version>1.8.4</org.mockito.version>
|
|
||||||
<org.slf4j.version>1.6.1</org.slf4j.version>
|
|
||||||
<org.codehaus.jackson.version>1.6.1</org.codehaus.jackson.version>
|
|
||||||
<org.springframework.version.30>3.0.7.RELEASE</org.springframework.version.30>
|
|
||||||
<org.springframework.version.40>4.0.0.RELEASE</org.springframework.version.40>
|
|
||||||
<org.springframework.version.range>[${org.springframework.version.30}, ${org.springframework.version.40})</org.springframework.version.range>
|
|
||||||
<data.commons.version>1.3.0.RC2</data.commons.version>
|
|
||||||
<aspectj.version>1.6.11.RELEASE</aspectj.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<distributionManagement>
|
|
||||||
<!-- see 'staging' profile for dry-run deployment settings -->
|
|
||||||
<downloadUrl>http://www.springsource.com/download/community
|
|
||||||
</downloadUrl>
|
|
||||||
<site>
|
|
||||||
<id>static.springframework.org</id>
|
|
||||||
<url>
|
|
||||||
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-mongodb/snapshot-site
|
|
||||||
</url>
|
|
||||||
</site>
|
|
||||||
<repository>
|
|
||||||
<id>spring-milestone</id>
|
|
||||||
<name>Spring Milestone Repository</name>
|
|
||||||
<url>s3://maven.springframework.org/milestone</url>
|
|
||||||
</repository>
|
|
||||||
<snapshotRepository>
|
|
||||||
<id>spring-snapshot</id>
|
|
||||||
<name>Spring Snapshot Repository</name>
|
|
||||||
<url>s3://maven.springframework.org/snapshot</url>
|
|
||||||
</snapshotRepository>
|
|
||||||
</distributionManagement>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
|
|
||||||
<!-- Test dependencies -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mockito</groupId>
|
|
||||||
<artifactId>mockito-all</artifactId>
|
|
||||||
<version>${org.mockito.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hamcrest</groupId>
|
|
||||||
<artifactId>hamcrest-all</artifactId>
|
|
||||||
<version>1.1</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>${junit.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>joda-time</groupId>
|
|
||||||
<artifactId>joda-time</artifactId>
|
|
||||||
<version>1.6</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-api</artifactId>
|
|
||||||
<version>${org.slf4j.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>jcl-over-slf4j</artifactId>
|
|
||||||
<version>${org.slf4j.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-log4j12</artifactId>
|
|
||||||
<version>${org.slf4j.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>log4j</groupId>
|
|
||||||
<artifactId>log4j</artifactId>
|
|
||||||
<version>${log4j.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-test</artifactId>
|
|
||||||
<version>${org.springframework.version.range}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<extensions>
|
|
||||||
<extension>
|
|
||||||
<!--
|
|
||||||
available only in the springframework maven repository. see
|
|
||||||
<repositories> section below
|
|
||||||
-->
|
|
||||||
<groupId>org.springframework.build.aws</groupId>
|
|
||||||
<artifactId>org.springframework.build.aws.maven</artifactId>
|
|
||||||
<version>3.1.0.RELEASE</version>
|
|
||||||
</extension>
|
|
||||||
</extensions>
|
|
||||||
<resources>
|
|
||||||
<resource>
|
|
||||||
<directory>${project.basedir}/src/main/java</directory>
|
|
||||||
<includes>
|
|
||||||
<include>**/*</include>
|
|
||||||
</includes>
|
|
||||||
<excludes>
|
|
||||||
<exclude>**/*.java</exclude>
|
|
||||||
</excludes>
|
|
||||||
</resource>
|
|
||||||
<resource>
|
|
||||||
<directory>${project.basedir}/src/main/resources</directory>
|
|
||||||
<includes>
|
|
||||||
<include>**/*</include>
|
|
||||||
</includes>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
|
||||||
<testResources>
|
|
||||||
<testResource>
|
|
||||||
<directory>${project.basedir}/src/test/java</directory>
|
|
||||||
<includes>
|
|
||||||
<include>**/*</include>
|
|
||||||
</includes>
|
|
||||||
<excludes>
|
|
||||||
<exclude>**/*.java</exclude>
|
|
||||||
</excludes>
|
|
||||||
</testResource>
|
|
||||||
<testResource>
|
|
||||||
<directory>${project.basedir}/src/test/resources</directory>
|
|
||||||
<includes>
|
|
||||||
<include>**/*</include>
|
|
||||||
</includes>
|
|
||||||
<excludes>
|
|
||||||
<exclude>**/*.java</exclude>
|
|
||||||
</excludes>
|
|
||||||
</testResource>
|
|
||||||
</testResources>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>2.3.2</version>
|
|
||||||
<configuration>
|
|
||||||
<source>1.5</source>
|
|
||||||
<target>1.5</target>
|
|
||||||
<compilerArgument>-Xlint:-path</compilerArgument>
|
|
||||||
<showWarnings>true</showWarnings>
|
|
||||||
<showDeprecation>false</showDeprecation>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<version>2.3.1</version>
|
|
||||||
<configuration>
|
|
||||||
<useDefaultManifestFile>true</useDefaultManifestFile>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<version>2.8</version>
|
|
||||||
<configuration>
|
|
||||||
<useFile>false</useFile>
|
|
||||||
<includes>
|
|
||||||
<include>**/*Tests.java</include>
|
|
||||||
</includes>
|
|
||||||
<excludes>
|
|
||||||
<exclude>**/PerformanceTests.java</exclude>
|
|
||||||
</excludes>
|
|
||||||
<junitArtifactName>junit:junit</junitArtifactName>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-source-plugin</artifactId>
|
|
||||||
<version>2.1.2</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>attach-sources</id>
|
|
||||||
<goals>
|
|
||||||
<goal>jar</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
<pluginManagement>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<!--
|
|
||||||
configures the springsource bundlor plugin, which generates
|
|
||||||
OSGI-compatible MANIFEST.MF files during the 'compile' phase of
|
|
||||||
the maven build. this plugin is declared within the
|
|
||||||
pluginManagement section because not every module that inherits
|
|
||||||
from this pom needs bundlor's services, e.g.:
|
|
||||||
spring-integration-samples and all its children. for this reason,
|
|
||||||
all modules that wish to use bundlor must declare it explicitly.
|
|
||||||
it is not necessary to specify the <version> or <configuration>
|
|
||||||
sections, but groupId and artifactId are required. see
|
|
||||||
http://static.springsource.org/s2-bundlor/1.0.x/user-guide/html/ch04s03.html
|
|
||||||
for more info
|
|
||||||
-->
|
|
||||||
<groupId>com.springsource.bundlor</groupId>
|
|
||||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
|
||||||
<version>1.0.0.RELEASE</version>
|
|
||||||
<configuration>
|
|
||||||
<failOnWarnings>true</failOnWarnings>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>bundlor</id>
|
|
||||||
<goals>
|
|
||||||
<goal>bundlor</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</pluginManagement>
|
|
||||||
</build>
|
|
||||||
<pluginRepositories>
|
|
||||||
<pluginRepository>
|
|
||||||
<id>spring-plugins-release</id>
|
|
||||||
<url>http://repo.springsource.org/plugins-release</url>
|
|
||||||
</pluginRepository>
|
|
||||||
</pluginRepositories>
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>spring-libs-snapshot</id>
|
|
||||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
<reporting>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<!--
|
|
||||||
significantly speeds up the 'Dependencies' report during site
|
|
||||||
creation see
|
|
||||||
http://old.nabble.com/Skipping-dependency-report-during-Maven2-site-generation-td20116761.html
|
|
||||||
-->
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
|
||||||
<version>2.1</version>
|
|
||||||
<configuration>
|
|
||||||
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</reporting>
|
|
||||||
</project>
|
|
||||||
@@ -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.0.3.1152">
|
<context version="7.1.7.187">
|
||||||
<scope name="spring-data-mongodb" type="Project">
|
<scope name="spring-data-mongodb" type="Project">
|
||||||
<element name="Filter" type="TypeFilterReferenceOverridden">
|
<element name="Filter" type="TypeFilterReferenceOverridden">
|
||||||
<element name="org.springframework.data.mongodb.**" type="IncludeTypePattern"/>
|
<element name="org.springframework.data.mongodb.**" type="IncludeTypePattern"/>
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
<element name="**.config.**" type="WeakTypePattern"/>
|
<element name="**.config.**" type="WeakTypePattern"/>
|
||||||
</element>
|
</element>
|
||||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Core"/>
|
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Core"/>
|
||||||
|
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|GridFS"/>
|
||||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Monitoring"/>
|
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Monitoring"/>
|
||||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Repositories"/>
|
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Repositories"/>
|
||||||
</element>
|
</element>
|
||||||
@@ -93,6 +94,12 @@
|
|||||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Query"/>
|
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Query"/>
|
||||||
</element>
|
</element>
|
||||||
</element>
|
</element>
|
||||||
|
<element name="API" type="Subsystem">
|
||||||
|
<element name="Assignment" type="TypeFilter">
|
||||||
|
<element name="org.springframework.data.mongodb.*" type="IncludeTypePattern"/>
|
||||||
|
</element>
|
||||||
|
<stereotype name="Public"/>
|
||||||
|
</element>
|
||||||
</architecture>
|
</architecture>
|
||||||
<workspace>
|
<workspace>
|
||||||
<element name="src/main/java" type="JavaRootDirectory">
|
<element name="src/main/java" type="JavaRootDirectory">
|
||||||
|
|||||||
@@ -1,95 +1,77 @@
|
|||||||
<?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/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>spring-data-mongodb</artifactId>
|
||||||
|
|
||||||
|
<name>Spring Data MongoDB - Core</name>
|
||||||
|
<description>MongoDB support for Spring Data</description>
|
||||||
|
|
||||||
<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.1.0.M1</version>
|
<version>1.3.6.BUILD-SNAPSHOT</version>
|
||||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-data-mongodb</artifactId>
|
|
||||||
<name>Spring Data MongoDB</name>
|
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<mongo.version>2.7.1</mongo.version>
|
<validation>1.0.0.GA</validation>
|
||||||
<querydsl.version>2.5.0</querydsl.version>
|
|
||||||
<cdi.version>1.0</cdi.version>
|
|
||||||
<validation.version>1.0.0.GA</validation.version>
|
|
||||||
<webbeans.version>1.1.3</webbeans.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<!-- Spring -->
|
<!-- Spring -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-tx</artifactId>
|
<artifactId>spring-tx</artifactId>
|
||||||
<version>${org.springframework.version.range}</version>
|
<version>${spring}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-context</artifactId>
|
<artifactId>spring-context</artifactId>
|
||||||
<version>${org.springframework.version.range}</version>
|
<version>${spring}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-beans</artifactId>
|
<artifactId>spring-beans</artifactId>
|
||||||
<version>${org.springframework.version.range}</version>
|
<version>${spring}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-core</artifactId>
|
<artifactId>spring-core</artifactId>
|
||||||
<version>${org.springframework.version.range}</version>
|
<version>${spring}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>commons-logging</groupId>
|
<groupId>commons-logging</groupId>
|
||||||
<artifactId>commons-logging</artifactId>
|
<artifactId>commons-logging</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-expression</artifactId>
|
<artifactId>spring-expression</artifactId>
|
||||||
<version>${org.springframework.version.range}</version>
|
<version>${spring}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Spring Data -->
|
<!-- Spring Data -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>spring-data-commons-core</artifactId>
|
<artifactId>spring-data-commons</artifactId>
|
||||||
<version>${data.commons.version}</version>
|
<version>${springdata.commons}</version>
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- MongoDB -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mongodb</groupId>
|
|
||||||
<artifactId>mongo-java-driver</artifactId>
|
|
||||||
<version>${mongo.version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>javax.persistence</groupId>
|
|
||||||
<artifactId>persistence-api</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.mysema.querydsl</groupId>
|
<groupId>com.mysema.querydsl</groupId>
|
||||||
<artifactId>querydsl-mongodb</artifactId>
|
<artifactId>querydsl-mongodb</artifactId>
|
||||||
<version>${querydsl.version}</version>
|
<version>${querydsl}</version>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>com.google.code.morphia</groupId>
|
|
||||||
<artifactId>morphia</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.mysema.querydsl</groupId>
|
<groupId>com.mysema.querydsl</groupId>
|
||||||
<artifactId>querydsl-apt</artifactId>
|
<artifactId>querydsl-apt</artifactId>
|
||||||
<version>${querydsl.version}</version>
|
<version>${querydsl}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
@@ -104,7 +86,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.enterprise</groupId>
|
<groupId>javax.enterprise</groupId>
|
||||||
<artifactId>cdi-api</artifactId>
|
<artifactId>cdi-api</artifactId>
|
||||||
<version>${cdi.version}</version>
|
<version>${cdi}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -112,14 +94,14 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.el</groupId>
|
<groupId>javax.el</groupId>
|
||||||
<artifactId>el-api</artifactId>
|
<artifactId>el-api</artifactId>
|
||||||
<version>${cdi.version}</version>
|
<version>${cdi}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.openwebbeans.test</groupId>
|
<groupId>org.apache.openwebbeans.test</groupId>
|
||||||
<artifactId>cditest-owb</artifactId>
|
<artifactId>cditest-owb</artifactId>
|
||||||
<version>${webbeans.version}</version>
|
<version>${webbeans}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
@@ -134,7 +116,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.validation</groupId>
|
<groupId>javax.validation</groupId>
|
||||||
<artifactId>validation-api</artifactId>
|
<artifactId>validation-api</artifactId>
|
||||||
<version>${validation.version}</version>
|
<version>${validation}</version>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
@@ -144,43 +126,37 @@
|
|||||||
<version>4.2.0.Final</version>
|
<version>4.2.0.Final</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>joda-time</groupId>
|
||||||
|
<artifactId>joda-time</artifactId>
|
||||||
|
<version>${jodatime}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>jul-to-slf4j</artifactId>
|
||||||
|
<version>${slf4j}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<profiles>
|
|
||||||
<profile>
|
|
||||||
<id>performance-tests</id>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<version>2.8</version>
|
|
||||||
<configuration>
|
|
||||||
<includes>
|
|
||||||
<include>**/PerformanceTests.java</include>
|
|
||||||
</includes>
|
|
||||||
<excludes>
|
|
||||||
<exclude>none</exclude>
|
|
||||||
</excludes>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>com.springsource.bundlor</groupId>
|
|
||||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.mysema.maven</groupId>
|
<groupId>com.mysema.maven</groupId>
|
||||||
<artifactId>maven-apt-plugin</artifactId>
|
<artifactId>apt-maven-plugin</artifactId>
|
||||||
<version>1.0.2</version>
|
<version>1.0.8</version>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.mysema.querydsl</groupId>
|
||||||
|
<artifactId>querydsl-apt</artifactId>
|
||||||
|
<version>${querydsl}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>generate-test-sources</phase>
|
<phase>generate-test-sources</phase>
|
||||||
@@ -194,7 +170,25 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.12</version>
|
||||||
|
<configuration>
|
||||||
|
<useFile>false</useFile>
|
||||||
|
<includes>
|
||||||
|
<include>**/*Tests.java</include>
|
||||||
|
</includes>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/PerformanceTests.java</exclude>
|
||||||
|
</excludes>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2012 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.
|
||||||
@@ -27,19 +27,23 @@ import org.springframework.core.convert.converter.Converter;
|
|||||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||||
import org.springframework.data.annotation.Persistent;
|
import org.springframework.data.annotation.Persistent;
|
||||||
import org.springframework.data.authentication.UserCredentials;
|
import org.springframework.data.authentication.UserCredentials;
|
||||||
|
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
|
||||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||||
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
||||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.CamelCaseAbbreviatingFieldNamingStrategy;
|
||||||
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.support.CachingIsNewStrategyFactory;
|
||||||
|
import org.springframework.data.support.IsNewStrategyFactory;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.mongodb.Mongo;
|
import com.mongodb.Mongo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for Spring Data Mongo configuration using JavaConfig.
|
* Base class for Spring Data MongoDB configuration using JavaConfig.
|
||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
@@ -55,12 +59,12 @@ public abstract class AbstractMongoConfiguration {
|
|||||||
protected abstract String getDatabaseName();
|
protected abstract String getDatabaseName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the {@link Mongo} instance to connect to.
|
* Return the {@link Mongo} instance to connect to. Annotate with {@link Bean} in case you want to expose a
|
||||||
|
* {@link Mongo} instance to the {@link org.springframework.context.ApplicationContext}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@Bean
|
|
||||||
public abstract Mongo mongo() throws Exception;
|
public abstract Mongo mongo() throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,22 +90,28 @@ public abstract class AbstractMongoConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
public SimpleMongoDbFactory mongoDbFactory() throws Exception {
|
public SimpleMongoDbFactory mongoDbFactory() throws Exception {
|
||||||
|
|
||||||
UserCredentials creadentials = getUserCredentials();
|
UserCredentials credentials = getUserCredentials();
|
||||||
|
|
||||||
if (creadentials == null) {
|
if (credentials == null) {
|
||||||
return new SimpleMongoDbFactory(mongo(), getDatabaseName());
|
return new SimpleMongoDbFactory(mongo(), getDatabaseName());
|
||||||
} else {
|
} else {
|
||||||
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), creadentials);
|
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), credentials);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the base package to scan for mapped {@link Document}s.
|
* Return the base package to scan for mapped {@link Document}s. Will return the package name of the configuration
|
||||||
|
* class' (the concrete class, not this one here) by default. So if you have a {@code com.acme.AppConfig} extending
|
||||||
|
* {@link AbstractMongoConfiguration} the base package will be considered {@code com.acme} unless the method is
|
||||||
|
* overriden to implement alternate behaviour.
|
||||||
*
|
*
|
||||||
* @return
|
* @return the base package to scan for mapped {@link Document} classes or {@literal null} to not enable scanning for
|
||||||
|
* entities.
|
||||||
*/
|
*/
|
||||||
protected String getMappingBasePackage() {
|
protected String getMappingBasePackage() {
|
||||||
return null;
|
|
||||||
|
Package mappingBasePackage = getClass().getPackage();
|
||||||
|
return mappingBasePackage == null ? null : mappingBasePackage.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,11 +137,25 @@ public abstract class AbstractMongoConfiguration {
|
|||||||
MongoMappingContext mappingContext = new MongoMappingContext();
|
MongoMappingContext mappingContext = new MongoMappingContext();
|
||||||
mappingContext.setInitialEntitySet(getInitialEntitySet());
|
mappingContext.setInitialEntitySet(getInitialEntitySet());
|
||||||
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
|
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
|
||||||
mappingContext.afterPropertiesSet();
|
|
||||||
|
if (abbreviateFieldNames()) {
|
||||||
|
mappingContext.setFieldNamingStrategy(new CamelCaseAbbreviatingFieldNamingStrategy());
|
||||||
|
}
|
||||||
|
|
||||||
return mappingContext;
|
return mappingContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link MappingContextIsNewStrategyFactory} wrapped into a {@link CachingIsNewStrategyFactory}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public IsNewStrategyFactory isNewStrategyFactory() throws ClassNotFoundException {
|
||||||
|
return new CachingIsNewStrategyFactory(new MappingContextIsNewStrategyFactory(mongoMappingContext()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
|
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
|
||||||
* {@link CustomConversions} will be registered with the {@link #mappingMongoConverter()} and
|
* {@link CustomConversions} will be registered with the {@link #mappingMongoConverter()} and
|
||||||
@@ -187,4 +211,15 @@ public abstract class AbstractMongoConfiguration {
|
|||||||
|
|
||||||
return initialEntitySet;
|
return initialEntitySet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures whether to abbreviate field names for domain objects by configuring a
|
||||||
|
* {@link CamelCaseAbbreviatingFieldNamingStrategy} on the {@link MongoMappingContext} instance created. For advanced
|
||||||
|
* customization needs, consider overriding {@link #mappingMongoConverter()}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected boolean abbreviateFieldNames() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -13,11 +13,14 @@
|
|||||||
* 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.config;
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
* Constants to declare bean names used by the namespace configuration.
|
||||||
|
*
|
||||||
|
* @author Jon Brisbin
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @author Martin Baumgartner
|
||||||
*/
|
*/
|
||||||
public abstract class BeanNames {
|
public abstract class BeanNames {
|
||||||
|
|
||||||
@@ -26,4 +29,8 @@ public abstract class BeanNames {
|
|||||||
static final String MONGO = "mongo";
|
static final String MONGO = "mongo";
|
||||||
static final String DB_FACTORY = "mongoDbFactory";
|
static final String DB_FACTORY = "mongoDbFactory";
|
||||||
static final String VALIDATING_EVENT_LISTENER = "validatingMongoEventListener";
|
static final String VALIDATING_EVENT_LISTENER = "validatingMongoEventListener";
|
||||||
|
static final String IS_NEW_STRATEGY_FACTORY = "isNewStrategyFactory";
|
||||||
|
static final String DEFAULT_CONVERTER_BEAN_NAME = "mappingConverter";
|
||||||
|
static final String MONGO_TEMPLATE = "mongoTemplate";
|
||||||
|
static final String GRID_FS_TEMPLATE = "gridFsTemplate";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.BeanDefinitionStoreException;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
||||||
|
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link BeanDefinitionParser} to parse {@code gridFsTemplate} elements into {@link BeanDefinition}s.
|
||||||
|
*
|
||||||
|
* @author Martin Baumgartner
|
||||||
|
*/
|
||||||
|
class GridFsTemplateParser extends AbstractBeanDefinitionParser {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (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)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||||
|
throws BeanDefinitionStoreException {
|
||||||
|
|
||||||
|
String id = super.resolveId(element, definition, parserContext);
|
||||||
|
return StringUtils.hasText(id) ? id : BeanNames.GRID_FS_TEMPLATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
||||||
|
|
||||||
|
BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext);
|
||||||
|
|
||||||
|
String converterRef = element.getAttribute("converter-ref");
|
||||||
|
String dbFactoryRef = element.getAttribute("db-factory-ref");
|
||||||
|
|
||||||
|
BeanDefinitionBuilder gridFsTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(GridFsTemplate.class);
|
||||||
|
|
||||||
|
if (StringUtils.hasText(dbFactoryRef)) {
|
||||||
|
gridFsTemplateBuilder.addConstructorArgReference(dbFactoryRef);
|
||||||
|
} else {
|
||||||
|
gridFsTemplateBuilder.addConstructorArgReference(BeanNames.DB_FACTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.hasText(converterRef)) {
|
||||||
|
gridFsTemplateBuilder.addConstructorArgReference(converterRef);
|
||||||
|
} else {
|
||||||
|
gridFsTemplateBuilder.addConstructorArgReference(BeanNames.DEFAULT_CONVERTER_BEAN_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (AbstractBeanDefinition) helper.getComponentIdButFallback(gridFsTemplateBuilder, BeanNames.GRID_FS_TEMPLATE)
|
||||||
|
.getBeanDefinition();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2012 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,12 +24,12 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.beans.BeanMetadataElement;
|
import org.springframework.beans.BeanMetadataElement;
|
||||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
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.support.AbstractBeanDefinition;
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
@@ -38,6 +38,7 @@ import org.springframework.beans.factory.support.ManagedList;
|
|||||||
import org.springframework.beans.factory.support.ManagedSet;
|
import org.springframework.beans.factory.support.ManagedSet;
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
@@ -48,9 +49,12 @@ import org.springframework.core.type.filter.AnnotationTypeFilter;
|
|||||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||||
import org.springframework.core.type.filter.TypeFilter;
|
import org.springframework.core.type.filter.TypeFilter;
|
||||||
import org.springframework.data.annotation.Persistent;
|
import org.springframework.data.annotation.Persistent;
|
||||||
|
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
||||||
|
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
|
||||||
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
||||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
|
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.CamelCaseAbbreviatingFieldNamingStrategy;
|
||||||
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.event.ValidatingMongoEventListener;
|
import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener;
|
||||||
@@ -66,26 +70,30 @@ import org.w3c.dom.Element;
|
|||||||
* @author Jon Brisbin
|
* @author Jon Brisbin
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Maciej Walkowiak
|
* @author Maciej Walkowiak
|
||||||
|
* @author Thomas Darimont
|
||||||
*/
|
*/
|
||||||
public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||||
|
|
||||||
private static final String BASE_PACKAGE = "base-package";
|
private static final String BASE_PACKAGE = "base-package";
|
||||||
private static final boolean jsr303Present = ClassUtils.isPresent("javax.validation.Validator",
|
private static final boolean jsr303Present = ClassUtils.isPresent("javax.validation.Validator",
|
||||||
MappingMongoConverterParser.class.getClassLoader());
|
MappingMongoConverterParser.class.getClassLoader());
|
||||||
|
|
||||||
@Override
|
/* (non-Javadoc)
|
||||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||||
throws BeanDefinitionStoreException {
|
*/
|
||||||
String id = super.resolveId(element, definition, parserContext);
|
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||||
return StringUtils.hasText(id) ? id : "mappingConverter";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
|
||||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||||
|
|
||||||
|
String id = element.getAttribute(AbstractBeanDefinitionParser.ID_ATTRIBUTE);
|
||||||
|
id = StringUtils.hasText(id) ? id : "mappingConverter";
|
||||||
|
|
||||||
|
parserContext.pushContainingComponent(new CompositeComponentDefinition("Mapping Mongo Converter", element));
|
||||||
|
|
||||||
BeanDefinition conversionsDefinition = getCustomConversions(element, parserContext);
|
BeanDefinition conversionsDefinition = getCustomConversions(element, parserContext);
|
||||||
String ctxRef = potentiallyCreateMappingContext(element, parserContext, conversionsDefinition);
|
String ctxRef = potentiallyCreateMappingContext(element, parserContext, conversionsDefinition, id);
|
||||||
|
|
||||||
|
createIsNewStrategyFactoryBeanDefinition(ctxRef, parserContext, element);
|
||||||
|
|
||||||
// Need a reference to a Mongo instance
|
// Need a reference to a Mongo instance
|
||||||
String dbFactoryRef = element.getAttribute("db-factory-ref");
|
String dbFactoryRef = element.getAttribute("db-factory-ref");
|
||||||
@@ -98,6 +106,11 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
|||||||
converterBuilder.addConstructorArgReference(dbFactoryRef);
|
converterBuilder.addConstructorArgReference(dbFactoryRef);
|
||||||
converterBuilder.addConstructorArgReference(ctxRef);
|
converterBuilder.addConstructorArgReference(ctxRef);
|
||||||
|
|
||||||
|
String typeMapperRef = element.getAttribute("type-mapper-ref");
|
||||||
|
if (StringUtils.hasText(typeMapperRef)) {
|
||||||
|
converterBuilder.addPropertyReference("typeMapper", typeMapperRef);
|
||||||
|
}
|
||||||
|
|
||||||
if (conversionsDefinition != null) {
|
if (conversionsDefinition != null) {
|
||||||
converterBuilder.addPropertyValue("customConversions", conversionsDefinition);
|
converterBuilder.addPropertyValue("customConversions", conversionsDefinition);
|
||||||
}
|
}
|
||||||
@@ -110,18 +123,24 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
BeanDefinitionBuilder indexHelperBuilder = BeanDefinitionBuilder
|
BeanDefinitionBuilder indexHelperBuilder = BeanDefinitionBuilder
|
||||||
.genericBeanDefinition(MongoPersistentEntityIndexCreator.class);
|
.genericBeanDefinition(MongoPersistentEntityIndexCreator.class);
|
||||||
indexHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(ctxRef));
|
indexHelperBuilder.addConstructorArgReference(ctxRef);
|
||||||
indexHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(dbFactoryRef));
|
indexHelperBuilder.addConstructorArgReference(dbFactoryRef);
|
||||||
registry.registerBeanDefinition(INDEX_HELPER, indexHelperBuilder.getBeanDefinition());
|
indexHelperBuilder.addDependsOn(ctxRef);
|
||||||
|
|
||||||
|
parserContext.registerBeanComponent(new BeanComponentDefinition(indexHelperBuilder.getBeanDefinition(),
|
||||||
|
INDEX_HELPER));
|
||||||
}
|
}
|
||||||
|
|
||||||
BeanDefinition validatingMongoEventListener = potentiallyCreateValidatingMongoEventListener(element, parserContext);
|
BeanDefinition validatingMongoEventListener = potentiallyCreateValidatingMongoEventListener(element, parserContext);
|
||||||
|
|
||||||
if (validatingMongoEventListener != null) {
|
if (validatingMongoEventListener != null) {
|
||||||
registry.registerBeanDefinition(VALIDATING_EVENT_LISTENER, validatingMongoEventListener);
|
parserContext.registerBeanComponent(new BeanComponentDefinition(validatingMongoEventListener,
|
||||||
|
VALIDATING_EVENT_LISTENER));
|
||||||
}
|
}
|
||||||
|
|
||||||
return converterBuilder.getBeanDefinition();
|
parserContext.registerBeanComponent(new BeanComponentDefinition(converterBuilder.getBeanDefinition(), id));
|
||||||
|
parserContext.popAndRegisterContainingComponent();
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BeanDefinition potentiallyCreateValidatingMongoEventListener(Element element, ParserContext parserContext) {
|
private BeanDefinition potentiallyCreateValidatingMongoEventListener(Element element, ParserContext parserContext) {
|
||||||
@@ -135,7 +154,6 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
|||||||
RuntimeBeanReference validator = getValidator(builder, parserContext);
|
RuntimeBeanReference validator = getValidator(builder, parserContext);
|
||||||
|
|
||||||
if (validator != null) {
|
if (validator != null) {
|
||||||
|
|
||||||
builder.getRawBeanDefinition().setBeanClass(ValidatingMongoEventListener.class);
|
builder.getRawBeanDefinition().setBeanClass(ValidatingMongoEventListener.class);
|
||||||
builder.addConstructorArgValue(validator);
|
builder.addConstructorArgValue(validator);
|
||||||
|
|
||||||
@@ -157,36 +175,48 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
|||||||
validatorDef.setSource(source);
|
validatorDef.setSource(source);
|
||||||
validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||||
String validatorName = parserContext.getReaderContext().registerWithGeneratedName(validatorDef);
|
String validatorName = parserContext.getReaderContext().registerWithGeneratedName(validatorDef);
|
||||||
parserContext.registerComponent(new BeanComponentDefinition(validatorDef, validatorName));
|
parserContext.registerBeanComponent(new BeanComponentDefinition(validatorDef, validatorName));
|
||||||
|
|
||||||
return new RuntimeBeanReference(validatorName);
|
return new RuntimeBeanReference(validatorName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
|
static String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
|
||||||
BeanDefinition conversionsDefinition) {
|
BeanDefinition conversionsDefinition, String converterId) {
|
||||||
|
|
||||||
String ctxRef = element.getAttribute("mapping-context-ref");
|
String ctxRef = element.getAttribute("mapping-context-ref");
|
||||||
if (!StringUtils.hasText(ctxRef)) {
|
|
||||||
BeanDefinitionBuilder mappingContextBuilder = BeanDefinitionBuilder
|
|
||||||
.genericBeanDefinition(MongoMappingContext.class);
|
|
||||||
|
|
||||||
Set<String> classesToAdd = getInititalEntityClasses(element, mappingContextBuilder);
|
if (StringUtils.hasText(ctxRef)) {
|
||||||
if (classesToAdd != null) {
|
return ctxRef;
|
||||||
mappingContextBuilder.addPropertyValue("initialEntitySet", classesToAdd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conversionsDefinition != null) {
|
|
||||||
AbstractBeanDefinition simpleTypesDefinition = new GenericBeanDefinition();
|
|
||||||
simpleTypesDefinition.setFactoryBeanName("customConversions");
|
|
||||||
simpleTypesDefinition.setFactoryMethodName("getSimpleTypeHolder");
|
|
||||||
|
|
||||||
mappingContextBuilder.addPropertyValue("simpleTypeHolder", simpleTypesDefinition);
|
|
||||||
}
|
|
||||||
|
|
||||||
parserContext.getRegistry().registerBeanDefinition(MAPPING_CONTEXT, mappingContextBuilder.getBeanDefinition());
|
|
||||||
ctxRef = MAPPING_CONTEXT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BeanComponentDefinitionBuilder componentDefinitionBuilder = new BeanComponentDefinitionBuilder(element,
|
||||||
|
parserContext);
|
||||||
|
|
||||||
|
BeanDefinitionBuilder mappingContextBuilder = BeanDefinitionBuilder
|
||||||
|
.genericBeanDefinition(MongoMappingContext.class);
|
||||||
|
|
||||||
|
Set<String> classesToAdd = getInititalEntityClasses(element, mappingContextBuilder);
|
||||||
|
if (classesToAdd != null) {
|
||||||
|
mappingContextBuilder.addPropertyValue("initialEntitySet", classesToAdd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conversionsDefinition != null) {
|
||||||
|
AbstractBeanDefinition simpleTypesDefinition = new GenericBeanDefinition();
|
||||||
|
simpleTypesDefinition.setFactoryBeanName("customConversions");
|
||||||
|
simpleTypesDefinition.setFactoryMethodName("getSimpleTypeHolder");
|
||||||
|
|
||||||
|
mappingContextBuilder.addPropertyValue("simpleTypeHolder", simpleTypesDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
String abbreviateFieldNames = element.getAttribute("abbreviate-field-names");
|
||||||
|
if ("true".equals(abbreviateFieldNames)) {
|
||||||
|
mappingContextBuilder.addPropertyValue("fieldNamingStrategy", new RootBeanDefinition(
|
||||||
|
CamelCaseAbbreviatingFieldNamingStrategy.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxRef = converterId + "." + MAPPING_CONTEXT;
|
||||||
|
|
||||||
|
parserContext.registerBeanComponent(componentDefinitionBuilder.getComponent(mappingContextBuilder, ctxRef));
|
||||||
return ctxRef;
|
return ctxRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +254,7 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
|||||||
AbstractBeanDefinition conversionsBean = conversionsBuilder.getBeanDefinition();
|
AbstractBeanDefinition conversionsBean = conversionsBuilder.getBeanDefinition();
|
||||||
conversionsBean.setSource(parserContext.extractSource(element));
|
conversionsBean.setSource(parserContext.extractSource(element));
|
||||||
|
|
||||||
parserContext.getRegistry().registerBeanDefinition("customConversions", conversionsBean);
|
parserContext.registerBeanComponent(new BeanComponentDefinition(conversionsBean, "customConversions"));
|
||||||
|
|
||||||
return conversionsBean;
|
return conversionsBean;
|
||||||
}
|
}
|
||||||
@@ -232,7 +262,7 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getInititalEntityClasses(Element element, BeanDefinitionBuilder builder) {
|
private static Set<String> getInititalEntityClasses(Element element, BeanDefinitionBuilder builder) {
|
||||||
|
|
||||||
String basePackage = element.getAttribute(BASE_PACKAGE);
|
String basePackage = element.getAttribute(BASE_PACKAGE);
|
||||||
|
|
||||||
@@ -271,6 +301,19 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String createIsNewStrategyFactoryBeanDefinition(String mappingContextRef, ParserContext context,
|
||||||
|
Element element) {
|
||||||
|
|
||||||
|
BeanDefinitionBuilder mappingContextStrategyFactoryBuilder = BeanDefinitionBuilder
|
||||||
|
.rootBeanDefinition(MappingContextIsNewStrategyFactory.class);
|
||||||
|
mappingContextStrategyFactoryBuilder.addConstructorArgReference(mappingContextRef);
|
||||||
|
|
||||||
|
BeanComponentDefinitionBuilder builder = new BeanComponentDefinitionBuilder(element, context);
|
||||||
|
context.registerBeanComponent(builder.getComponent(mappingContextStrategyFactoryBuilder, IS_NEW_STRATEGY_FACTORY));
|
||||||
|
|
||||||
|
return IS_NEW_STRATEGY_FACTORY;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link TypeFilter} that returns {@literal false} in case any of the given delegates matches.
|
* {@link TypeFilter} that returns {@literal false} in case any of the given delegates matches.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
|
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.data.config.IsNewAwareAuditingHandlerBeanDefinitionParser;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.event.AuditingEventListener;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link BeanDefinitionParser} to register a {@link AuditingEventListener} to transparently set auditing information on
|
||||||
|
* an entity.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public class MongoAuditingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Class<?> getBeanClass(Element element) {
|
||||||
|
return AuditingEventListener.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#shouldGenerateId()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean shouldGenerateId() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||||
|
|
||||||
|
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||||
|
|
||||||
|
if (!registry.containsBeanDefinition(BeanNames.IS_NEW_STRATEGY_FACTORY)) {
|
||||||
|
|
||||||
|
String mappingContextName = BeanNames.MAPPING_CONTEXT;
|
||||||
|
|
||||||
|
if (!registry.containsBeanDefinition(BeanNames.MAPPING_CONTEXT)) {
|
||||||
|
mappingContextName = MappingMongoConverterParser.potentiallyCreateMappingContext(element, parserContext, null,
|
||||||
|
BeanNames.DEFAULT_CONVERTER_BEAN_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
MappingMongoConverterParser.createIsNewStrategyFactoryBeanDefinition(mappingContextName, parserContext, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
BeanDefinitionParser parser = new IsNewAwareAuditingHandlerBeanDefinitionParser(BeanNames.IS_NEW_STRATEGY_FACTORY);
|
||||||
|
BeanDefinition handlerBeanDefinition = parser.parse(element, parserContext);
|
||||||
|
|
||||||
|
builder.addConstructorArgValue(handlerBeanDefinition);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011 by the original author(s).
|
* Copyright 2011-2012 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.
|
||||||
@@ -15,19 +15,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.config;
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
import static org.springframework.data.mongodb.config.BeanNames.*;
|
import static org.springframework.data.config.ParsingUtils.*;
|
||||||
import static org.springframework.data.mongodb.config.ParsingUtils.*;
|
import static org.springframework.data.mongodb.config.MongoParsingUtils.*;
|
||||||
|
|
||||||
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.config.RuntimeBeanReference;
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
|
||||||
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||||
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.authentication.UserCredentials;
|
import org.springframework.data.authentication.UserCredentials;
|
||||||
|
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
||||||
import org.springframework.data.mongodb.core.MongoFactoryBean;
|
import org.springframework.data.mongodb.core.MongoFactoryBean;
|
||||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@@ -44,19 +44,29 @@ import com.mongodb.MongoURI;
|
|||||||
*/
|
*/
|
||||||
public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (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)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||||
throws BeanDefinitionStoreException {
|
throws BeanDefinitionStoreException {
|
||||||
String id = element.getAttribute("id");
|
|
||||||
if (!StringUtils.hasText(id)) {
|
String id = super.resolveId(element, definition, parserContext);
|
||||||
id = DB_FACTORY;
|
return StringUtils.hasText(id) ? id : BeanNames.DB_FACTORY;
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
||||||
|
|
||||||
|
Object source = parserContext.extractSource(element);
|
||||||
|
|
||||||
|
BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext);
|
||||||
|
|
||||||
String uri = element.getAttribute("uri");
|
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");
|
||||||
@@ -64,12 +74,11 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
|||||||
|
|
||||||
// Common setup
|
// Common setup
|
||||||
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
|
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
|
||||||
ParsingUtils.setPropertyValue(element, dbFactoryBuilder, "write-concern", "writeConcern");
|
setPropertyValue(dbFactoryBuilder, element, "write-concern", "writeConcern");
|
||||||
|
|
||||||
if (StringUtils.hasText(uri)) {
|
if (StringUtils.hasText(uri)) {
|
||||||
if (StringUtils.hasText(mongoRef) || StringUtils.hasText(dbname) || userCredentials != null) {
|
if (StringUtils.hasText(mongoRef) || StringUtils.hasText(dbname) || userCredentials != null) {
|
||||||
parserContext.getReaderContext().error("Configure either Mongo URI or details individually!",
|
parserContext.getReaderContext().error("Configure either Mongo URI or details individually!", source);
|
||||||
parserContext.extractSource(element));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dbFactoryBuilder.addConstructorArgValue(getMongoUri(uri));
|
dbFactoryBuilder.addConstructorArgValue(getMongoUri(uri));
|
||||||
@@ -77,19 +86,26 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Defaulting
|
// Defaulting
|
||||||
mongoRef = StringUtils.hasText(mongoRef) ? mongoRef : registerMongoBeanDefinition(element, parserContext);
|
if (StringUtils.hasText(mongoRef)) {
|
||||||
dbname = StringUtils.hasText(dbname) ? dbname : "db";
|
dbFactoryBuilder.addConstructorArgReference(mongoRef);
|
||||||
|
} else {
|
||||||
|
dbFactoryBuilder.addConstructorArgValue(registerMongoBeanDefinition(element, parserContext));
|
||||||
|
}
|
||||||
|
|
||||||
dbFactoryBuilder.addConstructorArgValue(new RuntimeBeanReference(mongoRef));
|
dbname = StringUtils.hasText(dbname) ? dbname : "db";
|
||||||
dbFactoryBuilder.addConstructorArgValue(dbname);
|
dbFactoryBuilder.addConstructorArgValue(dbname);
|
||||||
|
|
||||||
if (userCredentials != null) {
|
if (userCredentials != null) {
|
||||||
dbFactoryBuilder.addConstructorArgValue(userCredentials);
|
dbFactoryBuilder.addConstructorArgValue(userCredentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParsingUtils.registerWriteConcernPropertyEditor(parserContext.getRegistry());
|
BeanDefinitionBuilder writeConcernPropertyEditorBuilder = getWriteConcernPropertyEditorBuilder();
|
||||||
|
|
||||||
return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
|
BeanComponentDefinition component = helper.getComponent(writeConcernPropertyEditorBuilder);
|
||||||
|
parserContext.registerBeanComponent(component);
|
||||||
|
|
||||||
|
return (AbstractBeanDefinition) helper.getComponentIdButFallback(dbFactoryBuilder, BeanNames.DB_FACTORY)
|
||||||
|
.getBeanDefinition();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,14 +116,13 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
|||||||
* @param parserContext must not be {@literal null}.
|
* @param parserContext must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private String registerMongoBeanDefinition(Element element, ParserContext parserContext) {
|
private BeanDefinition registerMongoBeanDefinition(Element element, ParserContext parserContext) {
|
||||||
|
|
||||||
BeanDefinitionBuilder mongoBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoFactoryBean.class);
|
BeanDefinitionBuilder mongoBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoFactoryBean.class);
|
||||||
ParsingUtils.setPropertyValue(element, mongoBuilder, "host");
|
setPropertyValue(mongoBuilder, element, "host");
|
||||||
ParsingUtils.setPropertyValue(element, mongoBuilder, "port");
|
setPropertyValue(mongoBuilder, element, "port");
|
||||||
|
|
||||||
return BeanDefinitionReaderUtils.registerWithGeneratedName(mongoBuilder.getBeanDefinition(),
|
return getSourceBeanDefinition(mongoBuilder, parserContext, element);
|
||||||
parserContext.getRegistry());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011 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.
|
||||||
@@ -16,26 +16,34 @@
|
|||||||
package org.springframework.data.mongodb.config;
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||||
import org.springframework.data.mongodb.repository.config.MongoRepositoryConfigParser;
|
import org.springframework.data.mongodb.repository.config.MongoRepositoryConfigurationExtension;
|
||||||
|
import org.springframework.data.repository.config.RepositoryBeanDefinitionParser;
|
||||||
|
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link org.springframework.beans.factory.xml.NamespaceHandler} for Mongo DB based repositories.
|
* {@link org.springframework.beans.factory.xml.NamespaceHandler} for Mongo DB configuration.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Martin Baumgartner
|
||||||
*/
|
*/
|
||||||
public class MongoNamespaceHandler extends NamespaceHandlerSupport {
|
public class MongoNamespaceHandler extends NamespaceHandlerSupport {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
|
||||||
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
|
*/
|
||||||
*/
|
|
||||||
public void init() {
|
public void init() {
|
||||||
|
|
||||||
registerBeanDefinitionParser("repositories", new MongoRepositoryConfigParser());
|
RepositoryConfigurationExtension extension = new MongoRepositoryConfigurationExtension();
|
||||||
|
RepositoryBeanDefinitionParser repositoryBeanDefinitionParser = new RepositoryBeanDefinitionParser(extension);
|
||||||
|
|
||||||
|
registerBeanDefinitionParser("repositories", repositoryBeanDefinitionParser);
|
||||||
registerBeanDefinitionParser("mapping-converter", new MappingMongoConverterParser());
|
registerBeanDefinitionParser("mapping-converter", new MappingMongoConverterParser());
|
||||||
registerBeanDefinitionParser("mongo", new MongoParser());
|
registerBeanDefinitionParser("mongo", new MongoParser());
|
||||||
registerBeanDefinitionParser("db-factory", new MongoDbFactoryParser());
|
registerBeanDefinitionParser("db-factory", new MongoDbFactoryParser());
|
||||||
registerBeanDefinitionParser("jmx", new MongoJmxParser());
|
registerBeanDefinitionParser("jmx", new MongoJmxParser());
|
||||||
|
registerBeanDefinitionParser("auditing", new MongoAuditingBeanDefinitionParser());
|
||||||
|
registerBeanDefinitionParser("template", new MongoTemplateParser());
|
||||||
|
registerBeanDefinitionParser("gridFsTemplate", new GridFsTemplateParser());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011 the original author or authors.
|
* Copyright 2011-2012 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* 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,20 +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.config;
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.CustomEditorConfigurer;
|
import org.springframework.beans.factory.config.CustomEditorConfigurer;
|
||||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
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.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
|
||||||
import org.springframework.beans.factory.support.ManagedMap;
|
import org.springframework.beans.factory.support.ManagedMap;
|
||||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
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.ParsingUtils;
|
||||||
import org.springframework.data.mongodb.core.MongoFactoryBean;
|
import org.springframework.data.mongodb.core.MongoFactoryBean;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
@@ -35,54 +35,59 @@ import org.w3c.dom.Element;
|
|||||||
* Parser for <mongo;gt; definitions.
|
* Parser for <mongo;gt; definitions.
|
||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public class MongoParser extends AbstractSingleBeanDefinitionParser {
|
public class MongoParser implements BeanDefinitionParser {
|
||||||
|
|
||||||
@Override
|
/*
|
||||||
protected Class<?> getBeanClass(Element element) {
|
* (non-Javadoc)
|
||||||
return MongoFactoryBean.class;
|
* @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) {
|
||||||
|
|
||||||
@Override
|
Object source = parserContext.extractSource(element);
|
||||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
String id = element.getAttribute("id");
|
||||||
|
|
||||||
ParsingUtils.setPropertyValue(element, builder, "port", "port");
|
BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext);
|
||||||
ParsingUtils.setPropertyValue(element, builder, "host", "host");
|
|
||||||
ParsingUtils.setPropertyValue(element, builder, "write-concern", "writeConcern");
|
|
||||||
|
|
||||||
ParsingUtils.parseMongoOptions(element, builder);
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MongoFactoryBean.class);
|
||||||
ParsingUtils.parseReplicaSet(element, builder);
|
ParsingUtils.setPropertyValue(builder, element, "port", "port");
|
||||||
|
ParsingUtils.setPropertyValue(builder, element, "host", "host");
|
||||||
|
ParsingUtils.setPropertyValue(builder, element, "write-concern", "writeConcern");
|
||||||
|
|
||||||
registerServerAddressPropertyEditor(parserContext.getRegistry());
|
MongoParsingUtils.parseMongoOptions(element, builder);
|
||||||
ParsingUtils.registerWriteConcernPropertyEditor(parserContext.getRegistry());
|
MongoParsingUtils.parseReplicaSet(element, builder);
|
||||||
|
|
||||||
|
String defaultedId = StringUtils.hasText(id) ? id : BeanNames.MONGO;
|
||||||
|
|
||||||
|
parserContext.pushContainingComponent(new CompositeComponentDefinition("Mongo", source));
|
||||||
|
|
||||||
|
BeanComponentDefinition mongoComponent = helper.getComponent(builder, defaultedId);
|
||||||
|
parserContext.registerBeanComponent(mongoComponent);
|
||||||
|
BeanComponentDefinition serverAddressPropertyEditor = helper.getComponent(registerServerAddressPropertyEditor());
|
||||||
|
parserContext.registerBeanComponent(serverAddressPropertyEditor);
|
||||||
|
BeanComponentDefinition writeConcernPropertyEditor = helper.getComponent(MongoParsingUtils
|
||||||
|
.getWriteConcernPropertyEditorBuilder());
|
||||||
|
parserContext.registerBeanComponent(writeConcernPropertyEditor);
|
||||||
|
|
||||||
|
parserContext.popAndRegisterContainingComponent();
|
||||||
|
|
||||||
|
return mongoComponent.getBeanDefinition();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* One should only register one bean definition but want to have the convenience of using
|
* 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
|
* AbstractSingleBeanDefinitionParser but have the side effect of registering a 'default' property editor with the
|
||||||
* container.
|
* container.
|
||||||
*
|
|
||||||
* @param parserContext the ParserContext to
|
|
||||||
*/
|
*/
|
||||||
private void registerServerAddressPropertyEditor(BeanDefinitionRegistry registry) {
|
private BeanDefinitionBuilder registerServerAddressPropertyEditor() {
|
||||||
|
|
||||||
BeanDefinitionBuilder customEditorConfigurer = BeanDefinitionBuilder
|
|
||||||
.genericBeanDefinition(CustomEditorConfigurer.class);
|
|
||||||
Map<String, String> customEditors = new ManagedMap<String, String>();
|
Map<String, String> customEditors = new ManagedMap<String, String>();
|
||||||
customEditors.put("com.mongodb.ServerAddress[]",
|
customEditors.put("com.mongodb.ServerAddress[]",
|
||||||
"org.springframework.data.mongodb.config.ServerAddressPropertyEditor");
|
"org.springframework.data.mongodb.config.ServerAddressPropertyEditor");
|
||||||
customEditorConfigurer.addPropertyValue("customEditors", customEditors);
|
|
||||||
BeanDefinitionReaderUtils.registerWithGeneratedName(customEditorConfigurer.getBeanDefinition(), registry);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
||||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
builder.addPropertyValue("customEditors", customEditors);
|
||||||
throws BeanDefinitionStoreException {
|
return builder;
|
||||||
String name = super.resolveId(element, definition, parserContext);
|
|
||||||
if (!StringUtils.hasText(name)) {
|
|
||||||
name = "mongo";
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* 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 static org.springframework.data.config.ParsingUtils.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.CustomEditorConfigurer;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.ManagedMap;
|
||||||
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
|
import org.springframework.data.mongodb.core.MongoOptionsFactoryBean;
|
||||||
|
import org.springframework.util.xml.DomUtils;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for {@link BeanDefinitionParser} implementations for MongoDB.
|
||||||
|
*
|
||||||
|
* @author Mark Pollack
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
abstract class MongoParsingUtils {
|
||||||
|
|
||||||
|
private MongoParsingUtils() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the mongo replica-set element.
|
||||||
|
*
|
||||||
|
* @param parserContext the parser context
|
||||||
|
* @param element the mongo element
|
||||||
|
* @param mongoBuilder the bean definition builder to populate
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static void parseReplicaSet(Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||||
|
setPropertyValue(mongoBuilder, element, "replica-set", "replicaSetSeeds");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the mongo:options sub-element. Populates the given attribute factory with the proper attributes.
|
||||||
|
*
|
||||||
|
* @return true if parsing actually occured, false otherwise
|
||||||
|
*/
|
||||||
|
static boolean parseMongoOptions(Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||||
|
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
|
||||||
|
if (optionsElement == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BeanDefinitionBuilder optionsDefBuilder = BeanDefinitionBuilder
|
||||||
|
.genericBeanDefinition(MongoOptionsFactoryBean.class);
|
||||||
|
|
||||||
|
setPropertyValue(optionsDefBuilder, optionsElement, "connections-per-host", "connectionsPerHost");
|
||||||
|
setPropertyValue(optionsDefBuilder, optionsElement, "threads-allowed-to-block-for-connection-multiplier",
|
||||||
|
"threadsAllowedToBlockForConnectionMultiplier");
|
||||||
|
setPropertyValue(optionsDefBuilder, optionsElement, "max-wait-time", "maxWaitTime");
|
||||||
|
setPropertyValue(optionsDefBuilder, optionsElement, "connect-timeout", "connectTimeout");
|
||||||
|
setPropertyValue(optionsDefBuilder, optionsElement, "socket-timeout", "socketTimeout");
|
||||||
|
setPropertyValue(optionsDefBuilder, optionsElement, "socket-keep-alive", "socketKeepAlive");
|
||||||
|
setPropertyValue(optionsDefBuilder, optionsElement, "auto-connect-retry", "autoConnectRetry");
|
||||||
|
setPropertyValue(optionsDefBuilder, optionsElement, "max-auto-connect-retry-time", "maxAutoConnectRetryTime");
|
||||||
|
setPropertyValue(optionsDefBuilder, optionsElement, "write-number", "writeNumber");
|
||||||
|
setPropertyValue(optionsDefBuilder, optionsElement, "write-timeout", "writeTimeout");
|
||||||
|
setPropertyValue(optionsDefBuilder, optionsElement, "write-fsync", "writeFsync");
|
||||||
|
setPropertyValue(optionsDefBuilder, optionsElement, "slave-ok", "slaveOk");
|
||||||
|
|
||||||
|
mongoBuilder.addPropertyValue("mongoOptions", optionsDefBuilder.getBeanDefinition());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a
|
||||||
|
* {@link WriteConcernPropertyEditor}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static BeanDefinitionBuilder getWriteConcernPropertyEditorBuilder() {
|
||||||
|
|
||||||
|
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
|
||||||
|
customEditors.put("com.mongodb.WriteConcern", WriteConcernPropertyEditor.class);
|
||||||
|
|
||||||
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
||||||
|
builder.addPropertyValue("customEditors", customEditors);
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2013 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 static org.springframework.data.config.ParsingUtils.*;
|
||||||
|
import static org.springframework.data.mongodb.config.MongoParsingUtils.*;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
||||||
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link BeanDefinitionParser} to parse {@code template} elements into {@link BeanDefinition}s.
|
||||||
|
*
|
||||||
|
* @author Martin Baumgartner
|
||||||
|
*/
|
||||||
|
class MongoTemplateParser extends AbstractBeanDefinitionParser {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (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)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||||
|
throws BeanDefinitionStoreException {
|
||||||
|
|
||||||
|
String id = super.resolveId(element, definition, parserContext);
|
||||||
|
return StringUtils.hasText(id) ? id : BeanNames.MONGO_TEMPLATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
||||||
|
|
||||||
|
BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext);
|
||||||
|
|
||||||
|
String converterRef = element.getAttribute("converter-ref");
|
||||||
|
String dbFactoryRef = element.getAttribute("db-factory-ref");
|
||||||
|
|
||||||
|
BeanDefinitionBuilder mongoTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoTemplate.class);
|
||||||
|
setPropertyValue(mongoTemplateBuilder, element, "write-concern", "writeConcern");
|
||||||
|
|
||||||
|
if (StringUtils.hasText(dbFactoryRef)) {
|
||||||
|
mongoTemplateBuilder.addConstructorArgReference(dbFactoryRef);
|
||||||
|
} else {
|
||||||
|
mongoTemplateBuilder.addConstructorArgReference(BeanNames.DB_FACTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.hasText(converterRef)) {
|
||||||
|
mongoTemplateBuilder.addConstructorArgReference(converterRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
BeanDefinitionBuilder writeConcernPropertyEditorBuilder = getWriteConcernPropertyEditorBuilder();
|
||||||
|
|
||||||
|
BeanComponentDefinition component = helper.getComponent(writeConcernPropertyEditorBuilder);
|
||||||
|
parserContext.registerBeanComponent(component);
|
||||||
|
|
||||||
|
return (AbstractBeanDefinition) helper.getComponentIdButFallback(mongoTemplateBuilder, BeanNames.MONGO_TEMPLATE)
|
||||||
|
.getBeanDefinition();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2011 by the original author(s).
|
|
||||||
*
|
|
||||||
* 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.util.Map;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
|
||||||
import org.springframework.beans.factory.config.CustomEditorConfigurer;
|
|
||||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
|
||||||
import org.springframework.beans.factory.support.ManagedMap;
|
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
|
||||||
import org.springframework.data.mongodb.core.MongoOptionsFactoryBean;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.util.xml.DomUtils;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
|
|
||||||
abstract class ParsingUtils {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the mongo replica-set element.
|
|
||||||
*
|
|
||||||
* @param parserContext the parser context
|
|
||||||
* @param element the mongo element
|
|
||||||
* @param mongoBuilder the bean definition builder to populate
|
|
||||||
* @return true if parsing actually occured, false otherwise
|
|
||||||
*/
|
|
||||||
static boolean parseReplicaSet(Element element, BeanDefinitionBuilder mongoBuilder) {
|
|
||||||
|
|
||||||
String replicaSetString = element.getAttribute("replica-set");
|
|
||||||
if (StringUtils.hasText(replicaSetString)) {
|
|
||||||
mongoBuilder.addPropertyValue("replicaSetSeeds", replicaSetString);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the mongo:options sub-element. Populates the given attribute factory with the proper attributes.
|
|
||||||
*
|
|
||||||
* @return true if parsing actually occured, false otherwise
|
|
||||||
*/
|
|
||||||
static boolean parseMongoOptions(Element element, BeanDefinitionBuilder mongoBuilder) {
|
|
||||||
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
|
|
||||||
if (optionsElement == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BeanDefinitionBuilder optionsDefBuilder = BeanDefinitionBuilder
|
|
||||||
.genericBeanDefinition(MongoOptionsFactoryBean.class);
|
|
||||||
|
|
||||||
setPropertyValue(optionsElement, optionsDefBuilder, "connections-per-host", "connectionsPerHost");
|
|
||||||
setPropertyValue(optionsElement, optionsDefBuilder, "threads-allowed-to-block-for-connection-multiplier",
|
|
||||||
"threadsAllowedToBlockForConnectionMultiplier");
|
|
||||||
setPropertyValue(optionsElement, optionsDefBuilder, "max-wait-time", "maxWaitTime");
|
|
||||||
setPropertyValue(optionsElement, optionsDefBuilder, "connect-timeout", "connectTimeout");
|
|
||||||
setPropertyValue(optionsElement, optionsDefBuilder, "socket-timeout", "socketTimeout");
|
|
||||||
setPropertyValue(optionsElement, optionsDefBuilder, "socket-keep-alive", "socketKeepAlive");
|
|
||||||
setPropertyValue(optionsElement, optionsDefBuilder, "auto-connect-retry", "autoConnectRetry");
|
|
||||||
setPropertyValue(optionsElement, optionsDefBuilder, "max-auto-connect-retry-time", "maxAutoConnectRetryTime");
|
|
||||||
setPropertyValue(optionsElement, optionsDefBuilder, "write-number", "writeNumber");
|
|
||||||
setPropertyValue(optionsElement, optionsDefBuilder, "write-timeout", "writeTimeout");
|
|
||||||
setPropertyValue(optionsElement, optionsDefBuilder, "write-fsync", "writeFsync");
|
|
||||||
setPropertyValue(optionsElement, optionsDefBuilder, "slave-ok", "slaveOk");
|
|
||||||
|
|
||||||
mongoBuilder.addPropertyValue("mongoOptions", optionsDefBuilder.getBeanDefinition());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setPropertyValue(Element element, BeanDefinitionBuilder builder, String attrName, String propertyName) {
|
|
||||||
String attr = element.getAttribute(attrName);
|
|
||||||
if (StringUtils.hasText(attr)) {
|
|
||||||
builder.addPropertyValue(propertyName, attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the property with the given attribute name on the given {@link BeanDefinitionBuilder} to the value of the
|
|
||||||
* attribute with the given name.
|
|
||||||
*
|
|
||||||
* @param element must not be {@literal null}.
|
|
||||||
* @param builder must not be {@literal null}.
|
|
||||||
* @param attrName must not be {@literal null} or empty.
|
|
||||||
*/
|
|
||||||
static void setPropertyValue(Element element, BeanDefinitionBuilder builder, String attrName) {
|
|
||||||
String attr = element.getAttribute(attrName);
|
|
||||||
if (StringUtils.hasText(attr)) {
|
|
||||||
builder.addPropertyValue(attrName, attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link BeanDefinition} built by the given {@link BeanDefinitionBuilder} enriched with source
|
|
||||||
* information derived from the given {@link Element}.
|
|
||||||
*
|
|
||||||
* @param builder must not be {@literal null}.
|
|
||||||
* @param context must not be {@literal null}.
|
|
||||||
* @param element must not be {@literal null}.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, ParserContext context,
|
|
||||||
Element element) {
|
|
||||||
AbstractBeanDefinition definition = builder.getBeanDefinition();
|
|
||||||
definition.setSource(context.extractSource(element));
|
|
||||||
return definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers a {@link WriteConcernPropertyEditor} in the given {@link BeanDefinitionRegistry}.
|
|
||||||
*
|
|
||||||
* @param registry must not be {@literal null}.
|
|
||||||
*/
|
|
||||||
static void registerWriteConcernPropertyEditor(BeanDefinitionRegistry registry) {
|
|
||||||
|
|
||||||
Assert.notNull(registry);
|
|
||||||
|
|
||||||
BeanDefinitionBuilder customEditorConfigurer = BeanDefinitionBuilder
|
|
||||||
.genericBeanDefinition(CustomEditorConfigurer.class);
|
|
||||||
Map<String, Class<?>> customEditors = new ManagedMap<String, Class<?>>();
|
|
||||||
customEditors.put("com.mongodb.WriteConcern", WriteConcernPropertyEditor.class);
|
|
||||||
customEditorConfigurer.addPropertyValue("customEditors", customEditors);
|
|
||||||
BeanDefinitionReaderUtils.registerWithGeneratedName(customEditorConfigurer.getBeanDefinition(), registry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011 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.
|
||||||
@@ -16,8 +16,14 @@
|
|||||||
package org.springframework.data.mongodb.config;
|
package org.springframework.data.mongodb.config;
|
||||||
|
|
||||||
import java.beans.PropertyEditorSupport;
|
import java.beans.PropertyEditorSupport;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.mongodb.ServerAddress;
|
import com.mongodb.ServerAddress;
|
||||||
@@ -27,9 +33,17 @@ import com.mongodb.ServerAddress;
|
|||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Thomas Darimont
|
||||||
*/
|
*/
|
||||||
public class ServerAddressPropertyEditor extends PropertyEditorSupport {
|
public class ServerAddressPropertyEditor extends PropertyEditorSupport {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A port is a number without a leading 0 at the end of the address that is proceeded by just a single :.
|
||||||
|
*/
|
||||||
|
private static final String HOST_PORT_SPLIT_PATTERN = "(?<!:):(?=[123456789]\\d*$)";
|
||||||
|
private static final String COULD_NOT_PARSE_ADDRESS_MESSAGE = "Could not parse address {} '{}'. Check your replica set configuration!";
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(ServerAddressPropertyEditor.class);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
|
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
|
||||||
@@ -37,22 +51,86 @@ public class ServerAddressPropertyEditor extends PropertyEditorSupport {
|
|||||||
@Override
|
@Override
|
||||||
public void setAsText(String replicaSetString) {
|
public void setAsText(String replicaSetString) {
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(replicaSetString)) {
|
||||||
|
setValue(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String[] replicaSetStringArray = StringUtils.commaDelimitedListToStringArray(replicaSetString);
|
String[] replicaSetStringArray = StringUtils.commaDelimitedListToStringArray(replicaSetString);
|
||||||
ServerAddress[] serverAddresses = new ServerAddress[replicaSetStringArray.length];
|
Set<ServerAddress> serverAddresses = new HashSet<ServerAddress>(replicaSetStringArray.length);
|
||||||
|
|
||||||
for (int i = 0; i < replicaSetStringArray.length; i++) {
|
for (String element : replicaSetStringArray) {
|
||||||
|
|
||||||
String[] hostAndPort = StringUtils.delimitedListToStringArray(replicaSetStringArray[i], ":");
|
ServerAddress address = parseServerAddress(element);
|
||||||
|
|
||||||
try {
|
if (address != null) {
|
||||||
serverAddresses[i] = new ServerAddress(hostAndPort[0], Integer.parseInt(hostAndPort[1]));
|
serverAddresses.add(address);
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
throw new IllegalArgumentException("Could not parse port " + hostAndPort[1], e);
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
throw new IllegalArgumentException("Could not parse host " + hostAndPort[0], e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(serverAddresses);
|
if (serverAddresses.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Could not resolve at least one server of the replica set configuration! Validate your config!");
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(serverAddresses.toArray(new ServerAddress[serverAddresses.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the given source into a {@link ServerAddress}.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* @return the
|
||||||
|
*/
|
||||||
|
private ServerAddress parseServerAddress(String source) {
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(source)) {
|
||||||
|
LOG.warn(COULD_NOT_PARSE_ADDRESS_MESSAGE, "source", source);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] hostAndPort = extractHostAddressAndPort(source.trim());
|
||||||
|
|
||||||
|
if (hostAndPort.length > 2) {
|
||||||
|
LOG.warn(COULD_NOT_PARSE_ADDRESS_MESSAGE, "source", source);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
InetAddress hostAddress = InetAddress.getByName(hostAndPort[0]);
|
||||||
|
Integer port = hostAndPort.length == 1 ? null : Integer.parseInt(hostAndPort[1]);
|
||||||
|
|
||||||
|
return port == null ? new ServerAddress(hostAddress) : new ServerAddress(hostAddress, port);
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
LOG.warn(COULD_NOT_PARSE_ADDRESS_MESSAGE, "host", hostAndPort[0]);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
LOG.warn(COULD_NOT_PARSE_ADDRESS_MESSAGE, "port", hostAndPort[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the host and port from the given {@link String}.
|
||||||
|
*
|
||||||
|
* @param addressAndPortSource must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String[] extractHostAddressAndPort(String addressAndPortSource) {
|
||||||
|
|
||||||
|
Assert.notNull(addressAndPortSource, "Address and port source must not be null!");
|
||||||
|
|
||||||
|
String[] hostAndPort = addressAndPortSource.split(HOST_PORT_SPLIT_PATTERN);
|
||||||
|
String hostAddress = hostAndPort[0];
|
||||||
|
|
||||||
|
if (isHostAddressInIPv6BracketNotation(hostAddress)) {
|
||||||
|
hostAndPort[0] = hostAddress.substring(1, hostAddress.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hostAndPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isHostAddressInIPv6BracketNotation(String hostAddress) {
|
||||||
|
return hostAddress.startsWith("[") && hostAddress.endsWith("]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011 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.
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
|
import static org.springframework.data.domain.Sort.Direction.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -22,7 +24,6 @@ import org.springframework.dao.DataAccessException;
|
|||||||
import org.springframework.data.mongodb.core.index.IndexDefinition;
|
import org.springframework.data.mongodb.core.index.IndexDefinition;
|
||||||
import org.springframework.data.mongodb.core.index.IndexField;
|
import org.springframework.data.mongodb.core.index.IndexField;
|
||||||
import org.springframework.data.mongodb.core.index.IndexInfo;
|
import org.springframework.data.mongodb.core.index.IndexInfo;
|
||||||
import org.springframework.data.mongodb.core.query.Order;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import com.mongodb.DBCollection;
|
import com.mongodb.DBCollection;
|
||||||
@@ -34,9 +35,13 @@ import com.mongodb.MongoException;
|
|||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Komi Innocent
|
||||||
*/
|
*/
|
||||||
public class DefaultIndexOperations implements IndexOperations {
|
public class DefaultIndexOperations implements IndexOperations {
|
||||||
|
|
||||||
|
private static final Double ONE = Double.valueOf(1);
|
||||||
|
private static final Double MINUS_ONE = Double.valueOf(-1);
|
||||||
|
|
||||||
private final MongoOperations mongoOperations;
|
private final MongoOperations mongoOperations;
|
||||||
private final String collectionName;
|
private final String collectionName;
|
||||||
|
|
||||||
@@ -135,12 +140,17 @@ public class DefaultIndexOperations implements IndexOperations {
|
|||||||
|
|
||||||
Object value = keyDbObject.get(key);
|
Object value = keyDbObject.get(key);
|
||||||
|
|
||||||
if (Integer.valueOf(1).equals(value)) {
|
if ("2d".equals(value)) {
|
||||||
indexFields.add(IndexField.create(key, Order.ASCENDING));
|
|
||||||
} else if (Integer.valueOf(-1).equals(value)) {
|
|
||||||
indexFields.add(IndexField.create(key, Order.DESCENDING));
|
|
||||||
} else if ("2d".equals(value)) {
|
|
||||||
indexFields.add(IndexField.geo(key));
|
indexFields.add(IndexField.geo(key));
|
||||||
|
} else {
|
||||||
|
|
||||||
|
Double keyValue = new Double(value.toString());
|
||||||
|
|
||||||
|
if (ONE.equals(keyValue)) {
|
||||||
|
indexFields.add(IndexField.create(key, ASC));
|
||||||
|
} else if (MINUS_ONE.equals(keyValue)) {
|
||||||
|
indexFields.add(IndexField.create(key, DESC));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011 the original author or authors.
|
* Copyright 2011-2012 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* 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,59 +13,53 @@
|
|||||||
* 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;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
import com.mongodb.WriteConcern;
|
import com.mongodb.WriteConcern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an action taken against the collection. Used by {@link WriteConcernResolver} to determine a custom
|
* Represents an action taken against the collection. Used by {@link WriteConcernResolver} to determine a custom
|
||||||
* WriteConcern based on this information.
|
* {@link WriteConcern} based on this information.
|
||||||
*
|
|
||||||
* Properties that will always be not-null are collectionName and defaultWriteConcern. The EntityClass is null only for
|
|
||||||
* the MongoActionOperaton.INSERT_LIST.
|
|
||||||
*
|
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>INSERT, SAVE have null query</li>
|
* <li>INSERT, SAVE have null query</li>
|
||||||
* <li>REMOVE has null document</li>
|
* <li>REMOVE has null document</li>
|
||||||
* <li>INSERT_LIST has null entityClass, document, and query</li>
|
* <li>INSERT_LIST has null entityType, document, and query</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
*
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public class MongoAction {
|
public class MongoAction {
|
||||||
|
|
||||||
private String collectionName;
|
private final String collectionName;
|
||||||
|
private final WriteConcern defaultWriteConcern;
|
||||||
private WriteConcern defaultWriteConcern;
|
private final Class<?> entityType;
|
||||||
|
private final MongoActionOperation mongoActionOperation;
|
||||||
private Class<?> entityClass;
|
private final DBObject query;
|
||||||
|
private final DBObject document;
|
||||||
private MongoActionOperation mongoActionOperation;
|
|
||||||
|
|
||||||
private DBObject query;
|
|
||||||
|
|
||||||
private DBObject document;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of a MongoAction
|
* Create an instance of a {@link MongoAction}.
|
||||||
*
|
*
|
||||||
* @param defaultWriteConcern the default write concern
|
* @param defaultWriteConcern the default write concern.
|
||||||
* @param mongoActionOperation action being taken against the collection
|
* @param mongoActionOperation action being taken against the collection
|
||||||
* @param collectionName the collection name
|
* @param collectionName the collection name, must not be {@literal null} or empty.
|
||||||
* @param entityClass the POJO that is being operated against
|
* @param entityType the POJO that is being operated against
|
||||||
* @param document the converted DBObject from the POJO or Spring Update object
|
* @param document the converted DBObject from the POJO or Spring Update object
|
||||||
* @param query the converted DBOjbect from the Spring Query object
|
* @param query the converted DBOjbect from the Spring Query object
|
||||||
*/
|
*/
|
||||||
public MongoAction(WriteConcern defaultWriteConcern, MongoActionOperation mongoActionOperation,
|
public MongoAction(WriteConcern defaultWriteConcern, MongoActionOperation mongoActionOperation,
|
||||||
String collectionName, Class<?> entityClass, DBObject document, DBObject query) {
|
String collectionName, Class<?> entityType, DBObject document, DBObject query) {
|
||||||
super();
|
|
||||||
|
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
||||||
|
|
||||||
this.defaultWriteConcern = defaultWriteConcern;
|
this.defaultWriteConcern = defaultWriteConcern;
|
||||||
this.mongoActionOperation = mongoActionOperation;
|
this.mongoActionOperation = mongoActionOperation;
|
||||||
this.collectionName = collectionName;
|
this.collectionName = collectionName;
|
||||||
this.entityClass = entityClass;
|
this.entityType = entityType;
|
||||||
this.query = query;
|
this.query = query;
|
||||||
this.document = document;
|
this.document = document;
|
||||||
}
|
}
|
||||||
@@ -78,8 +72,16 @@ public class MongoAction {
|
|||||||
return defaultWriteConcern;
|
return defaultWriteConcern;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link #getEntityType()} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public Class<?> getEntityClass() {
|
public Class<?> getEntityClass() {
|
||||||
return entityClass;
|
return entityType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getEntityType() {
|
||||||
|
return entityType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MongoActionOperation getMongoActionOperation() {
|
public MongoActionOperation getMongoActionOperation() {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011 the original author or authors.
|
* Copyright 2011-2012 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* 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,8 +20,8 @@ package org.springframework.data.mongodb.core;
|
|||||||
* for a given mutating operation
|
* for a given mutating operation
|
||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
|
* @author Oliver Gierke
|
||||||
* @see MongoAction
|
* @see MongoAction
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public enum MongoActionOperation {
|
public enum MongoActionOperation {
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.dao.DataIntegrityViolationException;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import com.mongodb.WriteResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mongo-specific {@link DataIntegrityViolationException}.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public class MongoDataIntegrityViolationException extends DataIntegrityViolationException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -186980521176764046L;
|
||||||
|
|
||||||
|
private final WriteResult writeResult;
|
||||||
|
private final MongoActionOperation actionOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link MongoDataIntegrityViolationException} using the given message and {@link WriteResult}.
|
||||||
|
*
|
||||||
|
* @param message the exception message
|
||||||
|
* @param writeResult the {@link WriteResult} that causes the exception, must not be {@literal null}.
|
||||||
|
* @param actionOperation the {@link MongoActionOperation} that caused the exception, must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public MongoDataIntegrityViolationException(String message, WriteResult writeResult,
|
||||||
|
MongoActionOperation actionOperation) {
|
||||||
|
|
||||||
|
super(message);
|
||||||
|
|
||||||
|
Assert.notNull(writeResult, "WriteResult must not be null!");
|
||||||
|
Assert.notNull(actionOperation, "MongoActionOperation must not be null!");
|
||||||
|
|
||||||
|
this.writeResult = writeResult;
|
||||||
|
this.actionOperation = actionOperation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link WriteResult} that caused the exception.
|
||||||
|
*
|
||||||
|
* @return the writeResult
|
||||||
|
*/
|
||||||
|
public WriteResult getWriteResult() {
|
||||||
|
return writeResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link MongoActionOperation} in which the current exception occured.
|
||||||
|
*
|
||||||
|
* @return the actionOperation
|
||||||
|
*/
|
||||||
|
public MongoActionOperation getActionOperation() {
|
||||||
|
return actionOperation;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2011 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.
|
||||||
@@ -26,14 +26,13 @@ import com.mongodb.DB;
|
|||||||
import com.mongodb.Mongo;
|
import com.mongodb.Mongo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class featuring helper methods for internal MongoDb classes.
|
* Helper class featuring helper methods for internal MongoDb classes. Mainly intended for internal use within the
|
||||||
* <p/>
|
* framework.
|
||||||
* <p>
|
|
||||||
* Mainly intended for internal use within the framework.
|
|
||||||
*
|
*
|
||||||
* @author Thomas Risberg
|
* @author Thomas Risberg
|
||||||
* @author Graeme Rocher
|
* @author Graeme Rocher
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Randy Watler
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
public abstract class MongoDbUtils {
|
public abstract class MongoDbUtils {
|
||||||
@@ -78,51 +77,65 @@ public abstract class MongoDbUtils {
|
|||||||
private static DB doGetDB(Mongo mongo, String databaseName, UserCredentials credentials, boolean allowCreate) {
|
private static DB doGetDB(Mongo mongo, String databaseName, UserCredentials credentials, boolean allowCreate) {
|
||||||
|
|
||||||
DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo);
|
DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo);
|
||||||
if (dbHolder != null && !dbHolder.isEmpty()) {
|
|
||||||
// pre-bound Mongo DB
|
// Do we have a populated holder and TX sync active?
|
||||||
DB db = null;
|
if (dbHolder != null && !dbHolder.isEmpty() && TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||||
if (TransactionSynchronizationManager.isSynchronizationActive() && dbHolder.doesNotHoldNonDefaultDB()) {
|
|
||||||
// Spring transaction management is active ->
|
DB db = dbHolder.getDB(databaseName);
|
||||||
db = dbHolder.getDB();
|
|
||||||
if (db != null && !dbHolder.isSynchronizedWithTransaction()) {
|
// DB found but not yet synchronized
|
||||||
LOGGER.debug("Registering Spring transaction synchronization for existing Mongo DB");
|
if (db != null && !dbHolder.isSynchronizedWithTransaction()) {
|
||||||
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(dbHolder, mongo));
|
|
||||||
dbHolder.setSynchronizedWithTransaction(true);
|
LOGGER.debug("Registering Spring transaction synchronization for existing MongoDB {}.", databaseName);
|
||||||
}
|
|
||||||
|
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(dbHolder, mongo));
|
||||||
|
dbHolder.setSynchronizedWithTransaction(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (db != null) {
|
if (db != null) {
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.trace("Getting Mongo Database name=[" + databaseName + "]");
|
// Lookup fresh database instance
|
||||||
|
LOGGER.debug("Getting Mongo Database name=[{}]", databaseName);
|
||||||
|
|
||||||
DB db = mongo.getDB(databaseName);
|
DB db = mongo.getDB(databaseName);
|
||||||
|
|
||||||
boolean credentialsGiven = credentials.hasUsername() && credentials.hasPassword();
|
boolean credentialsGiven = credentials.hasUsername() && credentials.hasPassword();
|
||||||
if (credentialsGiven && !db.isAuthenticated()) {
|
|
||||||
// Note, can only authenticate once against the same com.mongodb.DB object.
|
|
||||||
String username = credentials.getUsername();
|
|
||||||
String password = credentials.hasPassword() ? credentials.getPassword() : null;
|
|
||||||
|
|
||||||
if (!db.authenticate(username, password == null ? null : password.toCharArray())) {
|
synchronized (db) {
|
||||||
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName
|
|
||||||
+ "], username = [" + username + "], password = [" + password + "]", databaseName, credentials);
|
if (credentialsGiven && !db.isAuthenticated()) {
|
||||||
|
|
||||||
|
String username = credentials.getUsername();
|
||||||
|
String password = credentials.hasPassword() ? credentials.getPassword() : null;
|
||||||
|
|
||||||
|
if (!db.authenticate(username, password == null ? null : password.toCharArray())) {
|
||||||
|
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName + "], "
|
||||||
|
+ credentials.toString(), databaseName, credentials);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use same Session for further Mongo actions within the transaction.
|
// TX sync active, bind new database to thread
|
||||||
// Thread object will get removed by synchronization at transaction completion.
|
|
||||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||||
// We're within a Spring-managed transaction, possibly from JtaTransactionManager.
|
|
||||||
LOGGER.debug("Registering Spring transaction synchronization for new Hibernate Session");
|
LOGGER.debug("Registering Spring transaction synchronization for MongoDB instance {}.", databaseName);
|
||||||
|
|
||||||
DbHolder holderToUse = dbHolder;
|
DbHolder holderToUse = dbHolder;
|
||||||
|
|
||||||
if (holderToUse == null) {
|
if (holderToUse == null) {
|
||||||
holderToUse = new DbHolder(db);
|
holderToUse = new DbHolder(databaseName, db);
|
||||||
} else {
|
} else {
|
||||||
holderToUse.addDB(db);
|
holderToUse.addDB(databaseName, db);
|
||||||
}
|
}
|
||||||
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(holderToUse, mongo));
|
|
||||||
holderToUse.setSynchronizedWithTransaction(true);
|
// synchronize holder only if not yet synchronized
|
||||||
|
if (!holderToUse.isSynchronizedWithTransaction()) {
|
||||||
|
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(holderToUse, mongo));
|
||||||
|
holderToUse.setSynchronizedWithTransaction(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (holderToUse != dbHolder) {
|
if (holderToUse != dbHolder) {
|
||||||
TransactionSynchronizationManager.bindResource(mongo, holderToUse);
|
TransactionSynchronizationManager.bindResource(mongo, holderToUse);
|
||||||
}
|
}
|
||||||
@@ -146,11 +159,12 @@ public abstract class MongoDbUtils {
|
|||||||
* @return whether the DB is transactional
|
* @return whether the DB is transactional
|
||||||
*/
|
*/
|
||||||
public static boolean isDBTransactional(DB db, Mongo mongo) {
|
public static boolean isDBTransactional(DB db, Mongo mongo) {
|
||||||
|
|
||||||
if (mongo == null) {
|
if (mongo == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo);
|
DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo);
|
||||||
return (dbHolder != null && dbHolder.containsDB(db));
|
return dbHolder != null && dbHolder.containsDB(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -159,6 +173,7 @@ public abstract class MongoDbUtils {
|
|||||||
* @param db the DB to close (may be <code>null</code>)
|
* @param db the DB to close (may be <code>null</code>)
|
||||||
*/
|
*/
|
||||||
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 {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2011 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,12 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
import com.mongodb.MongoException;
|
|
||||||
import com.mongodb.MongoException.CursorNotFound;
|
|
||||||
import com.mongodb.MongoException.DuplicateKey;
|
|
||||||
import com.mongodb.MongoException.Network;
|
|
||||||
import com.mongodb.MongoInternalException;
|
|
||||||
|
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.DataAccessResourceFailureException;
|
import org.springframework.dao.DataAccessResourceFailureException;
|
||||||
import org.springframework.dao.DuplicateKeyException;
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
@@ -29,21 +23,26 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
|||||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||||
import org.springframework.data.mongodb.UncategorizedMongoDbException;
|
import org.springframework.data.mongodb.UncategorizedMongoDbException;
|
||||||
|
|
||||||
|
import com.mongodb.MongoException;
|
||||||
|
import com.mongodb.MongoException.CursorNotFound;
|
||||||
|
import com.mongodb.MongoException.DuplicateKey;
|
||||||
|
import com.mongodb.MongoException.Network;
|
||||||
|
import com.mongodb.MongoInternalException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
* exception from the {@code org.springframework.dao} hierarchy. Return {@literal null} if no translation is
|
* exception from the {@code org.springframework.dao} hierarchy. Return {@literal null} if no translation is
|
||||||
* appropriate: any other exception may have resulted from user code, and should not be translated.
|
* appropriate: any other exception may have resulted from user code, and should not be translated.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Michal Vich
|
||||||
*/
|
*/
|
||||||
public class MongoExceptionTranslator implements PersistenceExceptionTranslator {
|
public class MongoExceptionTranslator implements PersistenceExceptionTranslator {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
||||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#
|
*/
|
||||||
* translateExceptionIfPossible(java.lang.RuntimeException)
|
|
||||||
*/
|
|
||||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||||
|
|
||||||
// Check for well-known MongoException subclasses.
|
// Check for well-known MongoException subclasses.
|
||||||
@@ -52,14 +51,23 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator
|
|||||||
if (ex instanceof DuplicateKey) {
|
if (ex instanceof DuplicateKey) {
|
||||||
return new DuplicateKeyException(ex.getMessage(), ex);
|
return new DuplicateKeyException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ex instanceof Network) {
|
if (ex instanceof Network) {
|
||||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ex instanceof CursorNotFound) {
|
if (ex instanceof CursorNotFound) {
|
||||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ex instanceof MongoInternalException) {
|
||||||
|
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
|
||||||
if (ex instanceof MongoException) {
|
if (ex instanceof MongoException) {
|
||||||
|
|
||||||
int code = ((MongoException) ex).getCode();
|
int code = ((MongoException) ex).getCode();
|
||||||
|
|
||||||
if (code == 11000 || code == 11001) {
|
if (code == 11000 || code == 11001) {
|
||||||
throw new DuplicateKeyException(ex.getMessage(), ex);
|
throw new DuplicateKeyException(ex.getMessage(), ex);
|
||||||
} else if (code == 12000 || code == 13440) {
|
} else if (code == 12000 || code == 13440) {
|
||||||
@@ -69,9 +77,6 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator
|
|||||||
}
|
}
|
||||||
return new UncategorizedMongoDbException(ex.getMessage(), ex);
|
return new UncategorizedMongoDbException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
if (ex instanceof MongoInternalException) {
|
|
||||||
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we get here, we have an exception that resulted from user code,
|
// If we get here, we have an exception that resulted from user code,
|
||||||
// rather than the persistence provider, so we return null to indicate
|
// rather than the persistence provider, so we return null to indicate
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2012 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,7 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
@@ -24,6 +26,7 @@ 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;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.mongodb.Mongo;
|
import com.mongodb.Mongo;
|
||||||
import com.mongodb.MongoOptions;
|
import com.mongodb.MongoOptions;
|
||||||
@@ -36,6 +39,7 @@ import com.mongodb.WriteConcern;
|
|||||||
* @author Thomas Risberg
|
* @author Thomas Risberg
|
||||||
* @author Graeme Rocher
|
* @author Graeme Rocher
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Thomas Darimont
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, DisposableBean,
|
public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, DisposableBean,
|
||||||
@@ -57,11 +61,38 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, D
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setReplicaSetSeeds(ServerAddress[] replicaSetSeeds) {
|
public void setReplicaSetSeeds(ServerAddress[] replicaSetSeeds) {
|
||||||
this.replicaSetSeeds = Arrays.asList(replicaSetSeeds);
|
this.replicaSetSeeds = filterNonNullElementsAsList(replicaSetSeeds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link #setReplicaSetSeeds(ServerAddress[])} instead
|
||||||
|
*
|
||||||
|
* @param replicaPair
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setReplicaPair(ServerAddress[] replicaPair) {
|
public void setReplicaPair(ServerAddress[] replicaPair) {
|
||||||
this.replicaPair = Arrays.asList(replicaPair);
|
this.replicaPair = filterNonNullElementsAsList(replicaPair);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param elements the elements to filter <T>
|
||||||
|
* @return a new unmodifiable {@link List#} from the given elements without nulls
|
||||||
|
*/
|
||||||
|
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) {
|
||||||
@@ -117,6 +148,7 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, D
|
|||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
|
||||||
Mongo mongo;
|
Mongo mongo;
|
||||||
@@ -126,15 +158,15 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, D
|
|||||||
mongoOptions = new MongoOptions();
|
mongoOptions = new MongoOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (replicaPair != null) {
|
if (!isNullOrEmpty(replicaPair)) {
|
||||||
if (replicaPair.size() < 2) {
|
if (replicaPair.size() < 2) {
|
||||||
throw new CannotGetMongoDbConnectionException("A replica pair must have two server entries");
|
throw new CannotGetMongoDbConnectionException("A replica pair must have two server entries");
|
||||||
}
|
}
|
||||||
mongo = new Mongo(replicaPair.get(0), replicaPair.get(1), mongoOptions);
|
mongo = new Mongo(replicaPair.get(0), replicaPair.get(1), mongoOptions);
|
||||||
} else if (replicaSetSeeds != null) {
|
} else if (!isNullOrEmpty(replicaSetSeeds)) {
|
||||||
mongo = new Mongo(replicaSetSeeds, mongoOptions);
|
mongo = new Mongo(replicaSetSeeds, mongoOptions);
|
||||||
} else {
|
} else {
|
||||||
String mongoHost = host != null ? host : defaultOptions.getHost();
|
String mongoHost = StringUtils.hasText(host) ? host : defaultOptions.getHost();
|
||||||
mongo = port != null ? new Mongo(new ServerAddress(mongoHost, port), mongoOptions) : new Mongo(mongoHost,
|
mongo = port != null ? new Mongo(new ServerAddress(mongoHost, port), mongoOptions) : new Mongo(mongoHost,
|
||||||
mongoOptions);
|
mongoOptions);
|
||||||
}
|
}
|
||||||
@@ -146,6 +178,10 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, D
|
|||||||
this.mongo = mongo;
|
this.mongo = mongo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isNullOrEmpty(Collection<?> elements) {
|
||||||
|
return elements == null || elements.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2011 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.
|
||||||
@@ -19,6 +19,9 @@ import java.util.Collection;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
|
||||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||||
import org.springframework.data.mongodb.core.geo.GeoResult;
|
import org.springframework.data.mongodb.core.geo.GeoResult;
|
||||||
import org.springframework.data.mongodb.core.geo.GeoResults;
|
import org.springframework.data.mongodb.core.geo.GeoResults;
|
||||||
@@ -45,6 +48,8 @@ import com.mongodb.WriteResult;
|
|||||||
* @author Thomas Risberg
|
* @author Thomas Risberg
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Tobias Trelle
|
||||||
|
* @author Chuong Ngo
|
||||||
*/
|
*/
|
||||||
public interface MongoOperations {
|
public interface MongoOperations {
|
||||||
|
|
||||||
@@ -247,7 +252,7 @@ public interface MongoOperations {
|
|||||||
* 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/>
|
||||||
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
* configured otherwise, an instance of MappingMongoConverter will be used.
|
||||||
* <p/>
|
* <p/>
|
||||||
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way
|
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way
|
||||||
* to map objects since the test for class type is done in the client and not on the server.
|
* to map objects since the test for class type is done in the client and not on the server.
|
||||||
@@ -261,7 +266,7 @@ public interface MongoOperations {
|
|||||||
* Query for a list of objects of type T from the specified collection.
|
* Query for a list of objects of type T from the specified collection.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
* configured otherwise, an instance of MappingMongoConverter will be used.
|
||||||
* <p/>
|
* <p/>
|
||||||
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way
|
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way
|
||||||
* to map objects since the test for class type is done in the client and not on the server.
|
* to map objects since the test for class type is done in the client and not on the server.
|
||||||
@@ -301,6 +306,57 @@ public interface MongoOperations {
|
|||||||
*/
|
*/
|
||||||
<T> GroupByResults<T> group(Criteria criteria, String inputCollectionName, GroupBy groupBy, Class<T> entityClass);
|
<T> GroupByResults<T> group(Criteria criteria, String inputCollectionName, GroupBy groupBy, Class<T> entityClass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute an aggregation operation. The raw results will be mapped to the given entity class. The name of the
|
||||||
|
* inputCollection is derived from the inputType of the aggregation.
|
||||||
|
*
|
||||||
|
* @param aggregation The {@link TypedAggregation} specification holding the aggregation operations, must not be
|
||||||
|
* {@literal null}.
|
||||||
|
* @param collectionName The name of the input collection to use for the aggreation.
|
||||||
|
* @param outputType The parameterized type of the returned list, must not be {@literal null}.
|
||||||
|
* @return The results of the aggregation operation.
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
<O> AggregationResults<O> aggregate(TypedAggregation<?> aggregation, String collectionName, Class<O> outputType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute an aggregation operation. The raw results will be mapped to the given entity class. The name of the
|
||||||
|
* inputCollection is derived from the inputType of the aggregation.
|
||||||
|
*
|
||||||
|
* @param aggregation The {@link TypedAggregation} specification holding the aggregation operations, must not be
|
||||||
|
* {@literal null}.
|
||||||
|
* @param outputType The parameterized type of the returned list, must not be {@literal null}.
|
||||||
|
* @return The results of the aggregation operation.
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
<O> AggregationResults<O> aggregate(TypedAggregation<?> aggregation, Class<O> outputType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute an aggregation operation. The raw results will be mapped to the given entity class.
|
||||||
|
*
|
||||||
|
* @param aggregation The {@link Aggregation} specification holding the aggregation operations, must not be
|
||||||
|
* {@literal null}.
|
||||||
|
* @param inputType the inputType where the aggregation operation will read from, must not be {@literal null} or
|
||||||
|
* empty.
|
||||||
|
* @param outputType The parameterized type of the returned list, must not be {@literal null}.
|
||||||
|
* @return The results of the aggregation operation.
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
<O> AggregationResults<O> aggregate(Aggregation aggregation, Class<?> inputType, Class<O> outputType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute an aggregation operation. The raw results will be mapped to the given entity class.
|
||||||
|
*
|
||||||
|
* @param aggregation The {@link Aggregation} specification holding the aggregation operations, must not be
|
||||||
|
* {@literal null}.
|
||||||
|
* @param collectionName the collection where the aggregation operation will read from, must not be {@literal null} or
|
||||||
|
* empty.
|
||||||
|
* @param outputType The parameterized type of the returned list, must not be {@literal null}.
|
||||||
|
* @return The results of the aggregation operation.
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
<O> AggregationResults<O> aggregate(Aggregation aggregation, String collectionName, Class<O> outputType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a map-reduce operation. The map-reduce operation will be formed with an output type of INLINE
|
* Execute a map-reduce operation. The map-reduce operation will be formed with an output type of INLINE
|
||||||
*
|
*
|
||||||
@@ -382,7 +438,7 @@ public interface MongoOperations {
|
|||||||
* specified type.
|
* specified type.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
* configured otherwise, an instance of MappingMongoConverter will be used.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
|
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
|
||||||
* feature rich {@link Query}.
|
* feature rich {@link Query}.
|
||||||
@@ -399,7 +455,7 @@ public interface MongoOperations {
|
|||||||
* type.
|
* type.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
* configured otherwise, an instance of MappingMongoConverter will be used.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
|
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
|
||||||
* feature rich {@link Query}.
|
* feature rich {@link Query}.
|
||||||
@@ -408,16 +464,21 @@ public interface MongoOperations {
|
|||||||
* specification
|
* specification
|
||||||
* @param entityClass the parameterized type of the returned list.
|
* @param entityClass the parameterized type of the returned list.
|
||||||
* @param collectionName name of the collection to retrieve the objects from
|
* @param collectionName name of the collection to retrieve the objects from
|
||||||
*
|
|
||||||
* @return the converted object
|
* @return the converted object
|
||||||
*/
|
*/
|
||||||
<T> T findOne(Query query, Class<T> entityClass, String collectionName);
|
<T> T findOne(Query query, Class<T> entityClass, String collectionName);
|
||||||
|
|
||||||
|
boolean exists(Query query, String collectionName);
|
||||||
|
|
||||||
|
boolean exists(Query query, Class<?> entityClass);
|
||||||
|
|
||||||
|
boolean exists(Query query, Class<?> entityClass, String collectionName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map the results of an ad-hoc query on the collection for the entity class to a List of the specified type.
|
* Map the results of an ad-hoc query on the collection for the entity class to a List of the specified type.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
* configured otherwise, an instance of MappingMongoConverter will be used.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
|
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
|
||||||
* feature rich {@link Query}.
|
* feature rich {@link Query}.
|
||||||
@@ -433,7 +494,7 @@ public interface MongoOperations {
|
|||||||
* Map the results of an ad-hoc query on the specified collection to a List of the specified type.
|
* Map the results of an ad-hoc query on the specified collection to a List of the specified type.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
* configured otherwise, an instance of MappingMongoConverter will be used.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
|
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
|
||||||
* feature rich {@link Query}.
|
* feature rich {@link Query}.
|
||||||
@@ -442,7 +503,6 @@ public interface MongoOperations {
|
|||||||
* specification
|
* specification
|
||||||
* @param entityClass the parameterized type of the returned list.
|
* @param entityClass the parameterized type of the returned list.
|
||||||
* @param collectionName name of the collection to retrieve the objects from
|
* @param collectionName name of the collection to retrieve the objects from
|
||||||
*
|
|
||||||
* @return the List of converted objects
|
* @return the List of converted objects
|
||||||
*/
|
*/
|
||||||
<T> List<T> find(Query query, Class<T> entityClass, String collectionName);
|
<T> List<T> find(Query query, Class<T> entityClass, String collectionName);
|
||||||
@@ -464,7 +524,6 @@ public interface MongoOperations {
|
|||||||
* @param id the id of the document to return
|
* @param id the id of the document to return
|
||||||
* @param entityClass the type to convert the document to
|
* @param entityClass the type to convert the document to
|
||||||
* @param collectionName the collection to query for the document
|
* @param collectionName the collection to query for the document
|
||||||
*
|
|
||||||
* @param <T>
|
* @param <T>
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -501,7 +560,7 @@ public interface MongoOperations {
|
|||||||
* type. The first document that matches the query is returned and also removed from the collection in the database.
|
* type. The first document that matches the query is returned and also removed from the collection in the database.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
* configured otherwise, an instance of MappingMongoConverter will be used.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
|
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
|
||||||
* feature rich {@link Query}.
|
* feature rich {@link Query}.
|
||||||
@@ -510,7 +569,6 @@ public interface MongoOperations {
|
|||||||
* specification
|
* specification
|
||||||
* @param entityClass the parameterized type of the returned list.
|
* @param entityClass the parameterized type of the returned list.
|
||||||
* @param collectionName name of the collection to retrieve the objects from
|
* @param collectionName name of the collection to retrieve the objects from
|
||||||
*
|
|
||||||
* @return the converted object
|
* @return the converted object
|
||||||
*/
|
*/
|
||||||
<T> T findAndRemove(Query query, Class<T> entityClass, String collectionName);
|
<T> T findAndRemove(Query query, Class<T> entityClass, String collectionName);
|
||||||
@@ -555,7 +613,7 @@ public interface MongoOperations {
|
|||||||
* Insert the object into the specified collection.
|
* Insert the object into the specified collection.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
* configured otherwise, an instance of MappingMongoConverter will be used.
|
||||||
* <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.
|
||||||
*
|
*
|
||||||
@@ -593,7 +651,7 @@ public interface MongoOperations {
|
|||||||
* object is not already present, that is an 'upsert'.
|
* object is not already present, that is an 'upsert'.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
* configured otherwise, an instance of MappingMongoConverter will be used.
|
||||||
* <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
|
||||||
@@ -610,7 +668,7 @@ public interface MongoOperations {
|
|||||||
* is an 'upsert'.
|
* is an 'upsert'.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
* configured otherwise, an instance of MappingMongoConverter will be used.
|
||||||
* <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
|
||||||
@@ -646,6 +704,18 @@ public interface MongoOperations {
|
|||||||
*/
|
*/
|
||||||
WriteResult upsert(Query query, Update update, String collectionName);
|
WriteResult upsert(Query query, Update update, String collectionName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
|
||||||
|
* combining the query document and the update document.
|
||||||
|
*
|
||||||
|
* @param query the query document that specifies the criteria used to select a record to be upserted
|
||||||
|
* @param update the update document that contains the updated object or $ operators to manipulate the existing object
|
||||||
|
* @param entityClass class of the pojo to be operated on
|
||||||
|
* @param collectionName name of the collection to update the object in
|
||||||
|
* @return the WriteResult which lets you access the results of the previous write.
|
||||||
|
*/
|
||||||
|
WriteResult upsert(Query query, Update update, Class<?> entityClass, String collectionName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the first object that is found in the collection of the entity class that matches the query document with
|
* Updates the first object that is found in the collection of the entity class that matches the query document with
|
||||||
* the provided update document.
|
* the provided update document.
|
||||||
@@ -670,6 +740,19 @@ public interface MongoOperations {
|
|||||||
*/
|
*/
|
||||||
WriteResult updateFirst(Query query, Update update, String collectionName);
|
WriteResult updateFirst(Query query, Update update, String collectionName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the first object that is found in the specified collection that matches the query document criteria with
|
||||||
|
* the provided updated document.
|
||||||
|
*
|
||||||
|
* @param query the query document that specifies the criteria used to select a record to be updated
|
||||||
|
* @param update the update document that contains the updated object or $ operators to manipulate the existing
|
||||||
|
* object.
|
||||||
|
* @param entityClass class of the pojo to be operated on
|
||||||
|
* @param collectionName name of the collection to update the object in
|
||||||
|
* @return the WriteResult which lets you access the results of the previous write.
|
||||||
|
*/
|
||||||
|
WriteResult updateFirst(Query query, Update update, Class<?> entityClass, String collectionName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
|
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
|
||||||
* with the provided updated document.
|
* with the provided updated document.
|
||||||
@@ -694,6 +777,19 @@ public interface MongoOperations {
|
|||||||
*/
|
*/
|
||||||
WriteResult updateMulti(Query query, Update update, String collectionName);
|
WriteResult updateMulti(Query query, Update update, String collectionName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
|
||||||
|
* with the provided updated document.
|
||||||
|
*
|
||||||
|
* @param query the query document that specifies the criteria used to select a record to be updated
|
||||||
|
* @param update the update document that contains the updated object or $ operators to manipulate the existing
|
||||||
|
* object.
|
||||||
|
* @param entityClass class of the pojo to be operated on
|
||||||
|
* @param collectionName name of the collection to update the object in
|
||||||
|
* @return the WriteResult which lets you access the results of the previous write.
|
||||||
|
*/
|
||||||
|
WriteResult updateMulti(final Query query, final Update update, Class<?> entityClass, String collectionName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the given object from the collection by id.
|
* Remove the given object from the collection by id.
|
||||||
*
|
*
|
||||||
@@ -713,11 +809,12 @@ public interface MongoOperations {
|
|||||||
* Remove all documents that match the provided query document criteria from the the collection used to store the
|
* Remove all documents that match the provided query document criteria from the the collection used to store the
|
||||||
* entityClass. The Class parameter is also used to help convert the Id of the object if it is present in the query.
|
* entityClass. The Class parameter is also used to help convert the Id of the object if it is present in the query.
|
||||||
*
|
*
|
||||||
* @param <T>
|
|
||||||
* @param query
|
* @param query
|
||||||
* @param entityClass
|
* @param entityClass
|
||||||
*/
|
*/
|
||||||
<T> void remove(Query query, Class<T> entityClass);
|
void remove(Query query, Class<?> entityClass);
|
||||||
|
|
||||||
|
void remove(Query query, Class<?> entityClass, String collectionName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all documents from the specified collection that match the provided query document criteria. There is no
|
* Remove all documents from the specified collection that match the provided query document criteria. There is no
|
||||||
@@ -734,4 +831,4 @@ public interface MongoOperations {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
MongoConverter getConverter();
|
MongoConverter getConverter();
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -47,7 +47,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
|||||||
* Create an instance of {@link SimpleMongoDbFactory} given the {@link Mongo} instance and database name.
|
* Create an instance of {@link SimpleMongoDbFactory} given the {@link Mongo} instance and database name.
|
||||||
*
|
*
|
||||||
* @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}.
|
* @param databaseName database name, not be {@literal null} or empty.
|
||||||
*/
|
*/
|
||||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName) {
|
public SimpleMongoDbFactory(Mongo mongo, String databaseName) {
|
||||||
this(mongo, databaseName, UserCredentials.NO_CREDENTIALS, false);
|
this(mongo, databaseName, UserCredentials.NO_CREDENTIALS, false);
|
||||||
@@ -57,7 +57,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
|||||||
* Create an instance of SimpleMongoDbFactory given the Mongo instance, database name, and username/password
|
* Create an instance of SimpleMongoDbFactory given the Mongo instance, database name, and username/password
|
||||||
*
|
*
|
||||||
* @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}.
|
* @param databaseName Database name, must not be {@literal null} or empty.
|
||||||
* @param credentials username and password.
|
* @param credentials username and password.
|
||||||
*/
|
*/
|
||||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials) {
|
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011 the original author or authors.
|
* Copyright 2011-2012 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* 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,27 +13,25 @@
|
|||||||
* 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;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
import com.mongodb.WriteConcern;
|
import com.mongodb.WriteConcern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A strategy interface to determine the WriteConcern to use for a given MongoDbAction.
|
* A strategy interface to determine the {@link WriteConcern} to use for a given {@link MongoAction}. Return the passed
|
||||||
*
|
* in default {@link WriteConcern} (a property on {@link MongoAction}) if no determination can be made.
|
||||||
* Return the passed in default WriteConcern (a property on MongoAction) if no determination can be made.
|
|
||||||
*
|
*
|
||||||
* @author Mark Pollack
|
* @author Mark Pollack
|
||||||
*
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public interface WriteConcernResolver {
|
public interface WriteConcernResolver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the WriteConcern given the MongoAction
|
* Resolve the {@link WriteConcern} given the {@link MongoAction}.
|
||||||
*
|
*
|
||||||
* @param action describes the context of the Mongo action. Contains a default WriteConcern to use if one should not
|
* @param action describes the context of the Mongo action. Contains a default {@link WriteConcern} to use if one
|
||||||
* be resolved.
|
* should not be resolved.
|
||||||
* @return a WriteConcern based on the passed in MongoAction value, maybe null
|
* @return a {@link WriteConcern} based on the passed in {@link MongoAction} value, maybe {@literal null}.
|
||||||
*/
|
*/
|
||||||
WriteConcern resolve(MongoAction action);
|
WriteConcern resolve(MongoAction action);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
package org.springframework.data.mongodb.core;
|
package org.springframework.data.mongodb.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum to represent how strict the check of {@link com.mongodb.WriteResult} shall be. It can either be skipped entirely
|
||||||
|
* (use {@link #NONE}), or errors can be logged ({@link #LOG}) or cause an exception to be thrown {@link #EXCEPTION}.
|
||||||
|
*
|
||||||
|
* @author Thomas Risberg
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
public enum WriteResultChecking {
|
public enum WriteResultChecking {
|
||||||
|
|
||||||
NONE, LOG, EXCEPTION
|
NONE, LOG, EXCEPTION
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,305 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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 static org.springframework.data.mongodb.core.aggregation.Fields.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
|
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.Fields.AggregationField;
|
||||||
|
import org.springframework.data.mongodb.core.query.Criteria;
|
||||||
|
import org.springframework.data.mongodb.core.query.SerializationUtils;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An {@code Aggregation} is a representation of a list of aggregation steps to be performed by the MongoDB Aggregation
|
||||||
|
* Framework.
|
||||||
|
*
|
||||||
|
* @author Tobias Trelle
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public class Aggregation {
|
||||||
|
|
||||||
|
public static final AggregationOperationContext DEFAULT_CONTEXT = new NoOpAggregationOperationContext();
|
||||||
|
|
||||||
|
private final List<AggregationOperation> operations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
||||||
|
*
|
||||||
|
* @param operations must not be {@literal null} or empty.
|
||||||
|
*/
|
||||||
|
public static Aggregation newAggregation(List<? extends AggregationOperation> operations) {
|
||||||
|
return newAggregation(operations.toArray(new AggregationOperation[operations.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
||||||
|
*
|
||||||
|
* @param operations must not be {@literal null} or empty.
|
||||||
|
*/
|
||||||
|
public static Aggregation newAggregation(AggregationOperation... operations) {
|
||||||
|
return new Aggregation(operations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link TypedAggregation} for the given type and {@link AggregationOperation}s.
|
||||||
|
*
|
||||||
|
* @param type must not be {@literal null}.
|
||||||
|
* @param operations must not be {@literal null} or empty.
|
||||||
|
*/
|
||||||
|
public static <T> TypedAggregation<T> newAggregation(Class<T> type, List<? extends AggregationOperation> operations) {
|
||||||
|
return newAggregation(type, operations.toArray(new AggregationOperation[operations.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link TypedAggregation} for the given type and {@link AggregationOperation}s.
|
||||||
|
*
|
||||||
|
* @param type must not be {@literal null}.
|
||||||
|
* @param operations must not be {@literal null} or empty.
|
||||||
|
*/
|
||||||
|
public static <T> TypedAggregation<T> newAggregation(Class<T> type, AggregationOperation... operations) {
|
||||||
|
return new TypedAggregation<T>(type, operations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
||||||
|
*
|
||||||
|
* @param aggregationOperations must not be {@literal null} or empty.
|
||||||
|
*/
|
||||||
|
protected Aggregation(AggregationOperation... aggregationOperations) {
|
||||||
|
|
||||||
|
Assert.notNull(aggregationOperations, "AggregationOperations must not be null!");
|
||||||
|
Assert.isTrue(aggregationOperations.length > 0, "At least one AggregationOperation has to be provided");
|
||||||
|
|
||||||
|
this.operations = Arrays.asList(aggregationOperations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pointer to the previous {@link AggregationOperation}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String previousOperation() {
|
||||||
|
return "_id";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ProjectionOperation} including the given fields.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ProjectionOperation project(String... fields) {
|
||||||
|
return project(fields(fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ProjectionOperation} includeing the given {@link Fields}.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ProjectionOperation project(Fields fields) {
|
||||||
|
return new ProjectionOperation(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to create a new {@link UnwindOperation} for the field with the given name.
|
||||||
|
*
|
||||||
|
* @param fieldName must not be {@literal null} or empty.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static UnwindOperation unwind(String field) {
|
||||||
|
return new UnwindOperation(field(field));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link GroupOperation} for the given fields.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static GroupOperation group(String... fields) {
|
||||||
|
return group(fields(fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link GroupOperation} for the given {@link Fields}.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static GroupOperation group(Fields fields) {
|
||||||
|
return new GroupOperation(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to create a new {@link SortOperation} for the given {@link Sort}.
|
||||||
|
*
|
||||||
|
* @param sort must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static SortOperation sort(Sort sort) {
|
||||||
|
return new SortOperation(sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 fields must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static SortOperation sort(Direction direction, String... fields) {
|
||||||
|
return new SortOperation(new Sort(direction, fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link SkipOperation} skipping the given number of elements.
|
||||||
|
*
|
||||||
|
* @param elementsToSkip must not be less than zero.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static SkipOperation skip(int elementsToSkip) {
|
||||||
|
return new SkipOperation(elementsToSkip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link LimitOperation} limiting the result to the given number of elements.
|
||||||
|
*
|
||||||
|
* @param maxElements must not be less than zero.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static LimitOperation limit(long maxElements) {
|
||||||
|
return new LimitOperation(maxElements);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link MatchOperation} using the given {@link Criteria}.
|
||||||
|
*
|
||||||
|
* @param criteria must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static MatchOperation match(Criteria criteria) {
|
||||||
|
return new MatchOperation(criteria);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Fields} instance for the given field names.
|
||||||
|
*
|
||||||
|
* @see Fields#fields(String...)
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Fields fields(String... fields) {
|
||||||
|
return Fields.fields(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Fields} instance from the given field name and target reference.
|
||||||
|
*
|
||||||
|
* @param name must not be {@literal null} or empty.
|
||||||
|
* @param target must not be {@literal null} or empty.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Fields bind(String name, String target) {
|
||||||
|
return Fields.from(field(name, target));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this {@link Aggregation} specification to a {@link DBObject}.
|
||||||
|
*
|
||||||
|
* @param inputCollectionName the name of the input collection
|
||||||
|
* @return the {@code DBObject} representing this aggregation
|
||||||
|
*/
|
||||||
|
public DBObject toDbObject(String inputCollectionName, AggregationOperationContext rootContext) {
|
||||||
|
|
||||||
|
AggregationOperationContext context = rootContext;
|
||||||
|
List<DBObject> operationDocuments = new ArrayList<DBObject>(operations.size());
|
||||||
|
|
||||||
|
for (AggregationOperation operation : operations) {
|
||||||
|
|
||||||
|
operationDocuments.add(operation.toDBObject(context));
|
||||||
|
|
||||||
|
if (operation instanceof FieldsExposingAggregationOperation) {
|
||||||
|
FieldsExposingAggregationOperation exposedFieldsOperation = (FieldsExposingAggregationOperation) operation;
|
||||||
|
context = new ExposedFieldsAggregationOperationContext(exposedFieldsOperation.getFields());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DBObject command = new BasicDBObject("aggregate", inputCollectionName);
|
||||||
|
command.put("pipeline", operationDocuments);
|
||||||
|
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return SerializationUtils
|
||||||
|
.serializeToJsonSafely(toDbObject("__collection__", new NoOpAggregationOperationContext()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple {@link AggregationOperationContext} that just returns {@link FieldReference}s as is.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
private static class NoOpAggregationOperationContext implements AggregationOperationContext {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(com.mongodb.DBObject)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public DBObject getMappedObject(DBObject dbObject) {
|
||||||
|
return dbObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getReference(org.springframework.data.mongodb.core.aggregation.ExposedFields.AvailableField)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public FieldReference getReference(Field field) {
|
||||||
|
return new FieldReference(new ExposedField(field, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getReference(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public FieldReference getReference(String name) {
|
||||||
|
return new FieldReference(new ExposedField(new AggregationField(name), true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents one single operation in an aggregation pipeline.
|
||||||
|
*
|
||||||
|
* @author Sebastian Herold
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public interface AggregationOperation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns the {@link AggregationOperation} into a {@link DBObject} by using the given
|
||||||
|
* {@link AggregationOperationContext}.
|
||||||
|
*
|
||||||
|
* @return the DBObject
|
||||||
|
*/
|
||||||
|
DBObject toDBObject(AggregationOperationContext context);
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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 com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The context for an {@link AggregationOperation}.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public interface AggregationOperationContext {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the mapped {@link DBObject}, potentially converting the source considering mapping metadata etc.
|
||||||
|
*
|
||||||
|
* @param dbObject will never be {@literal null}.
|
||||||
|
* @return must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
DBObject getMappedObject(DBObject dbObject);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link FieldReference} for the given field or {@literal null} if the context does not expose the given
|
||||||
|
* field.
|
||||||
|
*
|
||||||
|
* @param field must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
FieldReference getReference(Field field);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link FieldReference} for the field with the given name or {@literal null} if the context does not
|
||||||
|
* expose a field with the given name.
|
||||||
|
*
|
||||||
|
* @param name must not be {@literal null} or empty.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
FieldReference getReference(String name);
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects the results of executing an aggregation operation.
|
||||||
|
*
|
||||||
|
* @author Tobias Trelle
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @param <T> The class in which the results are mapped onto.
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public class AggregationResults<T> implements Iterable<T> {
|
||||||
|
|
||||||
|
private final List<T> mappedResults;
|
||||||
|
private final DBObject rawResults;
|
||||||
|
private final String serverUsed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link AggregationResults} instance from the given mapped and raw results.
|
||||||
|
*
|
||||||
|
* @param mappedResults must not be {@literal null}.
|
||||||
|
* @param rawResults must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public AggregationResults(List<T> mappedResults, DBObject rawResults) {
|
||||||
|
|
||||||
|
Assert.notNull(mappedResults);
|
||||||
|
Assert.notNull(rawResults);
|
||||||
|
|
||||||
|
this.mappedResults = Collections.unmodifiableList(mappedResults);
|
||||||
|
this.rawResults = rawResults;
|
||||||
|
this.serverUsed = parseServerUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the aggregation results.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<T> getMappedResults() {
|
||||||
|
return mappedResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the unique mapped result. Assumes no result or exactly one.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws IllegalArgumentException in case more than one result is available.
|
||||||
|
*/
|
||||||
|
public T getUniqueMappedResult() {
|
||||||
|
Assert.isTrue(mappedResults.size() < 2, "Expected unique result or null, but got more than one!");
|
||||||
|
return mappedResults.size() == 1 ? mappedResults.get(0) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Iterable#iterator()
|
||||||
|
*/
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return mappedResults.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the server that has been used to perform the aggregation.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getServerUsed() {
|
||||||
|
return serverUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parseServerUsed() {
|
||||||
|
|
||||||
|
Object object = rawResults.get("serverUsed");
|
||||||
|
return object instanceof String ? (String) object : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,404 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.CompositeIterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value object to capture the fields exposed by an {@link AggregationOperation}.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public class ExposedFields implements Iterable<ExposedField> {
|
||||||
|
|
||||||
|
private static final List<ExposedField> NO_FIELDS = Collections.emptyList();
|
||||||
|
private static final ExposedFields EMPTY = new ExposedFields(NO_FIELDS, NO_FIELDS);
|
||||||
|
|
||||||
|
private final List<ExposedField> originalFields;
|
||||||
|
private final List<ExposedField> syntheticFields;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ExposedFields} instance from the given {@link ExposedField}s.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ExposedFields from(ExposedField... fields) {
|
||||||
|
return from(Arrays.asList(fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ExposedFields} instance from the given {@link ExposedField}s.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static ExposedFields from(List<ExposedField> fields) {
|
||||||
|
|
||||||
|
ExposedFields result = EMPTY;
|
||||||
|
|
||||||
|
for (ExposedField field : fields) {
|
||||||
|
result = result.and(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates synthetic {@link ExposedFields} from the given {@link Fields}.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ExposedFields synthetic(Fields fields) {
|
||||||
|
return createFields(fields, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates non-synthetic {@link ExposedFields} from the given {@link Fields}.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ExposedFields nonSynthetic(Fields fields) {
|
||||||
|
return createFields(fields, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ExposedFields} instance for the given fields in either sythetic or non-synthetic way.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
* @param synthetic
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static ExposedFields createFields(Fields fields, boolean synthetic) {
|
||||||
|
|
||||||
|
Assert.notNull(fields, "Fields must not be null!");
|
||||||
|
List<ExposedField> result = new ArrayList<ExposedField>();
|
||||||
|
|
||||||
|
for (Field field : fields) {
|
||||||
|
result.add(new ExposedField(field, synthetic));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExposedFields.from(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ExposedFields} with the given orignals and synthetics.
|
||||||
|
*
|
||||||
|
* @param originals must not be {@literal null}.
|
||||||
|
* @param synthetic must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
private ExposedFields(List<ExposedField> originals, List<ExposedField> synthetic) {
|
||||||
|
|
||||||
|
this.originalFields = originals;
|
||||||
|
this.syntheticFields = synthetic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ExposedFields} adding the given {@link ExposedField}.
|
||||||
|
*
|
||||||
|
* @param field must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ExposedFields and(ExposedField field) {
|
||||||
|
|
||||||
|
Assert.notNull(field, "Exposed field must not be null!");
|
||||||
|
|
||||||
|
ArrayList<ExposedField> result = new ArrayList<ExposedField>();
|
||||||
|
result.addAll(field.synthetic ? syntheticFields : originalFields);
|
||||||
|
result.add(field);
|
||||||
|
|
||||||
|
return new ExposedFields(field.synthetic ? originalFields : result, field.synthetic ? result : syntheticFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the field with the given name or {@literal null} if no field with the given name is available.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ExposedField getField(String name) {
|
||||||
|
|
||||||
|
for (ExposedField field : this) {
|
||||||
|
if (field.canBeReferredToBy(name)) {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the {@link ExposedFields} exposes no non-synthetic fields at all.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean exposesNoNonSyntheticFields() {
|
||||||
|
return originalFields.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the {@link ExposedFields} exposes a single non-synthetic field only.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean exposesSingleNonSyntheticFieldOnly() {
|
||||||
|
return originalFields.size() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the {@link ExposedFields} exposes no fields at all.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean exposesNoFields() {
|
||||||
|
return exposedFieldsCount() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the {@link ExposedFields} exposes a single field only.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean exposesSingleFieldOnly() {
|
||||||
|
return exposedFieldsCount() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private int exposedFieldsCount() {
|
||||||
|
return originalFields.size() + syntheticFields.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Iterable#iterator()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Iterator<ExposedField> iterator() {
|
||||||
|
|
||||||
|
CompositeIterator<ExposedField> iterator = new CompositeIterator<ExposedField>();
|
||||||
|
iterator.add(syntheticFields.iterator());
|
||||||
|
iterator.add(originalFields.iterator());
|
||||||
|
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single exposed field.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
static class ExposedField implements Field {
|
||||||
|
|
||||||
|
private final boolean synthetic;
|
||||||
|
private final Field field;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ExposedField} with the given key.
|
||||||
|
*
|
||||||
|
* @param key must not be {@literal null} or empty.
|
||||||
|
* @param synthetic whether the exposed field is synthetic.
|
||||||
|
*/
|
||||||
|
public ExposedField(String key, boolean synthetic) {
|
||||||
|
this(Fields.field(key), synthetic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ExposedField} for the given {@link Field}.
|
||||||
|
*
|
||||||
|
* @param delegate must not be {@literal null}.
|
||||||
|
* @param synthetic whether the exposed field is synthetic.
|
||||||
|
*/
|
||||||
|
public ExposedField(Field delegate, boolean synthetic) {
|
||||||
|
|
||||||
|
this.field = delegate;
|
||||||
|
this.synthetic = synthetic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.Field#getKey()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return field.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.Field#getTarget()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getTarget() {
|
||||||
|
return field.getTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.Field#isAliased()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isAliased() {
|
||||||
|
return field.isAliased();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the field can be referred to using the given name.
|
||||||
|
*
|
||||||
|
* @param input
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean canBeReferredToBy(String input) {
|
||||||
|
return getTarget().equals(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("AggregationField: %s, synthetic: %s", field, synthetic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#equals(java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(obj instanceof ExposedField)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExposedField that = (ExposedField) obj;
|
||||||
|
|
||||||
|
return this.field.equals(that.field) && this.synthetic == that.synthetic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#hashCode()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
|
||||||
|
int result = 17;
|
||||||
|
|
||||||
|
result += 31 * field.hashCode();
|
||||||
|
result += 31 * (synthetic ? 0 : 1);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference to an {@link ExposedField}.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
static class FieldReference {
|
||||||
|
|
||||||
|
private final ExposedField field;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link FieldReference} for the given {@link ExposedField}.
|
||||||
|
*
|
||||||
|
* @param field must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public FieldReference(ExposedField field) {
|
||||||
|
|
||||||
|
Assert.notNull(field, "ExposedField must not be null!");
|
||||||
|
this.field = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw, unqualified reference, i.e. the field reference without a {@literal $} prefix.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getRaw() {
|
||||||
|
String target = field.getTarget();
|
||||||
|
return field.synthetic ? target : String.format("%s.%s", Fields.UNDERSCORE_ID, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the referenve value for the given field reference. Will return 1 for a synthetic, unaliased field or the
|
||||||
|
* raw rendering of the reference otherwise.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Object getReferenceValue() {
|
||||||
|
return field.synthetic && !field.isAliased() ? 1 : toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("$%s", getRaw());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#equals(java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(obj instanceof FieldReference)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldReference that = (FieldReference) obj;
|
||||||
|
|
||||||
|
return this.field.equals(that.field);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#hashCode()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return field.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.ExposedFields.FieldReference;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link AggregationOperationContext} that combines the available field references from a given
|
||||||
|
* {@code AggregationOperationContext} and an {@link FieldsExposingAggregationOperation}.
|
||||||
|
*
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
class ExposedFieldsAggregationOperationContext implements AggregationOperationContext {
|
||||||
|
|
||||||
|
private final ExposedFields exposedFields;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ExposedFieldsAggregationOperationContext} from the given {@link ExposedFields}.
|
||||||
|
*
|
||||||
|
* @param exposedFields must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public ExposedFieldsAggregationOperationContext(ExposedFields exposedFields) {
|
||||||
|
|
||||||
|
Assert.notNull(exposedFields, "ExposedFields must not be null!");
|
||||||
|
this.exposedFields = exposedFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(com.mongodb.DBObject)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public DBObject getMappedObject(DBObject dbObject) {
|
||||||
|
return dbObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getReference(org.springframework.data.mongodb.core.aggregation.ExposedFields.AvailableField)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public FieldReference getReference(Field field) {
|
||||||
|
return getReference(field.getTarget());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getReference(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public FieldReference getReference(String name) {
|
||||||
|
|
||||||
|
ExposedField field = exposedFields.getField(name);
|
||||||
|
|
||||||
|
if (field != null) {
|
||||||
|
return new FieldReference(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException(String.format("Invalid reference '%s'!", name));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction for a field.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public interface Field {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the field.
|
||||||
|
*
|
||||||
|
* @return must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the target of the field. In case no explicit target is available {@link #getName()} should be returned.
|
||||||
|
*
|
||||||
|
* @return must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
String getTarget();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the Field is aliased, which means it has a name set different from the target.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean isAliased();
|
||||||
|
}
|
||||||
@@ -0,0 +1,280 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value object to capture a list of {@link Field} instances.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public class Fields implements Iterable<Field> {
|
||||||
|
|
||||||
|
private static final String AMBIGUOUS_EXCEPTION = "Found two fields both using '%s' as name: %s and %s! Please "
|
||||||
|
+ "customize your field definitions to get to unique field names!";
|
||||||
|
|
||||||
|
public static String UNDERSCORE_ID = "_id";
|
||||||
|
public static String UNDERSCORE_ID_REF = "$_id";
|
||||||
|
|
||||||
|
private final List<Field> fields;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Fields} instance from the given {@link Fields}.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null} or empty.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Fields from(Field... fields) {
|
||||||
|
|
||||||
|
Assert.notNull(fields, "Fields must not be null!");
|
||||||
|
return new Fields(Arrays.asList(fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Fields} instance for {@link Field}s with the given names.
|
||||||
|
*
|
||||||
|
* @param names must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Fields fields(String... names) {
|
||||||
|
|
||||||
|
Assert.notNull(names, "Field names must not be null!");
|
||||||
|
|
||||||
|
List<Field> fields = new ArrayList<Field>();
|
||||||
|
|
||||||
|
for (String name : names) {
|
||||||
|
fields.add(field(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Fields(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Field} with the given name.
|
||||||
|
*
|
||||||
|
* @param name must not be {@literal null} or empty.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Field field(String name) {
|
||||||
|
return new AggregationField(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Field field(String name, String target) {
|
||||||
|
Assert.hasText(target, "Target must not be null or empty!");
|
||||||
|
return new AggregationField(name, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Fields} instance using the given {@link Field}s.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
private Fields(List<Field> fields) {
|
||||||
|
|
||||||
|
Assert.notNull(fields, "Fields must not be null!");
|
||||||
|
|
||||||
|
this.fields = verify(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final List<Field> verify(List<Field> fields) {
|
||||||
|
|
||||||
|
Map<String, Field> reference = new HashMap<String, Field>();
|
||||||
|
|
||||||
|
for (Field field : fields) {
|
||||||
|
|
||||||
|
String name = field.getName();
|
||||||
|
Field found = reference.get(name);
|
||||||
|
|
||||||
|
if (found != null) {
|
||||||
|
throw new IllegalArgumentException(String.format(AMBIGUOUS_EXCEPTION, name, found, field));
|
||||||
|
}
|
||||||
|
|
||||||
|
reference.put(name, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Fields(Fields existing, Field tail) {
|
||||||
|
|
||||||
|
this.fields = new ArrayList<Field>(existing.fields.size() + 1);
|
||||||
|
this.fields.addAll(existing.fields);
|
||||||
|
this.fields.add(tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Fields} instance with a new {@link Field} of the given name added.
|
||||||
|
*
|
||||||
|
* @param name must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Fields and(String name) {
|
||||||
|
return and(new AggregationField(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Fields and(String name, String target) {
|
||||||
|
return and(new AggregationField(name, target));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Fields and(Field field) {
|
||||||
|
return new Fields(this, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Fields and(Fields fields) {
|
||||||
|
|
||||||
|
Fields result = this;
|
||||||
|
|
||||||
|
for (Field field : fields) {
|
||||||
|
result = result.and(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field getField(String name) {
|
||||||
|
|
||||||
|
for (Field field : fields) {
|
||||||
|
if (field.getName().equals(name)) {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Iterable#iterator()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Iterator<Field> iterator() {
|
||||||
|
return fields.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value object to encapsulate a field in an aggregation operation.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
static class AggregationField implements Field {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final String target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an aggregation fieldwith the given name. As no target is set explicitly, the name will be used as target
|
||||||
|
* as well.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
public AggregationField(String key) {
|
||||||
|
this(key, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AggregationField(String name, String target) {
|
||||||
|
|
||||||
|
Assert.hasText(name, "AggregationField name must not be null or empty!");
|
||||||
|
|
||||||
|
if (target == null && name.contains(".")) {
|
||||||
|
this.name = name.substring(name.indexOf(".") + 1);
|
||||||
|
this.target = name;
|
||||||
|
} else {
|
||||||
|
this.name = name;
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.Field#getKey()
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.Field#getAlias()
|
||||||
|
*/
|
||||||
|
public String getTarget() {
|
||||||
|
return StringUtils.hasText(this.target) ? this.target : this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.Field#isAliased()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isAliased() {
|
||||||
|
return !getName().equals(getTarget());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("AggregationField - name: %s, target: %s", name, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#equals(java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(obj instanceof AggregationField)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AggregationField that = (AggregationField) obj;
|
||||||
|
|
||||||
|
return this.name.equals(that.name) && ObjectUtils.nullSafeEquals(this.target, that.target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#hashCode()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
|
||||||
|
int result = 17;
|
||||||
|
|
||||||
|
result += 31 * name.hashCode();
|
||||||
|
result += 31 * ObjectUtils.nullSafeHashCode(target);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link AggregationOperation} that exposes new {@link ExposedFields} that can be used for later aggregation pipeline
|
||||||
|
* {@code AggregationOperation}s.
|
||||||
|
*
|
||||||
|
* @author Thomas Darimont
|
||||||
|
*/
|
||||||
|
public interface FieldsExposingAggregationOperation extends AggregationOperation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fields exposed by the {@link AggregationOperation}.
|
||||||
|
*
|
||||||
|
* @return will never be {@literal null}.
|
||||||
|
*/
|
||||||
|
ExposedFields getFields();
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.query.NearQuery;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public class GeoNearOperation implements AggregationOperation {
|
||||||
|
|
||||||
|
private final NearQuery nearQuery;
|
||||||
|
|
||||||
|
public GeoNearOperation(NearQuery nearQuery) {
|
||||||
|
|
||||||
|
Assert.notNull(nearQuery);
|
||||||
|
this.nearQuery = nearQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (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("$geoNear", context.getMappedObject(nearQuery.toDBObject()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,375 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates the aggregation framework {@code $group}-operation.
|
||||||
|
*
|
||||||
|
* @see http://docs.mongodb.org/manual/reference/aggregation/group/#stage._S_group
|
||||||
|
* @author Sebastian Herold
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public class GroupOperation implements FieldsExposingAggregationOperation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the non-synthetic fields which are the fields of the group-id structure.
|
||||||
|
*/
|
||||||
|
private final ExposedFields idFields;
|
||||||
|
|
||||||
|
private final List<Operation> operations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link GroupOperation} including the given {@link Fields}.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public GroupOperation(Fields fields) {
|
||||||
|
|
||||||
|
this.idFields = ExposedFields.nonSynthetic(fields);
|
||||||
|
this.operations = new ArrayList<Operation>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link GroupOperation} from the given {@link GroupOperation}.
|
||||||
|
*
|
||||||
|
* @param groupOperation must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
protected GroupOperation(GroupOperation groupOperation) {
|
||||||
|
this(groupOperation, Collections.<Operation> emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link GroupOperation} from the given {@link GroupOperation} and the given {@link Operation}s.
|
||||||
|
*
|
||||||
|
* @param groupOperation
|
||||||
|
* @param nextOperations
|
||||||
|
*/
|
||||||
|
private GroupOperation(GroupOperation groupOperation, List<Operation> nextOperations) {
|
||||||
|
|
||||||
|
Assert.notNull(groupOperation, "GroupOperation must not be null!");
|
||||||
|
Assert.notNull(nextOperations, "NextOperations must not be null!");
|
||||||
|
|
||||||
|
this.idFields = groupOperation.idFields;
|
||||||
|
this.operations = new ArrayList<Operation>(nextOperations.size() + 1);
|
||||||
|
this.operations.addAll(groupOperation.operations);
|
||||||
|
this.operations.addAll(nextOperations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link GroupOperation} from the current one adding the given {@link Operation}.
|
||||||
|
*
|
||||||
|
* @param operation must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected GroupOperation and(Operation operation) {
|
||||||
|
return new GroupOperation(this, Arrays.asList(operation));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for {@link GroupOperation}s on a field.
|
||||||
|
*
|
||||||
|
* @author Thomas Darimont
|
||||||
|
*/
|
||||||
|
public class GroupOperationBuilder {
|
||||||
|
|
||||||
|
private final GroupOperation groupOperation;
|
||||||
|
private final Operation operation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link GroupOperationBuilder} from the given {@link GroupOperation} and {@link Operation}.
|
||||||
|
*
|
||||||
|
* @param groupOperation
|
||||||
|
* @param operation
|
||||||
|
*/
|
||||||
|
private GroupOperationBuilder(GroupOperation groupOperation, Operation operation) {
|
||||||
|
|
||||||
|
Assert.notNull(groupOperation, "GroupOperation must not be null!");
|
||||||
|
Assert.notNull(operation, "Operation must not be null!");
|
||||||
|
|
||||||
|
this.groupOperation = groupOperation;
|
||||||
|
this.operation = operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to specify an alias for the new-operation operation.
|
||||||
|
*
|
||||||
|
* @param alias
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GroupOperation as(String alias) {
|
||||||
|
return this.groupOperation.and(operation.withAlias(alias));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@link GroupOperationBuilder} for a {@code $sum}-expression.
|
||||||
|
* <p>
|
||||||
|
* Count expressions are emulated via {@code $sum: 1}.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GroupOperationBuilder count() {
|
||||||
|
return newBuilder(GroupOps.SUM, null, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@link GroupOperationBuilder} for a {@code $sum}-expression for the given field-reference.
|
||||||
|
*
|
||||||
|
* @param reference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GroupOperationBuilder sum(String reference) {
|
||||||
|
return sum(reference, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GroupOperationBuilder sum(String reference, Object value) {
|
||||||
|
return newBuilder(GroupOps.SUM, reference, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@link GroupOperationBuilder} for an {@code $add_to_set}-expression for the given field-reference.
|
||||||
|
*
|
||||||
|
* @param reference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GroupOperationBuilder addToSet(String reference) {
|
||||||
|
return addToSet(reference, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@link GroupOperationBuilder} for an {@code $add_to_set}-expression for the given value.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GroupOperationBuilder addToSet(Object value) {
|
||||||
|
return addToSet(null, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GroupOperationBuilder addToSet(String reference, Object value) {
|
||||||
|
return newBuilder(GroupOps.ADD_TO_SET, reference, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@link GroupOperationBuilder} for an {@code $last}-expression for the given field-reference.
|
||||||
|
*
|
||||||
|
* @param reference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GroupOperationBuilder last(String reference) {
|
||||||
|
return newBuilder(GroupOps.LAST, reference, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@link GroupOperationBuilder} for a {@code $first}-expression for the given field-reference.
|
||||||
|
*
|
||||||
|
* @param reference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GroupOperationBuilder first(String reference) {
|
||||||
|
return newBuilder(GroupOps.FIRST, reference, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@link GroupOperationBuilder} for an {@code $avg}-expression for the given field-reference.
|
||||||
|
*
|
||||||
|
* @param reference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GroupOperationBuilder avg(String reference) {
|
||||||
|
return newBuilder(GroupOps.AVG, reference, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@link GroupOperationBuilder} for an {@code $push}-expression for the given field-reference.
|
||||||
|
*
|
||||||
|
* @param reference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GroupOperationBuilder push(String reference) {
|
||||||
|
return push(reference, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@link GroupOperationBuilder} for an {@code $push}-expression for the given value.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GroupOperationBuilder push(Object value) {
|
||||||
|
return push(null, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GroupOperationBuilder push(String reference, Object value) {
|
||||||
|
return newBuilder(GroupOps.PUSH, reference, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@link GroupOperationBuilder} for an {@code $min}-expression that for the given field-reference.
|
||||||
|
*
|
||||||
|
* @param reference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GroupOperationBuilder min(String reference) {
|
||||||
|
return newBuilder(GroupOps.MIN, reference, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@link GroupOperationBuilder} for an {@code $max}-expression that for the given field-reference.
|
||||||
|
*
|
||||||
|
* @param reference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public GroupOperationBuilder max(String reference) {
|
||||||
|
return newBuilder(GroupOps.MAX, reference, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GroupOperationBuilder newBuilder(Keyword keyword, String reference, Object value) {
|
||||||
|
return new GroupOperationBuilder(this, new Operation(keyword, null, reference, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getFields()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ExposedFields getFields() {
|
||||||
|
|
||||||
|
ExposedFields fields = this.idFields.and(new ExposedField(Fields.UNDERSCORE_ID, true));
|
||||||
|
|
||||||
|
for (Operation operation : operations) {
|
||||||
|
fields = fields.and(operation.asField());
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public com.mongodb.DBObject toDBObject(AggregationOperationContext context) {
|
||||||
|
|
||||||
|
BasicDBObject operationObject = new BasicDBObject();
|
||||||
|
|
||||||
|
if (idFields.exposesNoNonSyntheticFields()) {
|
||||||
|
|
||||||
|
operationObject.put(Fields.UNDERSCORE_ID, null);
|
||||||
|
|
||||||
|
} else if (idFields.exposesSingleNonSyntheticFieldOnly()) {
|
||||||
|
|
||||||
|
FieldReference reference = context.getReference(idFields.iterator().next());
|
||||||
|
operationObject.put(Fields.UNDERSCORE_ID, reference.toString());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
BasicDBObject inner = new BasicDBObject();
|
||||||
|
|
||||||
|
for (ExposedField field : idFields) {
|
||||||
|
FieldReference reference = context.getReference(field);
|
||||||
|
inner.put(field.getName(), reference.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
operationObject.put(Fields.UNDERSCORE_ID, inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Operation operation : operations) {
|
||||||
|
operationObject.putAll(operation.toDBObject(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BasicDBObject("$group", operationObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Keyword {
|
||||||
|
|
||||||
|
String toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static enum GroupOps implements Keyword {
|
||||||
|
|
||||||
|
SUM, LAST, FIRST, PUSH, AVG, MIN, MAX, ADD_TO_SET, COUNT;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
|
||||||
|
String[] parts = name().split("_");
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
for (String part : parts) {
|
||||||
|
String lowerCase = part.toLowerCase(Locale.US);
|
||||||
|
builder.append(builder.length() == 0 ? lowerCase : StringUtils.capitalize(lowerCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
return "$" + builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Operation implements AggregationOperation {
|
||||||
|
|
||||||
|
private final Keyword op;
|
||||||
|
private final String key;
|
||||||
|
private final String reference;
|
||||||
|
private final Object value;
|
||||||
|
|
||||||
|
public Operation(Keyword op, String key, String reference, Object value) {
|
||||||
|
|
||||||
|
this.op = op;
|
||||||
|
this.key = key;
|
||||||
|
this.reference = reference;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operation withAlias(String key) {
|
||||||
|
return new Operation(op, key, reference, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExposedField asField() {
|
||||||
|
return new ExposedField(key, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBObject toDBObject(AggregationOperationContext context) {
|
||||||
|
return new BasicDBObject(key, new BasicDBObject(op.toString(), getValue(context)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValue(AggregationOperationContext context) {
|
||||||
|
return reference == null ? value : context.getReference(reference).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Operation [op=" + op + ", key=" + key + ", reference=" + reference + ", value=" + value + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.util.Assert;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates the {@code $limit}-operation
|
||||||
|
*
|
||||||
|
* @see http://docs.mongodb.org/manual/reference/aggregation/limit/
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
class LimitOperation implements AggregationOperation {
|
||||||
|
|
||||||
|
private final long maxElements;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param maxElements Number of documents to consider.
|
||||||
|
*/
|
||||||
|
public LimitOperation(long maxElements) {
|
||||||
|
|
||||||
|
Assert.isTrue(maxElements >= 0, "Maximum number of elements must be greater or equal to zero!");
|
||||||
|
this.maxElements = maxElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (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("$limit", maxElements);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.query.Criteria;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates the {@code $match}-operation
|
||||||
|
*
|
||||||
|
* @see http://docs.mongodb.org/manual/reference/aggregation/match/
|
||||||
|
* @author Sebastian Herold
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public class MatchOperation implements AggregationOperation {
|
||||||
|
|
||||||
|
private final Criteria criteria;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link MatchOperation} for the given {@link Criteria}.
|
||||||
|
*
|
||||||
|
* @param criteria must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public MatchOperation(Criteria criteria) {
|
||||||
|
|
||||||
|
Assert.notNull(criteria, "Criteria must not be null!");
|
||||||
|
this.criteria = criteria;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (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("$match", context.getMappedObject(criteria.getCriteriaObject()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,652 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.ProjectionOperation.ProjectionOperationBuilder.FieldProjection;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBList;
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates the aggregation framework {@code $project}-operation. Projection of field to be used in an
|
||||||
|
* {@link Aggregation}. A projection is similar to a {@link Field} inclusion/exclusion but more powerful. It can
|
||||||
|
* generate new fields, change values of given field etc.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @see http://docs.mongodb.org/manual/reference/aggregation/project/
|
||||||
|
* @author Tobias Trelle
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public class ProjectionOperation implements FieldsExposingAggregationOperation {
|
||||||
|
|
||||||
|
private static final List<Projection> NONE = Collections.emptyList();
|
||||||
|
private static final String EXCLUSION_ERROR = "Exclusion of field %s not allowed. Projections by the mongodb "
|
||||||
|
+ "aggregation framework only support the exclusion of the %s field!";
|
||||||
|
|
||||||
|
private final List<Projection> projections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new empty {@link ProjectionOperation}.
|
||||||
|
*/
|
||||||
|
public ProjectionOperation() {
|
||||||
|
this(NONE, NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ProjectionOperation} including the given {@link Fields}.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public ProjectionOperation(Fields fields) {
|
||||||
|
this(NONE, ProjectionOperationBuilder.FieldProjection.from(fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy constructor to allow building up {@link ProjectionOperation} instances from already existing
|
||||||
|
* {@link Projection}s.
|
||||||
|
*
|
||||||
|
* @param current must not be {@literal null}.
|
||||||
|
* @param projections must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
private ProjectionOperation(List<? extends Projection> current, List<? extends Projection> projections) {
|
||||||
|
|
||||||
|
Assert.notNull(current, "Current projections must not be null!");
|
||||||
|
Assert.notNull(projections, "Projections must not be null!");
|
||||||
|
|
||||||
|
this.projections = new ArrayList<ProjectionOperation.Projection>(current.size() + projections.size());
|
||||||
|
this.projections.addAll(current);
|
||||||
|
this.projections.addAll(projections);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ProjectionOperation} with the current {@link Projection}s and the given one.
|
||||||
|
*
|
||||||
|
* @param projection must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private ProjectionOperation and(Projection projection) {
|
||||||
|
return new ProjectionOperation(this.projections, Arrays.asList(projection));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ProjectionOperation} with the current {@link Projection}s replacing the last current one with
|
||||||
|
* the given one.
|
||||||
|
*
|
||||||
|
* @param projection must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private ProjectionOperation andReplaceLastOneWith(Projection projection) {
|
||||||
|
|
||||||
|
List<Projection> projections = this.projections.isEmpty() ? Collections.<Projection> emptyList() : this.projections
|
||||||
|
.subList(0, this.projections.size() - 1);
|
||||||
|
return new ProjectionOperation(projections, Arrays.asList(projection));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ProjectionOperationBuilder} to define a projection for the field with the given name.
|
||||||
|
*
|
||||||
|
* @param name must not be {@literal null} or empty.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder and(String name) {
|
||||||
|
return new ProjectionOperationBuilder(name, this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excludes the given fields from the projection.
|
||||||
|
*
|
||||||
|
* @param fieldNames must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperation andExclude(String... fieldNames) {
|
||||||
|
|
||||||
|
for (String fieldName : fieldNames) {
|
||||||
|
Assert.isTrue(Fields.UNDERSCORE_ID.equals(fieldName),
|
||||||
|
String.format(EXCLUSION_ERROR, fieldName, Fields.UNDERSCORE_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<FieldProjection> excludeProjections = FieldProjection.from(Fields.fields(fieldNames), false);
|
||||||
|
return new ProjectionOperation(this.projections, excludeProjections);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Includes the given fields into the projection.
|
||||||
|
*
|
||||||
|
* @param fieldNames must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperation andInclude(String... fieldNames) {
|
||||||
|
|
||||||
|
List<FieldProjection> projections = FieldProjection.from(Fields.fields(fieldNames), true);
|
||||||
|
return new ProjectionOperation(this.projections, projections);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Includes the given fields into the projection.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperation andInclude(Fields fields) {
|
||||||
|
return new ProjectionOperation(this.projections, FieldProjection.from(fields, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation#getFields()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ExposedFields getFields() {
|
||||||
|
|
||||||
|
ExposedFields fields = null;
|
||||||
|
|
||||||
|
for (Projection projection : projections) {
|
||||||
|
ExposedField field = projection.getExposedField();
|
||||||
|
fields = fields == null ? ExposedFields.from(field) : fields.and(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (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 fieldObject = new BasicDBObject();
|
||||||
|
|
||||||
|
for (Projection projection : projections) {
|
||||||
|
fieldObject.putAll(projection.toDBObject(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BasicDBObject("$project", fieldObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for {@link ProjectionOperation}s on a field.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @author Thomas Darimont
|
||||||
|
*/
|
||||||
|
public static class ProjectionOperationBuilder implements AggregationOperation {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final ProjectionOperation operation;
|
||||||
|
private final OperationProjection previousProjection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ProjectionOperationBuilder} for the field with the given name on top of the given
|
||||||
|
* {@link ProjectionOperation}.
|
||||||
|
*
|
||||||
|
* @param name must not be {@literal null} or empty.
|
||||||
|
* @param operation must not be {@literal null}.
|
||||||
|
* @param previousProjection the previous operation projection, may be {@literal null}.
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder(String name, ProjectionOperation operation, OperationProjection previousProjection) {
|
||||||
|
|
||||||
|
Assert.hasText(name, "Field name must not be null or empty!");
|
||||||
|
Assert.notNull(operation, "ProjectionOperation must not be null!");
|
||||||
|
|
||||||
|
this.name = name;
|
||||||
|
this.operation = operation;
|
||||||
|
this.previousProjection = previousProjection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Projects the result of the previous operation onto the current field. Will automatically add an exclusion for
|
||||||
|
* {@code _id} as what would be held in it by default will now go into the field just projected into.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperation previousOperation() {
|
||||||
|
|
||||||
|
return this.operation.andExclude(Fields.UNDERSCORE_ID) //
|
||||||
|
.and(new PreviousOperationProjection(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a nested field binding for the current field.
|
||||||
|
*
|
||||||
|
* @param fields must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperation nested(Fields fields) {
|
||||||
|
return this.operation.and(new NestedFieldProjection(name, fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to specify an alias for the previous projection operation.
|
||||||
|
*
|
||||||
|
* @param string
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperation as(String alias) {
|
||||||
|
|
||||||
|
if (previousProjection != null) {
|
||||||
|
return this.operation.andReplaceLastOneWith(previousProjection.withAlias(alias));
|
||||||
|
} else {
|
||||||
|
return this.operation.and(new FieldProjection(Fields.field(alias, name), null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@code $add} expression that adds the given number to the previously mentioned field.
|
||||||
|
*
|
||||||
|
* @param number
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder plus(Number number) {
|
||||||
|
|
||||||
|
Assert.notNull(number, "Number must not be null!");
|
||||||
|
return project("add", number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@code $add} expression that adds the value of the given field to the previously mentioned field.
|
||||||
|
*
|
||||||
|
* @param fieldReference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder plus(String fieldReference) {
|
||||||
|
|
||||||
|
Assert.notNull(fieldReference, "Field reference must not be null!");
|
||||||
|
return project("add", Fields.field(fieldReference));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@code $subtract} expression that subtracts the given number to the previously mentioned field.
|
||||||
|
*
|
||||||
|
* @param number
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder minus(Number number) {
|
||||||
|
|
||||||
|
Assert.notNull(number, "Number must not be null!");
|
||||||
|
return project("subtract", number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@code $subtract} expression that subtracts the value of the given field to the previously mentioned
|
||||||
|
* field.
|
||||||
|
*
|
||||||
|
* @param fieldReference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder minus(String fieldReference) {
|
||||||
|
|
||||||
|
Assert.notNull(fieldReference, "Field reference must not be null!");
|
||||||
|
return project("subtract", Fields.field(fieldReference));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@code $multiply} expression that multiplies the given number with the previously mentioned field.
|
||||||
|
*
|
||||||
|
* @param number
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder multiply(Number number) {
|
||||||
|
|
||||||
|
Assert.notNull(number, "Number must not be null!");
|
||||||
|
return project("multiply", number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@code $multiply} expression that multiplies the value of the given field with the previously
|
||||||
|
* mentioned field.
|
||||||
|
*
|
||||||
|
* @param fieldReference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder multiply(String fieldReference) {
|
||||||
|
|
||||||
|
Assert.notNull(fieldReference, "Field reference must not be null!");
|
||||||
|
return project("multiply", Fields.field(fieldReference));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@code $divide} expression that divides the previously mentioned field by the given number.
|
||||||
|
*
|
||||||
|
* @param number
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder divide(Number number) {
|
||||||
|
|
||||||
|
Assert.notNull(number, "Number must not be null!");
|
||||||
|
Assert.isTrue(Math.abs(number.intValue()) != 0, "Number must not be zero!");
|
||||||
|
return project("divide", number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@code $divide} expression that divides the value of the given field by the previously mentioned
|
||||||
|
* field.
|
||||||
|
*
|
||||||
|
* @param fieldReference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder divide(String fieldReference) {
|
||||||
|
|
||||||
|
Assert.notNull(fieldReference, "Field reference must not be null!");
|
||||||
|
return project("divide", Fields.field(fieldReference));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@code $mod} expression that divides the previously mentioned field by the given number and returns
|
||||||
|
* the remainder.
|
||||||
|
*
|
||||||
|
* @param number
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder mod(Number number) {
|
||||||
|
|
||||||
|
Assert.notNull(number, "Number must not be null!");
|
||||||
|
Assert.isTrue(Math.abs(number.intValue()) != 0, "Number must not be zero!");
|
||||||
|
return project("mod", number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an {@code $mod} expression that divides the value of the given field by the previously mentioned field
|
||||||
|
* and returns the remainder.
|
||||||
|
*
|
||||||
|
* @param fieldReference
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder mod(String fieldReference) {
|
||||||
|
|
||||||
|
Assert.notNull(fieldReference, "Field reference must not be null!");
|
||||||
|
return project("mod", Fields.field(fieldReference));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (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 this.operation.toDBObject(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a generic projection for the current field.
|
||||||
|
*
|
||||||
|
* @param operation the operation key, e.g. {@code $add}.
|
||||||
|
* @param values the values to be set for the projection operation.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ProjectionOperationBuilder project(String operation, Object... values) {
|
||||||
|
OperationProjection projectionOperation = new OperationProjection(Fields.field(name), operation, values);
|
||||||
|
return new ProjectionOperationBuilder(name, this.operation.and(projectionOperation), projectionOperation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link Projection} to pull in the result of the previous operation.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
static class PreviousOperationProjection extends Projection {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link PreviousOperationProjection} for the field with the given name.
|
||||||
|
*
|
||||||
|
* @param name must not be {@literal null} or empty.
|
||||||
|
*/
|
||||||
|
public PreviousOperationProjection(String name) {
|
||||||
|
super(Fields.field(name));
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public DBObject toDBObject(AggregationOperationContext context) {
|
||||||
|
return new BasicDBObject(name, Fields.UNDERSCORE_ID_REF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link FieldProjection} to map a result of a previous {@link AggregationOperation} to a new field.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @author Thomas Darimont
|
||||||
|
*/
|
||||||
|
static class FieldProjection extends Projection {
|
||||||
|
|
||||||
|
private final Field field;
|
||||||
|
private final Object value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link FieldProjection} for the field of the given name, assigning the given value.
|
||||||
|
*
|
||||||
|
* @param name must not be {@literal null} or empty.
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public FieldProjection(String name, Object value) {
|
||||||
|
this(Fields.field(name), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FieldProjection(Field field, Object value) {
|
||||||
|
|
||||||
|
super(field);
|
||||||
|
|
||||||
|
this.field = field;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to easily create {@link FieldProjection}s for the given {@link Fields}. Fields are projected as
|
||||||
|
* references with their given name. A field {@code foo} will be projected as: {@code foo : 1 } .
|
||||||
|
*
|
||||||
|
* @param fields the {@link Fields} to in- or exclude, must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<? extends Projection> from(Fields fields) {
|
||||||
|
return from(fields, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to easily create {@link FieldProjection}s for the given {@link Fields}.
|
||||||
|
*
|
||||||
|
* @param fields the {@link Fields} to in- or exclude, must not be {@literal null}.
|
||||||
|
* @param value to use for the given field.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<FieldProjection> from(Fields fields, Object value) {
|
||||||
|
|
||||||
|
Assert.notNull(fields, "Fields must not be null!");
|
||||||
|
List<FieldProjection> projections = new ArrayList<FieldProjection>();
|
||||||
|
|
||||||
|
for (Field field : fields) {
|
||||||
|
projections.add(new FieldProjection(field, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return projections;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public DBObject toDBObject(AggregationOperationContext context) {
|
||||||
|
return new BasicDBObject(field.getName(), renderFieldValue(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object renderFieldValue(AggregationOperationContext context) {
|
||||||
|
|
||||||
|
// implicit reference or explicit include?
|
||||||
|
if (value == null || Boolean.TRUE.equals(value)) {
|
||||||
|
|
||||||
|
// check whether referenced field exists in the context
|
||||||
|
return context.getReference(field).getReferenceValue();
|
||||||
|
|
||||||
|
} else if (Boolean.FALSE.equals(value)) {
|
||||||
|
|
||||||
|
// render field as excluded
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class OperationProjection extends Projection {
|
||||||
|
|
||||||
|
private final Field field;
|
||||||
|
private final String operation;
|
||||||
|
private final List<Object> values;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link OperationProjection} for the given field.
|
||||||
|
*
|
||||||
|
* @param name the name of the field to add the operation projection for, must not be {@literal null} or empty.
|
||||||
|
* @param operation the actual operation key, must not be {@literal null} or empty.
|
||||||
|
* @param values the values to pass into the operation, must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public OperationProjection(Field field, String operation, Object[] values) {
|
||||||
|
|
||||||
|
super(field);
|
||||||
|
|
||||||
|
Assert.hasText(operation, "Operation must not be null or empty!");
|
||||||
|
Assert.notNull(values, "Values must not be null!");
|
||||||
|
|
||||||
|
this.field = field;
|
||||||
|
this.operation = operation;
|
||||||
|
this.values = Arrays.asList(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public DBObject toDBObject(AggregationOperationContext context) {
|
||||||
|
|
||||||
|
BasicDBList values = new BasicDBList();
|
||||||
|
values.addAll(buildReferences(context));
|
||||||
|
|
||||||
|
DBObject inner = new BasicDBObject("$" + operation, values);
|
||||||
|
|
||||||
|
return new BasicDBObject(this.field.getName(), inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Object> buildReferences(AggregationOperationContext context) {
|
||||||
|
|
||||||
|
List<Object> result = new ArrayList<Object>(values.size());
|
||||||
|
result.add(context.getReference(field.getTarget()).toString());
|
||||||
|
|
||||||
|
for (Object element : values) {
|
||||||
|
result.add(element instanceof Field ? context.getReference((Field) element).toString() : element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of this {@link OperationProjection} with the given alias.
|
||||||
|
*
|
||||||
|
* @param alias the alias to set
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public OperationProjection withAlias(String alias) {
|
||||||
|
return new OperationProjection(Fields.field(alias, this.field.getName()), operation, values.toArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class NestedFieldProjection extends Projection {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final Fields fields;
|
||||||
|
|
||||||
|
public NestedFieldProjection(String name, Fields fields) {
|
||||||
|
|
||||||
|
super(Fields.field(name));
|
||||||
|
this.name = name;
|
||||||
|
this.fields = fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public DBObject toDBObject(AggregationOperationContext context) {
|
||||||
|
|
||||||
|
DBObject nestedObject = new BasicDBObject();
|
||||||
|
|
||||||
|
for (Field field : fields) {
|
||||||
|
nestedObject.put(field.getName(), context.getReference(field.getTarget()).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BasicDBObject(name, nestedObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for {@link Projection} implementations.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
private static abstract class Projection {
|
||||||
|
|
||||||
|
private final ExposedField field;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new {@link Projection} for the given {@link Field}.
|
||||||
|
*
|
||||||
|
* @param field must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public Projection(Field field) {
|
||||||
|
|
||||||
|
Assert.notNull(field, "Field must not be null!");
|
||||||
|
this.field = new ExposedField(field, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the field exposed by the {@link Projection}.
|
||||||
|
*
|
||||||
|
* @return will never be {@literal null}.
|
||||||
|
*/
|
||||||
|
public ExposedField getExposedField() {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the current {@link Projection} into a {@link DBObject} based on the given
|
||||||
|
* {@link AggregationOperationContext}.
|
||||||
|
*
|
||||||
|
* @param context will never be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public abstract DBObject toDBObject(AggregationOperationContext context);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.util.Assert;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates the aggregation framework {@code $skip}-operation.
|
||||||
|
*
|
||||||
|
* @see http://docs.mongodb.org/manual/reference/aggregation/skip/
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public class SkipOperation implements AggregationOperation {
|
||||||
|
|
||||||
|
private final long skipCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link SkipOperation} skipping the given number of elements.
|
||||||
|
*
|
||||||
|
* @param skipCount number of documents to skip.
|
||||||
|
*/
|
||||||
|
public SkipOperation(long skipCount) {
|
||||||
|
|
||||||
|
Assert.isTrue(skipCount >= 0, "Skip count must not be negative!");
|
||||||
|
this.skipCount = skipCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (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("$skip", skipCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.domain.Sort;
|
||||||
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
|
import org.springframework.data.domain.Sort.Order;
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates the aggregation framework {@code $sort}-operation.
|
||||||
|
*
|
||||||
|
* @see http://docs.mongodb.org/manual/reference/aggregation/sort/#pipe._S_sort
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public class SortOperation implements AggregationOperation {
|
||||||
|
|
||||||
|
private final Sort sort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link SortOperation} for the given {@link Sort} instance.
|
||||||
|
*
|
||||||
|
* @param sort must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public SortOperation(Sort sort) {
|
||||||
|
|
||||||
|
Assert.notNull(sort, "Sort must not be null!");
|
||||||
|
this.sort = sort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SortOperation and(Direction direction, String... fields) {
|
||||||
|
return and(new Sort(direction, fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SortOperation and(Sort sort) {
|
||||||
|
return new SortOperation(this.sort.and(sort));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (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 object = new BasicDBObject();
|
||||||
|
|
||||||
|
for (Order order : sort) {
|
||||||
|
|
||||||
|
// Check reference
|
||||||
|
FieldReference reference = context.getReference(order.getProperty());
|
||||||
|
object.put(reference.getRaw(), order.isAscending() ? 1 : -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BasicDBObject("$sort", object);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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 static org.springframework.data.mongodb.core.aggregation.Fields.*;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.PropertyPath;
|
||||||
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
|
import org.springframework.data.mapping.context.PersistentPropertyPath;
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
|
||||||
|
import org.springframework.data.mongodb.core.convert.QueryMapper;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link AggregationOperationContext} aware of a particular type and a {@link MappingContext} to potentially translate
|
||||||
|
* property references into document field names.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public class TypeBasedAggregationOperationContext implements AggregationOperationContext {
|
||||||
|
|
||||||
|
private final Class<?> type;
|
||||||
|
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||||
|
private final QueryMapper mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link TypeBasedAggregationOperationContext} for the given type, {@link MappingContext} and
|
||||||
|
* {@link QueryMapper}.
|
||||||
|
*
|
||||||
|
* @param type must not be {@literal null}.
|
||||||
|
* @param mappingContext must not be {@literal null}.
|
||||||
|
* @param mapper must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public TypeBasedAggregationOperationContext(Class<?> type,
|
||||||
|
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext, QueryMapper mapper) {
|
||||||
|
|
||||||
|
Assert.notNull(type, "Type must not be null!");
|
||||||
|
Assert.notNull(mappingContext, "MappingContext must not be null!");
|
||||||
|
Assert.notNull(mapper, "QueryMapper must not be null!");
|
||||||
|
|
||||||
|
this.type = type;
|
||||||
|
this.mappingContext = mappingContext;
|
||||||
|
this.mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(com.mongodb.DBObject)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public DBObject getMappedObject(DBObject dbObject) {
|
||||||
|
return mapper.getMappedObject(dbObject, mappingContext.getPersistentEntity(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getReference(org.springframework.data.mongodb.core.aggregation.Field)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public FieldReference getReference(Field field) {
|
||||||
|
|
||||||
|
PropertyPath.from(field.getTarget(), type);
|
||||||
|
return getReferenceFor(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getReference(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public FieldReference getReference(String name) {
|
||||||
|
return getReferenceFor(field(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
private FieldReference getReferenceFor(Field field) {
|
||||||
|
|
||||||
|
PropertyPath path = PropertyPath.from(field.getTarget(), type);
|
||||||
|
|
||||||
|
PersistentPropertyPath<MongoPersistentProperty> propertyPath = mappingContext.getPersistentPropertyPath(path);
|
||||||
|
Field mappedField = field(propertyPath.getLeafProperty().getName(),
|
||||||
|
propertyPath.toDotPath(MongoPersistentProperty.PropertyToFieldNameConverter.INSTANCE));
|
||||||
|
|
||||||
|
return new FieldReference(new ExposedField(mappedField, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code TypedAggregation} is a special {@link Aggregation} that holds information of the input aggregation type.
|
||||||
|
*
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public class TypedAggregation<I> extends Aggregation {
|
||||||
|
|
||||||
|
private final Class<I> inputType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link TypedAggregation} from the given {@link AggregationOperation}s.
|
||||||
|
*
|
||||||
|
* @param operations must not be {@literal null} or empty.
|
||||||
|
*/
|
||||||
|
public TypedAggregation(Class<I> inputType, AggregationOperation... operations) {
|
||||||
|
|
||||||
|
super(operations);
|
||||||
|
|
||||||
|
Assert.notNull(inputType, "Input type must not be null!");
|
||||||
|
this.inputType = inputType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the input type for the {@link Aggregation}.
|
||||||
|
*
|
||||||
|
* @return the inputType will never be {@literal null}.
|
||||||
|
*/
|
||||||
|
public Class<I> getInputType() {
|
||||||
|
return inputType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.util.Assert;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates the aggregation framework {@code $unwind}-operation.
|
||||||
|
*
|
||||||
|
* @see http://docs.mongodb.org/manual/reference/aggregation/unwind/#pipe._S_unwind
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
public class UnwindOperation implements AggregationOperation {
|
||||||
|
|
||||||
|
private final ExposedField field;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link UnwindOperation} for the given {@link Field}.
|
||||||
|
*
|
||||||
|
* @param field must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public UnwindOperation(Field field) {
|
||||||
|
|
||||||
|
Assert.notNull(field);
|
||||||
|
this.field = new ExposedField(field, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (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("$unwind", context.getReference(field).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* Support for the MongoDB aggregation framework.
|
||||||
|
* @since 1.3
|
||||||
|
*/
|
||||||
|
package org.springframework.data.mongodb.core.aggregation;
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -13,7 +13,6 @@
|
|||||||
* 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.convert;
|
package org.springframework.data.mongodb.core.convert;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
@@ -33,8 +32,8 @@ import org.springframework.data.mongodb.core.convert.MongoConverters.StringToObj
|
|||||||
* Base class for {@link MongoConverter} implementations. Sets up a {@link GenericConversionService} and populates basic
|
* Base class for {@link MongoConverter} implementations. Sets up a {@link GenericConversionService} and populates basic
|
||||||
* converters. Allows registering {@link CustomConversions}.
|
* converters. Allows registering {@link CustomConversions}.
|
||||||
*
|
*
|
||||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
* @author Jon Brisbin
|
||||||
* @author Oliver Gierke ogierke@vmware.com
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractMongoConverter implements MongoConverter, InitializingBean {
|
public abstract class AbstractMongoConverter implements MongoConverter, InitializingBean {
|
||||||
|
|
||||||
@@ -94,6 +93,14 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
|
|||||||
conversions.registerConvertersIn(conversionService);
|
conversions.registerConvertersIn(conversionService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.MongoWriter#convertToMongoType(java.lang.Object)
|
||||||
|
*/
|
||||||
|
public Object convertToMongoType(Object obj) {
|
||||||
|
return convertToMongoType(obj, null);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.mongodb.core.core.convert.MongoConverter#getConversionService()
|
* @see org.springframework.data.mongodb.core.core.convert.MongoConverter#getConversionService()
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -18,9 +18,12 @@ package org.springframework.data.mongodb.core.convert;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -31,13 +34,17 @@ import org.springframework.core.convert.converter.ConverterFactory;
|
|||||||
import org.springframework.core.convert.converter.GenericConverter;
|
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.ReadingConverter;
|
import org.springframework.data.convert.ReadingConverter;
|
||||||
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.BigDecimalToStringConverter;
|
||||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter;
|
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.StringToBigDecimalConverter;
|
||||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
|
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.URLToStringConverter;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@@ -49,6 +56,7 @@ import org.springframework.util.Assert;
|
|||||||
* .
|
* .
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Thomas Darimont
|
||||||
*/
|
*/
|
||||||
public class CustomConversions {
|
public class CustomConversions {
|
||||||
|
|
||||||
@@ -60,6 +68,7 @@ public class CustomConversions {
|
|||||||
private final Set<ConvertiblePair> writingPairs;
|
private final Set<ConvertiblePair> writingPairs;
|
||||||
private final Set<Class<?>> customSimpleTypes;
|
private final Set<Class<?>> customSimpleTypes;
|
||||||
private final SimpleTypeHolder simpleTypeHolder;
|
private final SimpleTypeHolder simpleTypeHolder;
|
||||||
|
private final ConcurrentMap<ConvertiblePair, CacheValue> customReadTargetTypes;
|
||||||
|
|
||||||
private final List<Object> converters;
|
private final List<Object> converters;
|
||||||
|
|
||||||
@@ -79,17 +88,22 @@ public class CustomConversions {
|
|||||||
|
|
||||||
Assert.notNull(converters);
|
Assert.notNull(converters);
|
||||||
|
|
||||||
this.readingPairs = new HashSet<ConvertiblePair>();
|
this.readingPairs = new LinkedHashSet<ConvertiblePair>();
|
||||||
this.writingPairs = new HashSet<ConvertiblePair>();
|
this.writingPairs = new LinkedHashSet<ConvertiblePair>();
|
||||||
this.customSimpleTypes = new HashSet<Class<?>>();
|
this.customSimpleTypes = new HashSet<Class<?>>();
|
||||||
|
this.customReadTargetTypes = new ConcurrentHashMap<GenericConverter.ConvertiblePair, CacheValue>();
|
||||||
|
|
||||||
this.converters = new ArrayList<Object>();
|
this.converters = new ArrayList<Object>();
|
||||||
|
this.converters.addAll(converters);
|
||||||
this.converters.add(CustomToStringConverter.INSTANCE);
|
this.converters.add(CustomToStringConverter.INSTANCE);
|
||||||
this.converters.add(BigDecimalToStringConverter.INSTANCE);
|
this.converters.add(BigDecimalToStringConverter.INSTANCE);
|
||||||
this.converters.add(StringToBigDecimalConverter.INSTANCE);
|
this.converters.add(StringToBigDecimalConverter.INSTANCE);
|
||||||
this.converters.add(BigIntegerToStringConverter.INSTANCE);
|
this.converters.add(BigIntegerToStringConverter.INSTANCE);
|
||||||
this.converters.add(StringToBigIntegerConverter.INSTANCE);
|
this.converters.add(StringToBigIntegerConverter.INSTANCE);
|
||||||
this.converters.addAll(converters);
|
this.converters.add(URLToStringConverter.INSTANCE);
|
||||||
|
this.converters.add(StringToURLConverter.INSTANCE);
|
||||||
|
this.converters.add(DBObjectToStringConverter.INSTANCE);
|
||||||
|
this.converters.addAll(JodaTimeConverters.getConvertersToRegister());
|
||||||
|
|
||||||
for (Object c : this.converters) {
|
for (Object c : this.converters) {
|
||||||
registerConversion(c);
|
registerConversion(c);
|
||||||
@@ -182,25 +196,25 @@ public class CustomConversions {
|
|||||||
*
|
*
|
||||||
* @param pair
|
* @param pair
|
||||||
*/
|
*/
|
||||||
private void register(ConverterRegistration context) {
|
private void register(ConverterRegistration converterRegistration) {
|
||||||
|
|
||||||
ConvertiblePair pair = context.getConvertiblePair();
|
ConvertiblePair pair = converterRegistration.getConvertiblePair();
|
||||||
|
|
||||||
if (context.isReading()) {
|
if (converterRegistration.isReading()) {
|
||||||
|
|
||||||
readingPairs.add(pair);
|
readingPairs.add(pair);
|
||||||
|
|
||||||
if (LOG.isWarnEnabled() && !context.isSimpleSourceType()) {
|
if (LOG.isWarnEnabled() && !converterRegistration.isSimpleSourceType()) {
|
||||||
LOG.warn(String.format(READ_CONVERTER_NOT_SIMPLE, pair.getSourceType(), pair.getTargetType()));
|
LOG.warn(String.format(READ_CONVERTER_NOT_SIMPLE, pair.getSourceType(), pair.getTargetType()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.isWriting()) {
|
if (converterRegistration.isWriting()) {
|
||||||
|
|
||||||
writingPairs.add(pair);
|
writingPairs.add(pair);
|
||||||
customSimpleTypes.add(pair.getSourceType());
|
customSimpleTypes.add(pair.getSourceType());
|
||||||
|
|
||||||
if (LOG.isWarnEnabled() && !context.isSimpleTargetType()) {
|
if (LOG.isWarnEnabled() && !converterRegistration.isSimpleTargetType()) {
|
||||||
LOG.warn(String.format(WRITE_CONVERTER_NOT_SIMPLE, pair.getSourceType(), pair.getTargetType()));
|
LOG.warn(String.format(WRITE_CONVERTER_NOT_SIMPLE, pair.getSourceType(), pair.getTargetType()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,81 +224,90 @@ public class CustomConversions {
|
|||||||
* Returns the target type to convert to in case we have a custom conversion registered to convert the given source
|
* Returns the target type to convert to in case we have a custom conversion registered to convert the given source
|
||||||
* type into a Mongo native one.
|
* type into a Mongo native one.
|
||||||
*
|
*
|
||||||
* @param source must not be {@literal null}
|
* @param sourceType must not be {@literal null}
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Class<?> getCustomWriteTarget(Class<?> source) {
|
public Class<?> getCustomWriteTarget(Class<?> sourceType) {
|
||||||
return getCustomWriteTarget(source, null);
|
return getCustomWriteTarget(sourceType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the target type we can write an onject of the given source type to. The returned type might be a subclass
|
* Returns the target type we can write an onject of the given source type to. The returned type might be a subclass
|
||||||
* oth the given expected type though. If {@code expexctedTargetType} is {@literal null} we will simply return the
|
* oth the given expected type though. If {@code expectedTargetType} is {@literal null} we will simply return the
|
||||||
* first target type matching or {@literal null} if no conversion can be found.
|
* first target type matching or {@literal null} if no conversion can be found.
|
||||||
*
|
*
|
||||||
* @param source must not be {@literal null}
|
* @param sourceType must not be {@literal null}
|
||||||
* @param expectedTargetType
|
* @param requestedTargetType
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Class<?> getCustomWriteTarget(Class<?> source, Class<?> expectedTargetType) {
|
public Class<?> getCustomWriteTarget(Class<?> sourceType, Class<?> requestedTargetType) {
|
||||||
Assert.notNull(source);
|
|
||||||
return getCustomTarget(source, expectedTargetType, writingPairs);
|
Assert.notNull(sourceType);
|
||||||
|
|
||||||
|
return getCustomTarget(sourceType, requestedTargetType, writingPairs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether we have a custom conversion registered to write into a Mongo native type. The returned type might
|
* Returns whether we have a custom conversion registered to write into a Mongo native type. The returned type might
|
||||||
* be a subclass oth the given expected type though.
|
* be a subclass of the given expected type though.
|
||||||
*
|
*
|
||||||
* @param source must not be {@literal null}
|
* @param sourceType must not be {@literal null}
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean hasCustomWriteTarget(Class<?> source) {
|
public boolean hasCustomWriteTarget(Class<?> sourceType) {
|
||||||
return hasCustomWriteTarget(source, null);
|
|
||||||
|
Assert.notNull(sourceType);
|
||||||
|
return hasCustomWriteTarget(sourceType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether we have a custom conversion registered to write an object of the given source type into an object
|
* Returns whether we have a custom conversion registered to write an object of the given source type into an object
|
||||||
* of the given Mongo native target type.
|
* of the given Mongo native target type.
|
||||||
*
|
*
|
||||||
* @param source must not be {@literal null}.
|
* @param sourceType must not be {@literal null}.
|
||||||
* @param expectedTargetType
|
* @param requestedTargetType
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean hasCustomWriteTarget(Class<?> source, Class<?> expectedTargetType) {
|
public boolean hasCustomWriteTarget(Class<?> sourceType, Class<?> requestedTargetType) {
|
||||||
return getCustomWriteTarget(source, expectedTargetType) != null;
|
|
||||||
|
Assert.notNull(sourceType);
|
||||||
|
return getCustomWriteTarget(sourceType, requestedTargetType) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether we have a custom conversion registered to read the given source into the given target type.
|
* Returns whether we have a custom conversion registered to read the given source into the given target type.
|
||||||
*
|
*
|
||||||
* @param source must not be {@literal null}
|
* @param sourceType must not be {@literal null}
|
||||||
* @param expectedTargetType must not be {@literal null}
|
* @param requestedTargetType must not be {@literal null}
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean hasCustomReadTarget(Class<?> source, Class<?> expectedTargetType) {
|
public boolean hasCustomReadTarget(Class<?> sourceType, Class<?> requestedTargetType) {
|
||||||
Assert.notNull(source);
|
|
||||||
Assert.notNull(expectedTargetType);
|
Assert.notNull(sourceType);
|
||||||
return getCustomTarget(source, expectedTargetType, readingPairs) != null;
|
Assert.notNull(requestedTargetType);
|
||||||
|
|
||||||
|
return getCustomReadTarget(sourceType, requestedTargetType) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspects the given {@link ConvertiblePair} for ones that have a source compatible type as source. Additionally
|
* Inspects the given {@link ConvertiblePair} for ones that have a source compatible type as source. Additionally
|
||||||
* checks assignabilty of the target type if one is given.
|
* checks assignability of the target type if one is given.
|
||||||
*
|
*
|
||||||
* @param source must not be {@literal null}
|
* @param sourceType must not be {@literal null}.
|
||||||
* @param expectedTargetType
|
* @param requestedTargetType can be {@literal null}.
|
||||||
* @param pairs must not be {@literal null}
|
* @param pairs must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static Class<?> getCustomTarget(Class<?> source, Class<?> expectedTargetType, Iterable<ConvertiblePair> pairs) {
|
private static Class<?> getCustomTarget(Class<?> sourceType, Class<?> requestedTargetType,
|
||||||
|
Iterable<ConvertiblePair> pairs) {
|
||||||
|
|
||||||
Assert.notNull(source);
|
Assert.notNull(sourceType);
|
||||||
Assert.notNull(pairs);
|
Assert.notNull(pairs);
|
||||||
|
|
||||||
for (ConvertiblePair typePair : pairs) {
|
for (ConvertiblePair typePair : pairs) {
|
||||||
if (typePair.getSourceType().isAssignableFrom(source)) {
|
if (typePair.getSourceType().isAssignableFrom(sourceType)) {
|
||||||
Class<?> targetType = typePair.getTargetType();
|
Class<?> targetType = typePair.getTargetType();
|
||||||
if (expectedTargetType == null || targetType.isAssignableFrom(expectedTargetType)) {
|
if (requestedTargetType == null || targetType.isAssignableFrom(requestedTargetType)) {
|
||||||
return targetType;
|
return targetType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,13 +316,45 @@ public class CustomConversions {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the actual target type for the given {@code sourceType} and {@code requestedTargetType}. Note that the
|
||||||
|
* returned {@link Class} could be an assignable type to the given {@code requestedTargetType}.
|
||||||
|
*
|
||||||
|
* @param sourceType must not be {@literal null}.
|
||||||
|
* @param requestedTargetType can be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Class<?> getCustomReadTarget(Class<?> sourceType, Class<?> requestedTargetType) {
|
||||||
|
|
||||||
|
Assert.notNull(sourceType);
|
||||||
|
|
||||||
|
if (requestedTargetType == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConvertiblePair lookupKey = new ConvertiblePair(sourceType, requestedTargetType);
|
||||||
|
CacheValue readTargetTypeValue = customReadTargetTypes.get(lookupKey);
|
||||||
|
|
||||||
|
if (readTargetTypeValue != null) {
|
||||||
|
return readTargetTypeValue.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
readTargetTypeValue = CacheValue.of(getCustomTarget(sourceType, requestedTargetType, readingPairs));
|
||||||
|
CacheValue cacheValue = customReadTargetTypes.putIfAbsent(lookupKey, readTargetTypeValue);
|
||||||
|
|
||||||
|
return cacheValue != null ? cacheValue.getType() : readTargetTypeValue.getType();
|
||||||
|
}
|
||||||
|
|
||||||
@WritingConverter
|
@WritingConverter
|
||||||
private enum CustomToStringConverter implements GenericConverter {
|
private enum CustomToStringConverter implements GenericConverter {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||||
|
|
||||||
ConvertiblePair localeToString = new ConvertiblePair(Locale.class, String.class);
|
ConvertiblePair localeToString = new ConvertiblePair(Locale.class, String.class);
|
||||||
ConvertiblePair booleanToString = new ConvertiblePair(Character.class, String.class);
|
ConvertiblePair booleanToString = new ConvertiblePair(Character.class, String.class);
|
||||||
|
|
||||||
return new HashSet<ConvertiblePair>(Arrays.asList(localeToString, booleanToString));
|
return new HashSet<ConvertiblePair>(Arrays.asList(localeToString, booleanToString));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,4 +362,30 @@ public class CustomConversions {
|
|||||||
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011 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.
|
||||||
@@ -18,16 +18,19 @@ package org.springframework.data.mongodb.core.convert;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.data.convert.SimpleTypeInformationMapper;
|
|
||||||
import org.springframework.data.convert.DefaultTypeMapper;
|
import org.springframework.data.convert.DefaultTypeMapper;
|
||||||
|
import org.springframework.data.convert.SimpleTypeInformationMapper;
|
||||||
import org.springframework.data.convert.TypeAliasAccessor;
|
import org.springframework.data.convert.TypeAliasAccessor;
|
||||||
import org.springframework.data.convert.TypeInformationMapper;
|
import org.springframework.data.convert.TypeInformationMapper;
|
||||||
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.util.ClassTypeInformation;
|
import org.springframework.data.util.ClassTypeInformation;
|
||||||
import org.springframework.data.util.TypeInformation;
|
import org.springframework.data.util.TypeInformation;
|
||||||
|
|
||||||
import com.mongodb.BasicDBList;
|
import com.mongodb.BasicDBList;
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,33 +40,43 @@ import com.mongodb.DBObject;
|
|||||||
* respectively.
|
* respectively.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Thomas Darimont
|
||||||
*/
|
*/
|
||||||
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 String typeKey = DEFAULT_TYPE_KEY;
|
|
||||||
|
private final TypeAliasAccessor<DBObject> accessor;
|
||||||
|
private final String typeKey;
|
||||||
|
|
||||||
public DefaultMongoTypeMapper() {
|
public DefaultMongoTypeMapper() {
|
||||||
this(DEFAULT_TYPE_KEY, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
|
this(DEFAULT_TYPE_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultMongoTypeMapper(String typeKey) {
|
public DefaultMongoTypeMapper(String typeKey) {
|
||||||
super(new DBObjectTypeAliasAccessor(typeKey));
|
this(typeKey, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
|
||||||
this.typeKey = typeKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultMongoTypeMapper(String typeKey, MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext) {
|
public DefaultMongoTypeMapper(String typeKey, MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext) {
|
||||||
super(new DBObjectTypeAliasAccessor(typeKey), mappingContext, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
|
this(typeKey, new DBObjectTypeAliasAccessor(typeKey), mappingContext, Arrays
|
||||||
this.typeKey = typeKey;
|
.asList(SimpleTypeInformationMapper.INSTANCE));
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultMongoTypeMapper(String typeKey, List<? extends TypeInformationMapper> mappers) {
|
public DefaultMongoTypeMapper(String typeKey, List<? extends TypeInformationMapper> mappers) {
|
||||||
super(new DBObjectTypeAliasAccessor(typeKey), mappers);
|
this(typeKey, new DBObjectTypeAliasAccessor(typeKey), null, mappers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefaultMongoTypeMapper(String typeKey, TypeAliasAccessor<DBObject> accessor,
|
||||||
|
MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext, List<? extends TypeInformationMapper> mappers) {
|
||||||
|
|
||||||
|
super(accessor, mappingContext, mappers);
|
||||||
|
|
||||||
this.typeKey = typeKey;
|
this.typeKey = typeKey;
|
||||||
|
this.accessor = accessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -74,6 +87,31 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
|
|||||||
return typeKey == null ? false : typeKey.equals(key);
|
return typeKey == null ? false : typeKey.equals(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.MongoTypeMapper#writeTypeRestrictions(java.util.Set)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void writeTypeRestrictions(DBObject result, Set<Class<?>> restrictedTypes) {
|
||||||
|
|
||||||
|
if (restrictedTypes == null || restrictedTypes.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicDBList restrictedMappedTypes = new BasicDBList();
|
||||||
|
|
||||||
|
for (Class<?> restrictedType : restrictedTypes) {
|
||||||
|
|
||||||
|
Object typeAlias = getAliasFor(ClassTypeInformation.from(restrictedType));
|
||||||
|
|
||||||
|
if (typeAlias != null) {
|
||||||
|
restrictedMappedTypes.add(typeAlias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
accessor.writeTypeTo(result, new BasicDBObject("$in", restrictedMappedTypes));
|
||||||
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.springframework.data.convert.DefaultTypeMapper#getFallbackTypeFor(java.lang.Object)
|
* @see org.springframework.data.convert.DefaultTypeMapper#getFallbackTypeFor(java.lang.Object)
|
||||||
*/
|
*/
|
||||||
@@ -83,6 +121,7 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@link TypeAliasAccessor} to store aliases in a {@link DBObject}.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2012 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.
|
||||||
@@ -15,11 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core.convert;
|
package org.springframework.data.mongodb.core.convert;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
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.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@@ -31,11 +31,13 @@ import org.springframework.context.ApplicationContext;
|
|||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.core.CollectionFactory;
|
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.support.ConversionServiceFactory;
|
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||||
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.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.BeanWrapper;
|
import org.springframework.data.mapping.model.BeanWrapper;
|
||||||
@@ -46,6 +48,7 @@ import org.springframework.data.mapping.model.PersistentEntityParameterValueProv
|
|||||||
import org.springframework.data.mapping.model.PropertyValueProvider;
|
import org.springframework.data.mapping.model.PropertyValueProvider;
|
||||||
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;
|
||||||
|
import org.springframework.data.mapping.model.SpELExpressionParameterValueProvider;
|
||||||
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;
|
||||||
@@ -68,6 +71,8 @@ import com.mongodb.DBRef;
|
|||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Jon Brisbin
|
* @author Jon Brisbin
|
||||||
|
* @author Patrik Wasik
|
||||||
|
* @author Thomas Darimont
|
||||||
*/
|
*/
|
||||||
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware {
|
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware {
|
||||||
|
|
||||||
@@ -120,6 +125,15 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
mappingContext) : typeMapper;
|
mappingContext) : typeMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.MongoConverter#getTypeMapper()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MongoTypeMapper getTypeMapper() {
|
||||||
|
return this.typeMapper;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure the characters dots potentially contained in a {@link Map} shall be replaced with. By default we don't do
|
* Configure the characters dots potentially contained in a {@link Map} shall be replaced with. By default we don't do
|
||||||
* any translation but rather reject a {@link Map} with keys containing dots causing the conversion for the entire
|
* any translation but rather reject a {@link Map} with keys containing dots causing the conversion for the entire
|
||||||
@@ -215,9 +229,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
MongoDbPropertyValueProvider provider = new MongoDbPropertyValueProvider(source, evaluator, parent);
|
MongoDbPropertyValueProvider provider = new MongoDbPropertyValueProvider(source, evaluator, parent);
|
||||||
PersistentEntityParameterValueProvider<MongoPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<MongoPersistentProperty>(
|
PersistentEntityParameterValueProvider<MongoPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<MongoPersistentProperty>(
|
||||||
entity, provider, parent);
|
entity, provider, parent);
|
||||||
parameterProvider.setSpELEvaluator(evaluator);
|
|
||||||
|
|
||||||
return parameterProvider;
|
return new ConverterAwareSpELExpressionParameterValueProvider(evaluator, conversionService, parameterProvider,
|
||||||
|
parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo, Object parent) {
|
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo, Object parent) {
|
||||||
@@ -235,10 +249,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||||
public void doWithPersistentProperty(MongoPersistentProperty prop) {
|
public void doWithPersistentProperty(MongoPersistentProperty prop) {
|
||||||
|
|
||||||
boolean isConstructorProperty = entity.isConstructorArgument(prop);
|
if (!dbo.containsField(prop.getFieldName()) || entity.isConstructorArgument(prop)) {
|
||||||
boolean hasValueForProperty = dbo.containsField(prop.getFieldName());
|
|
||||||
|
|
||||||
if (!hasValueForProperty || isConstructorProperty) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,13 +263,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
||||||
MongoPersistentProperty inverseProp = association.getInverse();
|
MongoPersistentProperty inverseProp = association.getInverse();
|
||||||
Object obj = getValueInternal(inverseProp, dbo, evaluator, result);
|
Object obj = getValueInternal(inverseProp, dbo, evaluator, result);
|
||||||
try {
|
|
||||||
wrapper.setProperty(inverseProp, obj);
|
wrapper.setProperty(inverseProp, obj);
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new MappingException(e.getMessage(), e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
throw new MappingException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -350,16 +357,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
}
|
}
|
||||||
|
|
||||||
final BeanWrapper<MongoPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(obj, conversionService);
|
final BeanWrapper<MongoPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(obj, conversionService);
|
||||||
|
|
||||||
// Write the ID
|
|
||||||
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||||
|
|
||||||
if (!dbo.containsField("_id") && null != idProperty) {
|
if (!dbo.containsField("_id") && null != idProperty) {
|
||||||
|
|
||||||
|
boolean fieldAccessOnly = idProperty.usePropertyAccess() ? false : useFieldAccessOnly;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Object id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly);
|
Object id = wrapper.getProperty(idProperty, Object.class, fieldAccessOnly);
|
||||||
dbo.put("_id", idMapper.convertId(id));
|
dbo.put("_id", idMapper.convertId(id));
|
||||||
} catch (ConversionException ignored) {
|
} catch (ConversionException ignored) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the properties
|
// Write the properties
|
||||||
@@ -370,7 +377,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
|
boolean fieldAccessOnly = prop.usePropertyAccess() ? false : useFieldAccessOnly;
|
||||||
|
|
||||||
|
Object propertyObj = wrapper.getProperty(prop, prop.getType(), fieldAccessOnly);
|
||||||
|
|
||||||
if (null != propertyObj) {
|
if (null != propertyObj) {
|
||||||
if (!conversions.isSimpleType(propertyObj.getClass())) {
|
if (!conversions.isSimpleType(propertyObj.getClass())) {
|
||||||
@@ -412,8 +421,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (valueType.isMap()) {
|
if (valueType.isMap()) {
|
||||||
BasicDBObject mapDbObj = new BasicDBObject();
|
DBObject mapDbObj = createMap((Map<Object, Object>) obj, prop);
|
||||||
writeMapInternal((Map<Object, Object>) obj, mapDbObj, type);
|
|
||||||
dbo.put(name, mapDbObj);
|
dbo.put(name, mapDbObj);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -470,7 +478,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
*
|
*
|
||||||
* @param collection must not be {@literal null}.
|
* @param collection must not be {@literal null}.
|
||||||
* @param property must not be {@literal null}.
|
* @param property must not be {@literal null}.
|
||||||
*
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected DBObject createCollection(Collection<?> collection, MongoPersistentProperty property) {
|
protected DBObject createCollection(Collection<?> collection, MongoPersistentProperty property) {
|
||||||
@@ -494,6 +501,42 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
return dbList;
|
return dbList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the given {@link Map} using the given {@link MongoPersistentProperty} information.
|
||||||
|
*
|
||||||
|
* @param map must not {@literal null}.
|
||||||
|
* @param property must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected DBObject createMap(Map<Object, Object> map, MongoPersistentProperty property) {
|
||||||
|
|
||||||
|
Assert.notNull(map, "Given map must not be null!");
|
||||||
|
Assert.notNull(property, "PersistentProperty must not be null!");
|
||||||
|
|
||||||
|
if (!property.isDbReference()) {
|
||||||
|
return writeMapInternal(map, new BasicDBObject(), property.getTypeInformation());
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicDBObject dbObject = new BasicDBObject();
|
||||||
|
|
||||||
|
for (Map.Entry<Object, Object> entry : map.entrySet()) {
|
||||||
|
|
||||||
|
Object key = entry.getKey();
|
||||||
|
Object value = entry.getValue();
|
||||||
|
|
||||||
|
if (conversions.isSimpleType(key.getClass())) {
|
||||||
|
|
||||||
|
String simpleKey = potentiallyEscapeMapKey(key.toString());
|
||||||
|
dbObject.put(simpleKey, value != null ? createDBRef(value, property.getDBRef()) : null);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new MappingException("Cannot use a complex object as a key value.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dbObject;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the given {@link BasicDBList} with values from the given {@link Collection}.
|
* Populates the given {@link BasicDBList} with values from the given {@link Collection}.
|
||||||
*
|
*
|
||||||
@@ -676,6 +719,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
|
|
||||||
Assert.notNull(target);
|
Assert.notNull(target);
|
||||||
|
|
||||||
|
if (target instanceof DBRef) {
|
||||||
|
return (DBRef) target;
|
||||||
|
}
|
||||||
|
|
||||||
MongoPersistentEntity<?> targetEntity = mappingContext.getPersistentEntity(target.getClass());
|
MongoPersistentEntity<?> targetEntity = mappingContext.getPersistentEntity(target.getClass());
|
||||||
|
|
||||||
if (null == targetEntity) {
|
if (null == targetEntity) {
|
||||||
@@ -713,36 +760,41 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
*
|
*
|
||||||
* @param targetType must not be {@literal null}.
|
* @param targetType must not be {@literal null}.
|
||||||
* @param sourceValue must not be {@literal null}.
|
* @param sourceValue must not be {@literal null}.
|
||||||
* @return the converted {@link Collections}, will never be {@literal null}.
|
* @return the converted {@link Collection} or array, will never be {@literal null}.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Collection<?> readCollectionOrArray(TypeInformation<?> targetType, BasicDBList sourceValue, Object parent) {
|
private Object readCollectionOrArray(TypeInformation<?> targetType, BasicDBList sourceValue, Object parent) {
|
||||||
|
|
||||||
Assert.notNull(targetType);
|
Assert.notNull(targetType);
|
||||||
|
|
||||||
|
Class<?> collectionType = targetType.getType();
|
||||||
|
|
||||||
if (sourceValue.isEmpty()) {
|
if (sourceValue.isEmpty()) {
|
||||||
return Collections.emptySet();
|
return getPotentiallyConvertedSimpleRead(new HashSet<Object>(), collectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> collectionType = targetType.getType();
|
|
||||||
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
|
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
|
||||||
|
|
||||||
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>() : CollectionFactory
|
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>() : CollectionFactory
|
||||||
.createCollection(collectionType, sourceValue.size());
|
.createCollection(collectionType, sourceValue.size());
|
||||||
TypeInformation<?> componentType = targetType.getComponentType();
|
TypeInformation<?> componentType = targetType.getComponentType();
|
||||||
|
Class<?> rawComponentType = componentType == null ? null : componentType.getType();
|
||||||
|
|
||||||
for (int i = 0; i < sourceValue.size(); i++) {
|
for (int i = 0; i < sourceValue.size(); i++) {
|
||||||
|
|
||||||
Object dbObjItem = sourceValue.get(i);
|
Object dbObjItem = sourceValue.get(i);
|
||||||
|
|
||||||
if (dbObjItem instanceof DBRef) {
|
if (dbObjItem instanceof DBRef) {
|
||||||
items.add(read(componentType, ((DBRef) dbObjItem).fetch(), parent));
|
items.add(DBRef.class.equals(rawComponentType) ? dbObjItem : read(componentType, ((DBRef) dbObjItem).fetch(),
|
||||||
|
parent));
|
||||||
} else if (dbObjItem instanceof DBObject) {
|
} else if (dbObjItem instanceof DBObject) {
|
||||||
items.add(read(componentType, (DBObject) dbObjItem, parent));
|
items.add(read(componentType, (DBObject) dbObjItem, parent));
|
||||||
} else {
|
} else {
|
||||||
items.add(getPotentiallyConvertedSimpleRead(dbObjItem, componentType == null ? null : componentType.getType()));
|
items.add(getPotentiallyConvertedSimpleRead(dbObjItem, rawComponentType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return items;
|
return getPotentiallyConvertedSimpleRead(items, targetType.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -776,9 +828,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
|
|
||||||
Object value = entry.getValue();
|
Object value = entry.getValue();
|
||||||
TypeInformation<?> valueType = type.getMapValueType();
|
TypeInformation<?> valueType = type.getMapValueType();
|
||||||
|
Class<?> rawValueType = valueType == null ? null : valueType.getType();
|
||||||
|
|
||||||
if (value instanceof DBObject) {
|
if (value instanceof DBObject) {
|
||||||
map.put(key, read(valueType, (DBObject) value, parent));
|
map.put(key, read(valueType, (DBObject) value, parent));
|
||||||
|
} else if (value instanceof DBRef) {
|
||||||
|
map.put(key, DBRef.class.equals(rawValueType) ? value : read(valueType, ((DBRef) value).fetch()));
|
||||||
} 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));
|
||||||
@@ -803,19 +858,23 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
return rootList;
|
return rootList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.MongoWriter#convertToMongoType(java.lang.Object, org.springframework.data.util.TypeInformation)
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Object convertToMongoType(Object obj) {
|
public Object convertToMongoType(Object obj, TypeInformation<?> typeInformation) {
|
||||||
|
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> target = conversions.getCustomWriteTarget(getClass());
|
Class<?> target = conversions.getCustomWriteTarget(obj.getClass());
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
return conversionService.convert(obj, target);
|
return conversionService.convert(obj, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null != obj && conversions.isSimpleType(obj.getClass())) {
|
if (conversions.isSimpleType(obj.getClass())) {
|
||||||
// Doesn't need conversion
|
// Doesn't need conversion
|
||||||
return getPotentiallyConvertedSimpleWrite(obj);
|
return getPotentiallyConvertedSimpleWrite(obj);
|
||||||
}
|
}
|
||||||
@@ -851,7 +910,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
|
|
||||||
DBObject newDbo = new BasicDBObject();
|
DBObject newDbo = new BasicDBObject();
|
||||||
this.write(obj, newDbo);
|
this.write(obj, newDbo);
|
||||||
return removeTypeInfoRecursively(newDbo);
|
|
||||||
|
if (typeInformation == null) {
|
||||||
|
return removeTypeInfoRecursively(newDbo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !obj.getClass().equals(typeInformation.getType()) ? newDbo : removeTypeInfoRecursively(newDbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BasicDBList maybeConvertList(Iterable<?> source) {
|
public BasicDBList maybeConvertList(Iterable<?> source) {
|
||||||
@@ -923,7 +987,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.convert.PropertyValueProvider#getPropertyValue(org.springframework.data.mapping.PersistentProperty)
|
* @see org.springframework.data.convert.PropertyValueProvider#getPropertyValue(org.springframework.data.mapping.PersistentProperty)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T> T getPropertyValue(MongoPersistentProperty property) {
|
public <T> T getPropertyValue(MongoPersistentProperty property) {
|
||||||
|
|
||||||
String expression = property.getSpelExpression();
|
String expression = property.getSpelExpression();
|
||||||
@@ -933,20 +996,60 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeInformation<?> type = property.getTypeInformation();
|
return readValue(value, property.getTypeInformation(), parent);
|
||||||
Class<?> rawType = type.getType();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (conversions.hasCustomReadTarget(value.getClass(), rawType)) {
|
/**
|
||||||
return (T) conversionService.convert(value, rawType);
|
* Extension of {@link SpELExpressionParameterValueProvider} to recursively trigger value conversion on the raw
|
||||||
} else if (value instanceof DBRef) {
|
* resolved SpEL value.
|
||||||
return (T) read(type, ((DBRef) value).fetch(), parent);
|
*
|
||||||
} else if (value instanceof BasicDBList) {
|
* @author Oliver Gierke
|
||||||
return (T) getPotentiallyConvertedSimpleRead(readCollectionOrArray(type, (BasicDBList) value, parent), rawType);
|
*/
|
||||||
} else if (value instanceof DBObject) {
|
private class ConverterAwareSpELExpressionParameterValueProvider extends
|
||||||
return (T) read(type, (DBObject) value, parent);
|
SpELExpressionParameterValueProvider<MongoPersistentProperty> {
|
||||||
} else {
|
|
||||||
return (T) getPotentiallyConvertedSimpleRead(value, rawType);
|
private final Object parent;
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ConverterAwareSpELExpressionParameterValueProvider}.
|
||||||
|
*
|
||||||
|
* @param evaluator must not be {@literal null}.
|
||||||
|
* @param conversionService must not be {@literal null}.
|
||||||
|
* @param delegate must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public ConverterAwareSpELExpressionParameterValueProvider(SpELExpressionEvaluator evaluator,
|
||||||
|
ConversionService conversionService, ParameterValueProvider<MongoPersistentProperty> delegate, Object parent) {
|
||||||
|
|
||||||
|
super(evaluator, conversionService, delegate);
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mapping.model.SpELExpressionParameterValueProvider#potentiallyConvertSpelValue(java.lang.Object, org.springframework.data.mapping.PreferredConstructor.Parameter)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected <T> T potentiallyConvertSpelValue(Object object, Parameter<T, MongoPersistentProperty> parameter) {
|
||||||
|
return readValue(object, parameter.getType(), parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private <T> T readValue(Object value, TypeInformation<?> type, Object parent) {
|
||||||
|
|
||||||
|
Class<?> rawType = type.getType();
|
||||||
|
|
||||||
|
if (conversions.hasCustomReadTarget(value.getClass(), rawType)) {
|
||||||
|
return (T) conversionService.convert(value, rawType);
|
||||||
|
} else if (value instanceof DBRef) {
|
||||||
|
return (T) (rawType.equals(DBRef.class) ? value : read(type, ((DBRef) value).fetch(), parent));
|
||||||
|
} else if (value instanceof BasicDBList) {
|
||||||
|
return (T) readCollectionOrArray(type, (BasicDBList) value, parent);
|
||||||
|
} else if (value instanceof DBObject) {
|
||||||
|
return (T) read(type, (DBObject) value, parent);
|
||||||
|
} else {
|
||||||
|
return (T) getPotentiallyConvertedSimpleRead(value, rawType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2011 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.
|
||||||
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core.convert;
|
|||||||
|
|
||||||
import org.springframework.data.convert.EntityConverter;
|
import org.springframework.data.convert.EntityConverter;
|
||||||
import org.springframework.data.convert.EntityReader;
|
import org.springframework.data.convert.EntityReader;
|
||||||
|
import org.springframework.data.convert.TypeMapper;
|
||||||
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;
|
||||||
|
|
||||||
@@ -26,9 +27,17 @@ import com.mongodb.DBObject;
|
|||||||
* Central Mongo specific converter interface which combines {@link MongoWriter} and {@link MongoReader}.
|
* Central Mongo specific converter interface which combines {@link MongoWriter} and {@link MongoReader}.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Thomas Darimont
|
||||||
*/
|
*/
|
||||||
public interface MongoConverter extends
|
public interface MongoConverter extends
|
||||||
EntityConverter<MongoPersistentEntity<?>, MongoPersistentProperty, Object, DBObject>, MongoWriter<Object>,
|
EntityConverter<MongoPersistentEntity<?>, MongoPersistentProperty, Object, DBObject>, MongoWriter<Object>,
|
||||||
EntityReader<Object, DBObject> {
|
EntityReader<Object, DBObject> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns thw {@link TypeMapper} being used to write type information into {@link DBObject}s created with that
|
||||||
|
* converter.
|
||||||
|
*
|
||||||
|
* @return will never be {@literal null}.
|
||||||
|
*/
|
||||||
|
MongoTypeMapper getTypeMapper();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,18 @@ package org.springframework.data.mongodb.core.convert;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
|
import org.springframework.core.convert.ConversionFailedException;
|
||||||
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.data.convert.ReadingConverter;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper class to contain useful converters for the usage with Mongo.
|
* Wrapper class to contain useful converters for the usage with Mongo.
|
||||||
*
|
*
|
||||||
@@ -119,4 +126,39 @@ abstract class MongoConverters {
|
|||||||
return StringUtils.hasText(source) ? new BigInteger(source) : null;
|
return StringUtils.hasText(source) ? new BigInteger(source) : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static enum URLToStringConverter implements Converter<URL, String> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public String convert(URL source) {
|
||||||
|
return source == null ? null : source.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum StringToURLConverter implements Converter<String, URL> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
private static final TypeDescriptor SOURCE = TypeDescriptor.valueOf(String.class);
|
||||||
|
private static final TypeDescriptor TARGET = TypeDescriptor.valueOf(URL.class);
|
||||||
|
|
||||||
|
public URL convert(String source) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return source == null ? null : new URL(source);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new ConversionFailedException(SOURCE, TARGET, source, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReadingConverter
|
||||||
|
public static enum DBObjectToStringConverter implements Converter<DBObject, String> {
|
||||||
|
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String convert(DBObject source) {
|
||||||
|
return source == null ? null : source.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core.convert;
|
package org.springframework.data.mongodb.core.convert;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.data.convert.TypeMapper;
|
import org.springframework.data.convert.TypeMapper;
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
@@ -32,4 +34,14 @@ public interface MongoTypeMapper extends TypeMapper<DBObject> {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean isTypeKey(String key);
|
boolean isTypeKey(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes type restrictions to the given {@link DBObject}. This usually results in an {@code $in}-clause to be
|
||||||
|
* generated that restricts the type-key (e.g. {@code _class}) to be in the set of type aliases for the given
|
||||||
|
* {@code restrictedTypes}.
|
||||||
|
*
|
||||||
|
* @param result must not be {@literal null}
|
||||||
|
* @param restrictedTypes must not be {@literal null}
|
||||||
|
*/
|
||||||
|
void writeTypeRestrictions(DBObject result, Set<Class<?>> restrictedTypes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2012 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.
|
||||||
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core.convert;
|
|||||||
|
|
||||||
import org.springframework.data.convert.EntityWriter;
|
import org.springframework.data.convert.EntityWriter;
|
||||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||||
|
import org.springframework.data.util.TypeInformation;
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
import com.mongodb.DBRef;
|
import com.mongodb.DBRef;
|
||||||
@@ -35,11 +36,21 @@ public interface MongoWriter<T> extends EntityWriter<T, DBObject> {
|
|||||||
* Converts the given object into one Mongo will be able to store natively. If the given object can already be stored
|
* Converts the given object into one Mongo will be able to store natively. If the given object can already be stored
|
||||||
* as is, no conversion will happen.
|
* as is, no conversion will happen.
|
||||||
*
|
*
|
||||||
* @param obj
|
* @param obj can be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Object convertToMongoType(Object obj);
|
Object convertToMongoType(Object obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given object into one Mongo will be able to store natively but retains the type information in case
|
||||||
|
* the given {@link TypeInformation} differs from the given object type.
|
||||||
|
*
|
||||||
|
* @param obj can be {@literal null}.
|
||||||
|
* @param typeInformation can be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Object convertToMongoType(Object obj, TypeInformation<?> typeInformation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link DBRef} to refer to the given object.
|
* Creates a {@link DBRef} to refer to the given object.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -17,36 +17,44 @@ package org.springframework.data.mongodb.core.convert;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.bson.types.BasicBSONList;
|
|
||||||
import org.bson.types.ObjectId;
|
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.data.mapping.PersistentEntity;
|
import org.springframework.data.mapping.PersistentEntity;
|
||||||
|
import org.springframework.data.mapping.PropertyPath;
|
||||||
|
import org.springframework.data.mapping.PropertyReferenceException;
|
||||||
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.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.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import com.mongodb.BasicDBList;
|
import com.mongodb.BasicDBList;
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
|
import com.mongodb.DBRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class to encapsulate any modifications of a Query object before it gets submitted to the database.
|
* A helper class to encapsulate any modifications of a Query object before it gets submitted to the database.
|
||||||
*
|
*
|
||||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
* @author Jon Brisbin
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Patryk Wasik
|
||||||
|
* @author Thomas Darimont
|
||||||
*/
|
*/
|
||||||
public class QueryMapper {
|
public class QueryMapper {
|
||||||
|
|
||||||
private static final List<String> DEFAULT_ID_NAMES = Arrays.asList("id", "_id");
|
private static final List<String> DEFAULT_ID_NAMES = Arrays.asList("id", "_id");
|
||||||
private static final String N_OR_PATTERN = "\\$.*or";
|
|
||||||
|
|
||||||
private final ConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
private final MongoConverter converter;
|
private final MongoConverter converter;
|
||||||
|
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link QueryMapper} with the given {@link MongoConverter}.
|
* Creates a new {@link QueryMapper} with the given {@link MongoConverter}.
|
||||||
@@ -54,9 +62,12 @@ public class QueryMapper {
|
|||||||
* @param converter must not be {@literal null}.
|
* @param converter must not be {@literal null}.
|
||||||
*/
|
*/
|
||||||
public QueryMapper(MongoConverter converter) {
|
public QueryMapper(MongoConverter converter) {
|
||||||
|
|
||||||
Assert.notNull(converter);
|
Assert.notNull(converter);
|
||||||
|
|
||||||
this.conversionService = converter.getConversionService();
|
this.conversionService = converter.getConversionService();
|
||||||
this.converter = converter;
|
this.converter = converter;
|
||||||
|
this.mappingContext = converter.getMappingContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,50 +78,164 @@ public class QueryMapper {
|
|||||||
* @param entity can be {@literal null}.
|
* @param entity can be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public DBObject getMappedObject(DBObject query, MongoPersistentEntity<?> entity) {
|
public DBObject getMappedObject(DBObject query, MongoPersistentEntity<?> entity) {
|
||||||
|
|
||||||
DBObject newDbo = new BasicDBObject();
|
if (isNestedKeyword(query)) {
|
||||||
|
return getMappedKeyword(new Keyword(query), entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBObject result = new BasicDBObject();
|
||||||
|
|
||||||
for (String key : query.keySet()) {
|
for (String key : query.keySet()) {
|
||||||
|
|
||||||
MongoPersistentEntity<?> nestedEntity = getNestedEntity(entity, key);
|
// TODO: remove one once QueryMapper can work with Query instances directly
|
||||||
String newKey = key;
|
if (Query.isRestrictedTypeKey(key)) {
|
||||||
Object value = query.get(key);
|
|
||||||
|
|
||||||
if (isIdKey(key, entity)) {
|
@SuppressWarnings("unchecked")
|
||||||
if (value instanceof DBObject) {
|
Set<Class<?>> restrictedTypes = (Set<Class<?>>) query.get(key);
|
||||||
DBObject valueDbo = (DBObject) value;
|
this.converter.getTypeMapper().writeTypeRestrictions(result, restrictedTypes);
|
||||||
if (valueDbo.containsField("$in") || valueDbo.containsField("$nin")) {
|
|
||||||
String inKey = valueDbo.containsField("$in") ? "$in" : "$nin";
|
continue;
|
||||||
List<Object> ids = new ArrayList<Object>();
|
|
||||||
for (Object id : (Iterable<?>) valueDbo.get(inKey)) {
|
|
||||||
ids.add(convertId(id));
|
|
||||||
}
|
|
||||||
valueDbo.put(inKey, ids.toArray(new Object[ids.size()]));
|
|
||||||
} else {
|
|
||||||
value = getMappedObject((DBObject) value, nestedEntity);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value = convertId(value);
|
|
||||||
}
|
|
||||||
newKey = "_id";
|
|
||||||
} else if (key.matches(N_OR_PATTERN)) {
|
|
||||||
// $or/$nor
|
|
||||||
Iterable<?> conditions = (Iterable<?>) value;
|
|
||||||
BasicBSONList newConditions = new BasicBSONList();
|
|
||||||
Iterator<?> iter = conditions.iterator();
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
newConditions.add(getMappedObject((DBObject) iter.next(), nestedEntity));
|
|
||||||
}
|
|
||||||
value = newConditions;
|
|
||||||
} else if (key.equals("$ne")) {
|
|
||||||
value = convertId(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newDbo.put(newKey, convertSimpleOrDBObject(value, nestedEntity));
|
if (isKeyword(key)) {
|
||||||
|
result.putAll(getMappedKeyword(new Keyword(query, key), entity));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Field field = createPropertyField(entity, key, mappingContext);
|
||||||
|
|
||||||
|
Object rawValue = query.get(key);
|
||||||
|
String newKey = field.getMappedKey();
|
||||||
|
|
||||||
|
if (isNestedKeyword(rawValue) && !field.isIdField()) {
|
||||||
|
Keyword keyword = new Keyword((DBObject) rawValue);
|
||||||
|
result.put(newKey, getMappedKeyword(field, keyword));
|
||||||
|
} else {
|
||||||
|
result.put(newKey, getMappedValue(field, rawValue));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return newDbo;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param entity
|
||||||
|
* @param key
|
||||||
|
* @param mappingContext
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected Field createPropertyField(MongoPersistentEntity<?> entity, String key,
|
||||||
|
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||||
|
return entity == null ? new Field(key) : new MetadataBackedField(key, entity, mappingContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given {@link DBObject} representing a keyword by mapping the keyword's value.
|
||||||
|
*
|
||||||
|
* @param keyword the {@link DBObject} representing a keyword (e.g. {@code $ne : … } )
|
||||||
|
* @param entity
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private DBObject getMappedKeyword(Keyword keyword, MongoPersistentEntity<?> entity) {
|
||||||
|
|
||||||
|
// $or/$nor
|
||||||
|
if (keyword.isOrOrNor() || keyword.hasIterableValue()) {
|
||||||
|
|
||||||
|
Iterable<?> conditions = keyword.getValue();
|
||||||
|
BasicDBList newConditions = new BasicDBList();
|
||||||
|
|
||||||
|
for (Object condition : conditions) {
|
||||||
|
newConditions.add(condition instanceof DBObject ? getMappedObject((DBObject) condition, entity)
|
||||||
|
: convertSimpleOrDBObject(condition, entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BasicDBObject(keyword.getKey(), newConditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BasicDBObject(keyword.getKey(), convertSimpleOrDBObject(keyword.getValue(), entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the mapped keyword considered defining a criteria for the given property.
|
||||||
|
*
|
||||||
|
* @param property
|
||||||
|
* @param keyword
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private DBObject getMappedKeyword(Field property, Keyword keyword) {
|
||||||
|
|
||||||
|
boolean needsAssociationConversion = property.isAssociation() && !keyword.isExists();
|
||||||
|
Object value = keyword.getValue();
|
||||||
|
|
||||||
|
Object convertedValue = needsAssociationConversion ? convertAssociation(value, property.getProperty())
|
||||||
|
: getMappedValue(property.with(keyword.getKey()), value);
|
||||||
|
|
||||||
|
return new BasicDBObject(keyword.key, convertedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the mapped value for the given source object assuming it's a value for the given
|
||||||
|
* {@link MongoPersistentProperty}.
|
||||||
|
*
|
||||||
|
* @param value the source object to be mapped
|
||||||
|
* @param property the property the value is a value for
|
||||||
|
* @param newKey the key the value will be bound to eventually
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Object getMappedValue(Field documentField, Object value) {
|
||||||
|
|
||||||
|
if (documentField.isIdField()) {
|
||||||
|
|
||||||
|
if (value instanceof DBObject) {
|
||||||
|
DBObject valueDbo = (DBObject) value;
|
||||||
|
DBObject resultDbo = new BasicDBObject(valueDbo.toMap());
|
||||||
|
|
||||||
|
if (valueDbo.containsField("$in") || valueDbo.containsField("$nin")) {
|
||||||
|
String inKey = valueDbo.containsField("$in") ? "$in" : "$nin";
|
||||||
|
List<Object> ids = new ArrayList<Object>();
|
||||||
|
for (Object id : (Iterable<?>) valueDbo.get(inKey)) {
|
||||||
|
ids.add(convertId(id));
|
||||||
|
}
|
||||||
|
resultDbo.put(inKey, ids.toArray(new Object[ids.size()]));
|
||||||
|
} else if (valueDbo.containsField("$ne")) {
|
||||||
|
resultDbo.put("$ne", convertId(valueDbo.get("$ne")));
|
||||||
|
} else {
|
||||||
|
return getMappedObject(resultDbo, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultDbo;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return convertId(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNestedKeyword(value)) {
|
||||||
|
return getMappedKeyword(new Keyword((DBObject) value), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAssociationConversionNecessary(documentField, value)) {
|
||||||
|
return convertAssociation(value, documentField.getProperty());
|
||||||
|
}
|
||||||
|
|
||||||
|
return convertSimpleOrDBObject(value, documentField.getPropertyEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given {@link Field} represents an association reference that together with the given value
|
||||||
|
* requires conversion to a {@link org.springframework.data.mongodb.core.mapping.DBRef} object. We check whether the
|
||||||
|
* type of the given value is compatible with the type of the given document field in order to deal with potential
|
||||||
|
* query field exclusions, since MongoDB uses the {@code int} {@literal 0} as an indicator for an excluded field.
|
||||||
|
*
|
||||||
|
* @param documentField
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean isAssociationConversionNecessary(Field documentField, Object value) {
|
||||||
|
return documentField.isAssociation() && value != null
|
||||||
|
&& documentField.getProperty().getActualType().isAssignableFrom(value.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,43 +248,61 @@ public class QueryMapper {
|
|||||||
private Object convertSimpleOrDBObject(Object source, MongoPersistentEntity<?> entity) {
|
private Object convertSimpleOrDBObject(Object source, MongoPersistentEntity<?> entity) {
|
||||||
|
|
||||||
if (source instanceof BasicDBList) {
|
if (source instanceof BasicDBList) {
|
||||||
return converter.convertToMongoType(source);
|
return delegateConvertToMongoType(source, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source instanceof DBObject) {
|
if (source instanceof DBObject) {
|
||||||
return getMappedObject((DBObject) source, entity);
|
return getMappedObject((DBObject) source, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return delegateConvertToMongoType(source, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given source Object to a mongo type with the type information of the original source type omitted.
|
||||||
|
* Subclasses may overwrite this method to retain the type information of the source type on the resulting mongo type.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* @param entity
|
||||||
|
* @return the converted mongo type or null if source is null
|
||||||
|
*/
|
||||||
|
protected Object delegateConvertToMongoType(Object source, MongoPersistentEntity<?> entity) {
|
||||||
return converter.convertToMongoType(source);
|
return converter.convertToMongoType(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given key will be considered an id key.
|
* Converts the given source assuming it's actually an association to another object.
|
||||||
*
|
*
|
||||||
* @param key
|
* @param source
|
||||||
* @param entity
|
* @param property
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private boolean isIdKey(String key, MongoPersistentEntity<?> entity) {
|
private Object convertAssociation(Object source, MongoPersistentProperty property) {
|
||||||
|
|
||||||
if (null != entity && entity.getIdProperty() != null) {
|
if (property == null || !property.isAssociation() || source == null || source instanceof DBRef
|
||||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
|| !property.isEntity()) {
|
||||||
return idProperty.getName().equals(key) || idProperty.getFieldName().equals(key);
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DEFAULT_ID_NAMES.contains(key);
|
if (source instanceof Iterable) {
|
||||||
}
|
BasicDBList result = new BasicDBList();
|
||||||
|
for (Object element : (Iterable<?>) source) {
|
||||||
private MongoPersistentEntity<?> getNestedEntity(MongoPersistentEntity<?> entity, String key) {
|
result.add(element instanceof DBRef ? element : converter.toDBRef(element, property));
|
||||||
|
}
|
||||||
MongoPersistentProperty property = entity == null ? null : entity.getPersistentProperty(key);
|
return result;
|
||||||
|
|
||||||
if (property == null || !property.isEntity()) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> context = converter.getMappingContext();
|
if (property.isMap()) {
|
||||||
return context.getPersistentEntity(property);
|
BasicDBObject result = new BasicDBObject();
|
||||||
|
DBObject dbObject = (DBObject) source;
|
||||||
|
for (String key : dbObject.keySet()) {
|
||||||
|
Object o = dbObject.get(key);
|
||||||
|
result.put(key, o instanceof DBRef ? o : converter.toDBRef(o, property));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return converter.toDBRef(source, property);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -176,6 +319,296 @@ public class QueryMapper {
|
|||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
return converter.convertToMongoType(id);
|
return delegateConvertToMongoType(id, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given {@link Object} is a keyword, i.e. if it's a {@link DBObject} with a keyword key.
|
||||||
|
*
|
||||||
|
* @param candidate
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected boolean isNestedKeyword(Object candidate) {
|
||||||
|
|
||||||
|
if (!(candidate instanceof BasicDBObject)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicDBObject dbObject = (BasicDBObject) candidate;
|
||||||
|
Set<String> keys = dbObject.keySet();
|
||||||
|
|
||||||
|
if (keys.size() != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isKeyword(keys.iterator().next().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given {@link String} is a MongoDB keyword. The default implementation will check against the
|
||||||
|
* set of registered keywords returned by {@link #getKeywords()}.
|
||||||
|
*
|
||||||
|
* @param candidate
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected boolean isKeyword(String candidate) {
|
||||||
|
return candidate.startsWith("$");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value object to capture a query keyword representation.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
private static class Keyword {
|
||||||
|
|
||||||
|
private static final String N_OR_PATTERN = "\\$.*or";
|
||||||
|
|
||||||
|
private final String key;
|
||||||
|
private final Object value;
|
||||||
|
|
||||||
|
public Keyword(DBObject source, String key) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = source.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Keyword(DBObject dbObject) {
|
||||||
|
|
||||||
|
Set<String> keys = dbObject.keySet();
|
||||||
|
Assert.isTrue(keys.size() == 1, "Can only use a single value DBObject!");
|
||||||
|
|
||||||
|
this.key = keys.iterator().next();
|
||||||
|
this.value = dbObject.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the current keyword is the {@code $exists} keyword.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isExists() {
|
||||||
|
return "$exists".equalsIgnoreCase(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOrOrNor() {
|
||||||
|
return key.matches(N_OR_PATTERN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasIterableValue() {
|
||||||
|
return value instanceof Iterable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T getValue() {
|
||||||
|
return (T) value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value object to represent a field and its meta-information.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
protected static class Field {
|
||||||
|
|
||||||
|
private static final String ID_KEY = "_id";
|
||||||
|
|
||||||
|
protected final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link DocumentField} without meta-information but the given name.
|
||||||
|
*
|
||||||
|
* @param name must not be {@literal null} or empty.
|
||||||
|
*/
|
||||||
|
public Field(String name) {
|
||||||
|
|
||||||
|
Assert.hasText(name, "Name must not be null!");
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new {@link DocumentField} with the given name.
|
||||||
|
*
|
||||||
|
* @param name must not be {@literal null} or empty.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Field with(String name) {
|
||||||
|
return new Field(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the current field is the id field.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isIdField() {
|
||||||
|
return ID_KEY.equals(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the underlying {@link MongoPersistentProperty} backing the field.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public MongoPersistentProperty getProperty() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link MongoPersistentEntity} that field is conatined in.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public MongoPersistentEntity<?> getPropertyEntity() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the field represents an association.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isAssociation() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the key to be used in the mapped document eventually.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getMappedKey() {
|
||||||
|
return isIdField() ? ID_KEY : name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension of {@link DocumentField} to be backed with mapping metadata.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @author Thomas Darimont
|
||||||
|
*/
|
||||||
|
protected static class MetadataBackedField extends Field {
|
||||||
|
|
||||||
|
private final MongoPersistentEntity<?> entity;
|
||||||
|
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||||
|
private final MongoPersistentProperty property;
|
||||||
|
private final PersistentPropertyPath<MongoPersistentProperty> path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link MetadataBackedField} with the given name, {@link MongoPersistentEntity} and
|
||||||
|
* {@link MappingContext}.
|
||||||
|
*
|
||||||
|
* @param name must not be {@literal null} or empty.
|
||||||
|
* @param entity must not be {@literal null}.
|
||||||
|
* @param context must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public MetadataBackedField(String name, MongoPersistentEntity<?> entity,
|
||||||
|
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> context) {
|
||||||
|
|
||||||
|
super(name);
|
||||||
|
|
||||||
|
Assert.notNull(entity, "MongoPersistentEntity must not be null!");
|
||||||
|
|
||||||
|
this.entity = entity;
|
||||||
|
this.mappingContext = context;
|
||||||
|
|
||||||
|
this.path = getPath(name);
|
||||||
|
this.property = path == null ? null : path.getLeafProperty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#with(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MetadataBackedField with(String name) {
|
||||||
|
return new MetadataBackedField(name, entity, mappingContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#isIdKey()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isIdField() {
|
||||||
|
|
||||||
|
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||||
|
|
||||||
|
if (idProperty != null) {
|
||||||
|
return idProperty.getName().equals(name) || idProperty.getFieldName().equals(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEFAULT_ID_NAMES.contains(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#getProperty()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MongoPersistentProperty getProperty() {
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#getEntity()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MongoPersistentEntity<?> getPropertyEntity() {
|
||||||
|
MongoPersistentProperty property = getProperty();
|
||||||
|
return property == null ? null : mappingContext.getPersistentEntity(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#isAssociation()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isAssociation() {
|
||||||
|
|
||||||
|
MongoPersistentProperty property = getProperty();
|
||||||
|
return property == null ? false : property.isAssociation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#getTargetKey()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getMappedKey() {
|
||||||
|
return path == null ? name : path.toDotPath(getPropertyConverter());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link PersistentPropertyPath} for the given <code>pathExpression</code>.
|
||||||
|
*
|
||||||
|
* @param pathExpression
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private PersistentPropertyPath<MongoPersistentProperty> getPath(String pathExpression) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
PropertyPath path = PropertyPath.from(pathExpression, entity.getTypeInformation());
|
||||||
|
return mappingContext.getPersistentPropertyPath(path);
|
||||||
|
} catch (PropertyReferenceException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the {@link Converter} to be used to created the mapped key. Default implementation will use
|
||||||
|
* {@link PropertyToFieldNameConverter}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
|
||||||
|
return PropertyToFieldNameConverter.INSTANCE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2014 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.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
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.mapping.MongoPersistentProperty.PropertyToFieldNameConverter;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A subclass of {@link QueryMapper} that retains type information on the mongo types.
|
||||||
|
*
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public class UpdateMapper extends QueryMapper {
|
||||||
|
|
||||||
|
private final MongoWriter<?> converter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link UpdateMapper} using the given {@link MongoConverter}.
|
||||||
|
*
|
||||||
|
* @param converter must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public UpdateMapper(MongoConverter converter) {
|
||||||
|
|
||||||
|
super(converter);
|
||||||
|
this.converter = converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given source object to a mongo type retaining the original type information of the source type on the
|
||||||
|
* mongo type.
|
||||||
|
*
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.QueryMapper#delegateConvertToMongoType(java.lang.Object,
|
||||||
|
* org.springframework.data.mongodb.core.mapping.MongoPersistentEntity)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Object delegateConvertToMongoType(Object source, MongoPersistentEntity<?> entity) {
|
||||||
|
return entity == null ? super.delegateConvertToMongoType(source, null) : converter.convertToMongoType(source,
|
||||||
|
entity.getTypeInformation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.QueryMapper#createPropertyField(org.springframework.data.mongodb.core.mapping.MongoPersistentEntity, java.lang.String, org.springframework.data.mapping.context.MappingContext)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Field createPropertyField(MongoPersistentEntity<?> entity, String key,
|
||||||
|
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||||
|
|
||||||
|
return entity == null ? super.createPropertyField(entity, key, mappingContext) : //
|
||||||
|
new MetadataBackedUpdateField(entity, key, mappingContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link MetadataBackedField} that handles {@literal $} paths inside a field key. We clean up an update key
|
||||||
|
* containing a {@literal $} before handing it to the super class to make sure property lookups and transformations
|
||||||
|
* continue to work as expected. We provide a custom property converter to re-applied the cleaned up {@literal $}s
|
||||||
|
* when constructing the mapped key.
|
||||||
|
*
|
||||||
|
* @author Thomas Darimont
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
private static class MetadataBackedUpdateField extends MetadataBackedField {
|
||||||
|
|
||||||
|
private final String key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link MetadataBackedField} with the given {@link MongoPersistentEntity}, key and
|
||||||
|
* {@link MappingContext}. We clean up the key before handing it up to the super class to make sure it continues to
|
||||||
|
* work as expected.
|
||||||
|
*
|
||||||
|
* @param entity must not be {@literal null}.
|
||||||
|
* @param key must not be {@literal null} or empty.
|
||||||
|
* @param mappingContext must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public MetadataBackedUpdateField(MongoPersistentEntity<?> entity, String key,
|
||||||
|
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||||
|
|
||||||
|
super(key.replaceAll("\\.\\$", ""), entity, mappingContext);
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.convert.QueryMapper.MetadataBackedField#getPropertyConverter()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
|
||||||
|
return new UpdatePropertyConverter(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special {@link Converter} for {@link MongoPersistentProperty} instances that will concatenate the {@literal $}
|
||||||
|
* contained in the source update key.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
private static class UpdatePropertyConverter implements Converter<MongoPersistentProperty, String> {
|
||||||
|
|
||||||
|
private final Iterator<String> iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.iterator = Arrays.asList(updateKey.split("\\.")).iterator();
|
||||||
|
this.iterator.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String convert(MongoPersistentProperty property) {
|
||||||
|
|
||||||
|
String mappedName = PropertyToFieldNameConverter.INSTANCE.convert(property);
|
||||||
|
return iterator.hasNext() && iterator.next().equals("$") ? String.format("%s.$", mappedName) : mappedName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* Spring Data MongoDB specific converter infrastructure.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.mongodb.core.convert;
|
||||||
|
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value object to create custom {@link Metric}s on the fly.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public class CustomMetric implements Metric {
|
||||||
|
|
||||||
|
private final double multiplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a custom {@link Metric} using the given multiplier.
|
||||||
|
*
|
||||||
|
* @param multiplier
|
||||||
|
*/
|
||||||
|
public CustomMetric(double multiplier) {
|
||||||
|
this.multiplier = multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.geo.Metric#getMultiplier()
|
||||||
|
*/
|
||||||
|
public double getMultiplier() {
|
||||||
|
return multiplier;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -131,7 +131,7 @@ public class GeoResults<T> implements Iterable<GeoResult<T>> {
|
|||||||
private static Distance calculateAverageDistance(List<? extends GeoResult<?>> results, Metric metric) {
|
private static Distance calculateAverageDistance(List<? extends GeoResult<?>> results, Metric metric) {
|
||||||
|
|
||||||
if (results.isEmpty()) {
|
if (results.isEmpty()) {
|
||||||
return new Distance(0, null);
|
return new Distance(0, metric);
|
||||||
}
|
}
|
||||||
|
|
||||||
double averageDistance = 0;
|
double averageDistance = 0;
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* Support for MongoDB geo-spatial queries.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.mongodb.core.geo;
|
||||||
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -13,9 +13,9 @@
|
|||||||
* 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.index;
|
package org.springframework.data.mongodb.core.index;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.ElementType;
|
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;
|
||||||
@@ -24,14 +24,31 @@ import java.lang.annotation.Target;
|
|||||||
/**
|
/**
|
||||||
* Mark a class to use compound indexes.
|
* Mark a class to use compound indexes.
|
||||||
*
|
*
|
||||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
* @author Jon Brisbin
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @author Philipp Schneider
|
||||||
|
* @author Johno Crawford
|
||||||
*/
|
*/
|
||||||
@Target({ ElementType.TYPE })
|
@Target({ ElementType.TYPE })
|
||||||
|
@Documented
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface CompoundIndex {
|
public @interface CompoundIndex {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual index definition in JSON format. The keys of the JSON document are the fields to be indexed, the values
|
||||||
|
* define the index direction (1 for ascending, -1 for descending).
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
String def();
|
String def();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It does not actually make sense to use that attribute as the direction has to be defined in the {@link #def()}
|
||||||
|
* attribute actually.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
IndexDirection direction() default IndexDirection.ASCENDING;
|
IndexDirection direction() default IndexDirection.ASCENDING;
|
||||||
|
|
||||||
boolean unique() default false;
|
boolean unique() default false;
|
||||||
@@ -40,8 +57,34 @@ public @interface CompoundIndex {
|
|||||||
|
|
||||||
boolean dropDups() default false;
|
boolean dropDups() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the index to be created.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
String name() default "";
|
String name() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The collection the index will be created in. Will default to the collection the annotated domain class will be
|
||||||
|
* stored in.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
String collection() default "";
|
String collection() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If {@literal true} the index will be created in the background.
|
||||||
|
*
|
||||||
|
* @see http://docs.mongodb.org/manual/core/indexes/#background-construction
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean background() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the number of seconds after which the collection should expire. Defaults to -1 for no expiry.
|
||||||
|
*
|
||||||
|
* @see http://docs.mongodb.org/manual/tutorial/expire-data/
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int expireAfterSeconds() default -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2011 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,18 +18,20 @@ package org.springframework.data.mongodb.core.index;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
import org.springframework.data.mongodb.core.query.Order;
|
import org.springframework.data.mongodb.core.query.Order;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class Index implements IndexDefinition {
|
public class Index implements IndexDefinition {
|
||||||
|
|
||||||
public enum Duplicates {
|
public enum Duplicates {
|
||||||
RETAIN, DROP
|
RETAIN, DROP
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<String, Order> fieldSpec = new LinkedHashMap<String, Order>();
|
private final Map<String, Direction> fieldSpec = new LinkedHashMap<String, Direction>();
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@@ -42,12 +44,37 @@ public class Index implements IndexDefinition {
|
|||||||
public Index() {
|
public Index() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Index(String key, Order order) {
|
public Index(String key, Direction direction) {
|
||||||
fieldSpec.put(key, order);
|
fieldSpec.put(key, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Indexed} on the given key and {@link Order}.
|
||||||
|
*
|
||||||
|
* @deprecated use {@link #Index(String, Direction)} instead.
|
||||||
|
* @param key must not be {@literal null} or empty.
|
||||||
|
* @param order must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public Index(String key, Order order) {
|
||||||
|
this(key, order.toDirection());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given field to the index.
|
||||||
|
*
|
||||||
|
* @deprecated use {@link #on(String, Direction)} instead.
|
||||||
|
* @param key must not be {@literal null} or empty.
|
||||||
|
* @param order must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public Index on(String key, Order order) {
|
public Index on(String key, Order order) {
|
||||||
fieldSpec.put(key, order);
|
return on(key, order.toDirection());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Index on(String key, Direction direction) {
|
||||||
|
fieldSpec.put(key, direction);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +103,7 @@ public class Index implements IndexDefinition {
|
|||||||
public DBObject getIndexKeys() {
|
public DBObject getIndexKeys() {
|
||||||
DBObject dbo = new BasicDBObject();
|
DBObject dbo = new BasicDBObject();
|
||||||
for (String k : fieldSpec.keySet()) {
|
for (String k : fieldSpec.keySet()) {
|
||||||
dbo.put(k, (fieldSpec.get(k).equals(Order.ASCENDING) ? 1 : -1));
|
dbo.put(k, fieldSpec.get(k).equals(Direction.ASC) ? 1 : -1);
|
||||||
}
|
}
|
||||||
return dbo;
|
return dbo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012 the original author or authors.
|
* Copyright 2012-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,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core.index;
|
package org.springframework.data.mongodb.core.index;
|
||||||
|
|
||||||
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
import org.springframework.data.mongodb.core.query.Order;
|
import org.springframework.data.mongodb.core.query.Order;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
@@ -24,30 +25,38 @@ import org.springframework.util.ObjectUtils;
|
|||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public final class IndexField {
|
public final class IndexField {
|
||||||
|
|
||||||
private final String key;
|
private final String key;
|
||||||
private final Order order;
|
private final Direction direction;
|
||||||
private final boolean isGeo;
|
private final boolean isGeo;
|
||||||
|
|
||||||
private IndexField(String key, Order order, boolean isGeo) {
|
private IndexField(String key, Direction direction, boolean isGeo) {
|
||||||
|
|
||||||
Assert.hasText(key);
|
Assert.hasText(key);
|
||||||
Assert.isTrue(order != null ^ isGeo);
|
Assert.isTrue(direction != null ^ isGeo);
|
||||||
|
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.order = order;
|
this.direction = direction;
|
||||||
this.isGeo = isGeo;
|
this.isGeo = isGeo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a default {@link IndexField} with the given key and {@link Order}.
|
* Creates a default {@link IndexField} with the given key and {@link Order}.
|
||||||
*
|
*
|
||||||
|
* @deprecated use {@link #create(String, Direction)}.
|
||||||
* @param key must not be {@literal null} or emtpy.
|
* @param key must not be {@literal null} or emtpy.
|
||||||
* @param order must not be {@literal null}.
|
* @param direction must not be {@literal null}.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static IndexField create(String key, Order order) {
|
public static IndexField create(String key, Order order) {
|
||||||
|
Assert.notNull(order);
|
||||||
|
return new IndexField(key, order.toDirection(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IndexField create(String key, Direction order) {
|
||||||
Assert.notNull(order);
|
Assert.notNull(order);
|
||||||
return new IndexField(key, order, false);
|
return new IndexField(key, order, false);
|
||||||
}
|
}
|
||||||
@@ -70,12 +79,23 @@ public final class IndexField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the order of the {@link IndexField} or {@literal null} in case we have a geo index field.
|
* Returns the direction of the {@link IndexField} or {@literal null} in case we have a geo index field.
|
||||||
*
|
*
|
||||||
* @return the order
|
* @deprecated use {@link #getDirection()} instead.
|
||||||
|
* @return the direction
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public Order getOrder() {
|
public Order getOrder() {
|
||||||
return order;
|
return Direction.ASC.equals(direction) ? Order.ASCENDING : Order.DESCENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the direction of the {@link IndexField} or {@literal null} in case we have a geo index field.
|
||||||
|
*
|
||||||
|
* @return the direction
|
||||||
|
*/
|
||||||
|
public Direction getDirection() {
|
||||||
|
return direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,7 +124,8 @@ public final class IndexField {
|
|||||||
|
|
||||||
IndexField that = (IndexField) obj;
|
IndexField that = (IndexField) obj;
|
||||||
|
|
||||||
return this.key.equals(that.key) && ObjectUtils.nullSafeEquals(this.order, that.order) && this.isGeo == that.isGeo;
|
return this.key.equals(that.key) && ObjectUtils.nullSafeEquals(this.direction, that.direction)
|
||||||
|
&& this.isGeo == that.isGeo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -116,7 +137,7 @@ public final class IndexField {
|
|||||||
|
|
||||||
int result = 17;
|
int result = 17;
|
||||||
result += 31 * ObjectUtils.nullSafeHashCode(key);
|
result += 31 * ObjectUtils.nullSafeHashCode(key);
|
||||||
result += 31 * ObjectUtils.nullSafeHashCode(order);
|
result += 31 * ObjectUtils.nullSafeHashCode(direction);
|
||||||
result += 31 * ObjectUtils.nullSafeHashCode(isGeo);
|
result += 31 * ObjectUtils.nullSafeHashCode(isGeo);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -127,6 +148,6 @@ public final class IndexField {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("IndexField [ key: %s, order: %s, isGeo: %s]", key, order, isGeo);
|
return String.format("IndexField [ key: %s, direction: %s, isGeo: %s]", key, direction, isGeo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -13,7 +13,6 @@
|
|||||||
* 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.index;
|
package org.springframework.data.mongodb.core.index;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
@@ -24,7 +23,10 @@ import java.lang.annotation.Target;
|
|||||||
/**
|
/**
|
||||||
* Mark a field to be indexed using MongoDB's indexing feature.
|
* Mark a field to be indexed using MongoDB's indexing feature.
|
||||||
*
|
*
|
||||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
* @author Jon Brisbin
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @author Philipp Schneider
|
||||||
|
* @author Johno Crawford
|
||||||
*/
|
*/
|
||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.FIELD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@@ -41,4 +43,20 @@ public @interface Indexed {
|
|||||||
String name() default "";
|
String name() default "";
|
||||||
|
|
||||||
String collection() default "";
|
String collection() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If {@literal true} the index will be created in the background.
|
||||||
|
*
|
||||||
|
* @see http://docs.mongodb.org/manual/core/indexes/#background-construction
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean background() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the number of seconds after which the collection should expire. Defaults to -1 for no expiry.
|
||||||
|
*
|
||||||
|
* @see http://docs.mongodb.org/manual/tutorial/expire-data/
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int expireAfterSeconds() default -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -13,37 +13,51 @@
|
|||||||
* 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.index;
|
package org.springframework.data.mongodb.core.index;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationEvent;
|
import org.springframework.context.ApplicationEvent;
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.data.mapping.event.MappingContextEvent;
|
import org.springframework.data.mapping.context.MappingContextEvent;
|
||||||
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
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.AfterLoadEvent;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of ApplicationEventPublisher that will only fire MappingContextEvents for use by the index creator
|
* An implementation of ApplicationEventPublisher that will only fire {@link MappingContextEvent}s for use by the index
|
||||||
* when MongoTemplate is used 'stand-alone', that is not declared inside a Spring ApplicationContext.
|
* creator when MongoTemplate is used 'stand-alone', that is not declared inside a Spring {@link ApplicationContext}.
|
||||||
|
* Declare {@link MongoTemplate} inside an {@link ApplicationContext} to enable the publishing of all persistence events
|
||||||
|
* such as {@link AfterLoadEvent}, {@link AfterSaveEvent}, etc.
|
||||||
*
|
*
|
||||||
* Declare MongoTemplate inside an ApplicationContext to enable the publishing of all persistence events such as
|
* @author Jon Brisbin
|
||||||
* {@link AfterLoadEvent}, {@link AfterSaveEvent}, etc.
|
* @author Oliver Gierke
|
||||||
*
|
|
||||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
|
||||||
*/
|
*/
|
||||||
public class MongoMappingEventPublisher implements ApplicationEventPublisher {
|
public class MongoMappingEventPublisher implements ApplicationEventPublisher {
|
||||||
|
|
||||||
private MongoPersistentEntityIndexCreator indexCreator;
|
private final MongoPersistentEntityIndexCreator indexCreator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link MongoMappingEventPublisher} for the given {@link MongoPersistentEntityIndexCreator}.
|
||||||
|
*
|
||||||
|
* @param indexCreator must not be {@literal null}.
|
||||||
|
*/
|
||||||
public MongoMappingEventPublisher(MongoPersistentEntityIndexCreator indexCreator) {
|
public MongoMappingEventPublisher(MongoPersistentEntityIndexCreator indexCreator) {
|
||||||
|
|
||||||
|
Assert.notNull(indexCreator);
|
||||||
this.indexCreator = indexCreator;
|
this.indexCreator = indexCreator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.context.ApplicationEventPublisher#publishEvent(org.springframework.context.ApplicationEvent)
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void publishEvent(ApplicationEvent event) {
|
public void publishEvent(ApplicationEvent event) {
|
||||||
if (event instanceof MappingContextEvent) {
|
if (event instanceof MappingContextEvent) {
|
||||||
indexCreator
|
indexCreator.onApplicationEvent((MappingContextEvent<MongoPersistentEntity<?>, MongoPersistentProperty>) event);
|
||||||
.onApplicationEvent((MappingContextEvent<MongoPersistentEntity<MongoPersistentProperty>, MongoPersistentProperty>) event);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -13,7 +13,6 @@
|
|||||||
* 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.index;
|
package org.springframework.data.mongodb.core.index;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@@ -25,9 +24,9 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.data.mapping.PersistentEntity;
|
import org.springframework.data.mapping.PersistentEntity;
|
||||||
import org.springframework.data.mapping.PropertyHandler;
|
import org.springframework.data.mapping.PropertyHandler;
|
||||||
import org.springframework.data.mapping.event.MappingContextEvent;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
|
import org.springframework.data.mapping.context.MappingContextEvent;
|
||||||
import org.springframework.data.mongodb.MongoDbFactory;
|
import org.springframework.data.mongodb.MongoDbFactory;
|
||||||
import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity;
|
|
||||||
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;
|
||||||
@@ -39,32 +38,37 @@ import com.mongodb.DBObject;
|
|||||||
import com.mongodb.util.JSON;
|
import com.mongodb.util.JSON;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that inspects {@link BasicMongoPersistentEntity} instances contained in the given
|
* Component that inspects {@link MongoPersistentEntity} instances contained in the given {@link MongoMappingContext}
|
||||||
* {@link MongoMappingContext} for indexing metadata and ensures the indexes to be available.
|
* for indexing metadata and ensures the indexes to be available.
|
||||||
*
|
*
|
||||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
* @author Jon Brisbin
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Philipp Schneider
|
||||||
|
* @author Johno Crawford
|
||||||
*/
|
*/
|
||||||
public class MongoPersistentEntityIndexCreator implements
|
public class MongoPersistentEntityIndexCreator implements
|
||||||
ApplicationListener<MappingContextEvent<MongoPersistentEntity<MongoPersistentProperty>, MongoPersistentProperty>> {
|
ApplicationListener<MappingContextEvent<MongoPersistentEntity<?>, MongoPersistentProperty>> {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(MongoPersistentEntityIndexCreator.class);
|
private static final Logger log = LoggerFactory.getLogger(MongoPersistentEntityIndexCreator.class);
|
||||||
|
|
||||||
private final Map<Class<?>, Boolean> classesSeen = new ConcurrentHashMap<Class<?>, Boolean>();
|
private final Map<Class<?>, Boolean> classesSeen = new ConcurrentHashMap<Class<?>, Boolean>();
|
||||||
private final MongoDbFactory mongoDbFactory;
|
private final MongoDbFactory mongoDbFactory;
|
||||||
|
private final MongoMappingContext mappingContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creats a new {@link MongoPersistentEntityIndexCreator} for the given {@link MongoMappingContext} and
|
* Creats a new {@link MongoPersistentEntityIndexCreator} for the given {@link MongoMappingContext} and
|
||||||
* {@link MongoDbFactory}.
|
* {@link MongoDbFactory}.
|
||||||
*
|
*
|
||||||
* @param mappingContext must not be {@@iteral null}
|
* @param mappingContext must not be {@literal null}
|
||||||
* @param mongoDbFactory must not be {@@iteral null}
|
* @param mongoDbFactory must not be {@literal null}
|
||||||
*/
|
*/
|
||||||
public MongoPersistentEntityIndexCreator(MongoMappingContext mappingContext, MongoDbFactory mongoDbFactory) {
|
public MongoPersistentEntityIndexCreator(MongoMappingContext mappingContext, MongoDbFactory mongoDbFactory) {
|
||||||
|
|
||||||
Assert.notNull(mongoDbFactory);
|
Assert.notNull(mongoDbFactory);
|
||||||
Assert.notNull(mappingContext);
|
Assert.notNull(mappingContext);
|
||||||
|
|
||||||
this.mongoDbFactory = mongoDbFactory;
|
this.mongoDbFactory = mongoDbFactory;
|
||||||
|
this.mappingContext = mappingContext;
|
||||||
|
|
||||||
for (MongoPersistentEntity<?> entity : mappingContext.getPersistentEntities()) {
|
for (MongoPersistentEntity<?> entity : mappingContext.getPersistentEntities()) {
|
||||||
checkForIndexes(entity);
|
checkForIndexes(entity);
|
||||||
@@ -75,8 +79,11 @@ public class MongoPersistentEntityIndexCreator implements
|
|||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||||
*/
|
*/
|
||||||
public void onApplicationEvent(
|
public void onApplicationEvent(MappingContextEvent<MongoPersistentEntity<?>, MongoPersistentProperty> event) {
|
||||||
MappingContextEvent<MongoPersistentEntity<MongoPersistentProperty>, MongoPersistentProperty> event) {
|
|
||||||
|
if (!event.wasEmittedBy(mappingContext)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PersistentEntity<?, ?> entity = event.getPersistentEntity();
|
PersistentEntity<?, ?> entity = event.getPersistentEntity();
|
||||||
|
|
||||||
@@ -97,12 +104,13 @@ public class MongoPersistentEntityIndexCreator implements
|
|||||||
if (type.isAnnotationPresent(CompoundIndexes.class)) {
|
if (type.isAnnotationPresent(CompoundIndexes.class)) {
|
||||||
CompoundIndexes indexes = type.getAnnotation(CompoundIndexes.class);
|
CompoundIndexes indexes = type.getAnnotation(CompoundIndexes.class);
|
||||||
for (CompoundIndex index : indexes.value()) {
|
for (CompoundIndex index : indexes.value()) {
|
||||||
String indexColl = index.collection();
|
|
||||||
if ("".equals(indexColl)) {
|
String indexColl = StringUtils.hasText(index.collection()) ? index.collection() : entity.getCollection();
|
||||||
indexColl = entity.getCollection();
|
DBObject definition = (DBObject) JSON.parse(index.def());
|
||||||
}
|
|
||||||
ensureIndex(indexColl, index.name(), index.def(), index.direction(), index.unique(), index.dropDups(),
|
ensureIndex(indexColl, index.name(), definition, index.unique(), index.dropDups(), index.sparse(),
|
||||||
index.sparse());
|
index.background(), index.expireAfterSeconds());
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Created compound index " + index);
|
log.debug("Created compound index " + index);
|
||||||
}
|
}
|
||||||
@@ -111,10 +119,14 @@ public class MongoPersistentEntityIndexCreator implements
|
|||||||
|
|
||||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||||
public void doWithPersistentProperty(MongoPersistentProperty persistentProperty) {
|
public void doWithPersistentProperty(MongoPersistentProperty persistentProperty) {
|
||||||
|
|
||||||
Field field = persistentProperty.getField();
|
Field field = persistentProperty.getField();
|
||||||
|
|
||||||
if (field.isAnnotationPresent(Indexed.class)) {
|
if (field.isAnnotationPresent(Indexed.class)) {
|
||||||
|
|
||||||
Indexed index = field.getAnnotation(Indexed.class);
|
Indexed index = field.getAnnotation(Indexed.class);
|
||||||
String name = index.name();
|
String name = index.name();
|
||||||
|
|
||||||
if (!StringUtils.hasText(name)) {
|
if (!StringUtils.hasText(name)) {
|
||||||
name = persistentProperty.getFieldName();
|
name = persistentProperty.getFieldName();
|
||||||
} else {
|
} else {
|
||||||
@@ -126,11 +138,18 @@ public class MongoPersistentEntityIndexCreator implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String collection = StringUtils.hasText(index.collection()) ? index.collection() : entity.getCollection();
|
String collection = StringUtils.hasText(index.collection()) ? index.collection() : entity.getCollection();
|
||||||
ensureIndex(collection, name, null, index.direction(), index.unique(), index.dropDups(), index.sparse());
|
int direction = index.direction() == IndexDirection.ASCENDING ? 1 : -1;
|
||||||
|
DBObject definition = new BasicDBObject(persistentProperty.getFieldName(), direction);
|
||||||
|
|
||||||
|
ensureIndex(collection, name, definition, index.unique(), index.dropDups(), index.sparse(),
|
||||||
|
index.background(), index.expireAfterSeconds());
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Created property index " + index);
|
log.debug("Created property index " + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (field.isAnnotationPresent(GeoSpatialIndexed.class)) {
|
} else if (field.isAnnotationPresent(GeoSpatialIndexed.class)) {
|
||||||
|
|
||||||
GeoSpatialIndexed index = field.getAnnotation(GeoSpatialIndexed.class);
|
GeoSpatialIndexed index = field.getAnnotation(GeoSpatialIndexed.class);
|
||||||
@@ -155,21 +174,42 @@ public class MongoPersistentEntityIndexCreator implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void ensureIndex(String collection, final String name, final String def, final IndexDirection direction,
|
/**
|
||||||
final boolean unique, final boolean dropDups, final boolean sparse) {
|
* Returns whether the current index creator was registered for the given {@link MappingContext}.
|
||||||
DBObject defObj;
|
*
|
||||||
if (null != def) {
|
* @param context
|
||||||
defObj = (DBObject) JSON.parse(def);
|
* @return
|
||||||
} else {
|
*/
|
||||||
defObj = new BasicDBObject();
|
public boolean isIndexCreatorFor(MappingContext<?, ?> context) {
|
||||||
defObj.put(name, (direction == IndexDirection.ASCENDING ? 1 : -1));
|
return this.mappingContext.equals(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers the actual index creation.
|
||||||
|
*
|
||||||
|
* @param collection the collection to create the index in
|
||||||
|
* @param name the name of the index about to be created
|
||||||
|
* @param indexDefinition the index definition
|
||||||
|
* @param unique whether it shall be a unique index
|
||||||
|
* @param dropDups whether to drop duplicates
|
||||||
|
* @param sparse sparse or not
|
||||||
|
* @param background whether the index will be created in the background
|
||||||
|
* @param expireAfterSeconds the time to live for documents in the collection
|
||||||
|
*/
|
||||||
|
protected void ensureIndex(String collection, String name, DBObject indexDefinition, boolean unique,
|
||||||
|
boolean dropDups, boolean sparse, boolean background, int expireAfterSeconds) {
|
||||||
|
|
||||||
DBObject opts = new BasicDBObject();
|
DBObject opts = new BasicDBObject();
|
||||||
opts.put("name", name);
|
opts.put("name", name);
|
||||||
opts.put("dropDups", dropDups);
|
opts.put("dropDups", dropDups);
|
||||||
opts.put("sparse", sparse);
|
opts.put("sparse", sparse);
|
||||||
opts.put("unique", unique);
|
opts.put("unique", unique);
|
||||||
mongoDbFactory.getDb().getCollection(collection).ensureIndex(defObj, opts);
|
opts.put("background", background);
|
||||||
}
|
|
||||||
|
|
||||||
|
if (expireAfterSeconds != -1) {
|
||||||
|
opts.put("expireAfterSeconds", expireAfterSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
mongoDbFactory.getDb().getCollection(collection).ensureIndex(indexDefinition, opts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* Support for MongoDB document indexing.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.mongodb.core.index;
|
||||||
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -13,36 +13,45 @@
|
|||||||
* 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;
|
package org.springframework.data.mongodb.core.mapping;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
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.context.expression.BeanFactoryAccessor;
|
import org.springframework.context.expression.BeanFactoryAccessor;
|
||||||
import org.springframework.context.expression.BeanFactoryResolver;
|
import org.springframework.context.expression.BeanFactoryResolver;
|
||||||
import org.springframework.data.mapping.PersistentEntity;
|
import org.springframework.data.annotation.Id;
|
||||||
|
import org.springframework.data.mapping.Association;
|
||||||
|
import org.springframework.data.mapping.AssociationHandler;
|
||||||
|
import org.springframework.data.mapping.PropertyHandler;
|
||||||
import org.springframework.data.mapping.model.BasicPersistentEntity;
|
import org.springframework.data.mapping.model.BasicPersistentEntity;
|
||||||
|
import org.springframework.data.mapping.model.MappingException;
|
||||||
import org.springframework.data.mongodb.MongoCollectionUtils;
|
import org.springframework.data.mongodb.MongoCollectionUtils;
|
||||||
import org.springframework.data.util.TypeInformation;
|
import org.springframework.data.util.TypeInformation;
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
import org.springframework.expression.ParserContext;
|
import org.springframework.expression.ParserContext;
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mongo specific {@link PersistentEntity} implementation that adds Mongo specific meta-data such as the collection name
|
* MongoDB specific {@link MongoPersistentEntity} implementation that adds Mongo specific meta-data such as the
|
||||||
* and the like.
|
* collection name and the like.
|
||||||
*
|
*
|
||||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
* @author Jon Brisbin
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Thomas Darimont
|
||||||
*/
|
*/
|
||||||
public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements
|
public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements
|
||||||
MongoPersistentEntity<T>, ApplicationContextAware {
|
MongoPersistentEntity<T>, ApplicationContextAware {
|
||||||
|
|
||||||
|
private static final String AMBIGUOUS_FIELD_MAPPING = "Ambiguous field mapping detected! Both %s and %s map to the same field name %s! Disambiguate using @DocumentField annotation!";
|
||||||
private final String collection;
|
private final String collection;
|
||||||
private final SpelExpressionParser parser;
|
private final SpelExpressionParser parser;
|
||||||
private final StandardEvaluationContext context;
|
private final StandardEvaluationContext context;
|
||||||
@@ -76,22 +85,34 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
|||||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||||
*/
|
*/
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
|
||||||
context.addPropertyAccessor(new BeanFactoryAccessor());
|
context.addPropertyAccessor(new BeanFactoryAccessor());
|
||||||
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||||
context.setRootObject(applicationContext);
|
context.setRootObject(applicationContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Returns the collection the entity should be stored in.
|
* (non-Javadoc)
|
||||||
*
|
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#getCollection()
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public String getCollection() {
|
public String getCollection() {
|
||||||
|
|
||||||
Expression expression = parser.parseExpression(collection, ParserContext.TEMPLATE_EXPRESSION);
|
Expression expression = parser.parseExpression(collection, ParserContext.TEMPLATE_EXPRESSION);
|
||||||
return expression.getValue(context, String.class);
|
return expression.getValue(context, String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mapping.model.BasicPersistentEntity#verify()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void verify() {
|
||||||
|
|
||||||
|
AssertFieldNameUniquenessHandler handler = new AssertFieldNameUniquenessHandler();
|
||||||
|
|
||||||
|
doWithProperties(handler);
|
||||||
|
doWithAssociations(handler);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Comparator} implementation inspecting the {@link MongoPersistentProperty}'s order.
|
* {@link Comparator} implementation inspecting the {@link MongoPersistentProperty}'s order.
|
||||||
*
|
*
|
||||||
@@ -118,4 +139,91 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
|||||||
return o1.getFieldOrder() - o2.getFieldOrder();
|
return o1.getFieldOrder() - o2.getFieldOrder();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As a general note: An implicit id property has a name that matches "id" or "_id". An explicit id property is one
|
||||||
|
* that is annotated with @see {@link Id}. The property id is updated according to the following rules: 1) An id
|
||||||
|
* property which is defined explicitly takes precedence over an implicitly defined id property. 2) In case of any
|
||||||
|
* ambiguity a @see {@link MappingException} is thrown.
|
||||||
|
*
|
||||||
|
* @param property - the new id property candidate
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected MongoPersistentProperty returnPropertyIfBetterIdPropertyCandidateOrNull(MongoPersistentProperty property) {
|
||||||
|
|
||||||
|
Assert.notNull(property);
|
||||||
|
|
||||||
|
if (!property.isIdProperty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MongoPersistentProperty currentIdProperty = getIdProperty();
|
||||||
|
|
||||||
|
boolean currentIdPropertyIsSet = currentIdProperty != null;
|
||||||
|
@SuppressWarnings("null")
|
||||||
|
boolean currentIdPropertyIsExplicit = currentIdPropertyIsSet ? currentIdProperty.isExplicitIdProperty() : false;
|
||||||
|
boolean newIdPropertyIsExplicit = property.isExplicitIdProperty();
|
||||||
|
|
||||||
|
if (!currentIdPropertyIsSet) {
|
||||||
|
return property;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("null")
|
||||||
|
Field currentIdPropertyField = currentIdProperty.getField();
|
||||||
|
|
||||||
|
if (newIdPropertyIsExplicit && currentIdPropertyIsExplicit) {
|
||||||
|
throw new MappingException(String.format(
|
||||||
|
"Attempt to add explicit id property %s but already have an property %s registered "
|
||||||
|
+ "as explicit id. Check your mapping configuration!", property.getField(), currentIdPropertyField));
|
||||||
|
|
||||||
|
} else if (newIdPropertyIsExplicit && !currentIdPropertyIsExplicit) {
|
||||||
|
// explicit id property takes precedence over implicit id property
|
||||||
|
return property;
|
||||||
|
|
||||||
|
} else if (!newIdPropertyIsExplicit && currentIdPropertyIsExplicit) {
|
||||||
|
// no id property override - current property is explicitly defined
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new MappingException(String.format(
|
||||||
|
"Attempt to add id property %s but already have an property %s registered "
|
||||||
|
+ "as id. Check your mapping configuration!", property.getField(), currentIdPropertyField));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler to collect {@link MongoPersistentProperty} instances and check that each of them is mapped to a distinct
|
||||||
|
* field name.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
private static class AssertFieldNameUniquenessHandler implements PropertyHandler<MongoPersistentProperty>,
|
||||||
|
AssociationHandler<MongoPersistentProperty> {
|
||||||
|
|
||||||
|
private final Map<String, MongoPersistentProperty> properties = new HashMap<String, MongoPersistentProperty>();
|
||||||
|
|
||||||
|
public void doWithPersistentProperty(MongoPersistentProperty persistentProperty) {
|
||||||
|
assertUniqueness(persistentProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
||||||
|
assertUniqueness(association.getInverse());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertUniqueness(MongoPersistentProperty property) {
|
||||||
|
|
||||||
|
String fieldName = property.getFieldName();
|
||||||
|
MongoPersistentProperty existingProperty = properties.get(fieldName);
|
||||||
|
|
||||||
|
if (existingProperty != null) {
|
||||||
|
throw new MappingException(String.format(AMBIGUOUS_FIELD_MAPPING, property.toString(),
|
||||||
|
existingProperty.toString(), fieldName));
|
||||||
|
}
|
||||||
|
|
||||||
|
properties.put(fieldName, property);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -24,17 +24,22 @@ import java.util.Set;
|
|||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.data.annotation.Id;
|
||||||
import org.springframework.data.mapping.Association;
|
import org.springframework.data.mapping.Association;
|
||||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||||
|
import org.springframework.data.mapping.model.MappingException;
|
||||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mongo specific {@link org.springframework.data.mapping.PersistentProperty} implementation.
|
* MongoDB specific {@link org.springframework.data.mapping.MongoPersistentProperty} implementation.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Patryk Wasik
|
||||||
|
* @author Thomas Darimont
|
||||||
*/
|
*/
|
||||||
public class BasicMongoPersistentProperty extends AnnotationBasedPersistentProperty<MongoPersistentProperty> implements
|
public class BasicMongoPersistentProperty extends AnnotationBasedPersistentProperty<MongoPersistentProperty> implements
|
||||||
MongoPersistentProperty {
|
MongoPersistentProperty {
|
||||||
@@ -45,6 +50,8 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
|||||||
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<Class<?>>();
|
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<Class<?>>();
|
||||||
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<String>();
|
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<String>();
|
||||||
|
|
||||||
|
private static final Field CAUSE_FIELD;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
SUPPORTED_ID_TYPES.add(ObjectId.class);
|
SUPPORTED_ID_TYPES.add(ObjectId.class);
|
||||||
SUPPORTED_ID_TYPES.add(String.class);
|
SUPPORTED_ID_TYPES.add(String.class);
|
||||||
@@ -52,8 +59,12 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
|||||||
|
|
||||||
SUPPORTED_ID_PROPERTY_NAMES.add("id");
|
SUPPORTED_ID_PROPERTY_NAMES.add("id");
|
||||||
SUPPORTED_ID_PROPERTY_NAMES.add("_id");
|
SUPPORTED_ID_PROPERTY_NAMES.add("_id");
|
||||||
|
|
||||||
|
CAUSE_FIELD = ReflectionUtils.findField(Throwable.class, "cause");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final FieldNamingStrategy fieldNamingStrategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link BasicMongoPersistentProperty}.
|
* Creates a new {@link BasicMongoPersistentProperty}.
|
||||||
*
|
*
|
||||||
@@ -61,10 +72,14 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
|||||||
* @param propertyDescriptor
|
* @param propertyDescriptor
|
||||||
* @param owner
|
* @param owner
|
||||||
* @param simpleTypeHolder
|
* @param simpleTypeHolder
|
||||||
|
* @param fieldNamingStrategy
|
||||||
*/
|
*/
|
||||||
public BasicMongoPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
|
public BasicMongoPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
|
||||||
MongoPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
MongoPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder, FieldNamingStrategy fieldNamingStrategy) {
|
||||||
|
|
||||||
super(field, propertyDescriptor, owner, simpleTypeHolder);
|
super(field, propertyDescriptor, owner, simpleTypeHolder);
|
||||||
|
this.fieldNamingStrategy = fieldNamingStrategy == null ? PropertyNameFieldNamingStrategy.INSTANCE
|
||||||
|
: fieldNamingStrategy;
|
||||||
|
|
||||||
if (isIdProperty() && getFieldName() != ID_FIELD_NAME) {
|
if (isIdProperty() && getFieldName() != ID_FIELD_NAME) {
|
||||||
LOG.warn("Customizing field name for id property not allowed! Custom name will not be considered!");
|
LOG.warn("Customizing field name for id property not allowed! Custom name will not be considered!");
|
||||||
@@ -87,6 +102,7 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isIdProperty() {
|
public boolean isIdProperty() {
|
||||||
|
|
||||||
if (super.isIdProperty()) {
|
if (super.isIdProperty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -95,6 +111,15 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
|||||||
return SUPPORTED_ID_PROPERTY_NAMES.contains(field.getName());
|
return SUPPORTED_ID_PROPERTY_NAMES.contains(field.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isExplicitIdProperty()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isExplicitIdProperty() {
|
||||||
|
return isAnnotationPresent(Id.class);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the key to be used to store the value of the property inside a Mongo {@link DBObject}.
|
* Returns the key to be used to store the value of the property inside a Mongo {@link DBObject}.
|
||||||
*
|
*
|
||||||
@@ -103,16 +128,39 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
|||||||
public String getFieldName() {
|
public String getFieldName() {
|
||||||
|
|
||||||
if (isIdProperty()) {
|
if (isIdProperty()) {
|
||||||
return ID_FIELD_NAME;
|
|
||||||
|
if (owner == null) {
|
||||||
|
return ID_FIELD_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (owner.getIdProperty() == null) {
|
||||||
|
return ID_FIELD_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (owner.isIdProperty(this)) {
|
||||||
|
return ID_FIELD_NAME;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
org.springframework.data.mongodb.core.mapping.Field annotation = getField().getAnnotation(
|
org.springframework.data.mongodb.core.mapping.Field annotation = findAnnotation(org.springframework.data.mongodb.core.mapping.Field.class);
|
||||||
org.springframework.data.mongodb.core.mapping.Field.class);
|
|
||||||
return annotation != null && StringUtils.hasText(annotation.value()) ? annotation.value() : field.getName();
|
if (annotation != null && StringUtils.hasText(annotation.value())) {
|
||||||
|
return annotation.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
String fieldName = fieldNamingStrategy.getFieldName(this);
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(fieldName)) {
|
||||||
|
throw new MappingException(String.format("Invalid (null or empty) field name returned for property %s by %s!",
|
||||||
|
this, fieldNamingStrategy.getClass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return fieldName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/*
|
||||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentProperty#getFieldOrder()
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#getFieldOrder()
|
||||||
*/
|
*/
|
||||||
public int getFieldOrder() {
|
public int getFieldOrder() {
|
||||||
org.springframework.data.mongodb.core.mapping.Field annotation = getField().getAnnotation(
|
org.springframework.data.mongodb.core.mapping.Field annotation = getField().getAnnotation(
|
||||||
@@ -120,25 +168,36 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
|||||||
return annotation != null ? annotation.order() : Integer.MAX_VALUE;
|
return annotation != null ? annotation.order() : Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/*
|
||||||
* @see org.springframework.data.mapping.AbstractPersistentProperty#createAssociation()
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mapping.model.AbstractPersistentProperty#createAssociation()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Association<MongoPersistentProperty> createAssociation() {
|
protected Association<MongoPersistentProperty> createAssociation() {
|
||||||
return new Association<MongoPersistentProperty>(this, null);
|
return new Association<MongoPersistentProperty>(this, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/*
|
||||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentProperty#isDbReference()
|
* (non-Javadoc)
|
||||||
*/
|
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isDbReference()
|
||||||
|
*/
|
||||||
public boolean isDbReference() {
|
public boolean isDbReference() {
|
||||||
return getField().isAnnotationPresent(DBRef.class);
|
return getField().isAnnotationPresent(DBRef.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/*
|
||||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentProperty#getDBRef()
|
* (non-Javadoc)
|
||||||
*/
|
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#getDBRef()
|
||||||
|
*/
|
||||||
public DBRef getDBRef() {
|
public DBRef getDBRef() {
|
||||||
return getField().getAnnotation(DBRef.class);
|
return getField().getAnnotation(DBRef.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess()
|
||||||
|
*/
|
||||||
|
public boolean usePropertyAccess() {
|
||||||
|
return CAUSE_FIELD.equals(getField());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -38,10 +38,11 @@ public class CachingMongoPersistentProperty extends BasicMongoPersistentProperty
|
|||||||
* @param propertyDescriptor
|
* @param propertyDescriptor
|
||||||
* @param owner
|
* @param owner
|
||||||
* @param simpleTypeHolder
|
* @param simpleTypeHolder
|
||||||
|
* @param fieldNamingStrategy
|
||||||
*/
|
*/
|
||||||
public CachingMongoPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
|
public CachingMongoPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
|
||||||
MongoPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
MongoPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder, FieldNamingStrategy fieldNamingStrategy) {
|
||||||
super(field, propertyDescriptor, owner, simpleTypeHolder);
|
super(field, propertyDescriptor, owner, simpleTypeHolder, fieldNamingStrategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link FieldNamingStrategy} that abbreviates field names by using the very first letter of the camel case parts of
|
||||||
|
* the {@link MongoPersistentProperty}'s name.
|
||||||
|
*
|
||||||
|
* @since 1.3
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public class CamelCaseAbbreviatingFieldNamingStrategy implements FieldNamingStrategy {
|
||||||
|
|
||||||
|
private static final String CAMEL_CASE_PATTERN = "(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z])";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.mapping.FieldNamingStrategy#getFieldName(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty)
|
||||||
|
*/
|
||||||
|
public String getFieldName(MongoPersistentProperty property) {
|
||||||
|
|
||||||
|
String[] parts = property.getName().split(CAMEL_CASE_PATTERN);
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
for (String part : parts) {
|
||||||
|
builder.append(part.substring(0, 1).toLowerCase(Locale.US));
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SPI interface to determine how to name document fields in cases the field name is not manually defined.
|
||||||
|
*
|
||||||
|
* @see DocumentField
|
||||||
|
* @see PropertyNameFieldNamingStrategy
|
||||||
|
* @see CamelCaseAbbreviatingFieldNamingStrategy
|
||||||
|
* @since 1.3
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public interface FieldNamingStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the field name to be used for the given {@link MongoPersistentProperty}.
|
||||||
|
*
|
||||||
|
* @param property must not be {@literal null} or empty;
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String getFieldName(MongoPersistentProperty property);
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -13,26 +13,33 @@
|
|||||||
* 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;
|
package org.springframework.data.mongodb.core.mapping;
|
||||||
|
|
||||||
import java.beans.PropertyDescriptor;
|
import java.beans.PropertyDescriptor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.AbstractMap;
|
||||||
|
|
||||||
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.data.mapping.context.AbstractMappingContext;
|
import org.springframework.data.mapping.context.AbstractMappingContext;
|
||||||
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||||
import org.springframework.data.util.TypeInformation;
|
import org.springframework.data.util.TypeInformation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
* Default implementation of a {@link MappingContext} for MongoDB using {@link BasicMongoPersistentEntity} and
|
||||||
* @author Oliver Gierke ogierke@vmware.com
|
* {@link BasicMongoPersistentProperty} as primary abstractions.
|
||||||
|
*
|
||||||
|
* @author Jon Brisbin
|
||||||
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersistentEntity<?>, MongoPersistentProperty>
|
public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersistentEntity<?>, MongoPersistentProperty>
|
||||||
implements ApplicationContextAware {
|
implements ApplicationContextAware {
|
||||||
|
|
||||||
|
private static final FieldNamingStrategy DEFAULT_NAMING_STRATEGY = PropertyNameFieldNamingStrategy.INSTANCE;
|
||||||
|
|
||||||
|
private FieldNamingStrategy fieldNamingStrategy = DEFAULT_NAMING_STRATEGY;
|
||||||
private ApplicationContext context;
|
private ApplicationContext context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +49,26 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
|
|||||||
setSimpleTypeHolder(MongoSimpleTypes.HOLDER);
|
setSimpleTypeHolder(MongoSimpleTypes.HOLDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the {@link FieldNamingStrategy} to be used to determine the field name if no manual mapping is applied.
|
||||||
|
* Defaults to a strategy using the plain property name.
|
||||||
|
*
|
||||||
|
* @param fieldNamingStrategy the {@link FieldNamingStrategy} to be used to determine the field name if no manual
|
||||||
|
* mapping is applied.
|
||||||
|
*/
|
||||||
|
public void setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
|
||||||
|
this.fieldNamingStrategy = fieldNamingStrategy == null ? DEFAULT_NAMING_STRATEGY : fieldNamingStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mapping.context.AbstractMappingContext#shouldCreatePersistentEntityFor(org.springframework.data.util.TypeInformation)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean shouldCreatePersistentEntityFor(TypeInformation<?> type) {
|
||||||
|
return !MongoSimpleTypes.HOLDER.isSimpleType(type.getType()) && !AbstractMap.class.isAssignableFrom(type.getType());
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.mapping.AbstractMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.mapping.MutablePersistentEntity, org.springframework.data.mapping.SimpleTypeHolder)
|
* @see org.springframework.data.mapping.AbstractMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.mapping.MutablePersistentEntity, org.springframework.data.mapping.SimpleTypeHolder)
|
||||||
@@ -49,7 +76,7 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
|
|||||||
@Override
|
@Override
|
||||||
public MongoPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
public MongoPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
||||||
BasicMongoPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
BasicMongoPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||||
return new CachingMongoPersistentProperty(field, descriptor, owner, simpleTypeHolder);
|
return new CachingMongoPersistentProperty(field, descriptor, owner, simpleTypeHolder, fieldNamingStrategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -72,6 +99,7 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
|
|||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
this.context = applicationContext;
|
this.context = applicationContext;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* 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 org.springframework.data.mapping.PersistentEntity;
|
import org.springframework.data.mapping.PersistentEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* MongoDB specific {@link PersistentEntity} abstraction.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public interface MongoPersistentEntity<T> extends PersistentEntity<T, MongoPersistentProperty> {
|
public interface MongoPersistentEntity<T> extends PersistentEntity<T, MongoPersistentProperty> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the collection the entity shall be persisted to.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
String getCollection();
|
String getCollection();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 by the original author(s).
|
* 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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -16,12 +16,16 @@
|
|||||||
package org.springframework.data.mongodb.core.mapping;
|
package org.springframework.data.mongodb.core.mapping;
|
||||||
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.data.annotation.Id;
|
||||||
|
import org.springframework.data.mapping.PersistentEntity;
|
||||||
import org.springframework.data.mapping.PersistentProperty;
|
import org.springframework.data.mapping.PersistentProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mongo specific {@link org.springframework.data.mapping.PersistentProperty} implementation.
|
* MongoDB specific {@link org.springframework.data.mapping.PersistentProperty} extension.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Patryk Wasik
|
||||||
|
* @author Thomas Darimont
|
||||||
*/
|
*/
|
||||||
public interface MongoPersistentProperty extends PersistentProperty<MongoPersistentProperty> {
|
public interface MongoPersistentProperty extends PersistentProperty<MongoPersistentProperty> {
|
||||||
|
|
||||||
@@ -47,6 +51,14 @@ public interface MongoPersistentProperty extends PersistentProperty<MongoPersist
|
|||||||
*/
|
*/
|
||||||
boolean isDbReference();
|
boolean isDbReference();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the property is explicitly marked as an identifier property of the owning {@link PersistentEntity}.
|
||||||
|
* A property is an explicit id property if it is annotated with @see {@link Id}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean isExplicitIdProperty();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link DBRef} if the property is a reference.
|
* Returns the {@link DBRef} if the property is a reference.
|
||||||
*
|
*
|
||||||
@@ -72,4 +84,12 @@ public interface MongoPersistentProperty extends PersistentProperty<MongoPersist
|
|||||||
return source.getFieldName();
|
return source.getFieldName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether property access shall be used for reading the property value. This means it will use the getter
|
||||||
|
* instead of field access.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean usePropertyAccess();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link FieldNamingStrategy} simply using the {@link MongoPersistentProperty}'s name.
|
||||||
|
*
|
||||||
|
* @since 1.3
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public enum PropertyNameFieldNamingStrategy implements FieldNamingStrategy {
|
||||||
|
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.mongodb.core.mapping.FieldNamingStrategy#getFieldName(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty)
|
||||||
|
*/
|
||||||
|
public String getFieldName(MongoPersistentProperty property) {
|
||||||
|
return property.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2011 by the original author(s).
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.data.mapping.Association;
|
|
||||||
import org.springframework.data.mapping.context.AbstractMappingContext;
|
|
||||||
import org.springframework.data.mapping.model.AbstractPersistentProperty;
|
|
||||||
import org.springframework.data.mapping.model.BasicPersistentEntity;
|
|
||||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
|
||||||
import org.springframework.data.mongodb.MongoCollectionUtils;
|
|
||||||
import org.springframework.data.util.TypeInformation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
public class SimpleMongoMappingContext extends
|
|
||||||
AbstractMappingContext<SimpleMongoMappingContext.SimpleMongoPersistentEntity<?>, MongoPersistentProperty> {
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected <T> SimpleMongoPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
|
|
||||||
return new SimpleMongoPersistentEntity<T>(typeInformation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.util.TypeInformation, org.springframework.data.mapping.BasicPersistentEntity)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected SimplePersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
|
||||||
SimpleMongoPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
|
||||||
return new SimplePersistentProperty(field, descriptor, owner, simpleTypeHolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
static class SimplePersistentProperty extends AbstractPersistentProperty<MongoPersistentProperty> implements
|
|
||||||
MongoPersistentProperty {
|
|
||||||
|
|
||||||
private static final List<String> ID_FIELD_NAMES = Arrays.asList("id", "_id");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link SimplePersistentProperty}.
|
|
||||||
*
|
|
||||||
* @param field
|
|
||||||
* @param propertyDescriptor
|
|
||||||
* @param information
|
|
||||||
*/
|
|
||||||
public SimplePersistentProperty(Field field, PropertyDescriptor propertyDescriptor, MongoPersistentEntity<?> owner,
|
|
||||||
SimpleTypeHolder simpleTypeHolder) {
|
|
||||||
super(field, propertyDescriptor, owner, simpleTypeHolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mapping.BasicPersistentProperty#isIdProperty()
|
|
||||||
*/
|
|
||||||
public boolean isIdProperty() {
|
|
||||||
return ID_FIELD_NAMES.contains(field.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentProperty#getKey()
|
|
||||||
*/
|
|
||||||
public String getFieldName() {
|
|
||||||
return isIdProperty() ? "_id" : getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentProperty#getFieldOrder()
|
|
||||||
*/
|
|
||||||
public int getFieldOrder() {
|
|
||||||
return Integer.MAX_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mapping.AbstractPersistentProperty#createAssociation()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Association<MongoPersistentProperty> createAssociation() {
|
|
||||||
return new Association<MongoPersistentProperty>(this, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentProperty#isDbReference()
|
|
||||||
*/
|
|
||||||
public boolean isDbReference() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentProperty#getDBRef()
|
|
||||||
*/
|
|
||||||
public DBRef getDBRef() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class SimpleMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements
|
|
||||||
MongoPersistentEntity<T> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param information
|
|
||||||
*/
|
|
||||||
public SimpleMongoPersistentEntity(TypeInformation<T> information) {
|
|
||||||
super(information);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentEntity#getCollection()
|
|
||||||
*/
|
|
||||||
public String getCollection() {
|
|
||||||
return MongoCollectionUtils.getPreferredCollectionName(getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user