Compare commits
216 Commits
1.0.0.M4-M
...
1.0.x
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ca16f8d15 | ||
|
|
1b3d49e466 | ||
|
|
bf89cce43c | ||
|
|
aef493fdb8 | ||
|
|
eabd47ae8d | ||
|
|
1d9ee9a28f | ||
|
|
e0b0792643 | ||
|
|
d5f8285d51 | ||
|
|
4ce8da7ebf | ||
|
|
c1030abe96 | ||
|
|
2a8f13d5d5 | ||
|
|
e4adc0ce23 | ||
|
|
beeed68873 | ||
|
|
22872f97dc | ||
|
|
323de58efc | ||
|
|
58f12b8d8f | ||
|
|
48cb155f6c | ||
|
|
594ddbd1c1 | ||
|
|
2c2bbf415b | ||
|
|
9375e7b981 | ||
|
|
30a4682369 | ||
|
|
356e6acd43 | ||
|
|
09ed4aaf24 | ||
|
|
c7995eb462 | ||
|
|
2e6a9a6ee7 | ||
|
|
a82fbade95 | ||
|
|
7a9ba3fe3e | ||
|
|
134e7762a7 | ||
|
|
e41299ff38 | ||
|
|
5cf7a86023 | ||
|
|
0aacb887de | ||
|
|
ba81f21aba | ||
|
|
43dee69fe0 | ||
|
|
1be1297ef9 | ||
|
|
dad0789356 | ||
|
|
80ee7d9553 | ||
|
|
7e3dfa5504 | ||
|
|
b5b11772b6 | ||
|
|
416dc563f2 | ||
|
|
a41b877081 | ||
|
|
c4c8e368ca | ||
|
|
11f0c515b0 | ||
|
|
25a94bc45e | ||
|
|
783cec0325 | ||
|
|
b02e81c481 | ||
|
|
3c90b4987d | ||
|
|
a4a03b0164 | ||
|
|
651255ca58 | ||
|
|
ccf006e41b | ||
|
|
cb6a1b7110 | ||
|
|
ba5a764f5d | ||
|
|
3be35cba2d | ||
|
|
9421c45c5a | ||
|
|
885c1b0f2c | ||
|
|
c8bb46ffb3 | ||
|
|
f82de367c8 | ||
|
|
5e62675bae | ||
|
|
c805d9ccae | ||
|
|
2d97288917 | ||
|
|
e38448a569 | ||
|
|
b1065b8f2d | ||
|
|
8cac1d9368 | ||
|
|
7184950f8a | ||
|
|
edd71cac78 | ||
|
|
82bd7a69eb | ||
|
|
b434a0810e | ||
|
|
40236d4099 | ||
|
|
8f6d940036 | ||
|
|
95a92ccf5d | ||
|
|
a6db24554f | ||
|
|
2f6c61ef9c | ||
|
|
d8bf7ebf3f | ||
|
|
ce42783e73 | ||
|
|
69474327c6 | ||
|
|
1bbe2e8247 | ||
|
|
94af898ae3 | ||
|
|
f6298f7005 | ||
|
|
d5b3c651b2 | ||
|
|
33dd00f0b8 | ||
|
|
3207a81555 | ||
|
|
d231519012 | ||
|
|
e052ecc9a4 | ||
|
|
071f2934a1 | ||
|
|
d2a18e9b11 | ||
|
|
d684fa1f8e | ||
|
|
1a0077231d | ||
|
|
9cd33763b6 | ||
|
|
de8d2a1c74 | ||
|
|
9f940cd2b6 | ||
|
|
0d69baa32c | ||
|
|
433e5a660e | ||
|
|
ee33ce1571 | ||
|
|
9ac11e967a | ||
|
|
a89a0ac542 | ||
|
|
0ad0dad124 | ||
|
|
8f2771416e | ||
|
|
7af009cc7f | ||
|
|
35ad949c18 | ||
|
|
8206b5f950 | ||
|
|
170081137a | ||
|
|
6862bd8a45 | ||
|
|
490db7c39f | ||
|
|
f3979c3676 | ||
|
|
8d18729898 | ||
|
|
b5e0b2bec2 | ||
|
|
9eb47827c1 | ||
|
|
f97ab25411 | ||
|
|
6616761f50 | ||
|
|
89de566893 | ||
|
|
ea1f090b40 | ||
|
|
b5958fb5cc | ||
|
|
75b7aff80a | ||
|
|
7da0fcdd0c | ||
|
|
c88b6d89db | ||
|
|
de1540aadc | ||
|
|
d1b24d6cfb | ||
|
|
e85f3d3299 | ||
|
|
ef6e08d3f4 | ||
|
|
21010fbd49 | ||
|
|
4325d6c9fa | ||
|
|
bc16ccfded | ||
|
|
04f5f9f662 | ||
|
|
b1f1b8efaa | ||
|
|
de300e2643 | ||
|
|
20088b83d9 | ||
|
|
58f200f15e | ||
|
|
8718700249 | ||
|
|
f4063d1679 | ||
|
|
ef063613c7 | ||
|
|
2eda0f1701 | ||
|
|
ec7b65e21d | ||
|
|
c7f7571f3f | ||
|
|
9f71af42e8 | ||
|
|
92775170e1 | ||
|
|
4c7e338770 | ||
|
|
e3fff52d17 | ||
|
|
5477ab20b2 | ||
|
|
4cf3567f42 | ||
|
|
b26bb62a63 | ||
|
|
f156d7b5af | ||
|
|
7bf3643902 | ||
|
|
201ae3e92d | ||
|
|
07556ec58c | ||
|
|
39807b17e1 | ||
|
|
4913fe26ac | ||
|
|
7642a719ff | ||
|
|
6c1ce576a4 | ||
|
|
c99882201d | ||
|
|
ce6a64e4a9 | ||
|
|
2fcc323bcd | ||
|
|
17c7b1d2b5 | ||
|
|
cfefe46cd4 | ||
|
|
64921ddad1 | ||
|
|
edda1764fe | ||
|
|
8113b79109 | ||
|
|
9fde4dff3e | ||
|
|
d4b3e2b99d | ||
|
|
68a31d75f3 | ||
|
|
3e15c21419 | ||
|
|
e9f253d34f | ||
|
|
80aa057acb | ||
|
|
613b183b70 | ||
|
|
5d1320a82a | ||
|
|
8ccaf61d12 | ||
|
|
2c46cfd8fe | ||
|
|
45f2900d15 | ||
|
|
79934538b6 | ||
|
|
0e4e0094a5 | ||
|
|
5df61563f4 | ||
|
|
04ebec993d | ||
|
|
caa245dd08 | ||
|
|
717ff38319 | ||
|
|
33155ba0f4 | ||
|
|
9f62efa47c | ||
|
|
620fc876f4 | ||
|
|
cfcf839232 | ||
|
|
7ce1e5fbd3 | ||
|
|
2d12ba38f8 | ||
|
|
1554d489ca | ||
|
|
f030d304f4 | ||
|
|
105e1da82b | ||
|
|
dbc7601d7b | ||
|
|
ccf981b8fb | ||
|
|
8a43b4bbc0 | ||
|
|
1c2c592b96 | ||
|
|
cd4b409bf2 | ||
|
|
f71477f17d | ||
|
|
454df1e7f1 | ||
|
|
80641a0943 | ||
|
|
e405bf574c | ||
|
|
9f8e406aff | ||
|
|
7d26366352 | ||
|
|
864ae831dd | ||
|
|
bfb13d99e3 | ||
|
|
f39de4c28e | ||
|
|
3bdeb68617 | ||
|
|
6b40a27c92 | ||
|
|
237cbec945 | ||
|
|
39bc6771b7 | ||
|
|
73b2d5a99c | ||
|
|
5dab0c721e | ||
|
|
bf7c9663cf | ||
|
|
135742b7e4 | ||
|
|
dee0307055 | ||
|
|
06fb4144e0 | ||
|
|
5fdc600570 | ||
|
|
f54c69b6ef | ||
|
|
decdcff79f | ||
|
|
be8daa5268 | ||
|
|
c4cd074d4d | ||
|
|
8b7521a93b | ||
|
|
ba508f497c | ||
|
|
091246a9aa | ||
|
|
745e1f313d | ||
|
|
234e04f4a3 | ||
|
|
15ab529596 |
86
pom.xml
86
pom.xml
@@ -1,21 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-document-dist</artifactId>
|
||||
<name>Spring Data Document Distribution</name>
|
||||
<version>1.0.0.M4</version>
|
||||
<artifactId>spring-data-mongodb-dist</artifactId>
|
||||
<name>Spring Data MongoDB Distribution</name>
|
||||
<description>Spring Data project for MongoDB</description>
|
||||
<url>http://www.springsource.org/spring-data/mongodb</url>
|
||||
<version>1.0.5.BUILD-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>spring-data-document-parent</module>
|
||||
<module>spring-data-mongodb</module>
|
||||
<module>spring-data-mongodb-cross-store</module>
|
||||
<module>spring-data-mongodb-log4j</module>
|
||||
<!-- <module>spring-data-couchdb</module> -->
|
||||
<module>spring-data-mongodb-parent</module>
|
||||
</modules>
|
||||
|
||||
<developers>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>ogierke</id>
|
||||
<name>Oliver Gierke</name>
|
||||
<email>ogierke at vmware.com</email>
|
||||
<organization>SpringSource</organization>
|
||||
<organizationUrl>http://www.springsource.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Project lead</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>trisberg</id>
|
||||
<name>Thomas Risberg</name>
|
||||
@@ -40,17 +51,6 @@
|
||||
</roles>
|
||||
<timezone>-5</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>ogierke</id>
|
||||
<name>Oliver Gierke</name>
|
||||
<email>ogierke at vmware.com</email>
|
||||
<organization>SpringSource</organization>
|
||||
<organizationUrl>http://www.springsource.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>jbrisbin</id>
|
||||
<name>Jon Brisbin</name>
|
||||
@@ -90,7 +90,7 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<!-- dist.* properties are used by the antrun tasks below -->
|
||||
<dist.id>spring-data-document</dist.id>
|
||||
<dist.id>spring-data-mongo</dist.id>
|
||||
<dist.name>Spring Data Mongo</dist.name>
|
||||
<dist.key>SDMONGO</dist.key>
|
||||
<dist.version>${project.version}</dist.version>
|
||||
@@ -146,37 +146,35 @@
|
||||
<htmlCustomization>${project.basedir}/src/docbkx/resources/xsl/html.xsl</htmlCustomization>
|
||||
<useExtensions>1</useExtensions>
|
||||
<highlightSource>1</highlightSource>
|
||||
<highlightDefaultLanguage></highlightDefaultLanguage>
|
||||
<highlightDefaultLanguage />
|
||||
<!-- callouts -->
|
||||
<entities>
|
||||
<entity>
|
||||
<name>version</name>
|
||||
<value>${pom.version}</value>
|
||||
<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"/>
|
||||
<include name="**/*.html" />
|
||||
<include name="**/*.pdf" />
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy todir="${project.basedir}/target/site/reference/html">
|
||||
<fileset dir="${project.basedir}/src/docbkx/resources">
|
||||
<include name="**/*.css"/>
|
||||
<include name="**/*.png"/>
|
||||
<include name="**/*.gif"/>
|
||||
<include name="**/*.jpg"/>
|
||||
<include name="**/*.css" />
|
||||
<include name="**/*.png" />
|
||||
<include name="**/*.gif" />
|
||||
<include name="**/*.jpg" />
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy todir="${project.basedir}/target/site/reference/html">
|
||||
<fileset dir="${project.basedir}/src/docbkx/resources/images">
|
||||
<include name="*.png"/>
|
||||
<include name="*.png" />
|
||||
</fileset>
|
||||
</copy>
|
||||
<move file="${project.basedir}/target/site/reference/pdf/index.pdf"
|
||||
tofile="${project.basedir}/target/site/reference/pdf/spring-data-document-reference.pdf"
|
||||
failonerror="false"/>
|
||||
<move file="${project.basedir}/target/site/reference/pdf/index.pdf" tofile="${project.basedir}/target/site/reference/pdf/spring-data-mongo-reference.pdf" failonerror="false" />
|
||||
</postProcess>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@@ -185,7 +183,7 @@
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<javadoc:aggregate>true</javadoc:aggregate>
|
||||
<aggregate>true</aggregate>
|
||||
<breakiterator>true</breakiterator>
|
||||
<header>Spring Data Document</header>
|
||||
<source>1.5</source>
|
||||
@@ -235,7 +233,7 @@
|
||||
<configuration>
|
||||
<tasks>
|
||||
<ant antfile="${basedir}/src/ant/upload-dist.xml">
|
||||
<target name="upload-dist"/>
|
||||
<target name="upload-dist" />
|
||||
</ant>
|
||||
</tasks>
|
||||
</configuration>
|
||||
@@ -258,8 +256,8 @@
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<!-- the name of this project is 'spring-data-document-dist';
|
||||
make sure the zip file is just 'spring-data-document'. -->
|
||||
<!-- 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>
|
||||
|
||||
@@ -271,9 +269,9 @@
|
||||
<url>http://repository.springsource.com/maven/bundles/release</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>repository.springframework.maven.release</id>
|
||||
<id>spring-libs-release</id>
|
||||
<name>Spring Framework Maven Release Repository</name>
|
||||
<url>http://maven.springframework.org/release</url>
|
||||
<url>http://repo.springsource.org/libs-release</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
@@ -283,13 +281,13 @@
|
||||
<site>
|
||||
<id>static.springframework.org</id>
|
||||
<url>
|
||||
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-document/snapshot-site/
|
||||
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>
|
||||
<id>spring-release</id>
|
||||
<name>Spring Release Repository</name>
|
||||
<url>s3://maven.springframework.org/release</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>spring-snapshot</id>
|
||||
@@ -297,5 +295,7 @@
|
||||
<url>s3://maven.springframework.org/snapshot</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
<scm>
|
||||
<url>https://github.com/SpringSource/spring-data-mongodb</url>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
<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-document-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../spring-data-document-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-couchdb</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Spring Data CouchDB Support</name>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>tareq.abedrabbo</id>
|
||||
<name>Tareq Abedrabbo</name>
|
||||
<email>tareq.abedrabbo@opencredo.com</email>
|
||||
<organization>OpenCredo</organization>
|
||||
<organizationUrl>http://www.opencredo.org</organizationUrl>
|
||||
<roles>
|
||||
<role>Project Admin</role>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+0</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>tomas.lukosius</id>
|
||||
<name>Tomas Lukosius</name>
|
||||
<email>tomas.lukosius@opencredo.com</email>
|
||||
<organization>OpenCredo</organization>
|
||||
<organizationUrl>http://www.opencredo.org</organizationUrl>
|
||||
<roles>
|
||||
<role>Project Admin</role>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+0</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Data -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-commons-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Dependencies for web analytics functionality - to me moved into spring framework -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson JSON -->
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-core-asl</artifactId>
|
||||
<version>1.6.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
<version>1.6.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-all</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Couch DB -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.jcouchdb</groupId>
|
||||
<artifactId>jcouchdb</artifactId>
|
||||
<version>0.11.0-1</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.springsource.bundlor</groupId>
|
||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.web.client.HttpServerErrorException;
|
||||
|
||||
public class CouchServerResourceUsageException extends InvalidDataAccessResourceUsageException {
|
||||
|
||||
/**
|
||||
* Create a new CouchServerResourceUsageException,
|
||||
* wrapping an arbitrary HttpServerErrorException.
|
||||
*
|
||||
* @param cause the HttpServerErrorException thrown
|
||||
*/
|
||||
public CouchServerResourceUsageException(HttpServerErrorException cause) {
|
||||
super(cause != null ? cause.getMessage() : null, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
|
||||
public class CouchUsageException extends InvalidDataAccessApiUsageException {
|
||||
|
||||
/**
|
||||
* Create a new CouchUsageException,
|
||||
* wrapping an arbitrary HttpServerErrorException.
|
||||
*
|
||||
* @param cause the HttpServerErrorException thrown
|
||||
*/
|
||||
public CouchUsageException(HttpClientErrorException cause) {
|
||||
super(cause != null ? cause.getMessage() : null, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb;
|
||||
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
|
||||
public class DocumentExistsException extends DataIntegrityViolationException {
|
||||
|
||||
/**
|
||||
* Create a new DocumentExistsException,
|
||||
* wrapping an arbitrary HttpServerErrorException.
|
||||
*
|
||||
* @param cause the HttpServerErrorException thrown
|
||||
*/
|
||||
public DocumentExistsException(String documentId, HttpStatusCodeException cause) {
|
||||
super(cause != null ? cause.getMessage() : null, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb;
|
||||
|
||||
import org.springframework.dao.UncategorizedDataAccessException;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
|
||||
public class UncategorizedCouchDataAccessException extends UncategorizedDataAccessException {
|
||||
|
||||
/**
|
||||
* Create a new HibernateSystemException,
|
||||
* wrapping an arbitrary HibernateException.
|
||||
*
|
||||
* @param cause the HibernateException thrown
|
||||
*/
|
||||
public UncategorizedCouchDataAccessException(RestClientException cause) {
|
||||
super(cause != null ? cause.getMessage() : null, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb.admin;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.document.couchdb.support.CouchUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
public class CouchAdmin implements CouchAdminOperations {
|
||||
|
||||
private String databaseUrl;
|
||||
private RestOperations restOperations = new RestTemplate();
|
||||
|
||||
public CouchAdmin(String databaseUrl) {
|
||||
|
||||
if (!databaseUrl.trim().endsWith("/")) {
|
||||
this.databaseUrl = databaseUrl.trim() + "/";
|
||||
} else {
|
||||
this.databaseUrl = databaseUrl.trim();
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> listDatabases() {
|
||||
String dbs = restOperations.getForObject(databaseUrl + "_all_dbs", String.class);
|
||||
return Arrays.asList(StringUtils.commaDelimitedListToStringArray(dbs));
|
||||
}
|
||||
|
||||
public void createDatabase(String dbName) {
|
||||
org.springframework.util.Assert.hasText(dbName);
|
||||
restOperations.put(databaseUrl + dbName, null);
|
||||
|
||||
}
|
||||
|
||||
public void deleteDatabase(String dbName) {
|
||||
org.springframework.util.Assert.hasText(dbName);
|
||||
restOperations.delete(CouchUtils.ensureTrailingSlash(databaseUrl + dbName));
|
||||
|
||||
}
|
||||
|
||||
public DbInfo getDatabaseInfo(String dbName) {
|
||||
String url = CouchUtils.ensureTrailingSlash(databaseUrl + dbName);
|
||||
Map dbInfoMap = (Map) restOperations.getForObject(url, Map.class);
|
||||
return new DbInfo(dbInfoMap);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb.admin;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CouchAdminOperations {
|
||||
|
||||
|
||||
// functionality for /_special - replication, logs, UUIDs
|
||||
|
||||
List<String> listDatabases();
|
||||
|
||||
void createDatabase(String name);
|
||||
|
||||
void deleteDatabase(String name);
|
||||
|
||||
DbInfo getDatabaseInfo(String name);
|
||||
|
||||
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.couchdb.admin;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class DbInfo {
|
||||
|
||||
private Map dbInfoMap;
|
||||
|
||||
public DbInfo(Map dbInfoMap) {
|
||||
super();
|
||||
this.dbInfoMap = dbInfoMap;
|
||||
}
|
||||
|
||||
public boolean isCompactRunning() {
|
||||
return (Boolean) this.dbInfoMap.get("compact_running");
|
||||
}
|
||||
|
||||
public String getDbName() {
|
||||
return (String) this.dbInfoMap.get("db_name");
|
||||
}
|
||||
|
||||
public long getDiskFormatVersion() {
|
||||
return (Long) this.dbInfoMap.get("disk_format_version");
|
||||
}
|
||||
|
||||
public long getDiskSize() {
|
||||
return (Long) this.dbInfoMap.get("disk_size");
|
||||
}
|
||||
|
||||
public long getDocCount() {
|
||||
return (Long) this.dbInfoMap.get("doc_count");
|
||||
}
|
||||
|
||||
public long getDocDeleteCount() {
|
||||
return (Long) this.dbInfoMap.get("doc_del_count");
|
||||
}
|
||||
|
||||
public long getInstanceStartTime() {
|
||||
return (Long) this.dbInfoMap.get("instance_start_time");
|
||||
}
|
||||
|
||||
public long getPurgeSequence() {
|
||||
return (Long) this.dbInfoMap.get("purge_seq");
|
||||
}
|
||||
|
||||
public long getUpdateSequence() {
|
||||
return (Long) this.dbInfoMap.get("update_seq");
|
||||
}
|
||||
|
||||
public Map getDbInfoMap() {
|
||||
return Collections.unmodifiableMap(dbInfoMap);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.document.couchdb.monitor.ServerInfo;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
public class CouchJmxParser implements BeanDefinitionParser {
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
String databaseUrl = element.getAttribute("database-url");
|
||||
if (!StringUtils.hasText(databaseUrl)) {
|
||||
databaseUrl = "http://localhost:5984";
|
||||
}
|
||||
registerJmxComponents(databaseUrl, element, parserContext);
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void registerJmxComponents(String databaseUrl, Element element, ParserContext parserContext) {
|
||||
Object eleSource = parserContext.extractSource(element);
|
||||
|
||||
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
|
||||
|
||||
/*
|
||||
createBeanDefEntry(AssertMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||
createBeanDefEntry(BackgroundFlushingMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||
createBeanDefEntry(BtreeIndexCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||
createBeanDefEntry(ConnectionMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||
createBeanDefEntry(GlobalLockMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||
createBeanDefEntry(MemoryMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||
createBeanDefEntry(OperationCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||
*/
|
||||
createBeanDefEntry(ServerInfo.class, compositeDef, databaseUrl, eleSource, parserContext);
|
||||
//createBeanDefEntry(MongoAdmin.class, compositeDef, mongoRefName, eleSource, parserContext);
|
||||
|
||||
|
||||
parserContext.registerComponent(compositeDef);
|
||||
|
||||
}
|
||||
|
||||
protected void createBeanDefEntry(Class clazz, CompositeComponentDefinition compositeDef, String databaseUrl, Object eleSource, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
|
||||
builder.getRawBeanDefinition().setSource(eleSource);
|
||||
builder.addConstructorArg(databaseUrl);
|
||||
BeanDefinition assertDef = builder.getBeanDefinition();
|
||||
String assertName = parserContext.getReaderContext().registerWithGeneratedName(assertDef);
|
||||
compositeDef.addNestedComponent(new BeanComponentDefinition(assertDef, assertName));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb.core;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
|
||||
public interface CouchOperations {
|
||||
|
||||
/**
|
||||
* Reads a document from the database and maps it a Java object.
|
||||
* </p>
|
||||
* This method is intended to work when a default database
|
||||
* is set on the CouchDbDocumentOperations instance.
|
||||
*
|
||||
* @param id the id of the CouchDB document to read
|
||||
* @param targetClass the target type to map to
|
||||
* @return the mapped object
|
||||
*/
|
||||
<T> T findOne(String id, Class<T> targetClass);
|
||||
|
||||
/**
|
||||
* Reads a document from the database and maps it a Java object.
|
||||
*
|
||||
* @param uri the full URI of the document to read
|
||||
* @param targetClass the target type to map to
|
||||
* @return the mapped object
|
||||
*/
|
||||
<T> T findOne(URI uri, Class<T> targetClass);
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Java object to JSON and writes it to the database
|
||||
* </p>
|
||||
* This method is intended to work when a default database
|
||||
* is set on the CouchDbDocumentOperations instance.
|
||||
*
|
||||
* @param id the id of the document to write
|
||||
* @param document the object to write
|
||||
*/
|
||||
void save(String id, Object document);
|
||||
|
||||
/**
|
||||
* Maps a Java object to JSON and writes it to the database
|
||||
*
|
||||
* @param uri the full URI of the document to write
|
||||
* @param document the object to write
|
||||
*/
|
||||
void save(URI uri, Object document);
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.couchdb.core;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.data.document.couchdb.CouchServerResourceUsageException;
|
||||
import org.springframework.data.document.couchdb.CouchUsageException;
|
||||
import org.springframework.data.document.couchdb.DocumentRetrievalFailureException;
|
||||
import org.springframework.data.document.couchdb.UncategorizedCouchDataAccessException;
|
||||
import org.springframework.data.document.couchdb.support.CouchUtils;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.client.*;
|
||||
|
||||
|
||||
public class CouchTemplate implements CouchOperations {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private String defaultDocumentUrl;
|
||||
|
||||
private RestOperations restOperations = new RestTemplate();
|
||||
|
||||
/**
|
||||
* Constructs an instance of CouchDbDocumentTemplate with a default database
|
||||
*
|
||||
* @param defaultDatabaseUrl the default database to connect to
|
||||
*/
|
||||
public CouchTemplate(String defaultDatabaseUrl) {
|
||||
Assert.hasText(defaultDatabaseUrl, "defaultDatabaseUrl must not be empty");
|
||||
defaultDocumentUrl = CouchUtils.addId(defaultDatabaseUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of CouchDbDocumentTemplate with a default database
|
||||
*
|
||||
* @param defaultDatabaseUrl the default database to connect to
|
||||
*/
|
||||
public CouchTemplate(String defaultDatabaseUrl, RestOperations restOperations) {
|
||||
this(defaultDatabaseUrl);
|
||||
Assert.notNull(restOperations, "restOperations must not be null");
|
||||
this.restOperations = restOperations;
|
||||
}
|
||||
|
||||
|
||||
public <T> T findOne(String id, Class<T> targetClass) {
|
||||
Assert.state(defaultDocumentUrl != null, "defaultDatabaseUrl must be set to use this method");
|
||||
try {
|
||||
return restOperations.getForObject(defaultDocumentUrl, targetClass, id);
|
||||
//TODO check this exception translation and centralize.
|
||||
} catch (HttpClientErrorException clientError) {
|
||||
if (clientError.getStatusCode() == HttpStatus.NOT_FOUND) {
|
||||
throw new DocumentRetrievalFailureException(defaultDocumentUrl + "/" + id);
|
||||
}
|
||||
throw new CouchUsageException(clientError);
|
||||
} catch (HttpServerErrorException serverError) {
|
||||
throw new CouchServerResourceUsageException(serverError);
|
||||
} catch (RestClientException otherError) {
|
||||
throw new UncategorizedCouchDataAccessException(otherError);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T findOne(URI uri, Class<T> targetClass) {
|
||||
Assert.state(uri != null, "uri must be set to use this method");
|
||||
try {
|
||||
return restOperations.getForObject(uri, targetClass);
|
||||
//TODO check this exception translation and centralize.
|
||||
} catch (HttpClientErrorException clientError) {
|
||||
if (clientError.getStatusCode() == HttpStatus.NOT_FOUND) {
|
||||
throw new DocumentRetrievalFailureException(uri.getPath());
|
||||
}
|
||||
throw new CouchUsageException(clientError);
|
||||
} catch (HttpServerErrorException serverError) {
|
||||
throw new CouchServerResourceUsageException(serverError);
|
||||
} catch (RestClientException otherError) {
|
||||
throw new UncategorizedCouchDataAccessException(otherError);
|
||||
}
|
||||
}
|
||||
|
||||
public void save(String id, Object document) {
|
||||
Assert.notNull(document, "document must not be null for save");
|
||||
HttpEntity<?> httpEntity = createHttpEntity(document);
|
||||
try {
|
||||
ResponseEntity<Map> response = restOperations.exchange(defaultDocumentUrl, HttpMethod.PUT, httpEntity, Map.class, id);
|
||||
//TODO update the document revision id on the object from the returned value
|
||||
//TODO better exception translation
|
||||
} catch (RestClientException e) {
|
||||
throw new UncategorizedCouchDataAccessException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void save(URI uri, Object document) {
|
||||
Assert.notNull(document, "document must not be null for save");
|
||||
Assert.notNull(uri, "URI must not be null for save");
|
||||
HttpEntity<?> httpEntity = createHttpEntity(document);
|
||||
try {
|
||||
ResponseEntity<Map> response = restOperations.exchange(uri, HttpMethod.PUT, httpEntity, Map.class);
|
||||
//TODO update the document revision id on the object from the returned value
|
||||
//TODO better exception translation
|
||||
} catch (RestClientException e) {
|
||||
throw new UncategorizedCouchDataAccessException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private HttpEntity<?> createHttpEntity(Object document) {
|
||||
|
||||
if (document instanceof HttpEntity) {
|
||||
HttpEntity httpEntity = (HttpEntity) document;
|
||||
Assert.isTrue(httpEntity.getHeaders().getContentType().equals(MediaType.APPLICATION_JSON),
|
||||
"HttpEntity payload with non application/json content type found.");
|
||||
return httpEntity;
|
||||
}
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
HttpEntity<Object> httpEntity = new HttpEntity<Object>(document, httpHeaders);
|
||||
|
||||
return httpEntity;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,315 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb.core.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
|
||||
import org.codehaus.jackson.*;
|
||||
import org.codehaus.jackson.map.JsonMappingException;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.type.TypeFactory;
|
||||
import org.codehaus.jackson.type.JavaType;
|
||||
import org.springframework.http.HttpInputMessage;
|
||||
import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.AbstractHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.http.converter.HttpMessageNotWritableException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public class CouchDbMappingJacksonHttpMessageConverter extends
|
||||
AbstractHttpMessageConverter<Object> {
|
||||
|
||||
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
private static final String ROWS_FIELD_NAME = "rows";
|
||||
private static final String VALUE_FIELD_NAME = "value";
|
||||
private static final String INCLUDED_DOC_FIELD_NAME = "doc";
|
||||
private static final String TOTAL_ROWS_FIELD_NAME = "total_rows";
|
||||
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private boolean prefixJson = false;
|
||||
|
||||
/**
|
||||
* Construct a new {@code BindingJacksonHttpMessageConverter}.
|
||||
*/
|
||||
public CouchDbMappingJacksonHttpMessageConverter() {
|
||||
super(new MediaType("application", "json", DEFAULT_CHARSET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code ObjectMapper} for this view. If not set, a default
|
||||
* {@link ObjectMapper#ObjectMapper() ObjectMapper} is used.
|
||||
* <p/>
|
||||
* Setting a custom-configured {@code ObjectMapper} is one way to take
|
||||
* further control of the JSON serialization process. For example, an
|
||||
* extended {@link org.codehaus.jackson.map.SerializerFactory} can be
|
||||
* configured that provides custom serializers for specific types. The other
|
||||
* option for refining the serialization process is to use Jackson's
|
||||
* provided annotations on the types to be serialized, in which case a
|
||||
* custom-configured ObjectMapper is unnecessary.
|
||||
*/
|
||||
public void setObjectMapper(ObjectMapper objectMapper) {
|
||||
Assert.notNull(objectMapper, "'objectMapper' must not be null");
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the JSON output by this view should be prefixed with
|
||||
* "{} &&". Default is false.
|
||||
* <p/>
|
||||
* Prefixing the JSON string in this manner is used to help prevent JSON
|
||||
* Hijacking. The prefix renders the string syntactically invalid as a
|
||||
* script so that it cannot be hijacked. This prefix does not affect the
|
||||
* evaluation of JSON, but if JSON validation is performed on the string,
|
||||
* the prefix would need to be ignored.
|
||||
*/
|
||||
public void setPrefixJson(boolean prefixJson) {
|
||||
this.prefixJson = prefixJson;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRead(Class<?> clazz, MediaType mediaType) {
|
||||
JavaType javaType = getJavaType(clazz);
|
||||
return this.objectMapper.canDeserialize(javaType) && canRead(mediaType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Jackson {@link JavaType} for the specific class.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* Default implementation returns
|
||||
* {@link TypeFactory#type(java.lang.reflect.Type)}, but this can be
|
||||
* overridden in subclasses, to allow for custom generic collection
|
||||
* handling. For instance:
|
||||
* <p/>
|
||||
* <pre class="code">
|
||||
* protected JavaType getJavaType(Class<?> clazz) {
|
||||
* if (List.class.isAssignableFrom(clazz)) {
|
||||
* return TypeFactory.collectionType(ArrayList.class, MyBean.class);
|
||||
* } else {
|
||||
* return super.getJavaType(clazz);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param clazz the class to return the java type for
|
||||
* @return the java type
|
||||
*/
|
||||
protected JavaType getJavaType(Class<?> clazz) {
|
||||
return TypeFactory.type(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
|
||||
return this.objectMapper.canSerialize(clazz) && canWrite(mediaType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supports(Class<?> clazz) {
|
||||
// should not be called, since we override canRead/Write instead
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
|
||||
throws IOException, HttpMessageNotReadableException {
|
||||
JavaType javaType = getJavaType(clazz);
|
||||
try {
|
||||
return success(clazz, inputMessage);
|
||||
|
||||
// return this.objectMapper.readValue(inputMessage.getBody(),
|
||||
// javaType);
|
||||
} catch (Exception ex) {
|
||||
throw new HttpMessageNotReadableException("Could not read JSON: "
|
||||
+ ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Object success(Class<?> clazz, HttpInputMessage inputMessage)
|
||||
throws JsonParseException, IOException {
|
||||
|
||||
//Note, parsing code used from ektorp project
|
||||
JsonParser jp = objectMapper.getJsonFactory().createJsonParser(
|
||||
inputMessage.getBody());
|
||||
if (jp.nextToken() != JsonToken.START_OBJECT) {
|
||||
throw new RuntimeException("Expected data to start with an Object");
|
||||
}
|
||||
Map<String, Integer> fields = readHeaderFields(jp);
|
||||
|
||||
List result;
|
||||
if (fields.containsKey(TOTAL_ROWS_FIELD_NAME)) {
|
||||
int totalRows = fields.get(TOTAL_ROWS_FIELD_NAME);
|
||||
if (totalRows == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
result = new ArrayList(totalRows);
|
||||
} else {
|
||||
result = new ArrayList();
|
||||
}
|
||||
|
||||
ParseState state = new ParseState();
|
||||
|
||||
Object first = parseFirstRow(jp, state, clazz);
|
||||
if (first == null) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
result.add(first);
|
||||
}
|
||||
|
||||
while (jp.getCurrentToken() != null) {
|
||||
skipToField(jp, state.docFieldName, state);
|
||||
if (atEndOfRows(jp)) {
|
||||
return result;
|
||||
}
|
||||
result.add(jp.readValueAs(clazz));
|
||||
endRow(jp, state);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Object parseFirstRow(JsonParser jp, ParseState state, Class clazz)
|
||||
throws JsonParseException, IOException, JsonProcessingException,
|
||||
JsonMappingException {
|
||||
skipToField(jp, VALUE_FIELD_NAME, state);
|
||||
JsonNode value = null;
|
||||
if (atObjectStart(jp)) {
|
||||
value = jp.readValueAsTree();
|
||||
jp.nextToken();
|
||||
if (isEndOfRow(jp)) {
|
||||
state.docFieldName = VALUE_FIELD_NAME;
|
||||
Object doc = objectMapper.readValue(value, clazz);
|
||||
endRow(jp, state);
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
skipToField(jp, INCLUDED_DOC_FIELD_NAME, state);
|
||||
if (atObjectStart(jp)) {
|
||||
state.docFieldName = INCLUDED_DOC_FIELD_NAME;
|
||||
Object doc = jp.readValueAs(clazz);
|
||||
endRow(jp, state);
|
||||
return doc;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private boolean isEndOfRow(JsonParser jp) {
|
||||
return jp.getCurrentToken() == JsonToken.END_OBJECT;
|
||||
}
|
||||
|
||||
private void endRow(JsonParser jp, ParseState state) throws IOException, JsonParseException {
|
||||
state.inRow = false;
|
||||
jp.nextToken();
|
||||
}
|
||||
|
||||
private boolean atObjectStart(JsonParser jp) {
|
||||
return jp.getCurrentToken() == JsonToken.START_OBJECT;
|
||||
}
|
||||
|
||||
private boolean atEndOfRows(JsonParser jp) {
|
||||
return jp.getCurrentToken() != JsonToken.START_OBJECT;
|
||||
}
|
||||
|
||||
private void skipToField(JsonParser jp, String fieldName, ParseState state) throws JsonParseException, IOException {
|
||||
String lastFieldName = null;
|
||||
while (jp.getCurrentToken() != null) {
|
||||
switch (jp.getCurrentToken()) {
|
||||
case FIELD_NAME:
|
||||
lastFieldName = jp.getCurrentName();
|
||||
jp.nextToken();
|
||||
break;
|
||||
case START_OBJECT:
|
||||
if (!state.inRow) {
|
||||
state.inRow = true;
|
||||
jp.nextToken();
|
||||
} else {
|
||||
if (isInField(fieldName, lastFieldName)) {
|
||||
return;
|
||||
} else {
|
||||
jp.skipChildren();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (isInField(fieldName, lastFieldName)) {
|
||||
jp.nextToken();
|
||||
return;
|
||||
}
|
||||
jp.nextToken();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInField(String fieldName, String lastFieldName) {
|
||||
return lastFieldName != null && lastFieldName.equals(fieldName);
|
||||
}
|
||||
|
||||
|
||||
private Map<String, Integer> readHeaderFields(JsonParser jp)
|
||||
throws JsonParseException, IOException {
|
||||
Map<String, Integer> map = new HashMap<String, Integer>();
|
||||
jp.nextToken();
|
||||
String nextFieldName = jp.getCurrentName();
|
||||
while (!nextFieldName.equals(ROWS_FIELD_NAME)) {
|
||||
jp.nextToken();
|
||||
map.put(nextFieldName, Integer.valueOf(jp.getIntValue()));
|
||||
jp.nextToken();
|
||||
nextFieldName = jp.getCurrentName();
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeInternal(Object o, HttpOutputMessage outputMessage)
|
||||
throws IOException, HttpMessageNotWritableException {
|
||||
|
||||
JsonEncoding encoding = getEncoding(outputMessage.getHeaders()
|
||||
.getContentType());
|
||||
JsonGenerator jsonGenerator = this.objectMapper.getJsonFactory()
|
||||
.createJsonGenerator(outputMessage.getBody(), encoding);
|
||||
try {
|
||||
if (this.prefixJson) {
|
||||
jsonGenerator.writeRaw("{} && ");
|
||||
}
|
||||
this.objectMapper.writeValue(jsonGenerator, o);
|
||||
} catch (JsonGenerationException ex) {
|
||||
throw new HttpMessageNotWritableException("Could not write JSON: "
|
||||
+ ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private JsonEncoding getEncoding(MediaType contentType) {
|
||||
if (contentType != null && contentType.getCharSet() != null) {
|
||||
Charset charset = contentType.getCharSet();
|
||||
for (JsonEncoding encoding : JsonEncoding.values()) {
|
||||
if (charset.name().equals(encoding.getJavaName())) {
|
||||
return encoding;
|
||||
}
|
||||
}
|
||||
}
|
||||
return JsonEncoding.UTF8;
|
||||
}
|
||||
|
||||
private static class ParseState {
|
||||
boolean inRow;
|
||||
String docFieldName = "";
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb.monitor;
|
||||
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Base class to encapsulate common configuration settings when connecting to a CouchDB database
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
public abstract class AbstractMonitor {
|
||||
|
||||
|
||||
protected RestTemplate restTemplate;
|
||||
protected String databaseUrl;
|
||||
|
||||
/**
|
||||
* Gets the databaseUrl used to connect to CouchDB
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getDatabaseUrl() {
|
||||
return this.databaseUrl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb.monitor;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Expose basic server information via JMX
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
@ManagedResource(description = "Server Information")
|
||||
public class ServerInfo extends AbstractMonitor {
|
||||
|
||||
|
||||
public ServerInfo(String databaseUrl) {
|
||||
this.databaseUrl = databaseUrl;
|
||||
this.restTemplate = new RestTemplate();
|
||||
}
|
||||
|
||||
|
||||
@ManagedOperation(description = "Server host name")
|
||||
public String getHostName() throws UnknownHostException {
|
||||
return InetAddress.getLocalHost().getHostName();
|
||||
}
|
||||
|
||||
|
||||
@ManagedOperation(description = "CouchDB Server Version")
|
||||
public String getVersion() {
|
||||
return (String) getRoot().get("version");
|
||||
}
|
||||
|
||||
@ManagedOperation(description = "Message of the day")
|
||||
public String getMotd() {
|
||||
return (String) getRoot().get("greeting");
|
||||
}
|
||||
|
||||
public Map getRoot() {
|
||||
Map map = restTemplate.getForObject(getDatabaseUrl(), Map.class);
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* CouchDB specific JMX monitoring support.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb.monitor;
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.couchdb.support;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* Helper class featuring helper methods for internal CouchDB classes.
|
||||
* <p/>
|
||||
* <p>Mainly intended for internal use within the framework.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Tareq Abedrabbo
|
||||
* @since 1.0
|
||||
*/
|
||||
public abstract class CouchUtils {
|
||||
|
||||
/**
|
||||
* Convert the given runtime exception to an appropriate exception from the
|
||||
* <code>org.springframework.dao</code> hierarchy.
|
||||
* Return null if no translation is appropriate: any other exception may
|
||||
* have resulted from user code, and should not be translated.
|
||||
*
|
||||
* @param ex runtime exception that occurred
|
||||
* @return the corresponding DataAccessException instance,
|
||||
* or <code>null</code> if the exception should not be translated
|
||||
*/
|
||||
public static DataAccessException translateCouchExceptionIfPossible(RuntimeException ex) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an id variable to a URL
|
||||
*
|
||||
* @param url the URL to modify
|
||||
* @return the modified URL
|
||||
*/
|
||||
public static String addId(String url) {
|
||||
return ensureTrailingSlash(url) + "{id}";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a 'changes since' variable to a URL
|
||||
*
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public static String addChangesSince(String url) {
|
||||
return ensureTrailingSlash(url) + "_changes?since={seq}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that a URL ends with a slash.
|
||||
*
|
||||
* @param url the URL to modify
|
||||
* @return the modified URL
|
||||
*/
|
||||
public static String ensureTrailingSlash(String url) {
|
||||
if (!url.endsWith("/")) {
|
||||
url += "/";
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
http\://www.springframework.org/schema/data/couch=org.springframework.data.document.couchdb.config.CouchNamespaceHandler
|
||||
@@ -1,2 +0,0 @@
|
||||
http\://www.springframework.org/schema/data/couch/spring-couch-1.0.xsd=org/springframework/data/document/couchdb/config/spring-couch-1.0.xsd
|
||||
http\://www.springframework.org/schema/data/couch/spring-couch.xsd=org/springframework/data/document/couchdb/config/spring-couch-1.0.xsd
|
||||
@@ -1,4 +0,0 @@
|
||||
# Tooling related information for the Couch DB namespace
|
||||
http\://www.springframework.org/schema/data/couch@name=Couch Namespace
|
||||
http\://www.springframework.org/schema/data/couch@prefix=couch
|
||||
http\://www.springframework.org/schema/data/couch@icon=org/springframework/jdbc/config/spring-jdbc.gif
|
||||
@@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/data/couch"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:repository="http://www.springframework.org/schema/data/repository"
|
||||
targetNamespace="http://www.springframework.org/schema/data/couch"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/context"
|
||||
schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/data/repository"
|
||||
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd"/>
|
||||
|
||||
|
||||
<xsd:element name="jmx">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines a JMX Model MBeans for monitoring a CouchDB server'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="database-url" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The database URL of the CouchDB]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:schema>
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.couchdb;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* @author Tareq Abedrabbo (tareq.abedrabbo@opencredo.com)
|
||||
* @since 13/01/2011
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class DummyDocument {
|
||||
|
||||
private String message;
|
||||
|
||||
private String timestamp = new Date().toString();
|
||||
|
||||
public DummyDocument() {
|
||||
}
|
||||
|
||||
public DummyDocument(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
DummyDocument document = (DummyDocument) o;
|
||||
|
||||
if (message != null ? !message.equals(document.message) : document.message != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return message != null ? message.hashCode() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DummyDocument{" +
|
||||
"message='" + message + '\'' +
|
||||
", timestamp=" + timestamp +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.couchdb;
|
||||
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Factory;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
import org.springframework.http.HttpEntity;
|
||||
|
||||
/**
|
||||
* Matches the content of the body of an HttpEntity.
|
||||
*
|
||||
* @author Tareq Abedrabbo
|
||||
* @since 31/01/2011
|
||||
*/
|
||||
public class IsBodyEqual extends TypeSafeMatcher<HttpEntity> {
|
||||
|
||||
private Object object;
|
||||
|
||||
public IsBodyEqual(Object object) {
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesSafely(HttpEntity httpEntity) {
|
||||
return httpEntity.getBody().equals(object);
|
||||
}
|
||||
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("body equals ").appendValue(object);
|
||||
}
|
||||
|
||||
@Factory
|
||||
public static Matcher<HttpEntity> bodyEqual(Object object) {
|
||||
return new IsBodyEqual(object);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb.admin;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.document.couchdb.core.CouchConstants;
|
||||
|
||||
public class CouchAdminIntegrationTests {
|
||||
|
||||
@Test
|
||||
@Ignore("until CI has couch server running")
|
||||
public void dbLifecycle() {
|
||||
|
||||
CouchAdmin admin = new CouchAdmin(CouchConstants.COUCHDB_URL);
|
||||
admin.deleteDatabase("foo");
|
||||
List<String> dbs = admin.listDatabases();
|
||||
admin.createDatabase("foo");
|
||||
List<String> newDbs = admin.listDatabases();
|
||||
Assert.assertEquals(dbs.size() + 1, newDbs.size());
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.couchdb.core;
|
||||
|
||||
import static org.junit.Assume.assumeNoException;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Base class for CouchDB integration tests. Checks whether CouchDB is available before running each test,
|
||||
* in which case the test is executed. If CouchDB is not available, tests are ignored.
|
||||
*
|
||||
* @author Tareq Abedrabbo (tareq.abedrabbo@opencredo.com)
|
||||
* @since 13/01/2011
|
||||
*/
|
||||
|
||||
public abstract class AbstractCouchTemplateIntegrationTests {
|
||||
|
||||
|
||||
protected static final Log log = LogFactory.getLog(AbstractCouchTemplateIntegrationTests.class);
|
||||
|
||||
protected static final RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
/**
|
||||
* This methods ensures that the database is running. Otherwise, the test is ignored.
|
||||
*/
|
||||
@BeforeClass
|
||||
public static void assumeDatabaseIsUpAndRunning() {
|
||||
try {
|
||||
ResponseEntity<String> responseEntity = restTemplate.getForEntity(CouchConstants.COUCHDB_URL, String.class);
|
||||
assumeTrue(responseEntity.getStatusCode().equals(OK));
|
||||
log.debug("CouchDB is running on " + CouchConstants.COUCHDB_URL +
|
||||
" with status " + responseEntity.getStatusCode());
|
||||
} catch (RestClientException e) {
|
||||
log.debug("CouchDB is not running on " + CouchConstants.COUCHDB_URL);
|
||||
assumeNoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUpTestDatabase() throws Exception {
|
||||
RestTemplate template = new RestTemplate();
|
||||
template.setErrorHandler(new DefaultResponseErrorHandler() {
|
||||
@Override
|
||||
public void handleError(ClientHttpResponse response) throws IOException {
|
||||
// do nothing, error status will be handled in the switch statement
|
||||
}
|
||||
});
|
||||
ResponseEntity<String> response = template.getForEntity(CouchConstants.TEST_DATABASE_URL, String.class);
|
||||
HttpStatus statusCode = response.getStatusCode();
|
||||
switch (statusCode) {
|
||||
case NOT_FOUND:
|
||||
createNewTestDatabase();
|
||||
break;
|
||||
case OK:
|
||||
deleteExisitingTestDatabase();
|
||||
createNewTestDatabase();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported http status [" + statusCode + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteExisitingTestDatabase() {
|
||||
restTemplate.delete(CouchConstants.TEST_DATABASE_URL);
|
||||
}
|
||||
|
||||
private void createNewTestDatabase() {
|
||||
restTemplate.put(CouchConstants.TEST_DATABASE_URL, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a CouchDB document and converts it to the expected type.
|
||||
*/
|
||||
protected <T> T getDocument(String id, Class<T> expectedType) {
|
||||
String url = CouchConstants.TEST_DATABASE_URL + "{id}";
|
||||
return restTemplate.getForObject(url, expectedType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a CouchDB document
|
||||
*/
|
||||
protected String putDocument(Object document) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
HttpEntity request = new HttpEntity(document, headers);
|
||||
String id = UUID.randomUUID().toString();
|
||||
restTemplate.put(CouchConstants.TEST_DATABASE_URL + "{id}", request, id);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.document.couchdb.core;
|
||||
|
||||
public abstract class CouchConstants {
|
||||
|
||||
public static final String COUCHDB_URL = "http://127.0.0.1:5984/";
|
||||
public static final String TEST_DATABASE_URL = COUCHDB_URL + "si_couchdb_test/";
|
||||
|
||||
public CouchConstants() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.couchdb.core;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.document.couchdb.DummyDocument;
|
||||
|
||||
public class CouchTemplateIntegrationTests extends AbstractCouchTemplateIntegrationTests {
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore("until CI has couch server running")
|
||||
public void saveAndFindTest() {
|
||||
CouchTemplate template = new CouchTemplate(CouchConstants.TEST_DATABASE_URL);
|
||||
DummyDocument document = new DummyDocument("hello");
|
||||
String id = UUID.randomUUID().toString();
|
||||
template.save(id, document);
|
||||
DummyDocument foundDocument = template.findOne(id, DummyDocument.class);
|
||||
Assert.assertEquals(document.getMessage(), foundDocument.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.couchdb.monitor;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* Server application to test JMX functionality.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
public class JmxServer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new JmxServer().run();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
new ClassPathXmlApplicationContext(new String[]{"server-jmx.xml"});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +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 %p [%c] - <%m>%n
|
||||
|
||||
log4j.category.org.apache.activemq=ERROR
|
||||
log4j.category.org.springframework.batch=DEBUG
|
||||
log4j.category.org.springframework.transaction=INFO
|
||||
|
||||
log4j.category.org.hibernate.SQL=DEBUG
|
||||
# for debugging datasource initialization
|
||||
# log4j.category.test.jdbc=DEBUG
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:couch="http://www.springframework.org/schema/data/couch"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/data/couch http://www.springframework.org/schema/data/couch/spring-couch-1.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
|
||||
<couch:jmx/>
|
||||
|
||||
<context:mbean-export/>
|
||||
|
||||
<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"
|
||||
p:port="1099"/>
|
||||
|
||||
<!-- Expose JMX over RMI -->
|
||||
<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="registry"
|
||||
p:objectName="connector:name=rmi"
|
||||
p:serviceUrl="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector"/>
|
||||
|
||||
</beans>
|
||||
@@ -1,24 +0,0 @@
|
||||
Bundle-SymbolicName: org.springframework.data.couchdb
|
||||
Bundle-Name: Spring Data Couch DB Support
|
||||
Bundle-Vendor: SpringSource
|
||||
Bundle-ManifestVersion: 2
|
||||
Import-Package:
|
||||
sun.reflect;version="0";resolution:=optional
|
||||
Import-Template:
|
||||
org.springframework.beans.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.core.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.dao.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.http.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.web.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.util.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.context.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.jmx.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.remoting.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.data.core.*;version="[1.0.0, 2.0.0)",
|
||||
org.springframework.data.document.*;version="[1.0.0, 2.0.0)",
|
||||
org.codehaus.jackson.*;version="[1.0.0, 2.0.0)";resolution:=optional,
|
||||
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.w3c.dom.*;version="0"
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-document-parent</artifactId>
|
||||
<version>1.0.0.M4</version>
|
||||
<relativePath>../spring-data-document-parent/pom.xml</relativePath>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.0.5.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb-cross-store</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Spring Data MongoDB Cross-store Persistence Support</name>
|
||||
<dependencies>
|
||||
|
||||
@@ -24,7 +23,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
@@ -69,24 +68,6 @@
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>javax.jms</groupId>
|
||||
<artifactId>jms</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jdmk</groupId>
|
||||
<artifactId>jmxtools</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jmx</groupId>
|
||||
<artifactId>jmxri</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -96,17 +77,6 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
@@ -152,25 +122,7 @@
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jboss-repository</id>
|
||||
<name>JBoss Public Repository</name>
|
||||
<url>http://repository.jboss.org/nexus/content/groups/public-jboss</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-maven-milestones</id>
|
||||
<name>Springframework Maven Milestone Repository</name>
|
||||
<url>http://maven.springframework.org/milestone</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>spring-maven-release</id>
|
||||
<name>Springframework Maven Release Repository</name>
|
||||
<url>http://maven.springframework.org/release</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
@@ -1,30 +1,22 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.couchdb.core;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for CouchTemplate with mocks
|
||||
*/
|
||||
public class CouchTemplateTests {
|
||||
|
||||
@Test
|
||||
public void foo() {
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore;
|
||||
|
||||
import org.springframework.data.crossstore.ChangeSetBacked;
|
||||
|
||||
public interface DocumentBacked extends ChangeSetBacked {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.crossstore.ChangeSet;
|
||||
import org.springframework.data.crossstore.ChangeSetBacked;
|
||||
import org.springframework.data.crossstore.ChangeSetPersister;
|
||||
import org.springframework.data.mongodb.core.CollectionCallback;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||
|
||||
private static final String ENTITY_CLASS = "_entity_class";
|
||||
|
||||
private static final String ENTITY_ID = "_entity_id";
|
||||
|
||||
private static final String ENTITY_FIELD_NAME = "_entity_field_name";
|
||||
|
||||
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
private MongoTemplate mongoTemplate;
|
||||
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
public void setMongoTemplate(MongoTemplate mongoTemplate) {
|
||||
this.mongoTemplate = mongoTemplate;
|
||||
}
|
||||
|
||||
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
|
||||
this.entityManagerFactory = entityManagerFactory;
|
||||
}
|
||||
|
||||
|
||||
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass,
|
||||
Object id, final ChangeSet changeSet)
|
||||
throws DataAccessException, NotFoundException {
|
||||
|
||||
if (id == null) {
|
||||
log.debug("Unable to load MongoDB data for null id");
|
||||
return;
|
||||
}
|
||||
|
||||
String collName = getCollectionNameForEntity(entityClass);
|
||||
|
||||
final DBObject dbk = new BasicDBObject();
|
||||
dbk.put(ENTITY_ID, id);
|
||||
dbk.put(ENTITY_CLASS, entityClass.getName());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Loading MongoDB data for " + dbk);
|
||||
}
|
||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
for (DBObject dbo : collection.find(dbk)) {
|
||||
String key = (String) dbo.get(ENTITY_FIELD_NAME);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Processing key: " + key);
|
||||
}
|
||||
if (!changeSet.getValues().containsKey(key)) {
|
||||
String className = (String) dbo.get(ENTITY_FIELD_CLASS);
|
||||
if (className == null) {
|
||||
throw new DataIntegrityViolationException(
|
||||
"Unble to convert property " + key
|
||||
+ ": Invalid metadata, " + ENTITY_FIELD_CLASS + " not available");
|
||||
}
|
||||
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
|
||||
Object value = mongoTemplate.getConverter().read(clazz, dbo);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Adding to ChangeSet: " + key);
|
||||
}
|
||||
changeSet.set(key, value);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Object getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
||||
log.debug("getPersistentId called on " + entity);
|
||||
if (entityManagerFactory == null) {
|
||||
throw new DataAccessResourceFailureException("EntityManagerFactory cannot be null");
|
||||
}
|
||||
Object o = entityManagerFactory.getPersistenceUnitUtil().getIdentifier(entity);
|
||||
return o;
|
||||
}
|
||||
|
||||
public Object persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
||||
if (cs == null) {
|
||||
log.debug("Flush: changeset was null, nothing to flush.");
|
||||
return 0L;
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Flush: changeset: " + cs.getValues());
|
||||
}
|
||||
|
||||
String collName = getCollectionNameForEntity(entity.getClass());
|
||||
if (mongoTemplate.getCollection(collName) == null) {
|
||||
mongoTemplate.createCollection(collName);
|
||||
}
|
||||
|
||||
for (String key : cs.getValues().keySet()) {
|
||||
if (key != null && !key.startsWith("_") && !key.equals(ChangeSetPersister.ID_KEY)) {
|
||||
Object value = cs.getValues().get(key);
|
||||
final DBObject dbQuery = new BasicDBObject();
|
||||
dbQuery.put(ENTITY_ID, getPersistentId(entity, cs));
|
||||
dbQuery.put(ENTITY_CLASS, entity.getClass().getName());
|
||||
dbQuery.put(ENTITY_FIELD_NAME, key);
|
||||
DBObject dbId = mongoTemplate.execute(collName,
|
||||
new CollectionCallback<DBObject>() {
|
||||
public DBObject doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
return collection.findOne(dbQuery);
|
||||
}
|
||||
});
|
||||
if (value == null) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Flush: removing: " + dbQuery);
|
||||
}
|
||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
collection.remove(dbQuery);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
final DBObject dbDoc = new BasicDBObject();
|
||||
dbDoc.putAll(dbQuery);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Flush: saving: " + dbQuery);
|
||||
}
|
||||
mongoTemplate.getConverter().write(value, dbDoc);
|
||||
dbDoc.put(ENTITY_FIELD_CLASS, value.getClass().getName());
|
||||
if (dbId != null) {
|
||||
dbDoc.put("_id", dbId.get("_id"));
|
||||
}
|
||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
collection.save(dbDoc);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
private String getCollectionNameForEntity(Class<? extends ChangeSetBacked> entityClass) {
|
||||
return ClassUtils.getQualifiedName(entityClass);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,19 @@
|
||||
package org.springframework.data.persistence.document.mongodb;
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@@ -12,14 +27,14 @@ import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.reflect.FieldSignature;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.persistence.document.RelatedDocument;
|
||||
|
||||
import org.springframework.data.persistence.document.DocumentBacked;
|
||||
import org.springframework.data.persistence.document.DocumentBackedTransactionSynchronization;
|
||||
import org.springframework.data.persistence.ChangeSet;
|
||||
import org.springframework.data.persistence.ChangeSetPersister;
|
||||
import org.springframework.data.persistence.ChangeSetPersister.NotFoundException;
|
||||
import org.springframework.data.persistence.HashMapChangeSet;
|
||||
import org.springframework.data.mongodb.crossstore.RelatedDocument;
|
||||
import org.springframework.data.mongodb.crossstore.DocumentBacked;
|
||||
import org.springframework.data.crossstore.ChangeSetBackedTransactionSynchronization;
|
||||
import org.springframework.data.crossstore.ChangeSet;
|
||||
import org.springframework.data.crossstore.ChangeSetPersister;
|
||||
import org.springframework.data.crossstore.ChangeSetPersister.NotFoundException;
|
||||
import org.springframework.data.crossstore.HashMapChangeSet;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
@@ -130,7 +145,7 @@ public aspect MongoDocumentBacking {
|
||||
entity.setChangeSet(new HashMapChangeSet());
|
||||
entity.itdChangeSetPersister = changeSetPersister;
|
||||
entity.itdTransactionSynchronization =
|
||||
new DocumentBackedTransactionSynchronization(changeSetPersister, entity);
|
||||
new ChangeSetBackedTransactionSynchronization(changeSetPersister, entity);
|
||||
//registerTransactionSynchronization(entity);
|
||||
}
|
||||
|
||||
@@ -163,7 +178,7 @@ public aspect MongoDocumentBacking {
|
||||
|
||||
@Transient private ChangeSetPersister<?> DocumentBacked.itdChangeSetPersister;
|
||||
|
||||
@Transient private DocumentBackedTransactionSynchronization DocumentBacked.itdTransactionSynchronization;
|
||||
@Transient private ChangeSetBackedTransactionSynchronization DocumentBacked.itdTransactionSynchronization;
|
||||
|
||||
public void DocumentBacked.setChangeSet(ChangeSet cs) {
|
||||
this.changeSet = cs;
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
@@ -13,8 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.persistence.document;
|
||||
package org.springframework.data.mongodb.crossstore;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.springframework.data.persistence.document;
|
||||
|
||||
import org.springframework.data.persistence.ChangeSetBacked;
|
||||
|
||||
public interface DocumentBacked extends ChangeSetBacked {
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package org.springframework.data.persistence.document;
|
||||
|
||||
//public class DocumentBackedTransactionSynchronization {
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.data.persistence.ChangeSetBacked;
|
||||
import org.springframework.data.persistence.ChangeSetPersister;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
|
||||
public class DocumentBackedTransactionSynchronization implements TransactionSynchronization {
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
private ChangeSetPersister<Object> changeSetPersister;
|
||||
|
||||
private ChangeSetBacked entity;
|
||||
|
||||
private int changeSetTxStatus = -1;
|
||||
|
||||
public DocumentBackedTransactionSynchronization(ChangeSetPersister<Object> changeSetPersister, ChangeSetBacked entity) {
|
||||
this.changeSetPersister = changeSetPersister;
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
public void afterCommit() {
|
||||
log.debug("After Commit called for " + entity);
|
||||
changeSetPersister.persistState(entity, entity.getChangeSet());
|
||||
changeSetTxStatus = 0;
|
||||
}
|
||||
|
||||
public void afterCompletion(int status) {
|
||||
log.debug("After Completion called with status = " + status);
|
||||
if (changeSetTxStatus == 0) {
|
||||
if (status == STATUS_COMMITTED) {
|
||||
// this is good
|
||||
log.debug("ChangedSetBackedTransactionSynchronization completed successfully for " + this.entity);
|
||||
}
|
||||
else {
|
||||
// this could be bad - TODO: compensate
|
||||
log.error("ChangedSetBackedTransactionSynchronization failed for " + this.entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void beforeCommit(boolean readOnly) {
|
||||
}
|
||||
|
||||
public void beforeCompletion() {
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
throw new IllegalStateException("ChangedSetBackedTransactionSynchronization does not support transaction suspension currently.");
|
||||
}
|
||||
|
||||
public void suspend() {
|
||||
throw new IllegalStateException("ChangedSetBackedTransactionSynchronization does not support transaction suspension currently.");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
package org.springframework.data.persistence.document.mongodb;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.MongoException;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.mongodb.core.CollectionCallback;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.persistence.ChangeSet;
|
||||
import org.springframework.data.persistence.ChangeSetBacked;
|
||||
import org.springframework.data.persistence.ChangeSetPersister;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||
|
||||
private static final String ENTITY_CLASS = "_entity_class";
|
||||
|
||||
private static final String ENTITY_ID = "_entity_id";
|
||||
|
||||
private static final String ENTITY_FIELD_NAME = "_entity_field_name";
|
||||
|
||||
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
private MongoTemplate mongoTemplate;
|
||||
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
public void setMongoTemplate(MongoTemplate mongoTemplate) {
|
||||
this.mongoTemplate = mongoTemplate;
|
||||
}
|
||||
|
||||
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
|
||||
this.entityManagerFactory = entityManagerFactory;
|
||||
}
|
||||
|
||||
|
||||
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass,
|
||||
Object id, final ChangeSet changeSet)
|
||||
throws DataAccessException, NotFoundException {
|
||||
|
||||
if (id == null) {
|
||||
log.debug("Unable to load MongoDB data for null id");
|
||||
return;
|
||||
}
|
||||
|
||||
String collName = getCollectionNameForEntity(entityClass);
|
||||
|
||||
final DBObject dbk = new BasicDBObject();
|
||||
dbk.put(ENTITY_ID, id);
|
||||
dbk.put(ENTITY_CLASS, entityClass.getName());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Loading MongoDB data for " + dbk);
|
||||
}
|
||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
for (DBObject dbo : collection.find(dbk)) {
|
||||
String key = (String) dbo.get(ENTITY_FIELD_NAME);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Processing key: " + key);
|
||||
}
|
||||
if (!changeSet.getValues().containsKey(key)) {
|
||||
String className = (String) dbo.get(ENTITY_FIELD_CLASS);
|
||||
if (className == null) {
|
||||
throw new DataIntegrityViolationException(
|
||||
"Unble to convert property " + key
|
||||
+ ": Invalid metadata, " + ENTITY_FIELD_CLASS + " not available");
|
||||
}
|
||||
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
|
||||
Object value = mongoTemplate.getConverter().read(clazz, dbo);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Adding to ChangeSet: " + key);
|
||||
}
|
||||
changeSet.set(key, value);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Object getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
||||
log.debug("getPersistentId called on " + entity);
|
||||
if (entityManagerFactory == null) {
|
||||
throw new DataAccessResourceFailureException("EntityManagerFactory cannot be null");
|
||||
}
|
||||
Object o = entityManagerFactory.getPersistenceUnitUtil().getIdentifier(entity);
|
||||
return o;
|
||||
}
|
||||
|
||||
public Object persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
||||
if (cs == null) {
|
||||
log.debug("Flush: changeset was null, nothing to flush.");
|
||||
return 0L;
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Flush: changeset: " + cs.getValues());
|
||||
}
|
||||
|
||||
String collName = getCollectionNameForEntity(entity.getClass());
|
||||
DBCollection dbc = mongoTemplate.getCollection(collName);
|
||||
if (dbc == null) {
|
||||
dbc = mongoTemplate.createCollection(collName);
|
||||
}
|
||||
for (String key : cs.getValues().keySet()) {
|
||||
if (key != null && !key.startsWith("_") && !key.equals(ChangeSetPersister.ID_KEY)) {
|
||||
Object value = cs.getValues().get(key);
|
||||
final DBObject dbQuery = new BasicDBObject();
|
||||
dbQuery.put(ENTITY_ID, getPersistentId(entity, cs));
|
||||
dbQuery.put(ENTITY_CLASS, entity.getClass().getName());
|
||||
dbQuery.put(ENTITY_FIELD_NAME, key);
|
||||
DBObject dbId = mongoTemplate.execute(collName,
|
||||
new CollectionCallback<DBObject>() {
|
||||
public DBObject doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
return collection.findOne(dbQuery);
|
||||
}
|
||||
});
|
||||
if (value == null) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Flush: removing: " + dbQuery);
|
||||
}
|
||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
collection.remove(dbQuery);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
final DBObject dbDoc = new BasicDBObject();
|
||||
dbDoc.putAll(dbQuery);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Flush: saving: " + dbQuery);
|
||||
}
|
||||
mongoTemplate.getConverter().write(value, dbDoc);
|
||||
dbDoc.put(ENTITY_FIELD_CLASS, value.getClass().getName());
|
||||
if (dbId != null) {
|
||||
dbDoc.put("_id", dbId.get("_id"));
|
||||
}
|
||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
collection.save(dbDoc);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
private String getCollectionNameForEntity(Class<? extends ChangeSetBacked> entityClass) {
|
||||
return ClassUtils.getQualifiedName(entityClass);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
package org.springframework.data.document.persistence;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.document.persistence.test.Address;
|
||||
import org.springframework.data.document.persistence.test.Person;
|
||||
import org.springframework.data.document.persistence.test.Resume;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.test.annotation.Rollback;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:/META-INF/spring/applicationContext.xml")
|
||||
public class CrossStoreMongoTests {
|
||||
|
||||
@Autowired
|
||||
private MongoTemplate mongoTemplate;
|
||||
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
@PersistenceContext
|
||||
public void setEntityManager(EntityManager entityManager) {
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
private void clearData(String collectionName) {
|
||||
DBCollection col = this.mongoTemplate.getCollection(collectionName);
|
||||
if (col != null) {
|
||||
this.mongoTemplate.dropCollection(collectionName);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@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() {
|
||||
Person found = entityManager.find(Person.class, 1L);
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found.getResume());
|
||||
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; "
|
||||
+ "VMware, Developer, 2007-", found.getResume().getJobs());
|
||||
found.getResume().addJob("SpringDeveloper.com, Consultant, 2005-2006");
|
||||
found.setAge(44);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@Rollback(false)
|
||||
public void testUpdatedJpaToMongoEntityRelationship() {
|
||||
Person found = entityManager.find(Person.class, 1L);
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found.getResume());
|
||||
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; "
|
||||
+ "VMware, Developer, 2007-" + "; "
|
||||
+ "SpringDeveloper.com, Consultant, 2005-2006", found.getResume().getJobs());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeJpaEntityWithMongoDocument() {
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(transactionManager);
|
||||
final Person detached = entityManager.find(Person.class, 1L);
|
||||
detached.getResume().addJob("TargetRx, Developer, 2000-2005");
|
||||
Person merged = txTemplate.execute(new TransactionCallback<Person>() {
|
||||
public Person doInTransaction(TransactionStatus status) {
|
||||
return entityManager.merge(detached);
|
||||
}
|
||||
});
|
||||
Assert.assertTrue(detached.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);
|
||||
Assert.assertTrue(updated.getResume().getJobs().contains("TargetRx, Developer, 2000-2005"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveJpaEntityWithMongoDocument() {
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(transactionManager);
|
||||
txTemplate.execute(new TransactionCallback<Person>() {
|
||||
public Person doInTransaction(TransactionStatus status) {
|
||||
Person p2 = new Person("Thomas", 20);
|
||||
Resume r2 = new Resume();
|
||||
r2.addEducation("Skanstulls High School, 1975");
|
||||
r2.addJob("DiMark, DBA, 1990-2000");
|
||||
p2.setResume(r2);
|
||||
p2.setId(2L);
|
||||
entityManager.persist(p2);
|
||||
Person p3 = new Person("Thomas", 20);
|
||||
Resume r3 = new Resume();
|
||||
r3.addEducation("Univ. of Stockholm, 1980");
|
||||
r3.addJob("VMware, Developer, 2007-");
|
||||
p3.setResume(r3);
|
||||
p3.setId(3L);
|
||||
entityManager.persist(p3);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
txTemplate.execute(new TransactionCallback<Person>() {
|
||||
public Person doInTransaction(TransactionStatus status) {
|
||||
final Person found2 = entityManager.find(Person.class, 2L);
|
||||
entityManager.remove(found2);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
boolean weFound3 = false;
|
||||
for (DBObject dbo : this.mongoTemplate.getCollection(Person.class.getName()).find()) {
|
||||
Assert.assertTrue(!dbo.get("_entity_id").equals(2L));
|
||||
if (dbo.get("_entity_id").equals(3L)) {
|
||||
weFound3 = true;
|
||||
}
|
||||
}
|
||||
Assert.assertTrue(weFound3);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package org.springframework.data.document.persistence.test;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.springframework.data.persistence.document.RelatedDocument;
|
||||
|
||||
@Entity
|
||||
public class Person {
|
||||
|
||||
@Id
|
||||
Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
private java.util.Date birthDate;
|
||||
|
||||
@RelatedDocument
|
||||
private Address address;
|
||||
|
||||
@RelatedDocument
|
||||
private Resume resume;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
this.birthDate = new java.util.Date();
|
||||
}
|
||||
|
||||
public void birthday() {
|
||||
++age;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public java.util.Date getBirthDate() {
|
||||
return birthDate;
|
||||
}
|
||||
|
||||
public void setBirthDate(java.util.Date birthDate) {
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
|
||||
public Resume getResume() {
|
||||
return resume;
|
||||
}
|
||||
|
||||
public void setResume(Resume resume) {
|
||||
this.resume = resume;
|
||||
}
|
||||
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(Address address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package org.springframework.data.document.persistence.test;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
@Document
|
||||
public class Resume {
|
||||
|
||||
private static final Log LOGGER = LogFactory.getLog(Resume.class);
|
||||
|
||||
@Id
|
||||
private ObjectId id;
|
||||
|
||||
private String education = "";
|
||||
|
||||
private String jobs = "";
|
||||
|
||||
public String getId() {
|
||||
return id.toString();
|
||||
}
|
||||
|
||||
public String getEducation() {
|
||||
return education;
|
||||
}
|
||||
|
||||
public void addEducation(String education) {
|
||||
LOGGER.debug("Adding education " + education);
|
||||
this.education = this.education + (this.education.length() > 0 ? "; " : "") + education;
|
||||
}
|
||||
|
||||
public String getJobs() {
|
||||
return jobs;
|
||||
}
|
||||
|
||||
public void addJob(String job) {
|
||||
LOGGER.debug("Adding job " + job);
|
||||
this.jobs = this.jobs + (this.jobs.length() > 0 ? "; " : "") + job;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Resume [education=" + education + ", jobs=" + jobs + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.crossstore.test.Address;
|
||||
import org.springframework.data.mongodb.crossstore.test.Person;
|
||||
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.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:/META-INF/spring/applicationContext.xml")
|
||||
public class CrossStoreMongoTests {
|
||||
|
||||
@Autowired
|
||||
private MongoTemplate mongoTemplate;
|
||||
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
@PersistenceContext
|
||||
public void setEntityManager(EntityManager entityManager) {
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
private void clearData(String collectionName) {
|
||||
DBCollection col = this.mongoTemplate.getCollection(collectionName);
|
||||
if (col != null) {
|
||||
this.mongoTemplate.dropCollection(collectionName);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@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() {
|
||||
Person found = entityManager.find(Person.class, 1L);
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found.getResume());
|
||||
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; "
|
||||
+ "VMware, Developer, 2007-", found.getResume().getJobs());
|
||||
found.getResume().addJob("SpringDeveloper.com, Consultant, 2005-2006");
|
||||
found.setAge(44);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@Rollback(false)
|
||||
public void testUpdatedJpaToMongoEntityRelationship() {
|
||||
Person found = entityManager.find(Person.class, 1L);
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found.getResume());
|
||||
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; "
|
||||
+ "VMware, Developer, 2007-" + "; "
|
||||
+ "SpringDeveloper.com, Consultant, 2005-2006", found.getResume().getJobs());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeJpaEntityWithMongoDocument() {
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(transactionManager);
|
||||
final Person detached = entityManager.find(Person.class, 1L);
|
||||
detached.getResume().addJob("TargetRx, Developer, 2000-2005");
|
||||
Person merged = txTemplate.execute(new TransactionCallback<Person>() {
|
||||
public Person doInTransaction(TransactionStatus status) {
|
||||
return entityManager.merge(detached);
|
||||
}
|
||||
});
|
||||
Assert.assertTrue(detached.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);
|
||||
Assert.assertTrue(updated.getResume().getJobs().contains("TargetRx, Developer, 2000-2005"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveJpaEntityWithMongoDocument() {
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(transactionManager);
|
||||
txTemplate.execute(new TransactionCallback<Person>() {
|
||||
public Person doInTransaction(TransactionStatus status) {
|
||||
Person p2 = new Person("Thomas", 20);
|
||||
Resume r2 = new Resume();
|
||||
r2.addEducation("Skanstulls High School, 1975");
|
||||
r2.addJob("DiMark, DBA, 1990-2000");
|
||||
p2.setResume(r2);
|
||||
p2.setId(2L);
|
||||
entityManager.persist(p2);
|
||||
Person p3 = new Person("Thomas", 20);
|
||||
Resume r3 = new Resume();
|
||||
r3.addEducation("Univ. of Stockholm, 1980");
|
||||
r3.addJob("VMware, Developer, 2007-");
|
||||
p3.setResume(r3);
|
||||
p3.setId(3L);
|
||||
entityManager.persist(p3);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
txTemplate.execute(new TransactionCallback<Person>() {
|
||||
public Person doInTransaction(TransactionStatus status) {
|
||||
final Person found2 = entityManager.find(Person.class, 2L);
|
||||
entityManager.remove(found2);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
boolean weFound3 = false;
|
||||
for (DBObject dbo : this.mongoTemplate.getCollection(Person.class.getName()).find()) {
|
||||
Assert.assertTrue(!dbo.get("_entity_id").equals(2L));
|
||||
if (dbo.get("_entity_id").equals(3L)) {
|
||||
weFound3 = true;
|
||||
}
|
||||
}
|
||||
Assert.assertTrue(weFound3);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,28 @@
|
||||
package org.springframework.data.document.persistence.test;
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore.test;
|
||||
|
||||
public class Address {
|
||||
|
||||
|
||||
private Integer streetNumber;
|
||||
private String streetName;
|
||||
private String city;
|
||||
private String state;
|
||||
private String zip;
|
||||
|
||||
|
||||
public Address(Integer streetNumber, String streetName, String city,
|
||||
String state, String zip) {
|
||||
super();
|
||||
@@ -17,7 +32,7 @@ public class Address {
|
||||
this.state = state;
|
||||
this.zip = zip;
|
||||
}
|
||||
|
||||
|
||||
public Integer getStreetNumber() {
|
||||
return streetNumber;
|
||||
}
|
||||
@@ -48,7 +63,7 @@ public class Address {
|
||||
public void setZip(String zip) {
|
||||
this.zip = zip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore.test;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.springframework.data.mongodb.crossstore.RelatedDocument;
|
||||
|
||||
@Entity
|
||||
public class Person {
|
||||
|
||||
@Id
|
||||
Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
private java.util.Date birthDate;
|
||||
|
||||
@RelatedDocument
|
||||
private Address address;
|
||||
|
||||
@RelatedDocument
|
||||
private Resume resume;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
this.birthDate = new java.util.Date();
|
||||
}
|
||||
|
||||
public void birthday() {
|
||||
++age;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public java.util.Date getBirthDate() {
|
||||
return birthDate;
|
||||
}
|
||||
|
||||
public void setBirthDate(java.util.Date birthDate) {
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
|
||||
public Resume getResume() {
|
||||
return resume;
|
||||
}
|
||||
|
||||
public void setResume(Resume resume) {
|
||||
this.resume = resume;
|
||||
}
|
||||
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(Address address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore.test;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
@Document
|
||||
public class Resume {
|
||||
|
||||
private static final Log LOGGER = LogFactory.getLog(Resume.class);
|
||||
|
||||
@Id
|
||||
private ObjectId id;
|
||||
|
||||
private String education = "";
|
||||
|
||||
private String jobs = "";
|
||||
|
||||
public String getId() {
|
||||
return id.toString();
|
||||
}
|
||||
|
||||
public String getEducation() {
|
||||
return education;
|
||||
}
|
||||
|
||||
public void addEducation(String education) {
|
||||
LOGGER.debug("Adding education " + education);
|
||||
this.education = this.education + (this.education.length() > 0 ? "; " : "") + education;
|
||||
}
|
||||
|
||||
public String getJobs() {
|
||||
return jobs;
|
||||
}
|
||||
|
||||
public void addJob(String job) {
|
||||
LOGGER.debug("Adding job " + job);
|
||||
this.jobs = this.jobs + (this.jobs.length() > 0 ? "; " : "") + job;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Resume [education=" + education + ", jobs=" + jobs + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
|
||||
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
|
||||
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
||||
<class>org.springframework.data.document.persistence.test.Person</class>
|
||||
<class>org.springframework.data.mongodb.crossstore.test.Person</class>
|
||||
<properties>
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
|
||||
<!--value='create' to build a new database on each run; value='update' to modify an existing database; value='create-drop' means the same as 'create' but also drops tables when Hibernate closes; value='validate' makes no changes to the database-->
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<context:spring-configured/>
|
||||
|
||||
<context:component-scan base-package="org.springframework.persistence.test">
|
||||
<context:component-scan base-package="org.springframework.persistence.mongodb.test">
|
||||
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
|
||||
</context:component-scan>
|
||||
|
||||
@@ -38,12 +38,12 @@
|
||||
<bean class="org.springframework.data.mongodb.core.MongoExceptionTranslator"/>
|
||||
|
||||
<!-- Mongo aspect config -->
|
||||
<bean class="org.springframework.data.persistence.document.mongodb.MongoDocumentBacking"
|
||||
<bean class="org.springframework.data.mongodb.crossstore.MongoDocumentBacking"
|
||||
factory-method="aspectOf">
|
||||
<property name="changeSetPersister" ref="mongoChangeSetPersister"/>
|
||||
</bean>
|
||||
<bean id="mongoChangeSetPersister"
|
||||
class="org.springframework.data.persistence.document.mongodb.MongoChangeSetPersister">
|
||||
class="org.springframework.data.mongodb.crossstore.MongoChangeSetPersister">
|
||||
<property name="mongoTemplate" ref="mongoTemplate"/>
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory"/>
|
||||
</bean>
|
||||
|
||||
@@ -2,7 +2,7 @@ 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 %p [%c] - <%m>%n
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %40.40c:%4L - %m%n
|
||||
|
||||
log4j.category.org.springframework=INFO
|
||||
log4j.category.org.springframework.data=TRACE
|
||||
|
||||
@@ -5,7 +5,7 @@ and connects directly to the MongoDB server using the driver. It has no dependen
|
||||
|
||||
To use it, configure a host, port, (optionally) applicationId, and database property in your Log4J configuration:
|
||||
|
||||
log4j.appender.stdout=org.springframework.data.document.mongodb.log4j.MongoLog4jAppender
|
||||
log4j.appender.stdout=org.springframework.data.mongodb.log4j.MongoLog4jAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
|
||||
log4j.appender.stdout.host = localhost
|
||||
@@ -32,7 +32,7 @@ An example log entry might look like:
|
||||
{
|
||||
"_id" : ObjectId("4d89341a8ef397e06940d5cd"),
|
||||
"applicationId" : "my.application",
|
||||
"name" : "org.springframework.data.document.mongodb.log4j.AppenderTest",
|
||||
"name" : "org.springframework.data.mongodb.log4j.AppenderTest",
|
||||
"level" : "DEBUG",
|
||||
"timestamp" : ISODate("2011-03-23T16:53:46.778Z"),
|
||||
"properties" : {
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-document-parent</artifactId>
|
||||
<version>1.0.0.M4</version>
|
||||
<relativePath>../spring-data-document-parent/pom.xml</relativePath>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.0.5.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb-log4j</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Spring Data MongoDB Log4J Appender</name>
|
||||
|
||||
<properties>
|
||||
@@ -29,47 +27,9 @@
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>javax.jms</groupId>
|
||||
<artifactId>jms</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jdmk</groupId>
|
||||
<artifactId>jmxtools</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jmx</groupId>
|
||||
<artifactId>jmxri</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<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>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.mongodb.log4j;
|
||||
package org.springframework.data.mongodb.log4j;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.mongodb.log4j;
|
||||
package org.springframework.data.mongodb.log4j;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
@@ -1,6 +1,6 @@
|
||||
log4j.rootCategory=INFO, stdout
|
||||
|
||||
log4j.appender.stdout=org.springframework.data.document.mongodb.log4j.MongoLog4jAppender
|
||||
log4j.appender.stdout=org.springframework.data.mongodb.log4j.MongoLog4jAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
|
||||
log4j.appender.stdout.host = localhost
|
||||
|
||||
@@ -1,61 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-document-parent</artifactId>
|
||||
<name>Spring Data Document Parent</name>
|
||||
<url>http://www.springsource.org/spring-data/data-document</url>
|
||||
<version>1.0.0.M4</version>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<name>Spring Data MongoDB Parent</name>
|
||||
<description>Spring Data project for MongoDB</description>
|
||||
<url>http://www.springsource.org/spring-data/mongodb</url>
|
||||
<version>1.0.5.BUILD-SNAPSHOT</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.15</log4j.version>
|
||||
<junit.version>4.10</junit.version>
|
||||
<log4j.version>1.2.16</log4j.version>
|
||||
<org.mockito.version>1.8.4</org.mockito.version>
|
||||
<hamcrest.version>1.2.1</hamcrest.version>
|
||||
<org.slf4j.version>1.5.10</org.slf4j.version>
|
||||
<org.codehaus.jackson.version>1.6.1</org.codehaus.jackson.version>
|
||||
<org.springframework.version>3.0.6.RELEASE</org.springframework.version>
|
||||
<data.commons.version>1.2.0.M1</data.commons.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.2.1.RELEASE</data.commons.version>
|
||||
<aspectj.version>1.6.11.RELEASE</aspectj.version>
|
||||
</properties>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>strict</id>
|
||||
<properties>
|
||||
<maven.test.failure.ignore>false</maven.test.failure.ignore>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>fast</id>
|
||||
<properties>
|
||||
<maven.test.skip>true</maven.test.skip>
|
||||
<maven.javadoc.skip>true</maven.javadoc.skip>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>staging</id>
|
||||
<distributionManagement>
|
||||
<site>
|
||||
<id>spring-site-staging</id>
|
||||
<url>file:///${java.io.tmpdir}/spring-data/data-document/docs</url>
|
||||
</site>
|
||||
<repository>
|
||||
<id>spring-milestone-staging</id>
|
||||
<url>file:///${java.io.tmpdir}/spring-data/data-document/milestone</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>spring-snapshot-staging</id>
|
||||
<url>file:///${java.io.tmpdir}/spring-data/data-document/snapshot</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>bootstrap</id>
|
||||
<!-- TODO: move the repositories in here before release -->
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>ogierke</id>
|
||||
<name>Oliver Gierke</name>
|
||||
<email>ogierke at vmware.com</email>
|
||||
<organization>SpringSource</organization>
|
||||
<organizationUrl>http://www.springsource.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Project lead</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>trisberg</id>
|
||||
<name>Thomas Risberg</name>
|
||||
<email>trisberg at vmware.com</email>
|
||||
<organization>SpringSource</organization>
|
||||
<organizationUrl>http://www.SpringSource.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Project Admin</role>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-5</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>mpollack</id>
|
||||
<name>Mark Pollack</name>
|
||||
<email>mpollack at vmware.com</email>
|
||||
<organization>SpringSource</organization>
|
||||
<organizationUrl>http://www.SpringSource.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Project Admin</role>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-5</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>jbrisbin</id>
|
||||
<name>Jon Brisbin</name>
|
||||
<email>jbrisbin at vmware.com</email>
|
||||
<organization>SpringSource</organization>
|
||||
<organizationUrl>http://www.springsource.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-6</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
|
||||
<comments>
|
||||
Copyright 2010 the original author or authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<distributionManagement>
|
||||
<!-- see 'staging' profile for dry-run deployment settings -->
|
||||
<downloadUrl>http://www.springsource.com/download/community
|
||||
@@ -63,13 +103,13 @@
|
||||
<site>
|
||||
<id>static.springframework.org</id>
|
||||
<url>
|
||||
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-document/docs/${project.version}
|
||||
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>
|
||||
<id>spring-release</id>
|
||||
<name>Spring Release Repository</name>
|
||||
<url>s3://maven.springframework.org/release</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>spring-snapshot</id>
|
||||
@@ -77,6 +117,9 @@
|
||||
<url>s3://maven.springframework.org/snapshot</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
<scm>
|
||||
<url>https://github.com/SpringSource/spring-data-mongodb</url>
|
||||
</scm>
|
||||
<dependencyManagement>
|
||||
<!--
|
||||
inheritable <dependency> declarations for child poms. children still
|
||||
@@ -92,42 +135,47 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<version>${org.springframework.version.range}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -150,7 +198,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>1.0.5.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging -->
|
||||
@@ -176,24 +224,6 @@
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>javax.jms</groupId>
|
||||
<artifactId>jms</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jdmk</groupId>
|
||||
<artifactId>jmxtools</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.sun.jmx</groupId>
|
||||
<artifactId>jmxri</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -206,14 +236,14 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${org.mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<artifactId>junit-dep</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
@@ -221,19 +251,34 @@
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
<!--
|
||||
dependency definitions to be inherited by child poms. any
|
||||
<dependency> declarations here will automatically show up on child
|
||||
project classpaths. only items that are truly common across all
|
||||
projects (modules and samples) should go here. otherwise, consider
|
||||
<dependencyManagement> above
|
||||
-->
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<version>${hamcrest.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit-dep</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -248,47 +293,11 @@
|
||||
<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.5.1</version>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
@@ -308,19 +317,18 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.10</version>
|
||||
<configuration>
|
||||
<useFile>false</useFile>
|
||||
<includes>
|
||||
<include>**/*Tests.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/Abstract*.java</exclude>
|
||||
</excludes>
|
||||
<junitArtifactName>junit:junit</junitArtifactName>
|
||||
<junitArtifactName>junit:junit-dep</junitArtifactName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.1.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
@@ -367,32 +375,18 @@
|
||||
</build>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<!-- necessary for bundlor and utils -->
|
||||
<id>repository.plugin.springsource.release</id>
|
||||
<name>SpringSource Maven Repository</name>
|
||||
<url>http://repository.springsource.com/maven/bundles/release</url>
|
||||
<id>spring-plugins-release</id>
|
||||
<url>http://repo.springsource.org/plugins-release</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>repository.springframework.maven.release</id>
|
||||
<name>Spring Framework Maven Release Repository</name>
|
||||
<url>http://maven.springframework.org/release</url>
|
||||
<id>querydsl</id>
|
||||
<url>http://source.mysema.com/maven2/releases</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>repository.springframework.maven.release</id>
|
||||
<name>Spring Framework Maven Release Repository</name>
|
||||
<url>http://maven.springframework.org/release</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>repository.springframework.maven.milestone</id>
|
||||
<name>Spring Framework Maven Milestone Repository</name>
|
||||
<url>http://maven.springframework.org/milestone</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>repository.springframework.maven.snapshot</id>
|
||||
<name>Spring Framework Maven Snapshot Repository</name>
|
||||
<url>http://maven.springframework.org/snapshot</url>
|
||||
<id>spring-libs-release</id>
|
||||
<url>http://repo.springsource.org/libs-release</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<reporting>
|
||||
@@ -7,7 +7,7 @@
|
||||
<architecture>
|
||||
<element name="Config" type="Layer">
|
||||
<element name="Assignment" type="TypeFilter">
|
||||
<element name="**.config.**" type="IncludeTypePattern"/>
|
||||
<element name="**.config.**" type="WeakTypePattern"/>
|
||||
</element>
|
||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Core"/>
|
||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Monitoring"/>
|
||||
@@ -17,6 +17,30 @@
|
||||
<element name="Assignment" type="TypeFilter">
|
||||
<element name="**.repository.**" type="IncludeTypePattern"/>
|
||||
</element>
|
||||
<element name="API" type="Subsystem">
|
||||
<element name="Assignment" type="TypeFilter">
|
||||
<element name="**.repository.*" type="IncludeTypePattern"/>
|
||||
</element>
|
||||
</element>
|
||||
<element name="Query" type="Subsystem">
|
||||
<element name="Assignment" type="TypeFilter">
|
||||
<element name="**.query.**" type="IncludeTypePattern"/>
|
||||
</element>
|
||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Repositories::Subsystem|API"/>
|
||||
</element>
|
||||
<element name="Implementation" type="Subsystem">
|
||||
<element name="Assignment" type="TypeFilter">
|
||||
<element name="**.support.**" type="IncludeTypePattern"/>
|
||||
</element>
|
||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Repositories::Subsystem|API"/>
|
||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Repositories::Subsystem|Query"/>
|
||||
</element>
|
||||
<element name="Config" type="Subsystem">
|
||||
<element name="Assignment" type="TypeFilter">
|
||||
<element name="**.config.**" type="IncludeTypePattern"/>
|
||||
</element>
|
||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Repositories::Subsystem|Implementation"/>
|
||||
</element>
|
||||
<dependency type="AllowedDependency" toName="Project|spring-data-mongodb::Layer|Core"/>
|
||||
</element>
|
||||
<element name="Monitoring" type="Layer">
|
||||
|
||||
@@ -1,29 +1,39 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-document-parent</artifactId>
|
||||
<version>1.0.0.M4</version>
|
||||
<relativePath>../spring-data-document-parent/pom.xml</relativePath>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.0.5.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Spring Data MongoDB Support</name>
|
||||
<name>Spring Data MongoDB</name>
|
||||
|
||||
<properties>
|
||||
<mongo.version>2.6.5</mongo.version>
|
||||
<querydsl.version>2.2.0</querydsl.version>
|
||||
<mongo.version>2.7.1</mongo.version>
|
||||
<querydsl.version>2.3.0</querydsl.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
@@ -59,19 +69,6 @@
|
||||
<artifactId>querydsl-mongodb</artifactId>
|
||||
<version>${querydsl.version}</version>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.code.morphia</groupId>
|
||||
<artifactId>morphia</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.mysema.querydsl</groupId>
|
||||
<artifactId>querydsl-apt</artifactId>
|
||||
<version>${querydsl.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -81,25 +78,6 @@
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<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>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
@@ -110,8 +88,8 @@
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
@@ -129,6 +107,7 @@
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@@ -139,7 +118,14 @@
|
||||
<plugin>
|
||||
<groupId>com.mysema.maven</groupId>
|
||||
<artifactId>maven-apt-plugin</artifactId>
|
||||
<version>1.0.2</version>
|
||||
<version>1.0.4</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.mysema.querydsl</groupId>
|
||||
<artifactId>querydsl-apt</artifactId>
|
||||
<version>${querydsl.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-test-sources</phase>
|
||||
@@ -148,22 +134,12 @@
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>target/generated-test-sources</outputDirectory>
|
||||
<processor>org.springframework.data.mongodb.repository.MongoAnnotationProcessor</processor>
|
||||
<processor>org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor</processor>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>querydsl</id>
|
||||
<name>Mysema QueryDsl</name>
|
||||
<url>http://source.mysema.com/maven2/releases</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -35,10 +35,10 @@ public class CannotGetMongoDbConnectionException extends DataAccessResourceFailu
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public CannotGetMongoDbConnectionException(String msg, String database, String username, char[] password2) {
|
||||
public CannotGetMongoDbConnectionException(String msg, String database, String username, char[] password) {
|
||||
super(msg);
|
||||
this.username = username;
|
||||
this.password = password2;
|
||||
this.password = password == null ? null : password.clone();
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.mongodb.config;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
@@ -26,7 +25,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
import org.springframework.data.mapping.context.MappingContextAwareBeanPostProcessor;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||
@@ -36,6 +34,14 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
|
||||
/**
|
||||
* Abstract base class to ease JavaConfig setup for Spring Data MongoDB.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
public abstract class AbstractMongoConfiguration {
|
||||
|
||||
@@ -51,10 +57,11 @@ public abstract class AbstractMongoConfiguration {
|
||||
|
||||
@Bean
|
||||
public MongoDbFactory mongoDbFactory() throws Exception {
|
||||
if (getUserCredentials() == null) {
|
||||
UserCredentials credentials = getUserCredentials();
|
||||
if (credentials == null) {
|
||||
return new SimpleMongoDbFactory(mongo(), getDatabaseName());
|
||||
} else {
|
||||
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), getUserCredentials());
|
||||
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), credentials);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,12 +107,4 @@ public abstract class AbstractMongoConfiguration {
|
||||
*/
|
||||
protected void afterMappingMongoConverterCreation(MappingMongoConverter converter) {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MappingContextAwareBeanPostProcessor mappingContextAwareBeanPostProcessor() {
|
||||
MappingContextAwareBeanPostProcessor bpp = new MappingContextAwareBeanPostProcessor();
|
||||
bpp.setMappingContextBeanName("mongoMappingContext");
|
||||
return bpp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,4 @@ public abstract class BeanNames {
|
||||
static final String INDEX_HELPER = "indexCreationHelper";
|
||||
static final String MONGO = "mongo";
|
||||
static final String DB_FACTORY = "mongoDbFactory";
|
||||
static final String POST_PROCESSOR = "mappingContextAwareBeanPostProcessor";
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ package org.springframework.data.mongodb.config;
|
||||
|
||||
import static org.springframework.data.mongodb.config.BeanNames.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -36,14 +39,20 @@ import org.springframework.beans.factory.support.ManagedSet;
|
||||
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.mapping.context.MappingContextAwareBeanPostProcessor;
|
||||
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
@@ -70,15 +79,6 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
BeanDefinition conversionsDefinition = getCustomConversions(element, parserContext);
|
||||
String ctxRef = potentiallyCreateMappingContext(element, parserContext, conversionsDefinition);
|
||||
|
||||
try {
|
||||
registry.getBeanDefinition(POST_PROCESSOR);
|
||||
} catch (NoSuchBeanDefinitionException ignored) {
|
||||
BeanDefinitionBuilder postProcBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(MappingContextAwareBeanPostProcessor.class);
|
||||
postProcBuilder.addPropertyValue("mappingContextBeanName", ctxRef);
|
||||
registry.registerBeanDefinition(POST_PROCESSOR, postProcBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
// Need a reference to a Mongo instance
|
||||
String dbFactoryRef = element.getAttribute("db-factory-ref");
|
||||
if (!StringUtils.hasText(dbFactoryRef)) {
|
||||
@@ -143,15 +143,29 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
List<Element> customConvertersElements = DomUtils.getChildElementsByTagName(element, "custom-converters");
|
||||
|
||||
if (customConvertersElements.size() == 1) {
|
||||
|
||||
Element customerConvertersElement = customConvertersElements.get(0);
|
||||
ManagedList<BeanMetadataElement> converterBeans = new ManagedList<BeanMetadataElement>();
|
||||
List<Element> converterElements = DomUtils.getChildElementsByTagName(customerConvertersElement, "converter");
|
||||
|
||||
if (converterElements != null) {
|
||||
for (Element listenerElement : converterElements) {
|
||||
converterBeans.add(parseConverter(listenerElement, parserContext));
|
||||
}
|
||||
}
|
||||
|
||||
// Scan for Converter and GenericConverter beans in the given base-package
|
||||
String packageToScan = customerConvertersElement.getAttribute(BASE_PACKAGE);
|
||||
if (StringUtils.hasText(packageToScan)) {
|
||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
|
||||
provider.addExcludeFilter(new NegatingFilter(new AssignableTypeFilter(Converter.class),
|
||||
new AssignableTypeFilter(GenericConverter.class)));
|
||||
|
||||
for (BeanDefinition candidate : provider.findCandidateComponents(packageToScan)) {
|
||||
converterBeans.add(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder conversionsBuilder = BeanDefinitionBuilder.rootBeanDefinition(CustomConversions.class);
|
||||
conversionsBuilder.addConstructorArgValue(converterBeans);
|
||||
|
||||
@@ -204,4 +218,39 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
"Element <converter> must specify 'ref' or contain a bean definition for the converter", element);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link TypeFilter} that returns {@literal false} in case any of the given delegates matches.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class NegatingFilter implements TypeFilter {
|
||||
|
||||
private final Set<TypeFilter> delegates;
|
||||
|
||||
/**
|
||||
* Creates a new {@link NegatingFilter} with the given delegates.
|
||||
*
|
||||
* @param filters
|
||||
*/
|
||||
public NegatingFilter(TypeFilter... filters) {
|
||||
Assert.notNull(filters);
|
||||
this.delegates = new HashSet<TypeFilter>(Arrays.asList(filters));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.type.filter.TypeFilter#match(org.springframework.core.type.classreading.MetadataReader, org.springframework.core.type.classreading.MetadataReaderFactory)
|
||||
*/
|
||||
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
|
||||
|
||||
for (TypeFilter delegate : delegates) {
|
||||
if (delegate.match(metadataReader, metadataReaderFactory)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import static org.springframework.data.mongodb.config.BeanNames.*;
|
||||
import static org.springframework.data.mongodb.config.ParsingUtils.*;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -33,6 +34,7 @@ import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoURI;
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionParser} to parse {@code db-factory} elements into {@link BeanDefinition}s.
|
||||
@@ -55,30 +57,39 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
||||
|
||||
String uri = element.getAttribute("uri");
|
||||
String mongoRef = element.getAttribute("mongo-ref");
|
||||
if (!StringUtils.hasText(mongoRef)) {
|
||||
mongoRef = registerMongoBeanDefinition(element, parserContext);
|
||||
}
|
||||
|
||||
// Database name
|
||||
String dbname = element.getAttribute("dbname");
|
||||
if (!StringUtils.hasText(dbname)) {
|
||||
dbname = "db";
|
||||
BeanDefinition userCredentials = getUserCredentialsBeanDefinition(element, parserContext);
|
||||
|
||||
// Common setup
|
||||
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
|
||||
ParsingUtils.setPropertyValue(element, dbFactoryBuilder, "write-concern", "writeConcern");
|
||||
|
||||
if (StringUtils.hasText(uri)) {
|
||||
if (StringUtils.hasText(mongoRef) || StringUtils.hasText(dbname) || userCredentials != null) {
|
||||
parserContext.getReaderContext().error("Configure either Mongo URI or details individually!",
|
||||
parserContext.extractSource(element));
|
||||
}
|
||||
|
||||
dbFactoryBuilder.addConstructorArgValue(getMongoUri(uri));
|
||||
return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
|
||||
// Defaulting
|
||||
mongoRef = StringUtils.hasText(mongoRef) ? mongoRef : registerMongoBeanDefinition(element, parserContext);
|
||||
dbname = StringUtils.hasText(dbname) ? dbname : "db";
|
||||
|
||||
dbFactoryBuilder.addConstructorArgValue(new RuntimeBeanReference(mongoRef));
|
||||
dbFactoryBuilder.addConstructorArgValue(dbname);
|
||||
|
||||
BeanDefinition userCredentials = getUserCredentialsBeanDefinition(element);
|
||||
if (userCredentials != null) {
|
||||
dbFactoryBuilder.addConstructorArgValue(userCredentials);
|
||||
}
|
||||
|
||||
ParsingUtils.setPropertyValue(element, dbFactoryBuilder, "write-concern", "writeConcern");
|
||||
|
||||
return dbFactoryBuilder.getBeanDefinition();
|
||||
ParsingUtils.registerWriteConcernPropertyEditor(parserContext.getRegistry());
|
||||
|
||||
return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,7 +116,7 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
* @param element
|
||||
* @return the {@link BeanDefinition} or {@literal null} if neither username nor password given.
|
||||
*/
|
||||
private BeanDefinition getUserCredentialsBeanDefinition(Element element) {
|
||||
private BeanDefinition getUserCredentialsBeanDefinition(Element element, ParserContext context) {
|
||||
|
||||
String username = element.getAttribute("username");
|
||||
String password = element.getAttribute("password");
|
||||
@@ -118,6 +129,20 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
userCredentialsBuilder.addConstructorArgValue(StringUtils.hasText(username) ? username : null);
|
||||
userCredentialsBuilder.addConstructorArgValue(StringUtils.hasText(password) ? password : null);
|
||||
|
||||
return userCredentialsBuilder.getBeanDefinition();
|
||||
return getSourceBeanDefinition(userCredentialsBuilder, context, element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link BeanDefinition} for a {@link MongoURI}.
|
||||
*
|
||||
* @param uri
|
||||
* @return
|
||||
*/
|
||||
private BeanDefinition getMongoUri(String uri) {
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MongoURI.class);
|
||||
builder.addConstructorArgValue(uri);
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
import org.springframework.data.mongodb.repository.config.MongoRepositoryConfigParser;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.xml.NamespaceHandler} for Mongo DB based repositories.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoRepositoryNamespaceHandler extends NamespaceHandlerSupport {
|
||||
public class MongoNamespaceHandler extends NamespaceHandlerSupport {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -16,9 +16,15 @@
|
||||
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
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.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.mongodb.core.MongoFactoryBean;
|
||||
@@ -26,7 +32,7 @@ import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for <mongo;gt; definitions. If no name
|
||||
* Parser for <mongo;gt; definitions.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
@@ -39,15 +45,35 @@ public class MongoParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
super.doParse(element, builder);
|
||||
|
||||
ParsingUtils.setPropertyValue(element, builder, "port", "port");
|
||||
ParsingUtils.setPropertyValue(element, builder, "host", "host");
|
||||
ParsingUtils.setPropertyValue(element, builder, "write-concern", "writeConcern");
|
||||
|
||||
ParsingUtils.parseMongoOptions(parserContext, element, builder);
|
||||
ParsingUtils.parseReplicaSet(parserContext, element, builder);
|
||||
ParsingUtils.parseMongoOptions(element, builder);
|
||||
ParsingUtils.parseReplicaSet(element, builder);
|
||||
|
||||
registerServerAddressPropertyEditor(parserContext.getRegistry());
|
||||
ParsingUtils.registerWriteConcernPropertyEditor(parserContext.getRegistry());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* One should only register one bean definition but want to have the convenience of using
|
||||
* AbstractSingleBeanDefinitionParser but have the side effect of registering a 'default' property editor with the
|
||||
* container.
|
||||
*
|
||||
* @param parserContext the ParserContext to
|
||||
*/
|
||||
private void registerServerAddressPropertyEditor(BeanDefinitionRegistry registry) {
|
||||
|
||||
BeanDefinitionBuilder customEditorConfigurer = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(CustomEditorConfigurer.class);
|
||||
Map<String, String> customEditors = new ManagedMap<String, String>();
|
||||
customEditors.put("com.mongodb.ServerAddress[]",
|
||||
"org.springframework.data.mongodb.config.ServerAddressPropertyEditor");
|
||||
customEditorConfigurer.addPropertyValue("customEditors", customEditors);
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(customEditorConfigurer.getBeanDefinition(), registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,16 +16,22 @@
|
||||
|
||||
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.ManagedList;
|
||||
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;
|
||||
|
||||
import com.mongodb.ServerAddress;
|
||||
|
||||
abstract class ParsingUtils {
|
||||
|
||||
/**
|
||||
@@ -36,22 +42,11 @@ abstract class ParsingUtils {
|
||||
* @param mongoBuilder the bean definition builder to populate
|
||||
* @return true if parsing actually occured, false otherwise
|
||||
*/
|
||||
static boolean parseReplicaSet(ParserContext parserContext, Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||
static boolean parseReplicaSet(Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||
|
||||
String replicaSetString = element.getAttribute("replica-set");
|
||||
if (StringUtils.hasText(replicaSetString)) {
|
||||
ManagedList<Object> serverAddresses = new ManagedList<Object>();
|
||||
String[] replicaSetStringArray = StringUtils.commaDelimitedListToStringArray(replicaSetString);
|
||||
for (String element2 : replicaSetStringArray) {
|
||||
String[] hostAndPort = StringUtils.delimitedListToStringArray(element2, ":");
|
||||
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(ServerAddress.class);
|
||||
defBuilder.addConstructorArgValue(hostAndPort[0]);
|
||||
defBuilder.addConstructorArgValue(hostAndPort[1]);
|
||||
serverAddresses.add(defBuilder.getBeanDefinition());
|
||||
}
|
||||
if (!serverAddresses.isEmpty()) {
|
||||
mongoBuilder.addPropertyValue("replicaSetSeeds", serverAddresses);
|
||||
}
|
||||
mongoBuilder.addPropertyValue("replicaSetSeeds", replicaSetString);
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -62,7 +57,7 @@ abstract class ParsingUtils {
|
||||
*
|
||||
* @return true if parsing actually occured, false otherwise
|
||||
*/
|
||||
static boolean parseMongoOptions(ParserContext parserContext, Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||
static boolean parseMongoOptions(Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
|
||||
if (optionsElement == null) {
|
||||
return false;
|
||||
@@ -79,6 +74,7 @@ abstract class ParsingUtils {
|
||||
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");
|
||||
@@ -109,4 +105,37 @@ abstract class ParsingUtils {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.ServerAddress;
|
||||
|
||||
/**
|
||||
* Parse a {@link String} to a {@link ServerAddress} array. The format is host1:port1,host2:port2,host3:port3.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ServerAddressPropertyEditor extends PropertyEditorSupport {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(ServerAddressPropertyEditor.class);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setAsText(String replicaSetString) {
|
||||
|
||||
String[] replicaSetStringArray = StringUtils.commaDelimitedListToStringArray(replicaSetString);
|
||||
Set<ServerAddress> serverAddresses = new HashSet<ServerAddress>(replicaSetStringArray.length);
|
||||
|
||||
for (String element : replicaSetStringArray) {
|
||||
|
||||
ServerAddress address = parseServerAddress(element);
|
||||
|
||||
if (address != null) {
|
||||
serverAddresses.add(address);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
String[] hostAndPort = StringUtils.delimitedListToStringArray(source.trim(), ":");
|
||||
|
||||
if (!StringUtils.hasText(source) || hostAndPort.length > 2) {
|
||||
LOG.warn(String.format("Could not parse address source '%s'. Check your replica set configuration!", source));
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return hostAndPort.length == 1 ? new ServerAddress(hostAndPort[0]) : new ServerAddress(hostAndPort[0],
|
||||
Integer.parseInt(hostAndPort[1]));
|
||||
} catch (UnknownHostException e) {
|
||||
LOG.warn(String.format("Could not parse host '%s'. Check your replica set configuration!", hostAndPort[0]));
|
||||
} catch (NumberFormatException e) {
|
||||
LOG.warn(String.format("Could not parse port '%s'. Check your replica set configuration!", hostAndPort[1]));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.core.convert.converter.Converter;
|
||||
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* Converter to create {@link WriteConcern} instances from String representations.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class StringToWriteConcernConverter implements Converter<String, WriteConcern> {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
public WriteConcern convert(String source) {
|
||||
|
||||
WriteConcern writeConcern = WriteConcern.valueOf(source);
|
||||
return writeConcern != null ? writeConcern : new WriteConcern(source);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* Parse a string to a {@link WriteConcern}. If it is a well know {@link String} as identified by the
|
||||
* {@link WriteConcern#valueOf(String)}, use the well known {@link WriteConcern} value, otherwise pass the string as is
|
||||
* to the constructor of the write concern. There is no support for other constructor signatures when parsing from a
|
||||
* string value.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
public class WriteConcernPropertyEditor extends PropertyEditorSupport {
|
||||
|
||||
/**
|
||||
* Parse a string to a List<ServerAddress>
|
||||
*/
|
||||
@Override
|
||||
public void setAsText(String writeConcernString) {
|
||||
|
||||
WriteConcern writeConcern = WriteConcern.valueOf(writeConcernString);
|
||||
if (writeConcern != null) {
|
||||
// have a well known string
|
||||
setValue(writeConcern);
|
||||
} else {
|
||||
// pass on the string to the constructor
|
||||
setValue(new WriteConcern(writeConcernString));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import com.mongodb.DBCursor;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface CursorPreparer {
|
||||
interface CursorPreparer {
|
||||
|
||||
/**
|
||||
* Prepare the given cursor (apply limits, skips and so on). Returns th eprepared cursor.
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.mongodb.core.index.IndexDefinition;
|
||||
import org.springframework.data.mongodb.core.index.IndexField;
|
||||
import org.springframework.data.mongodb.core.index.IndexInfo;
|
||||
import org.springframework.data.mongodb.core.query.Order;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link IndexOperations}.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class DefaultIndexOperations implements IndexOperations {
|
||||
|
||||
private final MongoOperations mongoOperations;
|
||||
private final String collectionName;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultIndexOperations}.
|
||||
*
|
||||
* @param mongoOperations must not be {@literal null}.
|
||||
* @param collectionName must not be {@literal null}.
|
||||
*/
|
||||
public DefaultIndexOperations(MongoOperations mongoOperations, String collectionName) {
|
||||
|
||||
Assert.notNull(mongoOperations, "MongoOperations must not be null!");
|
||||
Assert.notNull(collectionName, "Collection name can not be null!");
|
||||
|
||||
this.mongoOperations = mongoOperations;
|
||||
this.collectionName = collectionName;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.IndexOperations#ensureIndex(org.springframework.data.mongodb.core.index.IndexDefinition)
|
||||
*/
|
||||
public void ensureIndex(final IndexDefinition indexDefinition) {
|
||||
mongoOperations.execute(collectionName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
DBObject indexOptions = indexDefinition.getIndexOptions();
|
||||
if (indexOptions != null) {
|
||||
collection.ensureIndex(indexDefinition.getIndexKeys(), indexOptions);
|
||||
} else {
|
||||
collection.ensureIndex(indexDefinition.getIndexKeys());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.IndexOperations#dropIndex(java.lang.String)
|
||||
*/
|
||||
public void dropIndex(final String name) {
|
||||
mongoOperations.execute(collectionName, new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.dropIndex(name);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.IndexOperations#dropAllIndexes()
|
||||
*/
|
||||
public void dropAllIndexes() {
|
||||
dropIndex("*");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.IndexOperations#resetIndexCache()
|
||||
*/
|
||||
public void resetIndexCache() {
|
||||
mongoOperations.execute(collectionName, new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.resetIndexCache();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.IndexOperations#getIndexInfo()
|
||||
*/
|
||||
public List<IndexInfo> getIndexInfo() {
|
||||
|
||||
return mongoOperations.execute(collectionName, new CollectionCallback<List<IndexInfo>>() {
|
||||
public List<IndexInfo> doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
List<DBObject> dbObjectList = collection.getIndexInfo();
|
||||
return getIndexData(dbObjectList);
|
||||
}
|
||||
|
||||
private List<IndexInfo> getIndexData(List<DBObject> dbObjectList) {
|
||||
|
||||
List<IndexInfo> indexInfoList = new ArrayList<IndexInfo>();
|
||||
|
||||
for (DBObject ix : dbObjectList) {
|
||||
|
||||
DBObject keyDbObject = (DBObject) ix.get("key");
|
||||
int numberOfElements = keyDbObject.keySet().size();
|
||||
|
||||
Map<String, Order> keyOrderMap = new HashMap<String, Order>();
|
||||
List<IndexField> indexFields = new ArrayList<IndexField>(numberOfElements);
|
||||
|
||||
for (String key : keyDbObject.keySet()) {
|
||||
|
||||
Object value = keyDbObject.get(key);
|
||||
|
||||
if (Integer.valueOf(1).equals(value)) {
|
||||
keyOrderMap.put(key, Order.ASCENDING);
|
||||
indexFields.add(IndexField.create(key, Order.ASCENDING));
|
||||
} else if (Integer.valueOf(-1).equals(value)) {
|
||||
keyOrderMap.put(key, Order.DESCENDING);
|
||||
indexFields.add(IndexField.create(key, Order.DESCENDING));
|
||||
} else if ("2d".equals(value)) {
|
||||
indexFields.add(IndexField.geo(key));
|
||||
}
|
||||
}
|
||||
|
||||
String name = ix.get("name").toString();
|
||||
|
||||
boolean unique = ix.containsField("unique") ? (Boolean) ix.get("unique") : false;
|
||||
boolean dropDuplicates = ix.containsField("dropDups") ? (Boolean) ix.get("dropDups") : false;
|
||||
boolean sparse = ix.containsField("sparse") ? (Boolean) ix.get("sparse") : false;
|
||||
|
||||
indexInfoList.add(new IndexInfo(keyOrderMap, indexFields, name, unique, dropDuplicates, sparse));
|
||||
}
|
||||
|
||||
return indexInfoList;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -21,15 +21,16 @@ import com.mongodb.DBObject;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
/**
|
||||
* An interface used by {@link MongoTemplate} for processing documents returned from a MongoDB query on a per-document basis.
|
||||
* Implementations of this interface perform the actual work of prcoessing each document but don't need to worry about
|
||||
* exception handling. {@MongoException}s will be caught and translated by the calling MongoTemplate
|
||||
* An interface used by {@link MongoTemplate} for processing documents returned from a MongoDB query on a per-document
|
||||
* basis. Implementations of this interface perform the actual work of prcoessing each document but don't need to worry
|
||||
* about exception handling. {@MongoException}s will be caught and translated by the calling
|
||||
* MongoTemplate
|
||||
*
|
||||
* An DocumentCallbackHandler is typically stateful: It keeps the result state within the object, to be available later for later
|
||||
* inspection.
|
||||
* An DocumentCallbackHandler is typically stateful: It keeps the result state within the object, to be available later
|
||||
* for later inspection.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface DocumentCallbackHandler {
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
public class FindAndModifyOptions {
|
||||
|
||||
boolean returnNew;
|
||||
|
||||
boolean upsert;
|
||||
|
||||
boolean remove;
|
||||
|
||||
/**
|
||||
* Static factory method to create a FindAndModifyOptions instance
|
||||
*
|
||||
* @return a new instance
|
||||
*/
|
||||
public static FindAndModifyOptions options() {
|
||||
return new FindAndModifyOptions();
|
||||
}
|
||||
|
||||
public FindAndModifyOptions returnNew(boolean returnNew) {
|
||||
this.returnNew = returnNew;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FindAndModifyOptions upsert(boolean upsert) {
|
||||
this.upsert = upsert;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FindAndModifyOptions remove(boolean remove) {
|
||||
this.remove = remove;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isReturnNew() {
|
||||
return returnNew;
|
||||
}
|
||||
|
||||
public boolean isUpsert() {
|
||||
return upsert;
|
||||
}
|
||||
|
||||
public boolean isRemove() {
|
||||
return remove;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.mongodb.core.index.IndexDefinition;
|
||||
import org.springframework.data.mongodb.core.index.IndexInfo;
|
||||
|
||||
/**
|
||||
* Index operations on a collection.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface IndexOperations {
|
||||
|
||||
/**
|
||||
* Ensure that an index for the provided {@link IndexDefinition} exists for the collection indicated by the entity
|
||||
* class. If not it will be created.
|
||||
*
|
||||
* @param indexDefinition must not be {@literal null}.
|
||||
*/
|
||||
void ensureIndex(IndexDefinition indexDefinition);
|
||||
|
||||
/**
|
||||
* Drops an index from this collection.
|
||||
*
|
||||
* @param name name of index to drop
|
||||
*/
|
||||
void dropIndex(String name);
|
||||
|
||||
/**
|
||||
* Drops all indices from this collection.
|
||||
*/
|
||||
void dropAllIndexes();
|
||||
|
||||
/**
|
||||
* Clears all indices that have not yet been applied to this collection.
|
||||
*/
|
||||
void resetIndexCache();
|
||||
|
||||
/**
|
||||
* Returns the index information on the collection.
|
||||
*
|
||||
* @return index information on the collection
|
||||
*/
|
||||
List<IndexInfo> getIndexInfo();
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* Represents an action taken against the collection. Used by {@link WriteConcernResolver} to determine a custom
|
||||
* WriteConcern based on this information.
|
||||
*
|
||||
* Properties that will always be not-null are collectionName and defaultWriteConcern. The EntityClass is null only for
|
||||
* the MongoActionOperaton.INSERT_LIST.
|
||||
*
|
||||
* <ul>
|
||||
* <li>INSERT, SAVE have null query</li>
|
||||
* <li>REMOVE has null document</li>
|
||||
* <li>INSERT_LIST has null entityClass, document, and query</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
*/
|
||||
public class MongoAction {
|
||||
|
||||
private String collectionName;
|
||||
|
||||
private WriteConcern defaultWriteConcern;
|
||||
|
||||
private Class<?> entityClass;
|
||||
|
||||
private MongoActionOperation mongoActionOperation;
|
||||
|
||||
private DBObject query;
|
||||
|
||||
private DBObject document;
|
||||
|
||||
/**
|
||||
* Create an instance of a MongoAction
|
||||
*
|
||||
* @param defaultWriteConcern the default write concern
|
||||
* @param mongoActionOperation action being taken against the collection
|
||||
* @param collectionName the collection name
|
||||
* @param entityClass the POJO that is being operated against
|
||||
* @param document the converted DBObject from the POJO or Spring Update object
|
||||
* @param query the converted DBOjbect from the Spring Query object
|
||||
*/
|
||||
public MongoAction(WriteConcern defaultWriteConcern, MongoActionOperation mongoActionOperation,
|
||||
String collectionName, Class<?> entityClass, DBObject document, DBObject query) {
|
||||
super();
|
||||
this.defaultWriteConcern = defaultWriteConcern;
|
||||
this.mongoActionOperation = mongoActionOperation;
|
||||
this.collectionName = collectionName;
|
||||
this.entityClass = entityClass;
|
||||
this.query = query;
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
public String getCollectionName() {
|
||||
return collectionName;
|
||||
}
|
||||
|
||||
public WriteConcern getDefaultWriteConcern() {
|
||||
return defaultWriteConcern;
|
||||
}
|
||||
|
||||
public Class<?> getEntityClass() {
|
||||
return entityClass;
|
||||
}
|
||||
|
||||
public MongoActionOperation getMongoActionOperation() {
|
||||
return mongoActionOperation;
|
||||
}
|
||||
|
||||
public DBObject getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public DBObject getDocument() {
|
||||
return document;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,16 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.query;
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
public class NorCriteria extends OrCriteria {
|
||||
/**
|
||||
* Enumeration for operations on a collection. Used with {@link MongoAction} to help determine the WriteConcern to use
|
||||
* for a given mutating operation
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @see MongoAction
|
||||
*
|
||||
*/
|
||||
public enum MongoActionOperation {
|
||||
|
||||
public NorCriteria(Query[] queries) {
|
||||
super(queries);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getOperator() {
|
||||
return "$nor";
|
||||
}
|
||||
REMOVE, UPDATE, INSERT, INSERT_LIST, SAVE
|
||||
}
|
||||
@@ -15,14 +15,15 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.data.mongodb.CannotGetMongoDbConnectionException;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
|
||||
/**
|
||||
* Helper class featuring helper methods for internal MongoDb classes.
|
||||
* <p/>
|
||||
@@ -78,7 +79,7 @@ public abstract class MongoDbUtils {
|
||||
DB db = null;
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive() && dbHolder.doesNotHoldNonDefaultDB()) {
|
||||
// Spring transaction management is active ->
|
||||
db = dbHolder.getDB();
|
||||
db = dbHolder.getDB(databaseName);
|
||||
if (db != null && !dbHolder.isSynchronizedWithTransaction()) {
|
||||
LOGGER.debug("Registering Spring transaction synchronization for existing Mongo DB");
|
||||
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(dbHolder, mongo));
|
||||
@@ -96,10 +97,12 @@ public abstract class MongoDbUtils {
|
||||
boolean credentialsGiven = username != null && password != null;
|
||||
if (credentialsGiven && !db.isAuthenticated()) {
|
||||
// Note, can only authenticate once against the same com.mongodb.DB object.
|
||||
if (!db.authenticate(username, password)) {
|
||||
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName
|
||||
+ "], username = [" + username + "], password = [" + new String(password) + "]", databaseName, username,
|
||||
password);
|
||||
synchronized (db) {
|
||||
if (!db.authenticate(username, password)) {
|
||||
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName
|
||||
+ "], username = [" + username + "], password = [" + new String(password) + "]", databaseName, username,
|
||||
password);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,9 +113,9 @@ public abstract class MongoDbUtils {
|
||||
LOGGER.debug("Registering Spring transaction synchronization for new Hibernate Session");
|
||||
DbHolder holderToUse = dbHolder;
|
||||
if (holderToUse == null) {
|
||||
holderToUse = new DbHolder(db);
|
||||
holderToUse = new DbHolder(databaseName, db);
|
||||
} else {
|
||||
holderToUse.addDB(db);
|
||||
holderToUse.addDB(databaseName, db);
|
||||
}
|
||||
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(holderToUse, mongo));
|
||||
holderToUse.setSynchronizedWithTransaction(true);
|
||||
@@ -143,7 +146,7 @@ public abstract class MongoDbUtils {
|
||||
return false;
|
||||
}
|
||||
DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo);
|
||||
return (dbHolder != null && dbHolder.containsDB(db));
|
||||
return dbHolder != null && dbHolder.containsDB(db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-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.
|
||||
@@ -13,17 +13,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.mongodb.CannotGetMongoDbConnectionException;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoOptions;
|
||||
import com.mongodb.ServerAddress;
|
||||
@@ -37,12 +38,10 @@ import com.mongodb.WriteConcern;
|
||||
* @author Oliver Gierke
|
||||
* @since 1.0
|
||||
*/
|
||||
public class MongoFactoryBean implements FactoryBean<Mongo>, PersistenceExceptionTranslator {
|
||||
public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, DisposableBean,
|
||||
PersistenceExceptionTranslator {
|
||||
|
||||
/**
|
||||
* Logger, available to subclasses.
|
||||
*/
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
private Mongo mongo;
|
||||
|
||||
private MongoOptions mongoOptions;
|
||||
private String host;
|
||||
@@ -57,12 +56,12 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, PersistenceExceptio
|
||||
this.mongoOptions = mongoOptions;
|
||||
}
|
||||
|
||||
public void setReplicaSetSeeds(List<ServerAddress> replicaSetSeeds) {
|
||||
this.replicaSetSeeds = replicaSetSeeds;
|
||||
public void setReplicaSetSeeds(ServerAddress[] replicaSetSeeds) {
|
||||
this.replicaSetSeeds = Arrays.asList(replicaSetSeeds);
|
||||
}
|
||||
|
||||
public void setReplicaPair(List<ServerAddress> replicaPair) {
|
||||
this.replicaPair = replicaPair;
|
||||
public void setReplicaPair(ServerAddress[] replicaPair) {
|
||||
this.replicaPair = Arrays.asList(replicaPair);
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
@@ -87,42 +86,7 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, PersistenceExceptio
|
||||
}
|
||||
|
||||
public Mongo getObject() throws Exception {
|
||||
|
||||
Mongo mongo;
|
||||
|
||||
if (host == null) {
|
||||
|
||||
logger.debug("Property host not specified. Using default configuration");
|
||||
mongo = new Mongo();
|
||||
|
||||
} else {
|
||||
|
||||
ServerAddress defaultOptions = new ServerAddress();
|
||||
|
||||
if (mongoOptions == null) {
|
||||
mongoOptions = new MongoOptions();
|
||||
}
|
||||
|
||||
if (replicaPair != null) {
|
||||
if (replicaPair.size() < 2) {
|
||||
throw new CannotGetMongoDbConnectionException("A replica pair must have two server entries");
|
||||
}
|
||||
mongo = new Mongo(replicaPair.get(0), replicaPair.get(1), mongoOptions);
|
||||
} else if (replicaSetSeeds != null) {
|
||||
mongo = new Mongo(replicaSetSeeds, mongoOptions);
|
||||
} else {
|
||||
String mongoHost = host != null ? host : defaultOptions.getHost();
|
||||
mongo = port != null ? new Mongo(new ServerAddress(mongoHost, port), mongoOptions) : new Mongo(mongoHost,
|
||||
mongoOptions);
|
||||
}
|
||||
}
|
||||
|
||||
if (writeConcern != null) {
|
||||
mongo.setWriteConcern(writeConcern);
|
||||
}
|
||||
|
||||
return mongo;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -148,4 +112,45 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, PersistenceExceptio
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
return exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
Mongo mongo;
|
||||
ServerAddress defaultOptions = new ServerAddress();
|
||||
|
||||
if (mongoOptions == null) {
|
||||
mongoOptions = new MongoOptions();
|
||||
}
|
||||
|
||||
if (replicaPair != null) {
|
||||
if (replicaPair.size() < 2) {
|
||||
throw new CannotGetMongoDbConnectionException("A replica pair must have two server entries");
|
||||
}
|
||||
mongo = new Mongo(replicaPair.get(0), replicaPair.get(1), mongoOptions);
|
||||
} else if (replicaSetSeeds != null) {
|
||||
mongo = new Mongo(replicaSetSeeds, mongoOptions);
|
||||
} else {
|
||||
String mongoHost = host != null ? host : defaultOptions.getHost();
|
||||
mongo = port != null ? new Mongo(new ServerAddress(mongoHost, port), mongoOptions) : new Mongo(mongoHost,
|
||||
mongoOptions);
|
||||
}
|
||||
|
||||
if (writeConcern != null) {
|
||||
mongo.setWriteConcern(writeConcern);
|
||||
}
|
||||
|
||||
this.mongo = mongo;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
*/
|
||||
public void destroy() throws Exception {
|
||||
this.mongo.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,21 +19,24 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResult;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResults;
|
||||
import org.springframework.data.mongodb.core.mapreduce.GroupBy;
|
||||
import org.springframework.data.mongodb.core.mapreduce.GroupByResults;
|
||||
import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions;
|
||||
import org.springframework.data.mongodb.core.mapreduce.MapReduceResults;
|
||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
|
||||
import com.mongodb.CommandResult;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.WriteResult;
|
||||
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResult;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResults;
|
||||
import org.springframework.data.mongodb.core.index.IndexDefinition;
|
||||
import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions;
|
||||
import org.springframework.data.mongodb.core.mapreduce.MapReduceResults;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
|
||||
/**
|
||||
* Interface that specifies a basic set of MongoDB operations. Implemented by {@link MongoTemplate}. Not often used but
|
||||
* a useful option for extensibility and testability (as it can be easily mocked, stubbed, or be the target of a JDK
|
||||
@@ -48,6 +51,7 @@ public interface MongoOperations {
|
||||
/**
|
||||
* The collection name used for the specified class by this template.
|
||||
*
|
||||
* @param entityClass must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
String getCollectionName(Class<?> entityClass);
|
||||
@@ -68,7 +72,7 @@ public interface MongoOperations {
|
||||
* @param command a MongoDB command
|
||||
*/
|
||||
CommandResult executeCommand(DBObject command);
|
||||
|
||||
|
||||
/**
|
||||
* Execute a MongoDB command. Any errors that result from executing this command will be converted into Spring's DAO
|
||||
* exception hierarchy.
|
||||
@@ -77,28 +81,16 @@ public interface MongoOperations {
|
||||
* @param options query options to use
|
||||
*/
|
||||
CommandResult executeCommand(DBObject command, int options);
|
||||
|
||||
|
||||
/**
|
||||
* Execute a MongoDB query and iterate over the query results on a per-document basis with a DocumentCallbackHandler.
|
||||
* Execute a MongoDB query and iterate over the query results on a per-document basis with a DocumentCallbackHandler.
|
||||
*
|
||||
* @param query the query class that specifies the criteria used to find a record and also an optional fields
|
||||
* specification
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
* @param dch the handler that will extract results, one document at a time
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
* @param dch the handler that will extract results, one document at a time
|
||||
*/
|
||||
void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch);
|
||||
|
||||
/**
|
||||
* Execute a MongoDB query and iterate over the query results on a per-document basis with a DocumentCallbackHandler using the
|
||||
* provided CursorPreparer.
|
||||
* @param query the query class that specifies the criteria used to find a record and also an optional fields
|
||||
* specification
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
* @param dch the handler that will extract results, one document at a time
|
||||
* @param preparer allows for customization of the DBCursor used when iterating over the result set, (apply limits,
|
||||
* skips and so on).
|
||||
*/
|
||||
void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch, CursorPreparer preparer);
|
||||
|
||||
/**
|
||||
* Executes a {@link DbCallback} translating any exceptions as necessary.
|
||||
@@ -237,6 +229,20 @@ public interface MongoOperations {
|
||||
*/
|
||||
void dropCollection(String collectionName);
|
||||
|
||||
/**
|
||||
* Returns the operations that can be performed on indexes
|
||||
*
|
||||
* @return index operations on the named collection
|
||||
*/
|
||||
IndexOperations indexOps(String collectionName);
|
||||
|
||||
/**
|
||||
* Returns the operations that can be performed on indexes
|
||||
*
|
||||
* @return index operations on the named collection associated with the given entity class
|
||||
*/
|
||||
IndexOperations indexOps(Class<?> entityClass);
|
||||
|
||||
/**
|
||||
* Query for a list of objects of type T from the collection used by the entity class.
|
||||
* <p/>
|
||||
@@ -265,11 +271,39 @@ public interface MongoOperations {
|
||||
* @return the converted collection
|
||||
*/
|
||||
<T> List<T> findAll(Class<T> entityClass, String collectionName);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Execute a map-reduce operation. The map-reduce operation will be formed with an output type of INLINE
|
||||
* Execute a group operation over the entire collection. The group operation entity class should match the 'shape' of
|
||||
* the returned object that takes int account the initial document structure as well as any finalize functions.
|
||||
*
|
||||
* @param criteria The criteria that restricts the row that are considered for grouping. If not specified all rows are
|
||||
* considered.
|
||||
* @param inputCollectionName the collection where the group operation will read from
|
||||
* @param groupBy the conditions under which the group operation will be performed, e.g. keys, initial document,
|
||||
* reduce function.
|
||||
* @param entityClass The parameterized type of the returned list
|
||||
* @return The results of the group operation
|
||||
*/
|
||||
<T> GroupByResults<T> group(String inputCollectionName, GroupBy groupBy, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Execute a group operation restricting the rows to those which match the provided Criteria. The group operation
|
||||
* entity class should match the 'shape' of the returned object that takes int account the initial document structure
|
||||
* as well as any finalize functions.
|
||||
*
|
||||
* @param criteria The criteria that restricts the row that are considered for grouping. If not specified all rows are
|
||||
* considered.
|
||||
* @param inputCollectionName the collection where the group operation will read from
|
||||
* @param groupBy the conditions under which the group operation will be performed, e.g. keys, initial document,
|
||||
* reduce function.
|
||||
* @param entityClass The parameterized type of the returned list
|
||||
* @return The results of the group operation
|
||||
*/
|
||||
<T> GroupByResults<T> group(Criteria criteria, String inputCollectionName, GroupBy groupBy, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Execute a map-reduce operation. The map-reduce operation will be formed with an output type of INLINE
|
||||
*
|
||||
* @param inputCollectionName the collection where the map-reduce will read from
|
||||
* @param mapFunction The JavaScript map function
|
||||
* @param reduceFunction The JavaScript reduce function
|
||||
@@ -277,11 +311,12 @@ public interface MongoOperations {
|
||||
* @param entityClass The parameterized type of the returned list
|
||||
* @return The results of the map reduce operation
|
||||
*/
|
||||
<T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction, Class<T> entityClass );
|
||||
<T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction,
|
||||
Class<T> entityClass);
|
||||
|
||||
|
||||
/**
|
||||
* Execute a map-reduce operation that takes additional map-reduce options.
|
||||
*
|
||||
* @param inputCollectionName the collection where the map-reduce will read from
|
||||
* @param mapFunction The JavaScript map function
|
||||
* @param reduceFunction The JavaScript reduce function
|
||||
@@ -289,12 +324,13 @@ public interface MongoOperations {
|
||||
* @param entityClass The parameterized type of the returned list
|
||||
* @return The results of the map reduce operation
|
||||
*/
|
||||
<T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction, MapReduceOptions mapReduceOptions, Class<T> entityClass );
|
||||
|
||||
|
||||
|
||||
<T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction,
|
||||
MapReduceOptions mapReduceOptions, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Execute a map-reduce operation that takes a query. The map-reduce operation will be formed with an output type of INLINE
|
||||
* Execute a map-reduce operation that takes a query. The map-reduce operation will be formed with an output type of
|
||||
* INLINE
|
||||
*
|
||||
* @param query The query to use to select the data for the map phase
|
||||
* @param inputCollectionName the collection where the map-reduce will read from
|
||||
* @param mapFunction The JavaScript map function
|
||||
@@ -303,10 +339,12 @@ public interface MongoOperations {
|
||||
* @param entityClass The parameterized type of the returned list
|
||||
* @return The results of the map reduce operation
|
||||
*/
|
||||
<T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction, String reduceFunction, Class<T> entityClass );
|
||||
|
||||
<T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction, String reduceFunction,
|
||||
Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Execute a map-reduce operation that takes a query and additional map-reduce options
|
||||
*
|
||||
* @param query The query to use to select the data for the map phase
|
||||
* @param inputCollectionName the collection where the map-reduce will read from
|
||||
* @param mapFunction The JavaScript map function
|
||||
@@ -315,7 +353,8 @@ public interface MongoOperations {
|
||||
* @param entityClass The parameterized type of the returned list
|
||||
* @return The results of the map reduce operation
|
||||
*/
|
||||
<T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction, String reduceFunction, MapReduceOptions mapReduceOptions, Class<T> entityClass );
|
||||
<T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction, String reduceFunction,
|
||||
MapReduceOptions mapReduceOptions, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Returns {@link GeoResult} for all entities matching the given {@link NearQuery}. Will consider entity mapping
|
||||
@@ -338,23 +377,6 @@ public interface MongoOperations {
|
||||
*/
|
||||
<T> GeoResults<T> geoNear(NearQuery near, Class<T> entityClass, String collectionName);
|
||||
|
||||
/**
|
||||
* Ensure that an index for the provided {@link IndexDefinition} exists for the collection indicated by the entity
|
||||
* class. If not it will be created.
|
||||
*
|
||||
* @param indexDefinition
|
||||
* @param entityClass class that determines the collection to use
|
||||
*/
|
||||
void ensureIndex(IndexDefinition indexDefinition, Class<?> entityClass);
|
||||
|
||||
/**
|
||||
* Ensure that an index for the provided {@link IndexDefinition} exists. If not it will be created.
|
||||
*
|
||||
* @param index
|
||||
* @param collectionName
|
||||
*/
|
||||
void ensureIndex(IndexDefinition indexDefinition, String collectionName);
|
||||
|
||||
/**
|
||||
* Map the results of an ad-hoc query on the collection for the entity class to a single instance of an object of the
|
||||
* specified type.
|
||||
@@ -425,26 +447,6 @@ public interface MongoOperations {
|
||||
*/
|
||||
<T> List<T> find(Query query, Class<T> entityClass, String collectionName);
|
||||
|
||||
/**
|
||||
* Map the results of an ad-hoc query on the specified collection to a List of the specified type.
|
||||
* <p/>
|
||||
* 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.
|
||||
* <p/>
|
||||
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
|
||||
* feature rich {@link Query}.
|
||||
*
|
||||
* @param query the query class that specifies the criteria used to find a record and also an optional fields
|
||||
* specification
|
||||
* @param entityClass the parameterized type of the returned list.
|
||||
* @param preparer allows for customization of the DBCursor used when iterating over the result set, (apply limits,
|
||||
* skips and so on).
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
*
|
||||
* @return the List of converted objects.
|
||||
*/
|
||||
<T> List<T> find(Query query, Class<T> entityClass, CursorPreparer preparer, String collectionName);
|
||||
|
||||
/**
|
||||
* Returns a document with the given id mapped onto the given class. The collection the query is ran against will be
|
||||
* derived from the given target class as well.
|
||||
@@ -468,6 +470,15 @@ public interface MongoOperations {
|
||||
*/
|
||||
<T> T findById(Object id, Class<T> entityClass, String collectionName);
|
||||
|
||||
<T> T findAndModify(Query query, Update update, Class<T> entityClass);
|
||||
|
||||
<T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName);
|
||||
|
||||
<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass);
|
||||
|
||||
<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass,
|
||||
String collectionName);
|
||||
|
||||
/**
|
||||
* Map the results of an ad-hoc query on the collection for the entity type to a single instance of an object of the
|
||||
* specified type. The first document that matches the query is returned and also removed from the collection in the
|
||||
@@ -504,6 +515,24 @@ public interface MongoOperations {
|
||||
*/
|
||||
<T> T findAndRemove(Query query, Class<T> entityClass, String collectionName);
|
||||
|
||||
/**
|
||||
* Returns the number of documents for the given {@link Query} by querying the collection of the given entity class.
|
||||
*
|
||||
* @param query
|
||||
* @param entityClass must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
long count(Query query, Class<?> entityClass);
|
||||
|
||||
/**
|
||||
* Returns the number of documents for the given {@link Query} querying the given collection.
|
||||
*
|
||||
* @param query
|
||||
* @param collectionName must not be {@literal null} or empty.
|
||||
* @return
|
||||
*/
|
||||
long count(Query query, String collectionName);
|
||||
|
||||
/**
|
||||
* Insert the object into the collection for the entity type of the object to save.
|
||||
* <p/>
|
||||
@@ -594,6 +623,29 @@ public interface MongoOperations {
|
||||
*/
|
||||
void save(Object objectToSave, 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 that determines the collection to use
|
||||
* @return the WriteResult which lets you access the results of the previous write.
|
||||
*/
|
||||
WriteResult upsert(Query query, Update update, Class<?> entityClass);
|
||||
|
||||
/**
|
||||
* 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 updated
|
||||
* @param update the update document that contains the updated object or $ operators to manipulate the existing
|
||||
* object.
|
||||
* @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, String collectionName);
|
||||
|
||||
/**
|
||||
* Updates the first object that is found in the collection of the entity class that matches the query document with
|
||||
* the provided update document.
|
||||
@@ -602,6 +654,7 @@ public interface MongoOperations {
|
||||
* @param update the update document that contains the updated object or $ operators to manipulate the existing
|
||||
* object.
|
||||
* @param entityClass class that determines the collection to use
|
||||
* @return the WriteResult which lets you access the results of the previous write.
|
||||
*/
|
||||
WriteResult updateFirst(Query query, Update update, Class<?> entityClass);
|
||||
|
||||
@@ -613,6 +666,7 @@ public interface MongoOperations {
|
||||
* @param update the update document that contains the updated object or $ operators to manipulate the existing
|
||||
* object.
|
||||
* @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, String collectionName);
|
||||
|
||||
@@ -624,6 +678,7 @@ public interface MongoOperations {
|
||||
* @param update the update document that contains the updated object or $ operators to manipulate the existing
|
||||
* object.
|
||||
* @param entityClass class that determines the collection to use
|
||||
* @return the WriteResult which lets you access the results of the previous write.
|
||||
*/
|
||||
WriteResult updateMulti(Query query, Update update, Class<?> entityClass);
|
||||
|
||||
@@ -635,16 +690,25 @@ public interface MongoOperations {
|
||||
* @param update the update document that contains the updated object or $ operators to manipulate the existing
|
||||
* object.
|
||||
* @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(Query query, Update update, String collectionName);
|
||||
|
||||
/**
|
||||
* Remove the given object from the collection by Id
|
||||
* Remove the given object from the collection by id.
|
||||
*
|
||||
* @param object
|
||||
*/
|
||||
void remove(Object object);
|
||||
|
||||
/**
|
||||
* Removes the given object from the given collection.
|
||||
*
|
||||
* @param object
|
||||
* @param collection must not be {@literal null} or empty.
|
||||
*/
|
||||
void remove(Object object, String collection);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
||||
@@ -68,6 +68,8 @@ public class MongoOptionsFactoryBean implements FactoryBean<MongoOptions>, Initi
|
||||
*/
|
||||
private boolean autoConnectRetry = MONGO_OPTIONS.autoConnectRetry;
|
||||
|
||||
private long maxAutoConnectRetryTime = MONGO_OPTIONS.maxAutoConnectRetryTime;
|
||||
|
||||
/**
|
||||
* This specifies the number of servers to wait for on the write operation, and exception raising behavior.
|
||||
*
|
||||
@@ -94,6 +96,7 @@ public class MongoOptionsFactoryBean implements FactoryBean<MongoOptions>, Initi
|
||||
*
|
||||
* Defaults to false
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private boolean slaveOk = MONGO_OPTIONS.slaveOk;
|
||||
|
||||
/**
|
||||
@@ -183,6 +186,16 @@ public class MongoOptionsFactoryBean implements FactoryBean<MongoOptions>, Initi
|
||||
this.autoConnectRetry = autoConnectRetry;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum amount of time in millisecons to spend retrying to open connection to the same server. Default is 0,
|
||||
* which means to use the default 15s if autoConnectRetry is on.
|
||||
*
|
||||
* @param maxAutoConnectRetryTime the maxAutoConnectRetryTime to set
|
||||
*/
|
||||
public void setMaxAutoConnectRetryTime(long maxAutoConnectRetryTime) {
|
||||
this.maxAutoConnectRetryTime = maxAutoConnectRetryTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies if the driver is allowed to read from secondaries or slaves. Defaults to false.
|
||||
*
|
||||
@@ -192,6 +205,7 @@ public class MongoOptionsFactoryBean implements FactoryBean<MongoOptions>, Initi
|
||||
this.slaveOk = slaveOk;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void afterPropertiesSet() {
|
||||
MONGO_OPTIONS.connectionsPerHost = connectionsPerHost;
|
||||
MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
|
||||
@@ -200,6 +214,7 @@ public class MongoOptionsFactoryBean implements FactoryBean<MongoOptions>, Initi
|
||||
MONGO_OPTIONS.socketTimeout = socketTimeout;
|
||||
MONGO_OPTIONS.socketKeepAlive = socketKeepAlive;
|
||||
MONGO_OPTIONS.autoConnectRetry = autoConnectRetry;
|
||||
MONGO_OPTIONS.maxAutoConnectRetryTime = maxAutoConnectRetryTime;
|
||||
MONGO_OPTIONS.slaveOk = slaveOk;
|
||||
MONGO_OPTIONS.w = writeNumber;
|
||||
MONGO_OPTIONS.wtimeout = writeTimeout;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,9 +25,12 @@ import org.bson.types.ObjectId;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
@@ -39,97 +42,131 @@ import com.mongodb.DBObject;
|
||||
*/
|
||||
public class QueryMapper {
|
||||
|
||||
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 MongoConverter converter;
|
||||
|
||||
/**
|
||||
* Creates a new {@link QueryMapper} with the given {@link ConversionService}.
|
||||
* Creates a new {@link QueryMapper} with the given {@link MongoConverter}.
|
||||
*
|
||||
* @param conversionService must not be {@literal null}.
|
||||
* @param converter must not be {@literal null}.
|
||||
*/
|
||||
public QueryMapper(ConversionService conversionService) {
|
||||
Assert.notNull(conversionService);
|
||||
this.conversionService = conversionService;
|
||||
public QueryMapper(MongoConverter converter) {
|
||||
Assert.notNull(converter);
|
||||
this.conversionService = converter.getConversionService();
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the property keys used in the given {@link DBObject} with the appropriate keys by using the
|
||||
* {@link PersistentEntity} metadata.
|
||||
*
|
||||
* @param query
|
||||
* @param entity
|
||||
* @param query must not be {@literal null}.
|
||||
* @param entity can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public DBObject getMappedObject(DBObject query, MongoPersistentEntity<?> entity) {
|
||||
String idKey = null;
|
||||
if (null != entity && entity.getIdProperty() != null) {
|
||||
idKey = entity.getIdProperty().getName();
|
||||
} else if (query.containsField("id")) {
|
||||
idKey = "id";
|
||||
} else if (query.containsField("_id")) {
|
||||
idKey = "_id";
|
||||
}
|
||||
|
||||
DBObject newDbo = new BasicDBObject();
|
||||
|
||||
for (String key : query.keySet()) {
|
||||
|
||||
String newKey = key;
|
||||
Object value = query.get(key);
|
||||
if (key.equals(idKey)) {
|
||||
|
||||
if (isIdKey(key, entity)) {
|
||||
if (value instanceof DBObject) {
|
||||
DBObject valueDbo = (DBObject) value;
|
||||
if (valueDbo.containsField("$in") || valueDbo.containsField("$nin")) {
|
||||
String inKey = valueDbo.containsField("$in") ? "$in" : "$nin";
|
||||
List<Object> ids = new ArrayList<Object>();
|
||||
for (Object id : (Object[]) valueDbo.get(inKey)) {
|
||||
for (Object id : (Iterable<?>) valueDbo.get(inKey)) {
|
||||
ids.add(convertId(id));
|
||||
}
|
||||
valueDbo.put(inKey, ids.toArray(new Object[ids.size()]));
|
||||
} else if (valueDbo.containsField("$ne")) {
|
||||
valueDbo.put("$ne", convertId(valueDbo.get("$ne")));
|
||||
} else {
|
||||
value = getMappedObject((DBObject) value, entity);
|
||||
value = getMappedObject((DBObject) value, null);
|
||||
}
|
||||
} else {
|
||||
|
||||
value = convertId(value);
|
||||
}
|
||||
newKey = "_id";
|
||||
} else if (key.startsWith("$") && key.endsWith("or")) {
|
||||
} else if (key.matches(N_OR_PATTERN)) {
|
||||
// $or/$nor
|
||||
BasicBSONList conditions = (BasicBSONList) value;
|
||||
Iterable<?> conditions = (Iterable<?>) value;
|
||||
BasicBSONList newConditions = new BasicBSONList();
|
||||
Iterator<Object> iter = conditions.iterator();
|
||||
Iterator<?> iter = conditions.iterator();
|
||||
while (iter.hasNext()) {
|
||||
newConditions.add(getMappedObject((DBObject) iter.next(), entity));
|
||||
}
|
||||
value = newConditions;
|
||||
} else {
|
||||
// TODO: Implement other forms of conversion (like @Alias and whatnot)
|
||||
}
|
||||
newDbo.put(newKey, value);
|
||||
|
||||
newDbo.put(newKey, convertSimpleOrDBObject(value, null));
|
||||
}
|
||||
|
||||
return newDbo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retriggers mapping if the given source is a {@link DBObject} or simply invokes the
|
||||
*
|
||||
* @param source
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
private Object convertSimpleOrDBObject(Object source, MongoPersistentEntity<?> entity) {
|
||||
|
||||
if (source instanceof BasicDBList) {
|
||||
return converter.convertToMongoType(source);
|
||||
}
|
||||
|
||||
if (source instanceof DBObject) {
|
||||
return getMappedObject((DBObject) source, entity);
|
||||
}
|
||||
|
||||
return converter.convertToMongoType(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given key will be considered an id key.
|
||||
*
|
||||
* @param key
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
private boolean isIdKey(String key, MongoPersistentEntity<?> entity) {
|
||||
|
||||
if (entity == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entity.getIdProperty() != null) {
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
return idProperty.getName().equals(key) || idProperty.getFieldName().equals(key);
|
||||
}
|
||||
|
||||
return DEFAULT_ID_NAMES.contains(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given raw id value into either {@link ObjectId} or {@link String}.
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object convertId(Object id) {
|
||||
|
||||
for (Class<?> type : Arrays.asList(ObjectId.class, String.class)) {
|
||||
|
||||
if (id.getClass().isAssignableFrom(type)) {
|
||||
return id;
|
||||
}
|
||||
|
||||
try {
|
||||
return conversionService.convert(id, type);
|
||||
} catch (ConversionException e) {
|
||||
// Ignore
|
||||
}
|
||||
try {
|
||||
return conversionService.convert(id, ObjectId.class);
|
||||
} catch (ConversionException e) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
return id;
|
||||
return converter.convertToMongoType(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
@@ -25,6 +25,8 @@ import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.MongoURI;
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
@@ -35,12 +37,10 @@ import com.mongodb.WriteConcern;
|
||||
*/
|
||||
public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final Mongo mongo;
|
||||
private final String databaseName;
|
||||
private String username;
|
||||
private String password;
|
||||
private final boolean mongoInstanceCreated;
|
||||
private final UserCredentials credentials;
|
||||
private WriteConcern writeConcern;
|
||||
|
||||
/**
|
||||
@@ -50,11 +50,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
* @param databaseName database name, not be {@literal null}.
|
||||
*/
|
||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName) {
|
||||
Assert.notNull(mongo, "Mongo must not be null");
|
||||
Assert.hasText(databaseName, "Database name must not be empty");
|
||||
Assert.isTrue(databaseName.matches("[\\w-]+"), "Database name must only contain letters, numbers, underscores and dashes!");
|
||||
this.mongo = mongo;
|
||||
this.databaseName = databaseName;
|
||||
this(mongo, databaseName, new UserCredentials(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,12 +58,36 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
*
|
||||
* @param mongo Mongo instance, must not be {@literal null}.
|
||||
* @param databaseName Database name, must not be {@literal null}.
|
||||
* @param userCredentials username and password must not be {@literal null}.
|
||||
* @param credentials username and password.
|
||||
*/
|
||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials userCredentials) {
|
||||
this(mongo, databaseName);
|
||||
this.username = userCredentials.getUsername();
|
||||
this.password = userCredentials.getPassword();
|
||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials) {
|
||||
this(mongo, databaseName, credentials, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoURI}.
|
||||
*
|
||||
* @param uri must not be {@literal null}.
|
||||
* @throws MongoException
|
||||
* @throws UnknownHostException
|
||||
* @see MongoURI
|
||||
*/
|
||||
public SimpleMongoDbFactory(MongoURI uri) throws MongoException, UnknownHostException {
|
||||
this(new Mongo(uri), uri.getDatabase(), new UserCredentials(uri.getUsername(), parseChars(uri.getPassword())), true);
|
||||
}
|
||||
|
||||
private SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials,
|
||||
boolean mongoInstanceCreated) {
|
||||
|
||||
Assert.notNull(mongo, "Mongo must not be null");
|
||||
Assert.hasText(databaseName, "Database name must not be empty");
|
||||
Assert.isTrue(databaseName.matches("[\\w-]+"),
|
||||
"Database name must only contain letters, numbers, underscores and dashes!");
|
||||
|
||||
this.mongo = mongo;
|
||||
this.databaseName = databaseName;
|
||||
this.mongoInstanceCreated = mongoInstanceCreated;
|
||||
this.credentials = credentials == null ? new UserCredentials() : credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,6 +115,9 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
|
||||
Assert.hasText(dbName, "Database name must not be empty.");
|
||||
|
||||
String username = credentials.getUsername();
|
||||
String password = credentials.getPassword();
|
||||
|
||||
DB db = MongoDbUtils.getDB(mongo, dbName, username, password == null ? null : password.toCharArray());
|
||||
|
||||
if (writeConcern != null) {
|
||||
@@ -105,9 +128,17 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up the Mongo instance.
|
||||
* Clean up the Mongo instance if it was created by the factory itself.
|
||||
*
|
||||
* @see DisposableBean#destroy()
|
||||
*/
|
||||
public void destroy() throws Exception {
|
||||
mongo.close();
|
||||
if (mongoInstanceCreated) {
|
||||
mongo.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static String parseChars(char[] chars) {
|
||||
return chars == null ? null : String.valueOf(chars);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* A strategy interface to determine the WriteConcern to use for a given MongoDbAction.
|
||||
*
|
||||
* Return the passed in default WriteConcern (a property on MongoAction) if no determination can be made.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
*/
|
||||
public interface WriteConcernResolver {
|
||||
|
||||
/**
|
||||
* Resolve the WriteConcern given the MongoAction
|
||||
*
|
||||
* @param action describes the context of the Mongo action. Contains a default WriteConcern to use if one should not
|
||||
* be resolved.
|
||||
* @return a WriteConcern based on the passed in MongoAction value, maybe null
|
||||
*/
|
||||
WriteConcern resolve(MongoAction action);
|
||||
}
|
||||
@@ -17,16 +17,15 @@
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToObjectIdConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToBigIntegerConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToObjectIdConverter;
|
||||
|
||||
/**
|
||||
@@ -46,10 +45,10 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
|
||||
*
|
||||
* @param conversionService
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public AbstractMongoConverter(GenericConversionService conversionService) {
|
||||
this.conversionService = conversionService == null ? ConversionServiceFactory.createDefaultConversionService()
|
||||
: conversionService;
|
||||
this.conversionService.removeConvertible(Object.class, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,12 +79,6 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
|
||||
if (!conversionService.canConvert(BigInteger.class, ObjectId.class)) {
|
||||
conversionService.addConverter(BigIntegerToObjectIdConverter.INSTANCE);
|
||||
}
|
||||
if (!conversionService.canConvert(BigInteger.class, String.class)) {
|
||||
conversionService.addConverter(BigIntegerToStringConverter.INSTANCE);
|
||||
}
|
||||
if (!conversionService.canConvert(String.class, BigInteger.class)) {
|
||||
conversionService.addConverter(StringToBigIntegerConverter.INSTANCE);
|
||||
}
|
||||
|
||||
conversions.registerConvertersIn(conversionService);
|
||||
}
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link TypeMapper} allowing to configure a {@link Map} containing {@link Class} to {@link String} mappings that will
|
||||
* be used to map the values found under the configured type key (see {@link DefaultTypeMapper#setTypeKey(String)}. This
|
||||
* allows declarative type mapping in a Spring config file for example.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ConfigurableTypeMapper extends DefaultTypeMapper {
|
||||
|
||||
private final Map<TypeInformation<?>, String> typeMap;
|
||||
private boolean handleUnmappedClasses = false;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConfigurableTypeMapper} for the given type map.
|
||||
*
|
||||
* @param sourceTypeMap must not be {@literal null}.
|
||||
*/
|
||||
public ConfigurableTypeMapper(Map<? extends Class<?>, String> sourceTypeMap) {
|
||||
|
||||
Assert.notNull(sourceTypeMap);
|
||||
|
||||
this.typeMap = new HashMap<TypeInformation<?>, String>(sourceTypeMap.size());
|
||||
|
||||
for (Entry<? extends Class<?>, String> entry : sourceTypeMap.entrySet()) {
|
||||
TypeInformation<?> key = ClassTypeInformation.from(entry.getKey());
|
||||
String value = entry.getValue();
|
||||
|
||||
if (typeMap.containsValue(value)) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Detected mapping ambiguity! String %s cannot be mapped to more than one type!", value));
|
||||
}
|
||||
|
||||
this.typeMap.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures whether to try to handle unmapped classes by simply writing the class' name or loading the class as
|
||||
* specified in the superclass. Defaults to {@literal false}.
|
||||
*
|
||||
* @param handleUnmappedClasses the handleUnmappedClasses to set
|
||||
*/
|
||||
public void setHandleUnmappedClasses(boolean handleUnmappedClasses) {
|
||||
this.handleUnmappedClasses = handleUnmappedClasses;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.DefaultTypeMapper#getTypeInformation(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
protected TypeInformation<?> getTypeInformation(String value) {
|
||||
|
||||
for (Entry<TypeInformation<?>, String> entry : typeMap.entrySet()) {
|
||||
if (entry.getValue().equals(value)) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
return handleUnmappedClasses ? super.getTypeInformation(value) : null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.DefaultTypeMapper#getTypeString(org.springframework.data.util.TypeInformation)
|
||||
*/
|
||||
@Override
|
||||
protected String getTypeString(TypeInformation<?> typeInformation) {
|
||||
|
||||
String key = typeMap.get(typeInformation);
|
||||
return key != null ? key : handleUnmappedClasses ? super.getTypeString(typeInformation) : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Conversion registration information.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class ConverterRegistration {
|
||||
|
||||
private final ConvertiblePair convertiblePair;
|
||||
private final boolean reading;
|
||||
private final boolean writing;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConverterRegistration}.
|
||||
*
|
||||
* @param convertiblePair must not be {@literal null}.
|
||||
* @param isReading whether to force to consider the converter for reading.
|
||||
* @param isWritingwhether to force to consider the converter for reading.
|
||||
*/
|
||||
public ConverterRegistration(ConvertiblePair convertiblePair, boolean isReading, boolean isWriting) {
|
||||
|
||||
Assert.notNull(convertiblePair);
|
||||
|
||||
this.convertiblePair = convertiblePair;
|
||||
this.reading = isReading;
|
||||
this.writing = isWriting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConverterRegistration} from the given source and target type and read/write flags.
|
||||
*
|
||||
* @param source the source type to be converted from, must not be {@literal null}.
|
||||
* @param target the target type to be converted to, must not be {@literal null}.
|
||||
* @param isReading whether to force to consider the converter for reading.
|
||||
* @param isWriting whether to force to consider the converter for writing.
|
||||
*/
|
||||
public ConverterRegistration(Class<?> source, Class<?> target, boolean isReading, boolean isWriting) {
|
||||
this(new ConvertiblePair(source, target), isReading, isWriting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the converter shall be used for writing.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isWriting() {
|
||||
return writing == true || (!reading && isSimpleTargetType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the converter shall be used for reading.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isReading() {
|
||||
return reading == true || (!writing && isSimpleSourceType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual conversion pair.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ConvertiblePair getConvertiblePair() {
|
||||
return convertiblePair;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the source type is a Mongo simple one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSimpleSourceType() {
|
||||
return isMongoBasicType(convertiblePair.getSourceType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the target type is a Mongo simple one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSimpleTargetType() {
|
||||
return isMongoBasicType(convertiblePair.getTargetType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given type is a type that Mongo can handle basically.
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
private static boolean isMongoBasicType(Class<?> type) {
|
||||
return MongoSimpleTypes.HOLDER.isSimpleType(type);
|
||||
}
|
||||
}
|
||||
@@ -17,13 +17,13 @@ package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
@@ -31,14 +31,18 @@ import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.ReadingConverter;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToURLConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.URLToStringConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Value object to capture custom conversion. That is essentially a {@link List} of converters and some additional logic
|
||||
* around them. The converters are pretty much builds up two sets of types which Mongo basic types {@see #MONGO_TYPES}
|
||||
@@ -50,9 +54,9 @@ import com.mongodb.DBObject;
|
||||
*/
|
||||
public class CustomConversions {
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private static final List<Class<?>> MONGO_TYPES = Arrays.asList(Number.class, Date.class, ObjectId.class,
|
||||
String.class, DBObject.class);
|
||||
private static final Log LOG = LogFactory.getLog(CustomConversions.class);
|
||||
private static final String READ_CONVERTER_NOT_SIMPLE = "Registering converter from %s to %s as reading converter although it doesn't convert from a Mongo supported type! You might wanna check you annotation setup at the converter implementation.";
|
||||
private static final String WRITE_CONVERTER_NOT_SIMPLE = "Registering converter from %s to %s as writing converter although it doesn't convert to a Mongo supported type! You might wanna check you annotation setup at the converter implementation.";
|
||||
|
||||
private final Set<ConvertiblePair> readingPairs;
|
||||
private final Set<ConvertiblePair> writingPairs;
|
||||
@@ -85,6 +89,10 @@ public class CustomConversions {
|
||||
this.converters.add(CustomToStringConverter.INSTANCE);
|
||||
this.converters.add(BigDecimalToStringConverter.INSTANCE);
|
||||
this.converters.add(StringToBigDecimalConverter.INSTANCE);
|
||||
this.converters.add(BigIntegerToStringConverter.INSTANCE);
|
||||
this.converters.add(StringToBigIntegerConverter.INSTANCE);
|
||||
this.converters.add(URLToStringConverter.INSTANCE);
|
||||
this.converters.add(StringToURLConverter.INSTANCE);
|
||||
this.converters.addAll(converters);
|
||||
|
||||
for (Object c : this.converters) {
|
||||
@@ -104,8 +112,10 @@ public class CustomConversions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given type is considered to be simple.
|
||||
* Returns whether the given type is considered to be simple. That means it's either a general simple type or we have
|
||||
* a writing {@link Converter} registered for a particular type.
|
||||
*
|
||||
* @see SimpleTypeHolder#isSimpleType(Class)
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
@@ -153,14 +163,18 @@ public class CustomConversions {
|
||||
*/
|
||||
private void registerConversion(Object converter) {
|
||||
|
||||
Class<?> type = converter.getClass();
|
||||
boolean isWriting = type.isAnnotationPresent(WritingConverter.class);
|
||||
boolean isReading = type.isAnnotationPresent(ReadingConverter.class);
|
||||
|
||||
if (converter instanceof GenericConverter) {
|
||||
GenericConverter genericConverter = (GenericConverter) converter;
|
||||
for (ConvertiblePair pair : genericConverter.getConvertibleTypes()) {
|
||||
register(pair);
|
||||
register(new ConverterRegistration(pair, isReading, isWriting));
|
||||
}
|
||||
} else if (converter instanceof Converter) {
|
||||
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), Converter.class);
|
||||
register(new ConvertiblePair(arguments[0], arguments[1]));
|
||||
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported Converter type!");
|
||||
}
|
||||
@@ -172,16 +186,27 @@ public class CustomConversions {
|
||||
*
|
||||
* @param pair
|
||||
*/
|
||||
private void register(ConvertiblePair pair) {
|
||||
private void register(ConverterRegistration context) {
|
||||
|
||||
ConvertiblePair pair = context.getConvertiblePair();
|
||||
|
||||
if (context.isReading()) {
|
||||
|
||||
if (isMongoBasicType(pair.getSourceType())) {
|
||||
readingPairs.add(pair);
|
||||
customSimpleTypes.add(pair.getTargetType());
|
||||
|
||||
if (LOG.isWarnEnabled() && !context.isSimpleSourceType()) {
|
||||
LOG.warn(String.format(READ_CONVERTER_NOT_SIMPLE, pair.getSourceType(), pair.getTargetType()));
|
||||
}
|
||||
}
|
||||
|
||||
if (isMongoBasicType(pair.getTargetType())) {
|
||||
if (context.isWriting()) {
|
||||
|
||||
writingPairs.add(pair);
|
||||
customSimpleTypes.add(pair.getSourceType());
|
||||
|
||||
if (LOG.isWarnEnabled() && !context.isSimpleTargetType()) {
|
||||
LOG.warn(String.format(WRITE_CONVERTER_NOT_SIMPLE, pair.getSourceType(), pair.getTargetType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,16 +297,7 @@ public class CustomConversions {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given type is a type that Mongo can handle basically.
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
private static boolean isMongoBasicType(Class<?> type) {
|
||||
return MONGO_TYPES.contains(type);
|
||||
}
|
||||
|
||||
@WritingConverter
|
||||
private enum CustomToStringConverter implements GenericConverter {
|
||||
INSTANCE;
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypedValue;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* {@link PropertyAccessor} to allow entity based field access to {@link DBObject}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class DBObjectPropertyAccessor extends MapAccessor {
|
||||
|
||||
static MapAccessor INSTANCE = new DBObjectPropertyAccessor();
|
||||
|
||||
@Override
|
||||
public Class<?>[] getSpecificTargetClasses() {
|
||||
return new Class[] { DBObject.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRead(EvaluationContext context, Object target, String name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public TypedValue read(EvaluationContext context, Object target, String name) {
|
||||
|
||||
Map<String, Object> source = (Map<String, Object>) target;
|
||||
|
||||
Object value = source.get(name);
|
||||
return value == null ? TypedValue.NULL : new TypedValue(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.convert.SimpleTypeInformationMapper;
|
||||
import org.springframework.data.convert.DefaultTypeMapper;
|
||||
import org.springframework.data.convert.TypeAliasAccessor;
|
||||
import org.springframework.data.convert.TypeInformationMapper;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link MongoTypeMapper} allowing configuration of the key to lookup and store type
|
||||
* information in {@link DBObject}. The key defaults to {@link #DEFAULT_TYPE_KEY}. Actual type-to-{@link String}
|
||||
* conversion and back is done in {@link #getTypeString(TypeInformation)} or {@link #getTypeInformation(String)}
|
||||
* respectively.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implements MongoTypeMapper {
|
||||
|
||||
public static final String DEFAULT_TYPE_KEY = "_class";
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final TypeInformation<List> LIST_TYPE_INFO = ClassTypeInformation.from(List.class);
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final TypeInformation<Map> MAP_TYPE_INFO = ClassTypeInformation.from(Map.class);
|
||||
private String typeKey = DEFAULT_TYPE_KEY;
|
||||
|
||||
public DefaultMongoTypeMapper() {
|
||||
this(DEFAULT_TYPE_KEY, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
|
||||
}
|
||||
|
||||
public DefaultMongoTypeMapper(String typeKey) {
|
||||
super(new DBObjectTypeAliasAccessor(typeKey));
|
||||
this.typeKey = typeKey;
|
||||
}
|
||||
|
||||
public DefaultMongoTypeMapper(String typeKey, MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext) {
|
||||
super(new DBObjectTypeAliasAccessor(typeKey), mappingContext, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
|
||||
this.typeKey = typeKey;
|
||||
}
|
||||
|
||||
public DefaultMongoTypeMapper(String typeKey, List<? extends TypeInformationMapper> mappers) {
|
||||
super(new DBObjectTypeAliasAccessor(typeKey), mappers);
|
||||
this.typeKey = typeKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.MongoTypeMapper#isTypeKey(java.lang.String)
|
||||
*/
|
||||
public boolean isTypeKey(String key) {
|
||||
return typeKey == null ? false : typeKey.equals(key);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.DefaultTypeMapper#getFallbackTypeFor(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected TypeInformation<?> getFallbackTypeFor(DBObject source) {
|
||||
return source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public static final class DBObjectTypeAliasAccessor implements TypeAliasAccessor<DBObject> {
|
||||
|
||||
private final String typeKey;
|
||||
|
||||
public DBObjectTypeAliasAccessor(String typeKey) {
|
||||
this.typeKey = typeKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.TypeAliasAccessor#readAliasFrom(java.lang.Object)
|
||||
*/
|
||||
public Object readAliasFrom(DBObject source) {
|
||||
|
||||
if (source instanceof BasicDBList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return source.get(typeKey);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.convert.TypeAliasAccessor#writeTypeTo(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
public void writeTypeTo(DBObject sink, Object alias) {
|
||||
if (typeKey != null) {
|
||||
sink.put(typeKey, alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link TypeMapper} allowing configuration of the key to lookup and store type information
|
||||
* in {@link DBObject}. The key defaults to {@link #DEFAULT_TYPE_KEY}. Actual type-to-{@link String} conversion and back
|
||||
* is done in {@link #getTypeString(TypeInformation)} or {@link #getTypeInformation(String)} respectively.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class DefaultTypeMapper implements TypeMapper {
|
||||
|
||||
public static final String DEFAULT_TYPE_KEY = "_class";
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final TypeInformation<List> LIST_TYPE_INFORMATION = ClassTypeInformation.from(List.class);
|
||||
|
||||
private String typeKey = DEFAULT_TYPE_KEY;
|
||||
|
||||
/**
|
||||
* Sets the key to store the type information under. If set to {@literal null} no type information will be stored in
|
||||
* the document.
|
||||
*
|
||||
* @param typeKey the typeKey to set
|
||||
*/
|
||||
public void setTypeKey(String typeKey) {
|
||||
this.typeKey = typeKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.TypeMapper#isTypeKey(java.lang.String)
|
||||
*/
|
||||
public boolean isTypeKey(String key) {
|
||||
return typeKey == null ? false : typeKey.equals(key);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.TypeMapper#readType(com.mongodb.DBObject)
|
||||
*/
|
||||
public TypeInformation<?> readType(DBObject dbObject) {
|
||||
|
||||
if (dbObject instanceof BasicDBList) {
|
||||
return LIST_TYPE_INFORMATION;
|
||||
}
|
||||
|
||||
if (typeKey == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Object classToBeUsed = dbObject.get(typeKey);
|
||||
|
||||
if (classToBeUsed == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getTypeInformation(classToBeUsed.toString());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.TypeMapper#writeType(java.lang.Class, com.mongodb.DBObject)
|
||||
*/
|
||||
public void writeType(Class<?> type, DBObject dbObject) {
|
||||
writeType(ClassTypeInformation.from(type), dbObject);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.TypeMapper#writeType(java.lang.Class, com.mongodb.DBObject)
|
||||
*/
|
||||
public void writeType(TypeInformation<?> info, DBObject dbObject) {
|
||||
|
||||
Assert.notNull(info);
|
||||
|
||||
if (typeKey == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String string = getTypeString(info);
|
||||
|
||||
if (string != null) {
|
||||
dbObject.put(typeKey, getTypeString(info));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the given type information into the String representation that shall be stored inside the {@link DBObject}. If
|
||||
* the returned String is {@literal null} no type information will be stored. Default implementation simply returns
|
||||
* the fully-qualified class name.
|
||||
*
|
||||
* @param typeInformation must not be {@literal null}.
|
||||
* @return the String representation to be stored or {@literal null} if no type information shall be stored.
|
||||
*/
|
||||
protected String getTypeString(TypeInformation<?> typeInformation) {
|
||||
return typeInformation.getType().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link TypeInformation} that shall be used when the given {@link String} value is found as type hint.
|
||||
* The default implementation will simply interpret the given value as fully-qualified class name and try to load the
|
||||
* class. Will return {@literal null} in case the given {@link String} is empty. Will not be called in case no
|
||||
* {@link String} was found for the configured type key at all.
|
||||
*
|
||||
* @param value the type to load, must not be {@literal null}.
|
||||
* @return the type to be used for the given {@link String} representation or {@literal null} if nothing found or the
|
||||
* class cannot be loaded.
|
||||
*/
|
||||
protected TypeInformation<?> getTypeInformation(String value) {
|
||||
|
||||
if (!StringUtils.hasText(value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return ClassTypeInformation.from(ClassUtils.forName(value, null));
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PreferredConstructor;
|
||||
import org.springframework.data.mapping.PreferredConstructor.Parameter;
|
||||
import org.springframework.data.mapping.PropertyPath;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.context.PersistentPropertyPath;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstraction for a {@link PreferredConstructor} alongside mapping information.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class MappedConstructor {
|
||||
|
||||
private static final String REJECT_CONSTRUCTOR = String.format("Entity doesn't have a usable constructor, either "
|
||||
+ "provide a custom converter or annotate a constructor with @%s!", PersistenceConstructor.class.getSimpleName());
|
||||
|
||||
private final Set<MappedConstructor.MappedParameter> parameters;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappedConstructor} from the given {@link MongoPersistentEntity} and {@link MappingContext}.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param context must not be {@literal null}.
|
||||
* @throws MappingException in case the {@link MongoPersistentEntity} handed in does not have a
|
||||
* {@link PreferredConstructor}.
|
||||
*/
|
||||
public MappedConstructor(MongoPersistentEntity<?> entity,
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> context) throws MappingException {
|
||||
|
||||
Assert.notNull(entity);
|
||||
Assert.notNull(context);
|
||||
|
||||
if (entity.getPreferredConstructor() == null) {
|
||||
throw new MappingException(REJECT_CONSTRUCTOR);
|
||||
}
|
||||
|
||||
this.parameters = new HashSet<MappedConstructor.MappedParameter>();
|
||||
|
||||
for (Parameter<?> parameter : entity.getPreferredConstructor().getParameters()) {
|
||||
parameters.add(new MappedParameter(parameter, entity, context));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link PersistentProperty} is referenced in a constructor argument of the
|
||||
* {@link PersistentEntity} backing this {@link MappedConstructor}.
|
||||
*
|
||||
* @param property must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public boolean isConstructorParameter(PersistentProperty<?> property) {
|
||||
|
||||
Assert.notNull(property);
|
||||
|
||||
for (MappedConstructor.MappedParameter parameter : parameters) {
|
||||
if (parameter.maps(property)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link MappedParameter} for the given {@link Parameter}.
|
||||
*
|
||||
* @param parameter must not be {@literal null}.
|
||||
* @return
|
||||
* @throws MappingException in case no {@link MappedParameter} can be found for the given {@link Parameter}.
|
||||
*/
|
||||
public MappedParameter getFor(Parameter<?> parameter) {
|
||||
|
||||
for (MappedParameter mappedParameter : parameters) {
|
||||
if (mappedParameter.parameter.equals(parameter)) {
|
||||
return mappedParameter;
|
||||
}
|
||||
}
|
||||
|
||||
throw new MappingException(String.format("Didn't find a MappedParameter for %s!", parameter.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstraction of a {@link Parameter} alongside mapping information.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
static class MappedParameter {
|
||||
|
||||
private final MongoPersistentProperty property;
|
||||
private final Parameter<?> parameter;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappedParameter} for the given {@link Parameter}, {@link MongoPersistentProperty} and
|
||||
* {@link MappingContext}.
|
||||
*
|
||||
* @param parameter must not be {@literal null}.
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param context must not be {@literal null}.
|
||||
*/
|
||||
public MappedParameter(Parameter<?> parameter, MongoPersistentEntity<?> entity,
|
||||
MappingContext<? extends MongoPersistentEntity<?>, ? extends MongoPersistentProperty> context) {
|
||||
|
||||
Assert.notNull(parameter);
|
||||
Assert.notNull(entity);
|
||||
Assert.notNull(context);
|
||||
|
||||
this.parameter = parameter;
|
||||
|
||||
PropertyPath propertyPath = PropertyPath.from(parameter.getName(), entity.getType());
|
||||
PersistentPropertyPath<? extends MongoPersistentProperty> path = context.getPersistentPropertyPath(propertyPath);
|
||||
this.property = path == null ? null : path.getLeafProperty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there is a SpEL expression configured for this parameter.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean hasSpELExpression() {
|
||||
return parameter.getKey() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the field name to be used to lookup the value which in turn shall be converted into the constructor
|
||||
* parameter.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getFieldName() {
|
||||
return property.getFieldName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the property backing the {@link Parameter}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public TypeInformation<?> getPropertyTypeInformation() {
|
||||
return property.getTypeInformation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link PersistentProperty} is mapped by the parameter.
|
||||
*
|
||||
* @param property
|
||||
* @return
|
||||
*/
|
||||
public boolean maps(PersistentProperty<?> property) {
|
||||
return this.property.equals(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 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.
|
||||
@@ -13,30 +13,20 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.DBRef;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
@@ -44,9 +34,10 @@ import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.data.convert.TypeMapper;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.AssociationHandler;
|
||||
import org.springframework.data.mapping.PreferredConstructor;
|
||||
import org.springframework.data.mapping.PreferredConstructor.Parameter;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.BeanWrapper;
|
||||
@@ -54,6 +45,7 @@ import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.model.ParameterValueProvider;
|
||||
import org.springframework.data.mapping.model.SpELAwareParameterValueProvider;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.QueryMapper;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
@@ -65,29 +57,31 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.DBRef;
|
||||
|
||||
/**
|
||||
* {@link MongoConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to
|
||||
* {@link DBObject}.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Oliver Gierke
|
||||
* @author Jon Brisbin
|
||||
*/
|
||||
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware,
|
||||
TypeMapperProvider {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final TypeInformation<Map> MAP_TYPE_INFORMATION = ClassTypeInformation.from(Map.class);
|
||||
private static final List<Class<?>> VALID_ID_TYPES = Arrays.asList(new Class<?>[] { ObjectId.class, String.class,
|
||||
BigInteger.class, byte[].class });
|
||||
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware {
|
||||
|
||||
protected static final Log log = LogFactory.getLog(MappingMongoConverter.class);
|
||||
|
||||
protected final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
protected final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
|
||||
protected final MongoDbFactory mongoDbFactory;
|
||||
protected final QueryMapper idMapper;
|
||||
protected ApplicationContext applicationContext;
|
||||
protected boolean useFieldAccessOnly = true;
|
||||
protected TypeMapper typeMapper = new DefaultTypeMapper();
|
||||
protected MongoTypeMapper typeMapper;
|
||||
protected String mapKeyDotReplacement = null;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingMongoConverter} given the new {@link MongoDbFactory} and {@link MappingContext}.
|
||||
@@ -95,6 +89,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @param mongoDbFactory must not be {@literal null}.
|
||||
* @param mappingContext must not be {@literal null}.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public MappingMongoConverter(MongoDbFactory mongoDbFactory,
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||
|
||||
@@ -105,30 +100,38 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
this.mongoDbFactory = mongoDbFactory;
|
||||
this.mappingContext = mappingContext;
|
||||
this.typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, mappingContext);
|
||||
this.idMapper = new QueryMapper(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link TypeMapper} to be used to add type information to {@link DBObject}s created by the converter
|
||||
* and how to lookup type information from {@link DBObject}s when reading them. Uses a {@link DefaultTypeMapper} by
|
||||
* default. Setting this to {@literal null} will reset the {@link TypeMapper} to the default one.
|
||||
* Configures the {@link MongoTypeMapper} to be used to add type information to {@link DBObject}s created by the
|
||||
* converter and how to lookup type information from {@link DBObject}s when reading them. Uses a
|
||||
* {@link DefaultMongoTypeMapper} by default. Setting this to {@literal null} will reset the {@link TypeMapper} to the
|
||||
* default one.
|
||||
*
|
||||
* @param typeMapper the typeMapper to set
|
||||
*/
|
||||
public void setTypeMapper(TypeMapper typeMapper) {
|
||||
this.typeMapper = typeMapper == null ? new DefaultTypeMapper() : typeMapper;
|
||||
public void setTypeMapper(MongoTypeMapper typeMapper) {
|
||||
this.typeMapper = typeMapper == null ? new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY,
|
||||
mappingContext) : typeMapper;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.MongoConverter#getTypeMapper()
|
||||
/**
|
||||
* Configure the characters dots potentially contained in a {@link Map} shall be replaced with. By default we don't do
|
||||
* any translation but rather reject a {@link Map} with keys containing dots causing the conversion for the entire
|
||||
* object to fail. If further customization of the translation is needed, have a look at
|
||||
* {@link #potentiallyEscapeMapKey(String)} as well as {@link #potentiallyUnescapeMapKey(String)}.
|
||||
*
|
||||
* @param mapKeyDotReplacement the mapKeyDotReplacement to set
|
||||
*/
|
||||
public TypeMapper getTypeMapper() {
|
||||
return this.typeMapper;
|
||||
public void setMapKeyDotReplacement(String mapKeyDotReplacement) {
|
||||
this.mapKeyDotReplacement = mapKeyDotReplacement;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.core.convert.MongoConverter#getMappingContext()
|
||||
* @see org.springframework.data.convert.EntityConverter#getMappingContext()
|
||||
*/
|
||||
public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext() {
|
||||
return mappingContext;
|
||||
@@ -168,13 +171,17 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return null;
|
||||
}
|
||||
|
||||
TypeInformation<? extends S> typeToUse = getMoreConcreteTargetType(dbo, type);
|
||||
TypeInformation<? extends S> typeToUse = typeMapper.readType(dbo, type);
|
||||
Class<? extends S> rawType = typeToUse.getType();
|
||||
|
||||
if (conversions.hasCustomReadTarget(dbo.getClass(), rawType)) {
|
||||
return conversionService.convert(dbo, rawType);
|
||||
}
|
||||
|
||||
if (DBObject.class.isAssignableFrom(rawType)) {
|
||||
return (S) dbo;
|
||||
}
|
||||
|
||||
if (typeToUse.isCollectionLike() && dbo instanceof BasicDBList) {
|
||||
return (S) readCollectionOrArray(typeToUse, (BasicDBList) dbo);
|
||||
}
|
||||
@@ -195,52 +202,17 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo) {
|
||||
|
||||
final StandardEvaluationContext spelCtx = new StandardEvaluationContext();
|
||||
if (null != applicationContext) {
|
||||
final StandardEvaluationContext spelCtx = new StandardEvaluationContext(dbo);
|
||||
spelCtx.addPropertyAccessor(DBObjectPropertyAccessor.INSTANCE);
|
||||
|
||||
if (applicationContext != null) {
|
||||
spelCtx.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||
}
|
||||
if (!(dbo instanceof BasicDBList)) {
|
||||
String[] keySet = dbo.keySet().toArray(new String[] {});
|
||||
for (String key : keySet) {
|
||||
spelCtx.setVariable(key, dbo.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
final List<String> ctorParamNames = new ArrayList<String>();
|
||||
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
final MappedConstructor constructor = new MappedConstructor(entity, mappingContext);
|
||||
|
||||
ParameterValueProvider provider = new SpELAwareParameterValueProvider(spelExpressionParser, spelCtx) {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getParameterValue(PreferredConstructor.Parameter<T> parameter) {
|
||||
|
||||
if (parameter.getKey() != null) {
|
||||
return super.getParameterValue(parameter);
|
||||
}
|
||||
|
||||
String name = parameter.getName();
|
||||
TypeInformation<T> type = parameter.getType();
|
||||
Class<T> rawType = parameter.getRawType();
|
||||
String key = idProperty == null ? name : idProperty.getName().equals(name) ? idProperty.getFieldName() : name;
|
||||
Object obj = dbo.get(key);
|
||||
|
||||
ctorParamNames.add(name);
|
||||
if (obj instanceof DBRef) {
|
||||
return read(type, ((DBRef) obj).fetch());
|
||||
} else if (obj instanceof BasicDBList) {
|
||||
BasicDBList objAsDbList = (BasicDBList) obj;
|
||||
return conversionService.convert(readCollectionOrArray(type, objAsDbList), rawType);
|
||||
} else if (obj instanceof DBObject) {
|
||||
return read(type, ((DBObject) obj));
|
||||
} else if (null != obj && obj.getClass().isAssignableFrom(rawType)) {
|
||||
return (T) obj;
|
||||
} else if (null != obj) {
|
||||
return conversionService.convert(obj, rawType);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SpELAwareParameterValueProvider delegate = new SpELAwareParameterValueProvider(spelExpressionParser, spelCtx);
|
||||
ParameterValueProvider provider = new DelegatingParameterValueProvider(constructor, dbo, delegate);
|
||||
|
||||
final BeanWrapper<MongoPersistentEntity<S>, S> wrapper = BeanWrapper.create(entity, provider, conversionService);
|
||||
|
||||
@@ -248,7 +220,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||
public void doWithPersistentProperty(MongoPersistentProperty prop) {
|
||||
|
||||
boolean isConstructorProperty = ctorParamNames.contains(prop.getName());
|
||||
boolean isConstructorProperty = constructor.isConstructorParameter(prop);
|
||||
boolean hasValueForProperty = dbo.containsField(prop.getFieldName());
|
||||
|
||||
if (!hasValueForProperty || isConstructorProperty) {
|
||||
@@ -256,13 +228,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
Object obj = getValueInternal(prop, dbo, spelCtx, prop.getSpelExpression());
|
||||
try {
|
||||
wrapper.setProperty(prop, obj, useFieldAccessOnly);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
}
|
||||
wrapper.setProperty(prop, obj, useFieldAccessOnly);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -297,12 +263,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
boolean handledByCustomConverter = conversions.getCustomWriteTarget(obj.getClass(), DBObject.class) != null;
|
||||
TypeInformation<? extends Object> type = ClassTypeInformation.from(obj.getClass());
|
||||
|
||||
if (!handledByCustomConverter) {
|
||||
typeMapper.writeType(ClassTypeInformation.from(obj.getClass()), dbo);
|
||||
if (!handledByCustomConverter && !(dbo instanceof BasicDBList)) {
|
||||
typeMapper.writeType(type, dbo);
|
||||
}
|
||||
|
||||
writeInternal(obj, dbo);
|
||||
writeInternal(obj, dbo, type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,7 +279,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @param dbo
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void writeInternal(final Object obj, final DBObject dbo) {
|
||||
protected void writeInternal(final Object obj, final DBObject dbo, final TypeInformation<?> typeHint) {
|
||||
|
||||
if (null == obj) {
|
||||
return;
|
||||
@@ -327,12 +294,18 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
if (Map.class.isAssignableFrom(obj.getClass())) {
|
||||
writeMapInternal((Map<Object, Object>) obj, dbo, null);
|
||||
writeMapInternal((Map<Object, Object>) obj, dbo, ClassTypeInformation.MAP);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Collection.class.isAssignableFrom(obj.getClass())) {
|
||||
writeCollectionInternal((Collection<?>) obj, ClassTypeInformation.LIST, (BasicDBList) dbo);
|
||||
return;
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(obj.getClass());
|
||||
writeInternal(obj, dbo, entity);
|
||||
addCustomTypeKeyIfNecessary(typeHint, obj, dbo);
|
||||
}
|
||||
|
||||
protected void writeInternal(Object obj, final DBObject dbo, MongoPersistentEntity<?> entity) {
|
||||
@@ -350,46 +323,24 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
// Write the ID
|
||||
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
if (!dbo.containsField("_id") && null != idProperty) {
|
||||
Object idObj = null;
|
||||
Class<?>[] targetClasses = new Class<?>[] { ObjectId.class, String.class, Object.class };
|
||||
for (Class<?> targetClass : targetClasses) {
|
||||
try {
|
||||
idObj = wrapper.getProperty(idProperty, targetClass, useFieldAccessOnly);
|
||||
if (null != idObj) {
|
||||
break;
|
||||
}
|
||||
} catch (ConversionException ignored) {
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (null != idObj) {
|
||||
dbo.put("_id", idObj);
|
||||
} else {
|
||||
if (!VALID_ID_TYPES.contains(idProperty.getType())) {
|
||||
throw new MappingException("Invalid data type " + idProperty.getType().getName()
|
||||
+ " for Id property. Should be one of " + VALID_ID_TYPES);
|
||||
}
|
||||
try {
|
||||
Object id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly);
|
||||
dbo.put("_id", idMapper.convertId(id));
|
||||
} catch (ConversionException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
// Write the properties
|
||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||
public void doWithPersistentProperty(MongoPersistentProperty prop) {
|
||||
|
||||
if (prop.equals(idProperty)) {
|
||||
return;
|
||||
}
|
||||
Object propertyObj;
|
||||
try {
|
||||
propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
|
||||
|
||||
if (null != propertyObj) {
|
||||
if (!conversions.isSimpleType(propertyObj.getClass())) {
|
||||
writePropertyInternal(propertyObj, dbo, prop);
|
||||
@@ -404,14 +355,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
||||
MongoPersistentProperty inverseProp = association.getInverse();
|
||||
Class<?> type = inverseProp.getType();
|
||||
Object propertyObj;
|
||||
try {
|
||||
propertyObj = wrapper.getProperty(inverseProp, type, useFieldAccessOnly);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
}
|
||||
Object propertyObj = wrapper.getProperty(inverseProp, type, useFieldAccessOnly);
|
||||
if (null != propertyObj) {
|
||||
writePropertyInternal(propertyObj, dbo, inverseProp);
|
||||
}
|
||||
@@ -427,16 +371,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
String name = prop.getFieldName();
|
||||
TypeInformation<?> valueType = ClassTypeInformation.from(obj.getClass());
|
||||
TypeInformation<?> type = prop.getTypeInformation();
|
||||
|
||||
if (prop.isCollection()) {
|
||||
if (valueType.isCollectionLike()) {
|
||||
DBObject collectionInternal = createCollection(asCollection(obj), prop);
|
||||
dbo.put(name, collectionInternal);
|
||||
return;
|
||||
}
|
||||
|
||||
TypeInformation<?> type = prop.getTypeInformation();
|
||||
|
||||
if (prop.isMap()) {
|
||||
if (valueType.isMap()) {
|
||||
BasicDBObject mapDbObj = new BasicDBObject();
|
||||
writeMapInternal((Map<Object, Object>) obj, mapDbObj, type);
|
||||
dbo.put(name, mapDbObj);
|
||||
@@ -495,13 +439,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
*
|
||||
* @param collection must not be {@literal null}.
|
||||
* @param property must not be {@literal null}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected DBObject createCollection(Collection<?> collection, MongoPersistentProperty property) {
|
||||
|
||||
if (!property.isDbReference()) {
|
||||
return createCollectionDBObject(collection, property.getTypeInformation());
|
||||
return writeCollectionInternal(collection, property.getTypeInformation(), new BasicDBList());
|
||||
}
|
||||
|
||||
BasicDBList dbList = new BasicDBList();
|
||||
@@ -520,63 +463,103 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link BasicDBList} from the given {@link Collection}.
|
||||
* Populates the given {@link BasicDBList} with values from the given {@link Collection}.
|
||||
*
|
||||
* @param source the collection to create a {@link BasicDBList} for, must not be {@literal null}.
|
||||
* @param type the {@link TypeInformation} to consider or {@literal null} if unknown.
|
||||
* @param sink the {@link BasicDBList} to write to.
|
||||
* @return
|
||||
*/
|
||||
private BasicDBList createCollectionDBObject(Collection<?> source, TypeInformation<?> type) {
|
||||
private BasicDBList writeCollectionInternal(Collection<?> source, TypeInformation<?> type, BasicDBList sink) {
|
||||
|
||||
BasicDBList dbList = new BasicDBList();
|
||||
TypeInformation<?> componentType = type == null ? null : type.getComponentType();
|
||||
|
||||
for (Object element : source) {
|
||||
|
||||
if (element == null) {
|
||||
continue;
|
||||
}
|
||||
Class<?> elementType = element == null ? null : element.getClass();
|
||||
|
||||
Class<?> elementType = element.getClass();
|
||||
|
||||
if (conversions.isSimpleType(elementType)) {
|
||||
dbList.add(getPotentiallyConvertedSimpleWrite(element));
|
||||
if (elementType == null || conversions.isSimpleType(elementType)) {
|
||||
sink.add(getPotentiallyConvertedSimpleWrite(element));
|
||||
} else if (element instanceof Collection || elementType.isArray()) {
|
||||
dbList.add(createCollectionDBObject(asCollection(element), componentType));
|
||||
sink.add(writeCollectionInternal(asCollection(element), componentType, new BasicDBList()));
|
||||
} else {
|
||||
BasicDBObject propDbObj = new BasicDBObject();
|
||||
writeInternal(element, propDbObj,
|
||||
mappingContext.getPersistentEntity(ClassTypeInformation.from(element.getClass())));
|
||||
addCustomTypeKeyIfNecessary(componentType, element, propDbObj);
|
||||
dbList.add(propDbObj);
|
||||
writeInternal(element, propDbObj, componentType);
|
||||
sink.add(propDbObj);
|
||||
}
|
||||
}
|
||||
|
||||
return dbList;
|
||||
return sink;
|
||||
}
|
||||
|
||||
protected void writeMapInternal(Map<Object, Object> obj, DBObject dbo, TypeInformation<?> propertyType) {
|
||||
/**
|
||||
* Writes the given {@link Map} to the given {@link DBObject} considering the given {@link TypeInformation}.
|
||||
*
|
||||
* @param obj must not be {@literal null}.
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param propertyType must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
protected DBObject writeMapInternal(Map<Object, Object> obj, DBObject dbo, TypeInformation<?> propertyType) {
|
||||
|
||||
for (Map.Entry<Object, Object> entry : obj.entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
Object val = entry.getValue();
|
||||
if (conversions.isSimpleType(key.getClass())) {
|
||||
// Don't use conversion service here as removal of ObjectToString converter results in some primitive types not
|
||||
// being convertable
|
||||
String simpleKey = key.toString();
|
||||
String simpleKey = potentiallyEscapeMapKey(key.toString());
|
||||
if (val == null || conversions.isSimpleType(val.getClass())) {
|
||||
writeSimpleInternal(val, dbo, simpleKey);
|
||||
} else if (val instanceof Collection) {
|
||||
dbo.put(simpleKey, createCollectionDBObject((Collection<?>) val, propertyType.getMapValueType()));
|
||||
} else if (val instanceof Collection || val.getClass().isArray()) {
|
||||
dbo.put(simpleKey,
|
||||
writeCollectionInternal(asCollection(val), propertyType.getMapValueType(), new BasicDBList()));
|
||||
} else {
|
||||
DBObject newDbo = new BasicDBObject();
|
||||
writeInternal(val, newDbo);
|
||||
addCustomTypeKeyIfNecessary(propertyType, val, newDbo);
|
||||
TypeInformation<?> valueTypeInfo = propertyType.isMap() ? propertyType.getMapValueType()
|
||||
: ClassTypeInformation.OBJECT;
|
||||
writeInternal(val, newDbo, valueTypeInfo);
|
||||
dbo.put(simpleKey, newDbo);
|
||||
}
|
||||
} else {
|
||||
throw new MappingException("Cannot use a complex object as a key value.");
|
||||
}
|
||||
}
|
||||
|
||||
return dbo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Potentially replaces dots in the given map key with the configured map key replacement if configured or aborts
|
||||
* conversion if none is configured.
|
||||
*
|
||||
* @see #setMapKeyDotReplacement(String)
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
protected String potentiallyEscapeMapKey(String source) {
|
||||
|
||||
if (!source.contains(".")) {
|
||||
return source;
|
||||
}
|
||||
|
||||
if (mapKeyDotReplacement == null) {
|
||||
throw new MappingException(String.format("Map key %s contains dots but no replacement was configured! Make "
|
||||
+ "sure map keys don't contain dots in the first place or configure an appropriate replacement!", source));
|
||||
}
|
||||
|
||||
return source.replaceAll("\\.", mapKeyDotReplacement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the map key replacements in the given key just read with a dot in case a map key replacement has been
|
||||
* configured.
|
||||
*
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
protected String potentiallyUnescapeMapKey(String source) {
|
||||
return mapKeyDotReplacement == null ? source : source.replaceAll(mapKeyDotReplacement, "\\.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -589,11 +572,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
*/
|
||||
protected void addCustomTypeKeyIfNecessary(TypeInformation<?> type, Object value, DBObject dbObject) {
|
||||
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Class<?> reference = type.getActualType().getType();
|
||||
TypeInformation<?> actualType = type != null ? type.getActualType() : type;
|
||||
Class<?> reference = actualType == null ? Object.class : actualType.getType();
|
||||
|
||||
boolean notTheSameClass = !value.getClass().equals(reference);
|
||||
if (notTheSameClass) {
|
||||
@@ -630,7 +610,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
if (customTarget != null) {
|
||||
return conversionService.convert(value, customTarget);
|
||||
} else {
|
||||
return value.getClass().isEnum() ? ((Enum<?>) value).name() : value;
|
||||
return Enum.class.isAssignableFrom(value.getClass()) ? ((Enum<?>) value).name() : value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -645,41 +625,34 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private Object getPotentiallyConvertedSimpleRead(Object value, Class<?> target) {
|
||||
|
||||
Assert.notNull(target);
|
||||
|
||||
if (value == null) {
|
||||
return null;
|
||||
if (value == null || target == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (conversions.hasCustomReadTarget(value.getClass(), target)) {
|
||||
return conversionService.convert(value, target);
|
||||
}
|
||||
|
||||
if (target.isEnum()) {
|
||||
if (Enum.class.isAssignableFrom(target)) {
|
||||
return Enum.valueOf((Class<Enum>) target, value.toString());
|
||||
}
|
||||
|
||||
return value;
|
||||
return target.isAssignableFrom(value.getClass()) ? value : conversionService.convert(value, target);
|
||||
}
|
||||
|
||||
protected DBRef createDBRef(Object target, org.springframework.data.mongodb.core.mapping.DBRef dbref) {
|
||||
|
||||
MongoPersistentEntity<?> targetEntity = mappingContext.getPersistentEntity(target.getClass());
|
||||
if (null == targetEntity || null == targetEntity.getIdProperty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MongoPersistentProperty idProperty = targetEntity.getIdProperty();
|
||||
Object id = null;
|
||||
BeanWrapper<MongoPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(target, conversionService);
|
||||
try {
|
||||
id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly);
|
||||
if (null == id) {
|
||||
throw new MappingException("Cannot create a reference to an object with a NULL id.");
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
Object id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly);
|
||||
|
||||
if (null == id) {
|
||||
throw new MappingException("Cannot create a reference to an object with a NULL id.");
|
||||
}
|
||||
|
||||
String collection = dbref.collection();
|
||||
@@ -689,7 +662,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
String dbname = dbref.db();
|
||||
DB db = StringUtils.hasText(dbname) ? mongoDbFactory.getDb(dbname) : mongoDbFactory.getDb();
|
||||
return new DBRef(db, collection, id);
|
||||
|
||||
return new DBRef(db, collection, idMapper.convertId(id));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -724,12 +698,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
&& ((DBObject) sourceValue).keySet().size() == 0) {
|
||||
// It's empty
|
||||
return Array.newInstance(prop.getComponentType(), 0);
|
||||
} else if (prop.isCollection() && sourceValue instanceof BasicDBList) {
|
||||
} else if (prop.isCollectionLike() && sourceValue instanceof BasicDBList) {
|
||||
return readCollectionOrArray((TypeInformation<? extends Collection<?>>) prop.getTypeInformation(),
|
||||
(BasicDBList) sourceValue);
|
||||
}
|
||||
|
||||
TypeInformation<?> toType = findTypeToBeUsed((DBObject) sourceValue);
|
||||
TypeInformation<?> toType = typeMapper.readType((DBObject) sourceValue, prop.getTypeInformation());
|
||||
|
||||
// It's a complex object, have to read it in
|
||||
if (toType != null) {
|
||||
@@ -754,12 +728,15 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
* @return the converted {@link Collections}, will never be {@literal null}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Collection<?> readCollectionOrArray(TypeInformation<?> targetType, BasicDBList sourceValue) {
|
||||
private Object readCollectionOrArray(TypeInformation<?> targetType, BasicDBList sourceValue) {
|
||||
|
||||
Assert.notNull(targetType);
|
||||
|
||||
Class<?> collectionType = targetType.getType();
|
||||
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
|
||||
|
||||
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>() : CollectionFactory
|
||||
.createCollection(targetType.getType(), sourceValue.size());
|
||||
.createCollection(collectionType, sourceValue.size());
|
||||
|
||||
for (int i = 0; i < sourceValue.size(); i++) {
|
||||
Object dbObjItem = sourceValue.get(i);
|
||||
@@ -768,11 +745,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
} else if (dbObjItem instanceof DBObject) {
|
||||
items.add(read(targetType.getComponentType(), (DBObject) dbObjItem));
|
||||
} else {
|
||||
items.add(getPotentiallyConvertedSimpleRead(dbObjItem, targetType.getComponentType().getType()));
|
||||
TypeInformation<?> componentType = targetType.getComponentType();
|
||||
items.add(getPotentiallyConvertedSimpleRead(dbObjItem, componentType == null ? null : componentType.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
return getPotentiallyConvertedSimpleRead(items, targetType.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -787,7 +765,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Assert.notNull(dbObject);
|
||||
|
||||
Class<?> mapType = getMoreConcreteTargetType(dbObject, type).getType();
|
||||
Class<?> mapType = typeMapper.readType(dbObject, type).getType();
|
||||
Map<Object, Object> map = CollectionFactory.createMap(mapType, dbObject.keySet().size());
|
||||
Map<String, Object> sourceMap = dbObject.toMap();
|
||||
|
||||
@@ -796,12 +774,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
continue;
|
||||
}
|
||||
|
||||
Object key = entry.getKey();
|
||||
Object key = potentiallyUnescapeMapKey(entry.getKey());
|
||||
|
||||
TypeInformation<?> keyTypeInformation = type.getComponentType();
|
||||
if (keyTypeInformation != null) {
|
||||
Class<?> keyType = keyTypeInformation.getType();
|
||||
key = conversionService.convert(entry.getKey(), keyType);
|
||||
key = conversionService.convert(key, keyType);
|
||||
}
|
||||
|
||||
Object value = entry.getValue();
|
||||
@@ -810,57 +788,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
if (value instanceof DBObject) {
|
||||
map.put(key, read(valueType, (DBObject) value));
|
||||
} else {
|
||||
valueType = valueType == null ? MAP_TYPE_INFORMATION : valueType;
|
||||
map.put(key, getPotentiallyConvertedSimpleRead(value, valueType.getType()));
|
||||
Class<?> valueClass = valueType == null ? null : valueType.getType();
|
||||
map.put(key, getPotentiallyConvertedSimpleRead(value, valueClass));
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type to be used to convert the DBObject given to. Will return {@literal null} if there's not type hint
|
||||
* found in the {@link DBObject} or the type hint found can't be converted into a {@link Class} as the type might not
|
||||
* be available.
|
||||
*
|
||||
* @param dbObject
|
||||
* @return the type to be used for converting the given {@link DBObject} into or {@literal null} if there's no type
|
||||
* found.
|
||||
*/
|
||||
protected TypeInformation<?> findTypeToBeUsed(DBObject dbObject) {
|
||||
return typeMapper.readType(dbObject);
|
||||
}
|
||||
|
||||
private Class<?> getDefaultedTypeToBeUsed(DBObject dbObject) {
|
||||
TypeInformation<?> result = findTypeToBeUsed(dbObject);
|
||||
|
||||
if (result != null) {
|
||||
return result.getType();
|
||||
}
|
||||
|
||||
return dbObject instanceof BasicDBList ? List.class : Map.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspects the a custom class definition stored inside the given {@link DBObject} and returns that in case it's a
|
||||
* subtype of the given basic one.
|
||||
*
|
||||
* @param dbObject
|
||||
* @param basicType
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <S> TypeInformation<? extends S> getMoreConcreteTargetType(DBObject dbObject, TypeInformation<S> basicType) {
|
||||
|
||||
Class<?> documentsTargetType = getDefaultedTypeToBeUsed(dbObject);
|
||||
Class<S> rawType = basicType == null ? null : basicType.getType();
|
||||
|
||||
boolean isMoreConcreteCustomType = rawType == null ? true : rawType.isAssignableFrom(documentsTargetType)
|
||||
&& !rawType.equals(documentsTargetType);
|
||||
return isMoreConcreteCustomType ? (TypeInformation<? extends S>) ClassTypeInformation.from(documentsTargetType)
|
||||
: basicType;
|
||||
}
|
||||
|
||||
protected <T> List<?> unwrapList(BasicDBList dbList, TypeInformation<T> targetType) {
|
||||
List<Object> rootList = new ArrayList<Object>();
|
||||
for (int i = 0; i < dbList.size(); i++) {
|
||||
@@ -883,7 +818,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<?> target = conversions.getCustomWriteTarget(getClass());
|
||||
Class<?> target = conversions.getCustomWriteTarget(obj.getClass());
|
||||
if (target != null) {
|
||||
return conversionService.convert(obj, target);
|
||||
}
|
||||
@@ -907,46 +842,119 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
if (obj instanceof Map) {
|
||||
Map<Object, Object> m = new HashMap<Object, Object>();
|
||||
DBObject result = new BasicDBObject();
|
||||
for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) obj).entrySet()) {
|
||||
m.put(entry.getKey(), convertToMongoType(entry.getValue()));
|
||||
result.put(entry.getKey().toString(), convertToMongoType(entry.getValue()));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
if (obj instanceof List) {
|
||||
List<?> l = (List<?>) obj;
|
||||
List<Object> newList = new ArrayList<Object>();
|
||||
for (Object o : l) {
|
||||
newList.add(convertToMongoType(o));
|
||||
}
|
||||
return newList;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (obj.getClass().isArray()) {
|
||||
return maybeConvertArray((Object[]) obj);
|
||||
return maybeConvertList(Arrays.asList((Object[]) obj));
|
||||
}
|
||||
|
||||
if (obj instanceof Collection) {
|
||||
return maybeConvertList((Collection<?>) obj);
|
||||
}
|
||||
|
||||
DBObject newDbo = new BasicDBObject();
|
||||
this.write(obj, newDbo);
|
||||
return newDbo;
|
||||
return removeTypeInfoRecursively(newDbo);
|
||||
}
|
||||
|
||||
public Object[] maybeConvertArray(Object[] src) {
|
||||
Object[] newArr = new Object[src.length];
|
||||
for (int i = 0; i < src.length; i++) {
|
||||
newArr[i] = convertToMongoType(src[i]);
|
||||
}
|
||||
return newArr;
|
||||
}
|
||||
|
||||
public BasicDBList maybeConvertList(BasicDBList dbl) {
|
||||
public BasicDBList maybeConvertList(Iterable<?> source) {
|
||||
BasicDBList newDbl = new BasicDBList();
|
||||
Iterator<?> iter = dbl.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Object o = iter.next();
|
||||
newDbl.add(convertToMongoType(o));
|
||||
for (Object element : source) {
|
||||
newDbl.add(convertToMongoType(element));
|
||||
}
|
||||
return newDbl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the type information from the conversion result.
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
private Object removeTypeInfoRecursively(Object object) {
|
||||
|
||||
if (!(object instanceof DBObject)) {
|
||||
return object;
|
||||
}
|
||||
|
||||
DBObject dbObject = (DBObject) object;
|
||||
String keyToRemove = null;
|
||||
for (String key : dbObject.keySet()) {
|
||||
|
||||
if (typeMapper.isTypeKey(key)) {
|
||||
keyToRemove = key;
|
||||
}
|
||||
|
||||
Object value = dbObject.get(key);
|
||||
if (value instanceof BasicDBList) {
|
||||
for (Object element : (BasicDBList) value) {
|
||||
removeTypeInfoRecursively(element);
|
||||
}
|
||||
} else {
|
||||
removeTypeInfoRecursively(value);
|
||||
}
|
||||
}
|
||||
|
||||
if (keyToRemove != null) {
|
||||
dbObject.removeField(keyToRemove);
|
||||
}
|
||||
|
||||
return dbObject;
|
||||
}
|
||||
|
||||
private class DelegatingParameterValueProvider implements ParameterValueProvider {
|
||||
|
||||
private final DBObject source;
|
||||
private final ParameterValueProvider delegate;
|
||||
private final MappedConstructor constructor;
|
||||
|
||||
/**
|
||||
* {@link ParameterValueProvider} to delegate source object lookup to a {@link SpELAwareParameterValueProvider} in
|
||||
* case a MappCon
|
||||
*
|
||||
* @param constructor must not be {@literal null}.
|
||||
* @param source must not be {@literal null}.
|
||||
* @param delegate must not be {@literal null}.
|
||||
*/
|
||||
public DelegatingParameterValueProvider(MappedConstructor constructor, DBObject source,
|
||||
SpELAwareParameterValueProvider delegate) {
|
||||
|
||||
Assert.notNull(constructor);
|
||||
Assert.notNull(source);
|
||||
Assert.notNull(delegate);
|
||||
|
||||
this.constructor = constructor;
|
||||
this.source = source;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getParameterValue(Parameter<T> parameter) {
|
||||
|
||||
MappedConstructor.MappedParameter mappedParameter = constructor.getFor(parameter);
|
||||
Object value = mappedParameter.hasSpELExpression() ? delegate.getParameterValue(parameter) : source
|
||||
.get(mappedParameter.getFieldName());
|
||||
|
||||
TypeInformation<?> type = mappedParameter.getPropertyTypeInformation();
|
||||
|
||||
if (value instanceof DBRef) {
|
||||
return (T) read(type, ((DBRef) value).fetch());
|
||||
} else if (value instanceof BasicDBList) {
|
||||
return (T) getPotentiallyConvertedSimpleRead(readCollectionOrArray(type, (BasicDBList) value), type.getType());
|
||||
} else if (value instanceof DBObject) {
|
||||
return (T) read(type, (DBObject) value);
|
||||
} else {
|
||||
return (T) getPotentiallyConvertedSimpleRead(value, type.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import static org.springframework.beans.PropertyAccessorFactory.forBeanPropertyAccess;
|
||||
import static org.springframework.beans.PropertyAccessorFactory.forDirectFieldAccess;
|
||||
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.ConfigurablePropertyAccessor;
|
||||
import org.springframework.beans.NotWritablePropertyException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.mongodb.core.convert.MongoPropertyDescriptors.MongoPropertyDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Custom Mongo specific {@link BeanWrapper} to allow access to bean properties via {@link MongoPropertyDescriptor}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class MongoBeanWrapper {
|
||||
|
||||
private final ConfigurablePropertyAccessor accessor;
|
||||
private final MongoPropertyDescriptors descriptors;
|
||||
private final boolean fieldAccess;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoBeanWrapper} for the given target object and {@link ConversionService}.
|
||||
*
|
||||
* @param target
|
||||
* @param conversionService
|
||||
* @param fieldAccess
|
||||
*/
|
||||
public MongoBeanWrapper(Object target, ConversionService conversionService, boolean fieldAccess) {
|
||||
|
||||
Assert.notNull(target);
|
||||
Assert.notNull(conversionService);
|
||||
|
||||
this.fieldAccess = fieldAccess;
|
||||
this.accessor = fieldAccess ? forDirectFieldAccess(target) : forBeanPropertyAccess(target);
|
||||
this.accessor.setConversionService(conversionService);
|
||||
this.descriptors = new MongoPropertyDescriptors(target.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all {@link MongoPropertyDescriptors.MongoPropertyDescriptor}s for the underlying target object.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public MongoPropertyDescriptors getDescriptors() {
|
||||
return this.descriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the underlying object for the given property.
|
||||
*
|
||||
* @param descriptor
|
||||
* @return
|
||||
*/
|
||||
public Object getValue(MongoPropertyDescriptors.MongoPropertyDescriptor descriptor) {
|
||||
Assert.notNull(descriptor);
|
||||
return accessor.getPropertyValue(descriptor.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the property of the underlying object to the given value.
|
||||
*
|
||||
* @param descriptor
|
||||
* @param value
|
||||
*/
|
||||
public void setValue(MongoPropertyDescriptors.MongoPropertyDescriptor descriptor, Object value) {
|
||||
Assert.notNull(descriptor);
|
||||
try {
|
||||
accessor.setPropertyValue(descriptor.getName(), value);
|
||||
} catch (NotWritablePropertyException e) {
|
||||
if (!fieldAccess) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,29 +15,20 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.convert.EntityConverter;
|
||||
import org.springframework.data.convert.EntityReader;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Central Mongo specific converter interface which combines {@link MongoWriter} and {@link MongoReader}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface MongoConverter extends MongoWriter<Object>, MongoReader<Object> {
|
||||
public interface MongoConverter extends
|
||||
EntityConverter<MongoPersistentEntity<?>, MongoPersistentProperty, Object, DBObject>, MongoWriter<Object>,
|
||||
EntityReader<Object, DBObject> {
|
||||
|
||||
/**
|
||||
* Returns the underlying {@link MappingContext} used by the converter.
|
||||
*
|
||||
* @return never {@literal null}
|
||||
*/
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext();
|
||||
|
||||
/**
|
||||
* Returns the underlying {@link ConversionService} used by the converter.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
ConversionService getConversionService();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,8 +17,12 @@ package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
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.util.StringUtils;
|
||||
|
||||
@@ -119,4 +123,28 @@ abstract class MongoConverters {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,244 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* An iterable of {@link MongoPropertyDescriptor}s that allows dedicated access to the {@link MongoPropertyDescriptor}
|
||||
* that captures the id-property.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoPropertyDescriptors implements Iterable<MongoPropertyDescriptors.MongoPropertyDescriptor> {
|
||||
|
||||
private final Collection<MongoPropertyDescriptors.MongoPropertyDescriptor> descriptors;
|
||||
private final MongoPropertyDescriptors.MongoPropertyDescriptor idDescriptor;
|
||||
|
||||
/**
|
||||
* Creates the {@link MongoPropertyDescriptors} for the given type.
|
||||
*
|
||||
* @param type
|
||||
*/
|
||||
public MongoPropertyDescriptors(Class<?> type) {
|
||||
|
||||
Assert.notNull(type);
|
||||
Set<MongoPropertyDescriptors.MongoPropertyDescriptor> descriptors = new HashSet<MongoPropertyDescriptors.MongoPropertyDescriptor>();
|
||||
MongoPropertyDescriptors.MongoPropertyDescriptor idDesciptor = null;
|
||||
|
||||
for (PropertyDescriptor candidates : BeanUtils.getPropertyDescriptors(type)) {
|
||||
MongoPropertyDescriptor descriptor = new MongoPropertyDescriptors.MongoPropertyDescriptor(candidates, type);
|
||||
descriptors.add(descriptor);
|
||||
if (descriptor.isIdProperty()) {
|
||||
idDesciptor = descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
this.descriptors = Collections.unmodifiableSet(descriptors);
|
||||
this.idDescriptor = idDesciptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link MongoPropertyDescriptor} for the id property.
|
||||
*
|
||||
* @return the idDescriptor
|
||||
*/
|
||||
public MongoPropertyDescriptors.MongoPropertyDescriptor getIdDescriptor() {
|
||||
return idDescriptor;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Iterable#iterator()
|
||||
*/
|
||||
public Iterator<MongoPropertyDescriptors.MongoPropertyDescriptor> iterator() {
|
||||
return descriptors.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple value object to have a more suitable abstraction for MongoDB specific property handling.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public static class MongoPropertyDescriptor {
|
||||
|
||||
public static Collection<Class<?>> SUPPORTED_ID_CLASSES;
|
||||
|
||||
static {
|
||||
Set<Class<?>> classes = new HashSet<Class<?>>();
|
||||
classes.add(ObjectId.class);
|
||||
classes.add(String.class);
|
||||
classes.add(BigInteger.class);
|
||||
SUPPORTED_ID_CLASSES = Collections.unmodifiableCollection(classes);
|
||||
}
|
||||
|
||||
private static final String ID_PROPERTY = "id";
|
||||
static final String ID_KEY = "_id";
|
||||
|
||||
private final PropertyDescriptor delegate;
|
||||
private final Class<?> owningType;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoPropertyDescriptor} for the given {@link PropertyDescriptor}.
|
||||
*
|
||||
* @param descriptor
|
||||
* @param owningType
|
||||
*/
|
||||
public MongoPropertyDescriptor(PropertyDescriptor descriptor, Class<?> owningType) {
|
||||
Assert.notNull(descriptor);
|
||||
this.delegate = descriptor;
|
||||
this.owningType = owningType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the property is the id-property. Will be identified by name for now ({@value #ID_PROPERTY}).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isIdProperty() {
|
||||
return ID_PROPERTY.equals(delegate.getName()) || ID_KEY.equals(delegate.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the property is of one of the supported id types. Currently we support {@link String},
|
||||
* {@link ObjectId} and {@link BigInteger}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isOfIdType() {
|
||||
return SUPPORTED_ID_CLASSES.contains(delegate.getPropertyType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key that shall be used for mapping. Will return {@value #ID_KEY} for the id property and the plain
|
||||
* name for all other ones.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getKeyToMap() {
|
||||
return isIdProperty() ? ID_KEY : delegate.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the property.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getName() {
|
||||
return delegate.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the underlying property is actually mappable. By default this will exclude the {@literal class}
|
||||
* property and only include properties with a getter.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isMappable() {
|
||||
|
||||
boolean isNotClassAttribute = !delegate.getName().equals("class");
|
||||
boolean hasGetter = delegate.getReadMethod() != null;
|
||||
boolean hasField = ReflectionUtils.findField(owningType, delegate.getName()) != null;
|
||||
|
||||
return isNotClassAttribute && hasGetter && hasField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plain property type.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Class<?> getPropertyType() {
|
||||
return delegate.getPropertyType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type type to be set. Will return the setter method's type and fall back to the getter method's return
|
||||
* type in case no setter is available. Useful for further (generics) inspection.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Type getTypeToSet() {
|
||||
|
||||
Method method = delegate.getWriteMethod();
|
||||
return method == null ? delegate.getReadMethod().getGenericReturnType() : method.getGenericParameterTypes()[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whther we describe a {@link Map}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isMap() {
|
||||
return Map.class.isAssignableFrom(getPropertyType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the descriptor is for a collection.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isCollection() {
|
||||
return Collection.class.isAssignableFrom(getPropertyType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the descriptor is for an {@link Enum}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isEnum() {
|
||||
return Enum.class.isAssignableFrom(getPropertyType());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || !getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
MongoPropertyDescriptor that = (MongoPropertyDescriptor) obj;
|
||||
return that.delegate.equals(this.delegate);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return delegate.hashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* A MongoWriter is responsible for converting a native MongoDB DBObject to an object of type T.
|
||||
*
|
||||
* @param <T> the type of the object to convert from a DBObject
|
||||
* @author Mark Pollack
|
||||
* @author Thomas Risberg
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface MongoReader<T> {
|
||||
|
||||
/**
|
||||
* Ready from the native MongoDB DBObject representation to an instance of the class T. The given type has to be the
|
||||
* starting point for marshalling the {@link DBObject} into it. So in case there's no real valid data inside
|
||||
* {@link DBObject} for the given type, just return an empty instance of the given type.
|
||||
*
|
||||
* @param clazz the type of the return value. Will never be {@literal null}.
|
||||
* @param dbo the {@link DBObject} to convert into a domain object. Might be {@literal null}.
|
||||
* @return the converted object. Might be {@literal null}.
|
||||
*/
|
||||
<S extends T> S read(Class<S> clazz, DBObject dbo);
|
||||
}
|
||||
@@ -15,17 +15,21 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import org.springframework.data.convert.TypeMapper;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Interfaces for components being able to provide a {@link TypeMapper}.
|
||||
* Mongo-specific {@link TypeMapper} exposing that {@link DBObject}s might contain a type key.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface TypeMapperProvider {
|
||||
public interface MongoTypeMapper extends TypeMapper<DBObject> {
|
||||
|
||||
/**
|
||||
* Returns the {@link TypeMapper}.
|
||||
* Returns whether the given key is the type key.
|
||||
*
|
||||
* @return the {@link TypeMapper} or {@literal null} if none available.
|
||||
* @return
|
||||
*/
|
||||
TypeMapper getTypeMapper();
|
||||
boolean isTypeKey(String key);
|
||||
}
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import org.springframework.data.convert.EntityWriter;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
@@ -25,15 +27,7 @@ import com.mongodb.DBObject;
|
||||
* @author Thomas Risberg
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface MongoWriter<T> {
|
||||
|
||||
/**
|
||||
* Write the given object of type T to the native MongoDB object representation DBObject.
|
||||
*
|
||||
* @param t The object to convert to a DBObject
|
||||
* @param dbo The DBObject to use for writing.
|
||||
*/
|
||||
void write(T t, DBObject dbo);
|
||||
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
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Interface to define strategies how to store type information in a {@link DBObject}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface TypeMapper {
|
||||
|
||||
/**
|
||||
* Returns whether the given key is the key being used as type key.
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
boolean isTypeKey(String key);
|
||||
|
||||
/**
|
||||
* Reads the {@link TypeInformation} from the given {@link DBObject}.
|
||||
*
|
||||
* @param dbObject must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
TypeInformation<?> readType(DBObject dbObject);
|
||||
|
||||
/**
|
||||
* Writes type information for the given type into the given {@link DBObject}.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @param dbObject must not be {@literal null}.
|
||||
*/
|
||||
void writeType(Class<?> type, DBObject dbObject);
|
||||
|
||||
/**
|
||||
* Writes type information for the given {@link TypeInformation} into the given {@link DBObject}.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @param dbObject must not be {@literal null}.
|
||||
*/
|
||||
void writeType(TypeInformation<?> type, DBObject dbObject);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user