First stab at mapping
This commit is contained in:
@@ -1,132 +1,136 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<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">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-document-parent</artifactId>
|
<artifactId>spring-data-document-parent</artifactId>
|
||||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||||
<relativePath>../spring-data-document-parent/pom.xml</relativePath>
|
<relativePath>../spring-data-document-parent/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-data-document-core</artifactId>
|
<artifactId>spring-data-document-core</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>Spring Data Document Support</name>
|
<name>Spring Data Document Support</name>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<!-- Spring -->
|
<!-- Spring -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-beans</artifactId>
|
<artifactId>spring-beans</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-tx</artifactId>
|
<artifactId>spring-tx</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Logging -->
|
<!-- Logging -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>jcl-over-slf4j</artifactId>
|
<artifactId>jcl-over-slf4j</artifactId>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-log4j12</artifactId>
|
<artifactId>slf4j-log4j12</artifactId>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>log4j</groupId>
|
<groupId>log4j</groupId>
|
||||||
<artifactId>log4j</artifactId>
|
<artifactId>log4j</artifactId>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>javax.mail</groupId>
|
<groupId>javax.mail</groupId>
|
||||||
<artifactId>mail</artifactId>
|
<artifactId>mail</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>javax.jms</groupId>
|
<groupId>javax.jms</groupId>
|
||||||
<artifactId>jms</artifactId>
|
<artifactId>jms</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>com.sun.jdmk</groupId>
|
<groupId>com.sun.jdmk</groupId>
|
||||||
<artifactId>jmxtools</artifactId>
|
<artifactId>jmxtools</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>com.sun.jmx</groupId>
|
<groupId>com.sun.jmx</groupId>
|
||||||
<artifactId>jmxri</artifactId>
|
<artifactId>jmxri</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.annotation</groupId>
|
<groupId>javax.annotation</groupId>
|
||||||
<artifactId>jsr250-api</artifactId>
|
<artifactId>jsr250-api</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>mockito-all</artifactId>
|
<artifactId>mockito-all</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- Dependencies for web analytics functionality - to me moved into spring framework -->
|
<!-- Dependencies for web analytics functionality - to me moved into spring framework -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>servlet-api</artifactId>
|
||||||
<version>2.5</version>
|
<version>2.5</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Spring dependencies -->
|
<!-- Spring dependencies -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-core</artifactId>
|
<artifactId>spring-core</artifactId>
|
||||||
<version>${org.springframework.version}</version>
|
<version>${org.springframework.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>commons-logging</groupId>
|
<groupId>commons-logging</groupId>
|
||||||
<artifactId>commons-logging</artifactId>
|
<artifactId>commons-logging</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-web</artifactId>
|
<artifactId>spring-web</artifactId>
|
||||||
<version>${org.springframework.version}</version>
|
<version>${org.springframework.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>commons-logging</groupId>
|
<groupId>commons-logging</groupId>
|
||||||
<artifactId>commons-logging</artifactId>
|
<artifactId>commons-logging</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-webmvc</artifactId>
|
<artifactId>spring-webmvc</artifactId>
|
||||||
<version>${org.springframework.version}</version>
|
<version>${org.springframework.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>commons-logging</groupId>
|
<groupId>commons-logging</groupId>
|
||||||
<artifactId>commons-logging</artifactId>
|
<artifactId>commons-logging</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.springsource.bundlor</groupId>
|
<groupId>com.springsource.bundlor</groupId>
|
||||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
<artifactId>com.springsource.bundlor.maven</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -24,9 +24,15 @@ Import-Template:
|
|||||||
org.springframework.core.*;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.dao.*;version="[3.0.0, 4.0.0)",
|
||||||
org.springframework.util.*;version="[3.0.0, 4.0.0)",
|
org.springframework.util.*;version="[3.0.0, 4.0.0)",
|
||||||
|
org.springframework.expression.*;version="[3.0.0, 4.0.0)",
|
||||||
|
org.springframework.expression.common.*;version="[3.0.0, 4.0.0)",
|
||||||
|
org.springframework.expression.spel.standard.*;version="[3.0.0, 4.0.0)",
|
||||||
|
org.springframework.expression.spel.support.*;version="[3.0.0, 4.0.0)",
|
||||||
|
org.springframework.validation.*;version="[3.0.0, 4.0.0)",
|
||||||
org.springframework.data.core.*;version="[1.0.0, 2.0.0)",
|
org.springframework.data.core.*;version="[1.0.0, 2.0.0)",
|
||||||
org.aopalliance.*;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.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||||
org.w3c.dom.*;version="0"
|
org.w3c.dom.*;version="0",
|
||||||
|
javax.persistence.*;version="[1.0, 2.0)"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,400 +1,407 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
<modelVersion>4.0.0</modelVersion>
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<groupId>org.springframework.data</groupId>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>spring-data-document-parent</artifactId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<name>Spring Data Document Parent</name>
|
<artifactId>spring-data-document-parent</artifactId>
|
||||||
<url>http://www.springsource.org/spring-data/data-document</url>
|
<name>Spring Data Document Parent</name>
|
||||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
<url>http://www.springsource.org/spring-data/data-document</url>
|
||||||
<packaging>pom</packaging>
|
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||||
<properties>
|
<packaging>pom</packaging>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<properties>
|
||||||
<!-- versions for commonly-used dependencies -->
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<junit.version>4.8.1</junit.version>
|
<!-- versions for commonly-used dependencies -->
|
||||||
<log4j.version>1.2.15</log4j.version>
|
<junit.version>4.8.1</junit.version>
|
||||||
<org.mockito.version>1.8.4</org.mockito.version>
|
<log4j.version>1.2.15</log4j.version>
|
||||||
<org.slf4j.version>1.5.10</org.slf4j.version>
|
<org.mockito.version>1.8.4</org.mockito.version>
|
||||||
<org.springframework.version>3.0.5.RELEASE</org.springframework.version>
|
<org.slf4j.version>1.5.10</org.slf4j.version>
|
||||||
<data.commons.version>1.0.0.BUILD-SNAPSHOT</data.commons.version>
|
<org.springframework.version>3.0.5.RELEASE</org.springframework.version>
|
||||||
<aspectj.version>1.6.11.M2</aspectj.version>
|
<data.commons.version>1.0.0.BUILD-SNAPSHOT</data.commons.version>
|
||||||
</properties>
|
<aspectj.version>1.6.11.M2</aspectj.version>
|
||||||
<profiles>
|
</properties>
|
||||||
<profile>
|
<profiles>
|
||||||
<id>strict</id>
|
<profile>
|
||||||
<properties>
|
<id>strict</id>
|
||||||
<maven.test.failure.ignore>false</maven.test.failure.ignore>
|
<properties>
|
||||||
</properties>
|
<maven.test.failure.ignore>false</maven.test.failure.ignore>
|
||||||
</profile>
|
</properties>
|
||||||
<profile>
|
</profile>
|
||||||
<id>fast</id>
|
<profile>
|
||||||
<properties>
|
<id>fast</id>
|
||||||
<maven.test.skip>true</maven.test.skip>
|
<properties>
|
||||||
<maven.javadoc.skip>true</maven.javadoc.skip>
|
<maven.test.skip>true</maven.test.skip>
|
||||||
</properties>
|
<maven.javadoc.skip>true</maven.javadoc.skip>
|
||||||
</profile>
|
</properties>
|
||||||
<profile>
|
</profile>
|
||||||
<id>staging</id>
|
<profile>
|
||||||
<distributionManagement>
|
<id>staging</id>
|
||||||
<site>
|
<distributionManagement>
|
||||||
<id>spring-site-staging</id>
|
<site>
|
||||||
<url>file:///${java.io.tmpdir}/spring-data/data-document/docs</url>
|
<id>spring-site-staging</id>
|
||||||
</site>
|
<url>file:///${java.io.tmpdir}/spring-data/data-document/docs</url>
|
||||||
<repository>
|
</site>
|
||||||
<id>spring-milestone-staging</id>
|
<repository>
|
||||||
<url>file:///${java.io.tmpdir}/spring-data/data-document/milestone</url>
|
<id>spring-milestone-staging</id>
|
||||||
</repository>
|
<url>file:///${java.io.tmpdir}/spring-data/data-document/milestone</url>
|
||||||
<snapshotRepository>
|
</repository>
|
||||||
<id>spring-snapshot-staging</id>
|
<snapshotRepository>
|
||||||
<url>file:///${java.io.tmpdir}/spring-data/data-document/snapshot</url>
|
<id>spring-snapshot-staging</id>
|
||||||
</snapshotRepository>
|
<url>file:///${java.io.tmpdir}/spring-data/data-document/snapshot</url>
|
||||||
</distributionManagement>
|
</snapshotRepository>
|
||||||
</profile>
|
</distributionManagement>
|
||||||
<profile>
|
</profile>
|
||||||
<id>bootstrap</id>
|
<profile>
|
||||||
<!-- TODO: move the repositories in here before release -->
|
<id>bootstrap</id>
|
||||||
</profile>
|
<!-- TODO: move the repositories in here before release -->
|
||||||
</profiles>
|
</profile>
|
||||||
<distributionManagement>
|
</profiles>
|
||||||
<!-- see 'staging' profile for dry-run deployment settings -->
|
<distributionManagement>
|
||||||
<downloadUrl>http://www.springsource.com/download/community
|
<!-- see 'staging' profile for dry-run deployment settings -->
|
||||||
</downloadUrl>
|
<downloadUrl>http://www.springsource.com/download/community
|
||||||
<site>
|
</downloadUrl>
|
||||||
<id>static.springframework.org</id>
|
<site>
|
||||||
<url>scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-document/docs/${project.version}
|
<id>static.springframework.org</id>
|
||||||
</url>
|
<url>
|
||||||
</site>
|
scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-document/docs/${project.version}
|
||||||
<repository>
|
</url>
|
||||||
<id>spring-milestone</id>
|
</site>
|
||||||
<name>Spring Milestone Repository</name>
|
<repository>
|
||||||
<url>s3://maven.springframework.org/milestone</url>
|
<id>spring-milestone</id>
|
||||||
</repository>
|
<name>Spring Milestone Repository</name>
|
||||||
<snapshotRepository>
|
<url>s3://maven.springframework.org/milestone</url>
|
||||||
<id>spring-snapshot</id>
|
</repository>
|
||||||
<name>Spring Snapshot Repository</name>
|
<snapshotRepository>
|
||||||
<url>s3://maven.springframework.org/snapshot</url>
|
<id>spring-snapshot</id>
|
||||||
</snapshotRepository>
|
<name>Spring Snapshot Repository</name>
|
||||||
</distributionManagement>
|
<url>s3://maven.springframework.org/snapshot</url>
|
||||||
<dependencyManagement>
|
</snapshotRepository>
|
||||||
<!--
|
</distributionManagement>
|
||||||
inheritable <dependency> declarations for child poms. children still
|
<dependencyManagement>
|
||||||
must explicitly declare the groupId/artifactId of these dependencies
|
<!--
|
||||||
in order for them to show up on the classpath, but metadata like
|
inheritable <dependency> declarations for child poms. children still
|
||||||
<version> and <scope> are inherited, which cuts down on verbosity.
|
must explicitly declare the groupId/artifactId of these dependencies
|
||||||
see
|
in order for them to show up on the classpath, but metadata like
|
||||||
http://www.sonatype.com/books/mvnref-book/reference/pom-relationships-sect-dep-manage.html
|
<version> and <scope> are inherited, which cuts down on verbosity.
|
||||||
-->
|
see
|
||||||
<dependencies>
|
http://www.sonatype.com/books/mvnref-book/reference/pom-relationships-sect-dep-manage.html
|
||||||
|
-->
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
<!-- Spring -->
|
<!-- Spring -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-aop</artifactId>
|
<artifactId>spring-aop</artifactId>
|
||||||
<version>${org.springframework.version}</version>
|
<version>${org.springframework.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-beans</artifactId>
|
<artifactId>spring-beans</artifactId>
|
||||||
<version>${org.springframework.version}</version>
|
<version>${org.springframework.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-core</artifactId>
|
<artifactId>spring-core</artifactId>
|
||||||
<version>${org.springframework.version}</version>
|
<version>${org.springframework.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>commons-logging</groupId>
|
<groupId>commons-logging</groupId>
|
||||||
<artifactId>commons-logging</artifactId>
|
<artifactId>commons-logging</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-tx</artifactId>
|
<artifactId>spring-tx</artifactId>
|
||||||
<version>${org.springframework.version}</version>
|
<version>${org.springframework.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-orm</artifactId>
|
<artifactId>spring-orm</artifactId>
|
||||||
<version>${org.springframework.version}</version>
|
<version>${org.springframework.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-test</artifactId>
|
<artifactId>spring-web</artifactId>
|
||||||
<version>${org.springframework.version}</version>
|
<version>${org.springframework.version}</version>
|
||||||
<scope>test</scope>
|
</dependency>
|
||||||
</dependency>
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-expression</artifactId>
|
||||||
|
<version>${org.springframework.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-test</artifactId>
|
||||||
|
<version>${org.springframework.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Spring Data -->
|
<!-- Spring Data -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-commons-core</artifactId>
|
<artifactId>spring-data-commons-core</artifactId>
|
||||||
<version>${data.commons.version}</version>
|
<version>${data.commons.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-commons-aspects</artifactId>
|
<artifactId>spring-data-commons-aspects</artifactId>
|
||||||
<version>${data.commons.version}</version>
|
<version>${data.commons.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-document-core</artifactId>
|
<artifactId>spring-data-couchdb</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-couchdb</artifactId>
|
<artifactId>spring-data-mongodb</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.data</groupId>
|
|
||||||
<artifactId>spring-data-mongodb</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Logging -->
|
<!-- Logging -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
<version>${org.slf4j.version}</version>
|
<version>${org.slf4j.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>jcl-over-slf4j</artifactId>
|
<artifactId>jcl-over-slf4j</artifactId>
|
||||||
<version>${org.slf4j.version}</version>
|
<version>${org.slf4j.version}</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-log4j12</artifactId>
|
<artifactId>slf4j-log4j12</artifactId>
|
||||||
<version>${org.slf4j.version}</version>
|
<version>${org.slf4j.version}</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>log4j</groupId>
|
<groupId>log4j</groupId>
|
||||||
<artifactId>log4j</artifactId>
|
<artifactId>log4j</artifactId>
|
||||||
<version>${log4j.version}</version>
|
<version>${log4j.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>javax.mail</groupId>
|
<groupId>javax.mail</groupId>
|
||||||
<artifactId>mail</artifactId>
|
<artifactId>mail</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>javax.jms</groupId>
|
<groupId>javax.jms</groupId>
|
||||||
<artifactId>jms</artifactId>
|
<artifactId>jms</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>com.sun.jdmk</groupId>
|
<groupId>com.sun.jdmk</groupId>
|
||||||
<artifactId>jmxtools</artifactId>
|
<artifactId>jmxtools</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>com.sun.jmx</groupId>
|
<groupId>com.sun.jmx</groupId>
|
||||||
<artifactId>jmxri</artifactId>
|
<artifactId>jmxri</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.annotation</groupId>
|
<groupId>javax.annotation</groupId>
|
||||||
<artifactId>jsr250-api</artifactId>
|
<artifactId>jsr250-api</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.0</version>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>mockito-all</artifactId>
|
<artifactId>mockito-all</artifactId>
|
||||||
<version>${org.mockito.version}</version>
|
<version>${org.mockito.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>${junit.version}</version>
|
<version>${junit.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!--
|
<!--
|
||||||
dependency definitions to be inherited by child poms. any
|
dependency definitions to be inherited by child poms. any
|
||||||
<dependency> declarations here will automatically show up on child
|
<dependency> declarations here will automatically show up on child
|
||||||
project classpaths. only items that are truly common across all
|
project classpaths. only items that are truly common across all
|
||||||
projects (modules and samples) should go here. otherwise, consider
|
projects (modules and samples) should go here. otherwise, consider
|
||||||
<dependencyManagement> above
|
<dependencyManagement> above
|
||||||
-->
|
-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>log4j</groupId>
|
<groupId>log4j</groupId>
|
||||||
<artifactId>log4j</artifactId>
|
<artifactId>log4j</artifactId>
|
||||||
<version>${log4j.version}</version>
|
<version>${log4j.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<extensions>
|
<extensions>
|
||||||
<extension>
|
<extension>
|
||||||
<!--
|
<!--
|
||||||
available only in the springframework maven repository. see
|
available only in the springframework maven repository. see
|
||||||
<repositories> section below
|
<repositories> section below
|
||||||
-->
|
-->
|
||||||
<groupId>org.springframework.build.aws</groupId>
|
<groupId>org.springframework.build.aws</groupId>
|
||||||
<artifactId>org.springframework.build.aws.maven</artifactId>
|
<artifactId>org.springframework.build.aws.maven</artifactId>
|
||||||
<version>3.1.0.RELEASE</version>
|
<version>3.1.0.RELEASE</version>
|
||||||
</extension>
|
</extension>
|
||||||
</extensions>
|
</extensions>
|
||||||
<resources>
|
<resources>
|
||||||
<resource>
|
<resource>
|
||||||
<directory>${project.basedir}/src/main/java</directory>
|
<directory>${project.basedir}/src/main/java</directory>
|
||||||
<includes>
|
<includes>
|
||||||
<include>**/*</include>
|
<include>**/*</include>
|
||||||
</includes>
|
</includes>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/*.java</exclude>
|
<exclude>**/*.java</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</resource>
|
</resource>
|
||||||
<resource>
|
<resource>
|
||||||
<directory>${project.basedir}/src/main/resources</directory>
|
<directory>${project.basedir}/src/main/resources</directory>
|
||||||
<includes>
|
<includes>
|
||||||
<include>**/*</include>
|
<include>**/*</include>
|
||||||
</includes>
|
</includes>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
<testResources>
|
<testResources>
|
||||||
<testResource>
|
<testResource>
|
||||||
<directory>${project.basedir}/src/test/java</directory>
|
<directory>${project.basedir}/src/test/java</directory>
|
||||||
<includes>
|
<includes>
|
||||||
<include>**/*</include>
|
<include>**/*</include>
|
||||||
</includes>
|
</includes>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/*.java</exclude>
|
<exclude>**/*.java</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</testResource>
|
</testResource>
|
||||||
<testResource>
|
<testResource>
|
||||||
<directory>${project.basedir}/src/test/resources</directory>
|
<directory>${project.basedir}/src/test/resources</directory>
|
||||||
<includes>
|
<includes>
|
||||||
<include>**/*</include>
|
<include>**/*</include>
|
||||||
</includes>
|
</includes>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/*.java</exclude>
|
<exclude>**/*.java</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</testResource>
|
</testResource>
|
||||||
</testResources>
|
</testResources>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>1.5</source>
|
<source>1.5</source>
|
||||||
<target>1.5</target>
|
<target>1.5</target>
|
||||||
<compilerArgument>-Xlint:all</compilerArgument>
|
<compilerArgument>-Xlint:all</compilerArgument>
|
||||||
<showWarnings>true</showWarnings>
|
<showWarnings>true</showWarnings>
|
||||||
<showDeprecation>false</showDeprecation>
|
<showDeprecation>false</showDeprecation>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<useFile>false</useFile>
|
<useFile>false</useFile>
|
||||||
<includes>
|
<includes>
|
||||||
<include>**/*Tests.java</include>
|
<include>**/*Tests.java</include>
|
||||||
</includes>
|
</includes>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/Abstract*.java</exclude>
|
<exclude>**/Abstract*.java</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
<junitArtifactName>junit:junit</junitArtifactName>
|
<junitArtifactName>junit:junit</junitArtifactName>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-source-plugin</artifactId>
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>attach-sources</id>
|
<id>attach-sources</id>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>jar</goal>
|
<goal>jar</goal>
|
||||||
</goals>
|
</goals>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
<pluginManagement>
|
<pluginManagement>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<!--
|
<!--
|
||||||
configures the springsource bundlor plugin, which generates
|
configures the springsource bundlor plugin, which generates
|
||||||
OSGI-compatible MANIFEST.MF files during the 'compile' phase of
|
OSGI-compatible MANIFEST.MF files during the 'compile' phase of
|
||||||
the maven build. this plugin is declared within the
|
the maven build. this plugin is declared within the
|
||||||
pluginManagement section because not every module that inherits
|
pluginManagement section because not every module that inherits
|
||||||
from this pom needs bundlor's services, e.g.:
|
from this pom needs bundlor's services, e.g.:
|
||||||
spring-integration-samples and all its children. for this reason,
|
spring-integration-samples and all its children. for this reason,
|
||||||
all modules that wish to use bundlor must declare it explicitly.
|
all modules that wish to use bundlor must declare it explicitly.
|
||||||
it is not necessary to specify the <version> or <configuration>
|
it is not necessary to specify the <version> or <configuration>
|
||||||
sections, but groupId and artifactId are required. see
|
sections, but groupId and artifactId are required. see
|
||||||
http://static.springsource.org/s2-bundlor/1.0.x/user-guide/html/ch04s03.html
|
http://static.springsource.org/s2-bundlor/1.0.x/user-guide/html/ch04s03.html
|
||||||
for more info
|
for more info
|
||||||
-->
|
-->
|
||||||
<groupId>com.springsource.bundlor</groupId>
|
<groupId>com.springsource.bundlor</groupId>
|
||||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
<artifactId>com.springsource.bundlor.maven</artifactId>
|
||||||
<version>1.0.0.RELEASE</version>
|
<version>1.0.0.RELEASE</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<failOnWarnings>true</failOnWarnings>
|
<failOnWarnings>true</failOnWarnings>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>bundlor</id>
|
<id>bundlor</id>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>bundlor</goal>
|
<goal>bundlor</goal>
|
||||||
</goals>
|
</goals>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</pluginManagement>
|
</pluginManagement>
|
||||||
</build>
|
</build>
|
||||||
<pluginRepositories>
|
<pluginRepositories>
|
||||||
<pluginRepository>
|
<pluginRepository>
|
||||||
<!-- necessary for bundlor and utils -->
|
<!-- necessary for bundlor and utils -->
|
||||||
<id>repository.plugin.springsource.release</id>
|
<id>repository.plugin.springsource.release</id>
|
||||||
<name>SpringSource Maven Repository</name>
|
<name>SpringSource Maven Repository</name>
|
||||||
<url>http://repository.springsource.com/maven/bundles/release</url>
|
<url>http://repository.springsource.com/maven/bundles/release</url>
|
||||||
</pluginRepository>
|
</pluginRepository>
|
||||||
</pluginRepositories>
|
</pluginRepositories>
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>repository.springframework.maven.release</id>
|
<id>repository.springframework.maven.release</id>
|
||||||
<name>Spring Framework Maven Release Repository</name>
|
<name>Spring Framework Maven Release Repository</name>
|
||||||
<url>http://maven.springframework.org/release</url>
|
<url>http://maven.springframework.org/release</url>
|
||||||
</repository>
|
</repository>
|
||||||
<repository>
|
<repository>
|
||||||
<id>repository.springframework.maven.milestone</id>
|
<id>repository.springframework.maven.milestone</id>
|
||||||
<name>Spring Framework Maven Milestone Repository</name>
|
<name>Spring Framework Maven Milestone Repository</name>
|
||||||
<url>http://maven.springframework.org/milestone</url>
|
<url>http://maven.springframework.org/milestone</url>
|
||||||
</repository>
|
</repository>
|
||||||
<repository>
|
<repository>
|
||||||
<id>repository.springframework.maven.snapshot</id>
|
<id>repository.springframework.maven.snapshot</id>
|
||||||
<name>Spring Framework Maven Snapshot Repository</name>
|
<name>Spring Framework Maven Snapshot Repository</name>
|
||||||
<url>http://maven.springframework.org/snapshot</url>
|
<url>http://maven.springframework.org/snapshot</url>
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
<reporting>
|
<reporting>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<!--
|
<!--
|
||||||
significantly speeds up the 'Dependencies' report during site
|
significantly speeds up the 'Dependencies' report during site
|
||||||
creation see
|
creation see
|
||||||
http://old.nabble.com/Skipping-dependency-report-during-Maven2-site-generation-td20116761.html
|
http://old.nabble.com/Skipping-dependency-report-during-Maven2-site-generation-td20116761.html
|
||||||
-->
|
-->
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||||
<version>2.1</version>
|
<version>2.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
|
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</reporting>
|
</reporting>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,120 +1,132 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
<modelVersion>4.0.0</modelVersion>
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<parent>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.springframework.data</groupId>
|
<parent>
|
||||||
<artifactId>spring-data-document-parent</artifactId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
<artifactId>spring-data-document-parent</artifactId>
|
||||||
<relativePath>../spring-data-document-parent/pom.xml</relativePath>
|
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||||
</parent>
|
<relativePath>../spring-data-document-parent/pom.xml</relativePath>
|
||||||
<artifactId>spring-data-mongodb</artifactId>
|
</parent>
|
||||||
<packaging>jar</packaging>
|
<artifactId>spring-data-mongodb</artifactId>
|
||||||
<name>Spring Data MongoDB Support</name>
|
<packaging>jar</packaging>
|
||||||
<dependencies>
|
<name>Spring Data MongoDB Support</name>
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
<!-- Spring -->
|
<!-- Spring -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-beans</artifactId>
|
<artifactId>spring-beans</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-tx</artifactId>
|
<artifactId>spring-tx</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-test</artifactId>
|
<artifactId>spring-expression</artifactId>
|
||||||
<scope>test</scope>
|
</dependency>
|
||||||
</dependency>
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Spring Data -->
|
<!-- Spring Data -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-document-core</artifactId>
|
<artifactId>spring-data-document-core</artifactId>
|
||||||
</dependency>
|
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||||
<dependency>
|
</dependency>
|
||||||
<groupId>org.springframework.data</groupId>
|
<dependency>
|
||||||
<artifactId>spring-data-commons-core</artifactId>
|
<groupId>org.springframework.data</groupId>
|
||||||
</dependency>
|
<artifactId>spring-data-commons-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Logging -->
|
<!-- Logging -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>jcl-over-slf4j</artifactId>
|
<artifactId>jcl-over-slf4j</artifactId>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-log4j12</artifactId>
|
<artifactId>slf4j-log4j12</artifactId>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>log4j</groupId>
|
<groupId>log4j</groupId>
|
||||||
<artifactId>log4j</artifactId>
|
<artifactId>log4j</artifactId>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>javax.mail</groupId>
|
<groupId>javax.mail</groupId>
|
||||||
<artifactId>mail</artifactId>
|
<artifactId>mail</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>javax.jms</groupId>
|
<groupId>javax.jms</groupId>
|
||||||
<artifactId>jms</artifactId>
|
<artifactId>jms</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>com.sun.jdmk</groupId>
|
<groupId>com.sun.jdmk</groupId>
|
||||||
<artifactId>jmxtools</artifactId>
|
<artifactId>jmxtools</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>com.sun.jmx</groupId>
|
<groupId>com.sun.jmx</groupId>
|
||||||
<artifactId>jmxri</artifactId>
|
<artifactId>jmxri</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.annotation</groupId>
|
<groupId>javax.annotation</groupId>
|
||||||
<artifactId>jsr250-api</artifactId>
|
<artifactId>jsr250-api</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>javax.persistence</groupId>
|
||||||
<artifactId>mockito-all</artifactId>
|
<artifactId>persistence-api</artifactId>
|
||||||
<scope>test</scope>
|
<version>1.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hamcrest</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>hamcrest-all</artifactId>
|
<artifactId>mockito-all</artifactId>
|
||||||
<version>1.1</version>
|
<scope>test</scope>
|
||||||
<scope>test</scope>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>org.hamcrest</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>hamcrest-all</artifactId>
|
||||||
</dependency>
|
<version>1.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- MongoDB -->
|
<!-- MongoDB -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mongodb</groupId>
|
<groupId>org.mongodb</groupId>
|
||||||
<artifactId>mongo-java-driver</artifactId>
|
<artifactId>mongo-java-driver</artifactId>
|
||||||
<version>2.3</version>
|
<version>2.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.springsource.bundlor</groupId>
|
<groupId>com.springsource.bundlor</groupId>
|
||||||
<artifactId>com.springsource.bundlor.maven</artifactId>
|
<artifactId>com.springsource.bundlor.maven</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -15,20 +15,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.document.mongodb;
|
package org.springframework.data.document.mongodb;
|
||||||
|
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.beans.PropertyDescriptor;
|
import java.beans.PropertyDescriptor;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.bson.types.ObjectId;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An iterable of {@link MongoPropertyDescriptor}s that allows dedicated access to the {@link MongoPropertyDescriptor}
|
* An iterable of {@link MongoPropertyDescriptor}s that allows dedicated access to the {@link MongoPropertyDescriptor}
|
||||||
@@ -38,202 +33,204 @@ import org.springframework.util.Assert;
|
|||||||
*/
|
*/
|
||||||
public class MongoPropertyDescriptors implements Iterable<MongoPropertyDescriptors.MongoPropertyDescriptor> {
|
public class MongoPropertyDescriptors implements Iterable<MongoPropertyDescriptors.MongoPropertyDescriptor> {
|
||||||
|
|
||||||
private final Collection<MongoPropertyDescriptors.MongoPropertyDescriptor> descriptors;
|
private final Collection<MongoPropertyDescriptors.MongoPropertyDescriptor> descriptors;
|
||||||
private final MongoPropertyDescriptors.MongoPropertyDescriptor idDescriptor;
|
private final MongoPropertyDescriptors.MongoPropertyDescriptor idDescriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the {@link MongoPropertyDescriptors} for the given type.
|
* Creates the {@link MongoPropertyDescriptors} for the given type.
|
||||||
*
|
*
|
||||||
* @param type
|
* @param type
|
||||||
*/
|
*/
|
||||||
public MongoPropertyDescriptors(Class<?> type) {
|
public MongoPropertyDescriptors(Class<?> type) {
|
||||||
|
|
||||||
Assert.notNull(type);
|
Assert.notNull(type);
|
||||||
Set<MongoPropertyDescriptors.MongoPropertyDescriptor> descriptors = new HashSet<MongoPropertyDescriptors.MongoPropertyDescriptor>();
|
Set<MongoPropertyDescriptors.MongoPropertyDescriptor> descriptors = new HashSet<MongoPropertyDescriptors.MongoPropertyDescriptor>();
|
||||||
MongoPropertyDescriptors.MongoPropertyDescriptor idDesciptor = null;
|
MongoPropertyDescriptors.MongoPropertyDescriptor idDesciptor = null;
|
||||||
|
|
||||||
for (PropertyDescriptor candidates : BeanUtils.getPropertyDescriptors(type)) {
|
for (PropertyDescriptor candidates : BeanUtils.getPropertyDescriptors(type)) {
|
||||||
MongoPropertyDescriptor descriptor = new MongoPropertyDescriptors.MongoPropertyDescriptor(candidates);
|
MongoPropertyDescriptor descriptor = new MongoPropertyDescriptors.MongoPropertyDescriptor(candidates);
|
||||||
descriptors.add(descriptor);
|
descriptors.add(descriptor);
|
||||||
if (descriptor.isIdProperty()) {
|
if (descriptor.isIdProperty()) {
|
||||||
idDesciptor = descriptor;
|
idDesciptor = descriptor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.descriptors = Collections.unmodifiableSet(descriptors);
|
this.descriptors = Collections.unmodifiableSet(descriptors);
|
||||||
this.idDescriptor = idDesciptor;
|
this.idDescriptor = idDesciptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link MongoPropertyDescriptor} for the id property.
|
* Returns the {@link MongoPropertyDescriptor} for the id property.
|
||||||
*
|
*
|
||||||
* @return the idDescriptor
|
* @return the idDescriptor
|
||||||
*/
|
*/
|
||||||
public MongoPropertyDescriptors.MongoPropertyDescriptor getIdDescriptor() {
|
public MongoPropertyDescriptors.MongoPropertyDescriptor getIdDescriptor() {
|
||||||
return idDescriptor;
|
return idDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see java.lang.Iterable#iterator()
|
* @see java.lang.Iterable#iterator()
|
||||||
*/
|
*/
|
||||||
public Iterator<MongoPropertyDescriptors.MongoPropertyDescriptor> iterator() {
|
public Iterator<MongoPropertyDescriptors.MongoPropertyDescriptor> iterator() {
|
||||||
return descriptors.iterator();
|
return descriptors.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple value object to have a more suitable abstraction for MongoDB specific property handling.
|
* Simple value object to have a more suitable abstraction for MongoDB specific property handling.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public static class MongoPropertyDescriptor {
|
public static class MongoPropertyDescriptor {
|
||||||
|
|
||||||
public static Collection<Class<?>> SUPPORTED_ID_CLASSES;
|
public static Collection<Class<?>> SUPPORTED_ID_CLASSES;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Set<Class<?>> classes = new HashSet<Class<?>>();
|
Set<Class<?>> classes = new HashSet<Class<?>>();
|
||||||
classes.add(ObjectId.class);
|
classes.add(ObjectId.class);
|
||||||
classes.add(String.class);
|
classes.add(String.class);
|
||||||
classes.add(BigInteger.class);
|
classes.add(BigInteger.class);
|
||||||
SUPPORTED_ID_CLASSES = Collections.unmodifiableCollection(classes);
|
SUPPORTED_ID_CLASSES = Collections.unmodifiableCollection(classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String ID_PROPERTY = "id";
|
private static final String ID_PROPERTY = "id";
|
||||||
static final String ID_KEY = "_id";
|
static final String ID_KEY = "_id";
|
||||||
|
|
||||||
private final PropertyDescriptor delegate;
|
private final PropertyDescriptor delegate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link MongoPropertyDescriptor} for the given {@link PropertyDescriptor}.
|
* Creates a new {@link MongoPropertyDescriptor} for the given {@link PropertyDescriptor}.
|
||||||
*
|
*
|
||||||
* @param descriptor
|
* @param descriptor
|
||||||
*/
|
*/
|
||||||
public MongoPropertyDescriptor(PropertyDescriptor descriptor) {
|
public MongoPropertyDescriptor(PropertyDescriptor descriptor) {
|
||||||
Assert.notNull(descriptor);
|
Assert.notNull(descriptor);
|
||||||
this.delegate = descriptor;
|
this.delegate = descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the property is the id-property. Will be identified by name for now ({@value #ID_PROPERTY}).
|
* Returns whether the property is the id-property. Will be identified by name for now ({@value #ID_PROPERTY}).
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean isIdProperty() {
|
public boolean isIdProperty() {
|
||||||
return ID_PROPERTY.equals(delegate.getName()) || ID_KEY.equals(delegate.getName());
|
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},
|
* Returns whether the property is of one of the supported id types. Currently we support {@link String},
|
||||||
* {@link ObjectId} and {@link BigInteger}.
|
* {@link ObjectId} and {@link BigInteger}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean isOfIdType() {
|
public boolean isOfIdType() {
|
||||||
return SUPPORTED_ID_CLASSES.contains(delegate.getPropertyType());
|
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
|
* 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.
|
* plain name for all other ones.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getKeyToMap() {
|
public String getKeyToMap() {
|
||||||
return isIdProperty() ? ID_KEY : delegate.getName();
|
return isIdProperty() ? ID_KEY : delegate.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of the property.
|
* Returns the name of the property.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return delegate.getName();
|
return delegate.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the underlying property is actually mappable. By default this will exclude the
|
* Returns whether the underlying property is actually mappable. By default this will exclude the
|
||||||
* {@literal class} property and only include properties with a getter.
|
* {@literal class} property and only include properties with a getter.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean isMappable() {
|
public boolean isMappable() {
|
||||||
return !delegate.getName().equals("class") && delegate.getReadMethod() != null;
|
return !delegate.getName().equals("class") && delegate.getReadMethod() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the plain property type.
|
* Returns the plain property type.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Class<?> getPropertyType() {
|
public Class<?> getPropertyType() {
|
||||||
return delegate.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
|
* 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 type in case no setter is available. Useful for further (generics) inspection.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Type getTypeToSet() {
|
public Type getTypeToSet() {
|
||||||
|
|
||||||
Method method = delegate.getWriteMethod();
|
Method method = delegate.getWriteMethod();
|
||||||
return method == null ? delegate.getReadMethod().getGenericReturnType()
|
return method == null ? delegate.getReadMethod().getGenericReturnType()
|
||||||
: method.getGenericParameterTypes()[0];
|
: method.getGenericParameterTypes()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whther we describe a {@link Map}.
|
* Returns whther we describe a {@link Map}.
|
||||||
* @return
|
*
|
||||||
*/
|
* @return
|
||||||
public boolean isMap() {
|
*/
|
||||||
return Map.class.isAssignableFrom(getPropertyType());
|
public boolean isMap() {
|
||||||
}
|
return Map.class.isAssignableFrom(getPropertyType());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the descriptor is for a collection.
|
* Returns whether the descriptor is for a collection.
|
||||||
* @return
|
*
|
||||||
*/
|
* @return
|
||||||
public boolean isCollection() {
|
*/
|
||||||
return Collection.class.isAssignableFrom(getPropertyType());
|
public boolean isCollection() {
|
||||||
}
|
return Collection.class.isAssignableFrom(getPropertyType());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the descriptor is for an {@link Enum}.
|
* Returns whether the descriptor is for an {@link Enum}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean isEnum() {
|
public boolean isEnum() {
|
||||||
return Enum.class.isAssignableFrom(getPropertyType());
|
return Enum.class.isAssignableFrom(getPropertyType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see java.lang.Object#equals(java.lang.Object)
|
* @see java.lang.Object#equals(java.lang.Object)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj == this) {
|
if (obj == this) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (obj == null || !getClass().equals(obj.getClass())) {
|
if (obj == null || !getClass().equals(obj.getClass())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MongoPropertyDescriptor that = (MongoPropertyDescriptor) obj;
|
MongoPropertyDescriptor that = (MongoPropertyDescriptor) obj;
|
||||||
return that.delegate.equals(this.delegate);
|
return that.delegate.equals(this.delegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see java.lang.Object#hashCode()
|
* @see java.lang.Object#hashCode()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return delegate.hashCode();
|
return delegate.hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,21 +20,21 @@ import com.mongodb.DBObject;
|
|||||||
/**
|
/**
|
||||||
* A MongoWriter is responsible for converting a native MongoDB DBObject to an object of type T.
|
* 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 Mark Pollack
|
||||||
* @author Thomas Risberg
|
* @author Thomas Risberg
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*
|
|
||||||
* @param <T> the type of the object to convert from a DBObject
|
|
||||||
*/
|
*/
|
||||||
public interface MongoReader<T> {
|
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
|
* 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
|
* 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.
|
* {@link DBObject} for the given type, just return an empty instance of the given type.
|
||||||
* @param clazz the type of the return value
|
*
|
||||||
* @param dbo theDBObject
|
* @param clazz the type of the return value
|
||||||
* @return the converted object
|
* @param dbo theDBObject
|
||||||
*/
|
* @return the converted object
|
||||||
<S extends T> S read(Class<S> clazz, DBObject dbo);
|
*/
|
||||||
|
<S extends T> S read(Class<S> clazz, DBObject dbo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoP
|
|||||||
import org.springframework.data.document.mongodb.query.IndexDefinition;
|
import org.springframework.data.document.mongodb.query.IndexDefinition;
|
||||||
import org.springframework.data.document.mongodb.query.Query;
|
import org.springframework.data.document.mongodb.query.Query;
|
||||||
import org.springframework.data.document.mongodb.query.Update;
|
import org.springframework.data.document.mongodb.query.Update;
|
||||||
|
import org.springframework.data.document.mongodb.convert.MongoConverter;
|
||||||
|
import org.springframework.data.document.mongodb.convert.SimpleMongoConverter;
|
||||||
import org.springframework.jca.cci.core.ConnectionCallback;
|
import org.springframework.jca.cci.core.ConnectionCallback;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@@ -130,7 +132,7 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor used for a template configuration with a default collection name and a custom {@link MongoConverter}
|
* Constructor used for a template configuration with a default collection name and a custom {@link org.springframework.data.document.mongodb.convert.MongoConverter}
|
||||||
* @param mongo
|
* @param mongo
|
||||||
* @param databaseName
|
* @param databaseName
|
||||||
* @param defaultCollectionName
|
* @param defaultCollectionName
|
||||||
@@ -205,7 +207,7 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the default {@link MongoConverter}.
|
* Returns the default {@link org.springframework.data.document.mongodb.convert.MongoConverter}.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,557 +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.document.mongodb;
|
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.lang.reflect.GenericArrayType;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.lang.reflect.TypeVariable;
|
|
||||||
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.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.bson.types.CodeWScope;
|
|
||||||
import org.bson.types.ObjectId;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
import org.springframework.core.CollectionFactory;
|
|
||||||
import org.springframework.core.convert.ConversionFailedException;
|
|
||||||
import org.springframework.core.convert.ConversionService;
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
|
||||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
|
||||||
import org.springframework.core.convert.support.GenericConversionService;
|
|
||||||
import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoPropertyDescriptor;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.comparator.CompoundComparator;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBList;
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import com.mongodb.DBRef;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic {@link MongoConverter} implementation to convert between domain classes and {@link DBObject}s.
|
|
||||||
*
|
|
||||||
* @author Mark Pollack
|
|
||||||
* @author Thomas Risberg
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
public class SimpleMongoConverter implements MongoConverter {
|
|
||||||
|
|
||||||
private static final Log LOG = LogFactory.getLog(SimpleMongoConverter.class);
|
|
||||||
private static final Set<String> SIMPLE_TYPES;
|
|
||||||
|
|
||||||
static {
|
|
||||||
Set<String> basics = new HashSet<String>();
|
|
||||||
basics.add(boolean.class.getName());
|
|
||||||
basics.add(long.class.getName());
|
|
||||||
basics.add(short.class.getName());
|
|
||||||
basics.add(int.class.getName());
|
|
||||||
basics.add(byte.class.getName());
|
|
||||||
basics.add(float.class.getName());
|
|
||||||
basics.add(double.class.getName());
|
|
||||||
basics.add(char.class.getName());
|
|
||||||
basics.add(Boolean.class.getName());
|
|
||||||
basics.add(Long.class.getName());
|
|
||||||
basics.add(Short.class.getName());
|
|
||||||
basics.add(Integer.class.getName());
|
|
||||||
basics.add(Byte.class.getName());
|
|
||||||
basics.add(Float.class.getName());
|
|
||||||
basics.add(Double.class.getName());
|
|
||||||
basics.add(Character.class.getName());
|
|
||||||
basics.add(String.class.getName());
|
|
||||||
basics.add(java.util.Date.class.getName());
|
|
||||||
// basics.add(Time.class.getName());
|
|
||||||
// basics.add(Timestamp.class.getName());
|
|
||||||
// basics.add(java.sql.Date.class.getName());
|
|
||||||
// basics.add(BigDecimal.class.getName());
|
|
||||||
// basics.add(BigInteger.class.getName());
|
|
||||||
basics.add(Locale.class.getName());
|
|
||||||
// basics.add(Calendar.class.getName());
|
|
||||||
// basics.add(GregorianCalendar.class.getName());
|
|
||||||
// basics.add(java.util.Currency.class.getName());
|
|
||||||
// basics.add(TimeZone.class.getName());
|
|
||||||
// basics.add(Object.class.getName());
|
|
||||||
basics.add(Class.class.getName());
|
|
||||||
// basics.add(byte[].class.getName());
|
|
||||||
// basics.add(Byte[].class.getName());
|
|
||||||
// basics.add(char[].class.getName());
|
|
||||||
// basics.add(Character[].class.getName());
|
|
||||||
// basics.add(Blob.class.getName());
|
|
||||||
// basics.add(Clob.class.getName());
|
|
||||||
// basics.add(Serializable.class.getName());
|
|
||||||
// basics.add(URI.class.getName());
|
|
||||||
// basics.add(URL.class.getName());
|
|
||||||
basics.add(DBRef.class.getName());
|
|
||||||
basics.add(Pattern.class.getName());
|
|
||||||
basics.add(CodeWScope.class.getName());
|
|
||||||
basics.add(ObjectId.class.getName());
|
|
||||||
// TODO check on enums..
|
|
||||||
basics.add(Enum.class.getName());
|
|
||||||
SIMPLE_TYPES = Collections.unmodifiableSet(basics);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final GenericConversionService conversionService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@link SimpleMongoConverter}.
|
|
||||||
*/
|
|
||||||
public SimpleMongoConverter() {
|
|
||||||
this.conversionService = ConversionServiceFactory.createDefaultConversionService();
|
|
||||||
initializeConverters();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link SimpleMongoConverter} for the given {@link ConversionService}.
|
|
||||||
*
|
|
||||||
* @param conversionService
|
|
||||||
*/
|
|
||||||
public SimpleMongoConverter(GenericConversionService conversionService) {
|
|
||||||
Assert.notNull(conversionService);
|
|
||||||
this.conversionService = conversionService;
|
|
||||||
initializeConverters();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes additional converters that handle {@link ObjectId} conversion. Will register converters for supported
|
|
||||||
* id types if none are registered for those conversion already. {@link GenericConversionService} is configured.
|
|
||||||
*/
|
|
||||||
protected void initializeConverters() {
|
|
||||||
|
|
||||||
if (!conversionService.canConvert(ObjectId.class, String.class)) {
|
|
||||||
conversionService.addConverter(ObjectIdToStringConverter.INSTANCE);
|
|
||||||
conversionService.addConverter(StringToObjectIdConverter.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!conversionService.canConvert(ObjectId.class, BigInteger.class)) {
|
|
||||||
conversionService.addConverter(ObjectIdToBigIntegerConverter.INSTANCE);
|
|
||||||
conversionService.addConverter(BigIntegerToIdConverter.INSTANCE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.springframework.data.document.mongodb.MongoWriter#write(java.lang.Object, com.mongodb.DBObject)
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public void write(Object obj, DBObject dbo) {
|
|
||||||
|
|
||||||
MongoBeanWrapper beanWrapper = createWrapper(obj, false);
|
|
||||||
for (MongoPropertyDescriptor descriptor : beanWrapper.getDescriptors()) {
|
|
||||||
if (descriptor.isMappable()) {
|
|
||||||
Object value = beanWrapper.getValue(descriptor);
|
|
||||||
|
|
||||||
if (value == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String keyToUse = descriptor.getKeyToMap();
|
|
||||||
// TODO validate Enums...
|
|
||||||
if (descriptor.isEnum()) {
|
|
||||||
writeValue(dbo, keyToUse, ((Enum) value).name());
|
|
||||||
} else if (descriptor.isIdProperty() && descriptor.isOfIdType()) {
|
|
||||||
if (value instanceof String && ObjectId.isValid((String)value)) {
|
|
||||||
try {
|
|
||||||
writeValue(dbo, keyToUse, conversionService.convert(value, ObjectId.class));
|
|
||||||
} catch (ConversionFailedException iae) {
|
|
||||||
LOG.warn("Unable to convert the String " + value + " to an ObjectId");
|
|
||||||
writeValue(dbo, keyToUse, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// we can't convert this id - use as is
|
|
||||||
writeValue(dbo, keyToUse, value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
writeValue(dbo, keyToUse, value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!"class".equals(descriptor.getName())) {
|
|
||||||
LOG.warn("Unable to map property " + descriptor.getName() + ". Skipping.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the given value to the given {@link DBObject}. Will skip {@literal null} values.
|
|
||||||
*
|
|
||||||
* @param dbo
|
|
||||||
* @param keyToUse
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
private void writeValue(DBObject dbo, String keyToUse, Object value) {
|
|
||||||
|
|
||||||
if (!isSimpleType(value.getClass())) {
|
|
||||||
writeCompoundValue(dbo, keyToUse, value);
|
|
||||||
} else {
|
|
||||||
dbo.put(keyToUse, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the given {@link CompoundComparator} value to the given {@link DBObject}.
|
|
||||||
*
|
|
||||||
* @param dbo
|
|
||||||
* @param keyToUse
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void writeCompoundValue(DBObject dbo, String keyToUse, Object value) {
|
|
||||||
if (value instanceof Map) {
|
|
||||||
writeMap(dbo, keyToUse, (Map<String, Object>) value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (value instanceof Collection) {
|
|
||||||
// Should write a collection!
|
|
||||||
writeArray(dbo, keyToUse, ((Collection<Object>) value).toArray());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (value instanceof Object[]) {
|
|
||||||
// Should write an array!
|
|
||||||
writeArray(dbo, keyToUse, (Object[]) value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DBObject nestedDbo = new BasicDBObject();
|
|
||||||
write(value, nestedDbo);
|
|
||||||
dbo.put(keyToUse, nestedDbo);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the given {@link Map} to the given {@link DBObject}.
|
|
||||||
*
|
|
||||||
* @param dbo
|
|
||||||
* @param mapKey
|
|
||||||
* @param map
|
|
||||||
*/
|
|
||||||
protected void writeMap(DBObject dbo, String mapKey, Map<String, Object> map) {
|
|
||||||
// TODO support non-string based keys as long as there is a Spring Converter obj->string and (optionally)
|
|
||||||
// string->obj
|
|
||||||
DBObject dboToPopulate = null;
|
|
||||||
|
|
||||||
// TODO - Does that make sense? If we create a new object here it's content will never make it out of this
|
|
||||||
// method
|
|
||||||
if (mapKey != null) {
|
|
||||||
dboToPopulate = new BasicDBObject();
|
|
||||||
} else {
|
|
||||||
dboToPopulate = dbo;
|
|
||||||
}
|
|
||||||
if (map != null) {
|
|
||||||
for (Entry<String, Object> entry : map.entrySet()) {
|
|
||||||
|
|
||||||
Object entryValue = entry.getValue();
|
|
||||||
String entryKey = entry.getKey();
|
|
||||||
|
|
||||||
if (!isSimpleType(entryValue.getClass())) {
|
|
||||||
writeCompoundValue(dboToPopulate, entryKey, entryValue);
|
|
||||||
} else {
|
|
||||||
dboToPopulate.put(entryKey, entryValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dbo.put(mapKey, dboToPopulate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the given array to the given {@link DBObject}.
|
|
||||||
*
|
|
||||||
* @param dbo
|
|
||||||
* @param keyToUse
|
|
||||||
* @param array
|
|
||||||
*/
|
|
||||||
protected void writeArray(DBObject dbo, String keyToUse, Object[] array) {
|
|
||||||
// TODO
|
|
||||||
Object[] dboValues;
|
|
||||||
if (array != null) {
|
|
||||||
dboValues = new Object[array.length];
|
|
||||||
int i = 0;
|
|
||||||
for (Object o : array) {
|
|
||||||
if (!isSimpleType(o.getClass())) {
|
|
||||||
DBObject dboValue = new BasicDBObject();
|
|
||||||
write(o, dboValue);
|
|
||||||
dboValues[i] = dboValue;
|
|
||||||
} else {
|
|
||||||
dboValues[i] = o;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
dbo.put(keyToUse, dboValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.springframework.data.document.mongodb.MongoReader#read(java.lang.Class, com.mongodb.DBObject)
|
|
||||||
*/
|
|
||||||
public <S> S read(Class<S> clazz, DBObject source) {
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.notNull(clazz, "Mapped class was not specified");
|
|
||||||
S target = BeanUtils.instantiateClass(clazz);
|
|
||||||
MongoBeanWrapper bw = new MongoBeanWrapper(target, conversionService, true);
|
|
||||||
|
|
||||||
for (MongoPropertyDescriptor descriptor : bw.getDescriptors()) {
|
|
||||||
String keyToUse = descriptor.getKeyToMap();
|
|
||||||
if (source.containsField(keyToUse)) {
|
|
||||||
if (descriptor.isMappable()) {
|
|
||||||
Object value = source.get(keyToUse);
|
|
||||||
if (!isSimpleType(value.getClass())) {
|
|
||||||
if (value instanceof Object[]) {
|
|
||||||
bw.setValue(descriptor, readCollection(descriptor, Arrays.asList((Object[]) value))
|
|
||||||
.toArray());
|
|
||||||
} else if (value instanceof BasicDBList) {
|
|
||||||
bw.setValue(descriptor, readCollection(descriptor, (BasicDBList) value));
|
|
||||||
} else if (value instanceof DBObject) {
|
|
||||||
bw.setValue(descriptor, readCompoundValue(descriptor, (DBObject) value));
|
|
||||||
} else {
|
|
||||||
LOG.warn("Unable to map compound DBObject field " + keyToUse + " to property "
|
|
||||||
+ descriptor.getName()
|
|
||||||
+ ". The field value should have been a 'DBObject.class' but was "
|
|
||||||
+ value.getClass().getName());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bw.setValue(descriptor, value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG.warn("Unable to map DBObject field " + keyToUse + " to property " + descriptor.getName()
|
|
||||||
+ ". Skipping.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the given collection values (that are {@link DBObject}s potentially) into a {@link Collection} of domain
|
|
||||||
* objects.
|
|
||||||
*
|
|
||||||
* @param descriptor
|
|
||||||
* @param values
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Collection<Object> readCollection(MongoPropertyDescriptor descriptor, Collection<?> values) {
|
|
||||||
|
|
||||||
Class<?> targetCollectionType = descriptor.getPropertyType();
|
|
||||||
boolean targetIsArray = targetCollectionType.isArray();
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Collection<Object> result = targetIsArray ? new ArrayList<Object>(values.size()) : CollectionFactory
|
|
||||||
.createCollection(targetCollectionType, values.size());
|
|
||||||
|
|
||||||
for (Object o : values) {
|
|
||||||
if (o instanceof DBObject) {
|
|
||||||
Class<?> type;
|
|
||||||
if (targetIsArray) {
|
|
||||||
type = targetCollectionType.getComponentType();
|
|
||||||
} else {
|
|
||||||
type = getGenericParameters(descriptor.getTypeToSet()).get(0);
|
|
||||||
}
|
|
||||||
result.add(read(type, (DBObject) o));
|
|
||||||
} else {
|
|
||||||
result.add(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a compound value from the given {@link DBObject} for the given property.
|
|
||||||
*
|
|
||||||
* @param pd
|
|
||||||
* @param dbo
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Object readCompoundValue(MongoPropertyDescriptors.MongoPropertyDescriptor pd, DBObject dbo) {
|
|
||||||
|
|
||||||
Assert.isTrue(!pd.isCollection(), "Collections not supported!");
|
|
||||||
|
|
||||||
if (pd.isMap()) {
|
|
||||||
return readMap(pd, dbo, getGenericParameters(pd.getTypeToSet()).get(1));
|
|
||||||
} else {
|
|
||||||
return read(pd.getPropertyType(), dbo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link Map} instance. Will return a {@link HashMap} by default. Subclasses might want to override this
|
|
||||||
* method to use a custom {@link Map} implementation.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected Map<String, Object> createMap() {
|
|
||||||
return new HashMap<String, Object>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads every key/value pair from the {@link DBObject} into a {@link Map} instance.
|
|
||||||
*
|
|
||||||
* @param pd
|
|
||||||
* @param dbo
|
|
||||||
* @param targetType
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected Map<?, ?> readMap(MongoPropertyDescriptors.MongoPropertyDescriptor pd, DBObject dbo, Class<?> targetType) {
|
|
||||||
Map<String, Object> map = createMap();
|
|
||||||
for (String key : dbo.keySet()) {
|
|
||||||
Object value = dbo.get(key);
|
|
||||||
if (!isSimpleType(value.getClass())) {
|
|
||||||
map.put(key, read(targetType, (DBObject) value));
|
|
||||||
// Can do some reflection tricks here -
|
|
||||||
// throw new RuntimeException("User types not supported yet as values for Maps");
|
|
||||||
} else {
|
|
||||||
map.put(key, conversionService.convert(value, targetType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static boolean isSimpleType(Class<?> propertyType) {
|
|
||||||
if (propertyType == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (propertyType.isArray()) {
|
|
||||||
return isSimpleType(propertyType.getComponentType());
|
|
||||||
}
|
|
||||||
return SIMPLE_TYPES.contains(propertyType.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to allow customizing creation of a {@link MongoBeanWrapper}.
|
|
||||||
*
|
|
||||||
* @param target the target object to wrap
|
|
||||||
* @param fieldAccess whether to use field access or property access
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected MongoBeanWrapper createWrapper(Object target, boolean fieldAccess) {
|
|
||||||
|
|
||||||
return new MongoBeanWrapper(target, conversionService, fieldAccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Class<?>> getGenericParameters(Type genericParameterType) {
|
|
||||||
|
|
||||||
List<Class<?>> actualGenericParameterTypes = new ArrayList<Class<?>>();
|
|
||||||
|
|
||||||
if (genericParameterType instanceof ParameterizedType) {
|
|
||||||
ParameterizedType aType = (ParameterizedType) genericParameterType;
|
|
||||||
Type[] parameterArgTypes = aType.getActualTypeArguments();
|
|
||||||
for (Type parameterArgType : parameterArgTypes) {
|
|
||||||
if (parameterArgType instanceof GenericArrayType) {
|
|
||||||
Class<?> arrayType = (Class<?>) ((GenericArrayType) parameterArgType).getGenericComponentType();
|
|
||||||
actualGenericParameterTypes.add(Array.newInstance(arrayType, 0).getClass());
|
|
||||||
} else {
|
|
||||||
if (parameterArgType instanceof ParameterizedType) {
|
|
||||||
ParameterizedType paramTypeArgs = (ParameterizedType) parameterArgType;
|
|
||||||
actualGenericParameterTypes.add((Class<?>) paramTypeArgs.getRawType());
|
|
||||||
} else {
|
|
||||||
if (parameterArgType instanceof TypeVariable) {
|
|
||||||
throw new RuntimeException("Can not map " + ((TypeVariable<?>) parameterArgType).getName());
|
|
||||||
} else {
|
|
||||||
if (parameterArgType instanceof Class) {
|
|
||||||
actualGenericParameterTypes.add((Class<?>) parameterArgType);
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("Can not map " + parameterArgType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return actualGenericParameterTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.document.mongodb.MongoConverter#convertObjectId(org.bson.types.ObjectId, java.lang.Class)
|
|
||||||
*/
|
|
||||||
public <T> T convertObjectId(ObjectId id, Class<T> targetType) {
|
|
||||||
return conversionService.convert(id, targetType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.data.document.mongodb.MongoConverter#convertObjectId(java.lang.Object)
|
|
||||||
*/
|
|
||||||
public ObjectId convertObjectId(Object id) {
|
|
||||||
return conversionService.convert(id, ObjectId.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple singleton to convert {@link ObjectId}s to their {@link String} representation.
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
public static enum ObjectIdToStringConverter implements Converter<ObjectId, String> {
|
|
||||||
INSTANCE;
|
|
||||||
public String convert(ObjectId id) {
|
|
||||||
return id.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple singleton to convert {@link String}s to their {@link ObjectId} representation.
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
public static enum StringToObjectIdConverter implements Converter<String, ObjectId> {
|
|
||||||
INSTANCE;
|
|
||||||
public ObjectId convert(String source) {
|
|
||||||
return new ObjectId(source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple singleton to convert {@link ObjectId}s to their {@link BigInteger} representation.
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
public static enum ObjectIdToBigIntegerConverter implements Converter<ObjectId, BigInteger> {
|
|
||||||
INSTANCE;
|
|
||||||
public BigInteger convert(ObjectId source) {
|
|
||||||
return new BigInteger(source.toString(), 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple singleton to convert {@link BigInteger}s to their {@link ObjectId} representation.
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
public static enum BigIntegerToIdConverter implements Converter<BigInteger, ObjectId> {
|
|
||||||
INSTANCE;
|
|
||||||
public ObjectId convert(BigInteger source) {
|
|
||||||
return new ObjectId(source.toString(16));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||||
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by IntelliJ IDEA.
|
||||||
|
* User: jbrisbin
|
||||||
|
* Date: 2/28/11
|
||||||
|
* Time: 9:26 AM
|
||||||
|
* To change this template use File | Settings | File Templates.
|
||||||
|
*/
|
||||||
|
public class MongoMappingConverterParser extends AbstractSingleBeanDefinitionParser {
|
||||||
|
|
||||||
|
private static final String BASE_PACKAGE = "base-package";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) throws BeanDefinitionStoreException {
|
||||||
|
String id = super.resolveId(element, definition, parserContext);
|
||||||
|
if (!StringUtils.hasText(id)) {
|
||||||
|
return "mongoMappingConverter";
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||||
|
super.doParse(element, parserContext, builder);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -32,164 +32,161 @@ import org.w3c.dom.Element;
|
|||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public class SimpleMongoRepositoryConfiguration
|
public class SimpleMongoRepositoryConfiguration extends RepositoryConfig<SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration, SimpleMongoRepositoryConfiguration> {
|
||||||
extends
|
|
||||||
RepositoryConfig<SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration, SimpleMongoRepositoryConfiguration> {
|
|
||||||
|
|
||||||
private static final String MONGO_TEMPLATE_REF = "mongo-template-ref";
|
private static final String MONGO_TEMPLATE_REF = "mongo-template-ref";
|
||||||
private static final String DEFAULT_MONGO_TEMPLATE_REF = "mongoTemplate";
|
private static final String DEFAULT_MONGO_TEMPLATE_REF = "mongoTemplate";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link SimpleMongoRepositoryConfiguration} for the given
|
||||||
|
* {@link Element}.
|
||||||
|
*
|
||||||
|
* @param repositoriesElement
|
||||||
|
*/
|
||||||
|
protected SimpleMongoRepositoryConfiguration(Element repositoriesElement) {
|
||||||
|
|
||||||
|
super(repositoriesElement, MongoRepositoryFactoryBean.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the bean name of the {@link org.springframework.data.document.mongodb.MongoTemplate} to be referenced.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getMongoTemplateRef() {
|
||||||
|
|
||||||
|
String templateRef = getSource().getAttribute(MONGO_TEMPLATE_REF);
|
||||||
|
return StringUtils.hasText(templateRef) ? templateRef
|
||||||
|
: DEFAULT_MONGO_TEMPLATE_REF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.springframework.data.repository.config.GlobalRepositoryConfigInformation
|
||||||
|
* #getAutoconfigRepositoryInformation(java.lang.String)
|
||||||
|
*/
|
||||||
|
public MongoRepositoryConfiguration getAutoconfigRepositoryInformation(
|
||||||
|
String interfaceName) {
|
||||||
|
|
||||||
|
return new AutomaticMongoRepositoryConfiguration(interfaceName, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.springframework.data.repository.config.GlobalRepositoryConfigInformation
|
||||||
|
* #getRepositoryBaseInterface()
|
||||||
|
*/
|
||||||
|
public Class<?> getRepositoryBaseInterface() {
|
||||||
|
|
||||||
|
return MongoRepository.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see org.springframework.data.repository.config.RepositoryConfig#
|
||||||
|
* createSingleRepositoryConfigInformationFor(org.w3c.dom.Element)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected MongoRepositoryConfiguration createSingleRepositoryConfigInformationFor(
|
||||||
|
Element element) {
|
||||||
|
|
||||||
|
return new ManualMongoRepositoryConfiguration(element, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple interface for configuration values specific to Mongo repositories.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public interface MongoRepositoryConfiguration
|
||||||
|
extends
|
||||||
|
SingleRepositoryConfigInformation<SimpleMongoRepositoryConfiguration> {
|
||||||
|
|
||||||
|
String getMongoTemplateRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements manual lookup of the additional attributes.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
private static class ManualMongoRepositoryConfiguration
|
||||||
|
extends
|
||||||
|
ManualRepositoryConfigInformation<SimpleMongoRepositoryConfiguration>
|
||||||
|
implements MongoRepositoryConfiguration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link SimpleMongoRepositoryConfiguration} for the given
|
* Creates a new {@link ManualMongoRepositoryConfiguration} for the
|
||||||
* {@link Element}.
|
* given {@link Element} and parent.
|
||||||
*
|
*
|
||||||
* @param repositoriesElement
|
* @param element
|
||||||
* @param defaultRepositoryFactoryBeanClassName
|
* @param parent
|
||||||
*/
|
*/
|
||||||
protected SimpleMongoRepositoryConfiguration(Element repositoriesElement) {
|
public ManualMongoRepositoryConfiguration(Element element,
|
||||||
|
SimpleMongoRepositoryConfiguration parent) {
|
||||||
|
|
||||||
super(repositoriesElement, MongoRepositoryFactoryBean.class.getName());
|
super(element, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Returns the bean name of the {@link org.springframework.data.document.mongodb.MongoTemplate} to be referenced.
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @return
|
* @see org.springframework.data.document.mongodb.repository.config.
|
||||||
*/
|
* SimpleMongoRepositoryConfiguration
|
||||||
|
* .MongoRepositoryConfiguration#getMongoTemplateRef()
|
||||||
|
*/
|
||||||
public String getMongoTemplateRef() {
|
public String getMongoTemplateRef() {
|
||||||
|
|
||||||
String templateRef = getSource().getAttribute(MONGO_TEMPLATE_REF);
|
return getAttribute(MONGO_TEMPLATE_REF);
|
||||||
return StringUtils.hasText(templateRef) ? templateRef
|
}
|
||||||
: DEFAULT_MONGO_TEMPLATE_REF;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the lookup of the additional attributes during automatic
|
||||||
|
* configuration.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
private static class AutomaticMongoRepositoryConfiguration
|
||||||
|
extends
|
||||||
|
AutomaticRepositoryConfigInformation<SimpleMongoRepositoryConfiguration>
|
||||||
|
implements MongoRepositoryConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link AutomaticMongoRepositoryConfiguration} for the
|
||||||
|
* given interface and parent.
|
||||||
|
*
|
||||||
|
* @param interfaceName
|
||||||
|
* @param parent
|
||||||
|
*/
|
||||||
|
public AutomaticMongoRepositoryConfiguration(String interfaceName,
|
||||||
|
SimpleMongoRepositoryConfiguration parent) {
|
||||||
|
|
||||||
|
super(interfaceName, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see
|
* @see org.springframework.data.document.mongodb.repository.config.
|
||||||
* org.springframework.data.repository.config.GlobalRepositoryConfigInformation
|
* SimpleMongoRepositoryConfiguration
|
||||||
* #getAutoconfigRepositoryInformation(java.lang.String)
|
* .MongoRepositoryConfiguration#getMongoTemplateRef()
|
||||||
*/
|
*/
|
||||||
public MongoRepositoryConfiguration getAutoconfigRepositoryInformation(
|
public String getMongoTemplateRef() {
|
||||||
String interfaceName) {
|
|
||||||
|
|
||||||
return new AutomaticMongoRepositoryConfiguration(interfaceName, this);
|
return getParent().getMongoTemplateRef();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see
|
|
||||||
* org.springframework.data.repository.config.GlobalRepositoryConfigInformation
|
|
||||||
* #getRepositoryBaseInterface()
|
|
||||||
*/
|
|
||||||
public Class<?> getRepositoryBaseInterface() {
|
|
||||||
|
|
||||||
return MongoRepository.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.springframework.data.repository.config.RepositoryConfig#
|
|
||||||
* createSingleRepositoryConfigInformationFor(org.w3c.dom.Element)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected MongoRepositoryConfiguration createSingleRepositoryConfigInformationFor(
|
|
||||||
Element element) {
|
|
||||||
|
|
||||||
return new ManualMongoRepositoryConfiguration(element, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple interface for configuration values specific to Mongo repositories.
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
public interface MongoRepositoryConfiguration
|
|
||||||
extends
|
|
||||||
SingleRepositoryConfigInformation<SimpleMongoRepositoryConfiguration> {
|
|
||||||
|
|
||||||
String getMongoTemplateRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements manual lookup of the additional attributes.
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
private static class ManualMongoRepositoryConfiguration
|
|
||||||
extends
|
|
||||||
ManualRepositoryConfigInformation<SimpleMongoRepositoryConfiguration>
|
|
||||||
implements MongoRepositoryConfiguration {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link ManualMongoRepositoryConfiguration} for the
|
|
||||||
* given {@link Element} and parent.
|
|
||||||
*
|
|
||||||
* @param element
|
|
||||||
* @param parent
|
|
||||||
*/
|
|
||||||
public ManualMongoRepositoryConfiguration(Element element,
|
|
||||||
SimpleMongoRepositoryConfiguration parent) {
|
|
||||||
|
|
||||||
super(element, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.springframework.data.document.mongodb.repository.config.
|
|
||||||
* SimpleMongoRepositoryConfiguration
|
|
||||||
* .MongoRepositoryConfiguration#getMongoTemplateRef()
|
|
||||||
*/
|
|
||||||
public String getMongoTemplateRef() {
|
|
||||||
|
|
||||||
return getAttribute(MONGO_TEMPLATE_REF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements the lookup of the additional attributes during automatic
|
|
||||||
* configuration.
|
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
|
||||||
*/
|
|
||||||
private static class AutomaticMongoRepositoryConfiguration
|
|
||||||
extends
|
|
||||||
AutomaticRepositoryConfigInformation<SimpleMongoRepositoryConfiguration>
|
|
||||||
implements MongoRepositoryConfiguration {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new {@link AutomaticMongoRepositoryConfiguration} for the
|
|
||||||
* given interface and parent.
|
|
||||||
*
|
|
||||||
* @param interfaceName
|
|
||||||
* @param parent
|
|
||||||
*/
|
|
||||||
public AutomaticMongoRepositoryConfiguration(String interfaceName,
|
|
||||||
SimpleMongoRepositoryConfiguration parent) {
|
|
||||||
|
|
||||||
super(interfaceName, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.springframework.data.document.mongodb.repository.config.
|
|
||||||
* SimpleMongoRepositoryConfiguration
|
|
||||||
* .MongoRepositoryConfiguration#getMongoTemplateRef()
|
|
||||||
*/
|
|
||||||
public String getMongoTemplateRef() {
|
|
||||||
|
|
||||||
return getParent().getMongoTemplateRef();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,487 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.convert;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBList;
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
import com.mongodb.DBRef;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.bson.types.CodeWScope;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.context.expression.BeanFactoryResolver;
|
||||||
|
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||||
|
import org.springframework.core.convert.support.GenericConversionService;
|
||||||
|
import org.springframework.data.document.mongodb.mapping.MappingException;
|
||||||
|
import org.springframework.data.document.mongodb.mapping.MappingIntrospector;
|
||||||
|
import org.springframework.data.document.mongodb.mapping.MongoMappingContext;
|
||||||
|
import org.springframework.data.mapping.annotation.Id;
|
||||||
|
import org.springframework.data.mapping.annotation.Persistent;
|
||||||
|
import org.springframework.data.mapping.annotation.Transient;
|
||||||
|
import org.springframework.data.mapping.annotation.Value;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
import org.springframework.data.mapping.model.PersistentProperty;
|
||||||
|
import org.springframework.data.mapping.model.types.Association;
|
||||||
|
import org.springframework.data.mapping.model.types.Simple;
|
||||||
|
import org.springframework.data.mapping.reflect.ClassPropertyFetcher;
|
||||||
|
import org.springframework.data.mapping.reflect.ReflectionUtils;
|
||||||
|
import org.springframework.expression.Expression;
|
||||||
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
|
|
||||||
|
import java.beans.IntrospectionException;
|
||||||
|
import java.beans.Introspector;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
public class MappingMongoConverter implements MongoConverter, ApplicationContextAware {
|
||||||
|
|
||||||
|
protected static final Log log = LogFactory.getLog(MappingMongoConverter.class);
|
||||||
|
protected static final Set<String> SIMPLE_TYPES;
|
||||||
|
protected static final ConcurrentMap<Class<?>, Map<String, Field>> fieldsByName = new ConcurrentHashMap<Class<?>, Map<String, Field>>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
Set<String> basics = new HashSet<String>();
|
||||||
|
basics.add(boolean.class.getName());
|
||||||
|
basics.add(long.class.getName());
|
||||||
|
basics.add(short.class.getName());
|
||||||
|
basics.add(int.class.getName());
|
||||||
|
basics.add(byte.class.getName());
|
||||||
|
basics.add(float.class.getName());
|
||||||
|
basics.add(double.class.getName());
|
||||||
|
basics.add(char.class.getName());
|
||||||
|
basics.add(Boolean.class.getName());
|
||||||
|
basics.add(Long.class.getName());
|
||||||
|
basics.add(Short.class.getName());
|
||||||
|
basics.add(Integer.class.getName());
|
||||||
|
basics.add(Byte.class.getName());
|
||||||
|
basics.add(Float.class.getName());
|
||||||
|
basics.add(Double.class.getName());
|
||||||
|
basics.add(Character.class.getName());
|
||||||
|
basics.add(String.class.getName());
|
||||||
|
basics.add(java.util.Date.class.getName());
|
||||||
|
basics.add(Locale.class.getName());
|
||||||
|
basics.add(Class.class.getName());
|
||||||
|
basics.add(DBRef.class.getName());
|
||||||
|
basics.add(Pattern.class.getName());
|
||||||
|
basics.add(CodeWScope.class.getName());
|
||||||
|
basics.add(ObjectId.class.getName());
|
||||||
|
// TODO check on enums..
|
||||||
|
basics.add(Enum.class.getName());
|
||||||
|
SIMPLE_TYPES = Collections.unmodifiableSet(basics);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GenericConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
|
||||||
|
protected MongoMappingContext mappingContext;
|
||||||
|
protected ApplicationContext applicationContext;
|
||||||
|
protected boolean autowirePersistentBeans = false;
|
||||||
|
|
||||||
|
public MappingMongoConverter() {
|
||||||
|
initializeConverters();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MappingMongoConverter(MongoMappingContext mappingContext) {
|
||||||
|
this.mappingContext = mappingContext;
|
||||||
|
initializeConverters();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MappingMongoConverter(MongoMappingContext mappingContext, List<Converter<?, ?>> converters) {
|
||||||
|
this.mappingContext = mappingContext;
|
||||||
|
if (null != converters) {
|
||||||
|
for (Converter<?, ?> c : converters) {
|
||||||
|
conversionService.addConverter(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initializeConverters();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MongoMappingContext getMappingContext() {
|
||||||
|
return mappingContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappingContext(MongoMappingContext mappingContext) {
|
||||||
|
this.mappingContext = mappingContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAutowirePersistentBeans() {
|
||||||
|
return autowirePersistentBeans;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutowirePersistentBeans(boolean autowirePersistentBeans) {
|
||||||
|
this.autowirePersistentBeans = autowirePersistentBeans;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T convertObjectId(ObjectId id, Class<T> targetType) {
|
||||||
|
return conversionService.convert(id, targetType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectId convertObjectId(Object id) {
|
||||||
|
return conversionService.convert(id, ObjectId.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <S extends Object> S read(Class<S> clazz, final DBObject dbo) {
|
||||||
|
final StandardEvaluationContext ctx = new StandardEvaluationContext();
|
||||||
|
if (null != applicationContext) {
|
||||||
|
ctx.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||||
|
}
|
||||||
|
String[] keySet = dbo.keySet().toArray(new String[]{});
|
||||||
|
for (String key : keySet) {
|
||||||
|
ctx.setVariable(key, dbo.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ((clazz.isArray() || clazz.isAssignableFrom(Collection.class)) && dbo instanceof BasicDBList) {
|
||||||
|
List l = new ArrayList<S>();
|
||||||
|
BasicDBList dbList = (BasicDBList) dbo;
|
||||||
|
for (Object o : dbList) {
|
||||||
|
if (o instanceof DBObject) {
|
||||||
|
Object newObj = read(clazz.getComponentType(), (DBObject) o);
|
||||||
|
if (newObj.getClass().isAssignableFrom(clazz.getComponentType())) {
|
||||||
|
l.add(newObj);
|
||||||
|
} else {
|
||||||
|
l.add(conversionService.convert(newObj, clazz.getComponentType()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
l.add(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return conversionService.convert(l, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
final MappingIntrospector<S> introspector = MappingIntrospector.getInstance(clazz);
|
||||||
|
final List<String> cparamNames = new ArrayList<String>();
|
||||||
|
final S instance = introspector.createInstance(new MappingIntrospector.ParameterValueProvider() {
|
||||||
|
public <T> T getParameterValue(String name, Class<T> type, Expression spelExpr) {
|
||||||
|
Object o = getValueInternal(name, type, dbo, ctx, spelExpr);
|
||||||
|
if (null != o && o.getClass().isAssignableFrom(type)) {
|
||||||
|
cparamNames.add(name);
|
||||||
|
return (T) o;
|
||||||
|
} else {
|
||||||
|
cparamNames.add(name);
|
||||||
|
return conversionService.convert(o, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
introspector.doWithProperties(new MappingIntrospector.PropertyHandler() {
|
||||||
|
public void doWithProperty(PropertyDescriptor descriptor, Field field, Expression spelExpr) {
|
||||||
|
String name = descriptor.getName();
|
||||||
|
if (!cparamNames.contains(name)) {
|
||||||
|
Object o = getValueInternal(name, descriptor.getPropertyType(), dbo, ctx, spelExpr);
|
||||||
|
try {
|
||||||
|
introspector.setValue(name, instance, o);
|
||||||
|
} catch (MappingException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
introspector.maybeAutowire(instance, applicationContext, autowirePersistentBeans);
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
} catch (MappingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(final Object o, final DBObject dbo) {
|
||||||
|
try {
|
||||||
|
final MappingIntrospector<?> introspector = MappingIntrospector.getInstance(o.getClass());
|
||||||
|
|
||||||
|
Field idFld = introspector.getIdField();
|
||||||
|
if (null != idFld) {
|
||||||
|
Object idObj = introspector.getFieldValue(idFld.getName(), o);
|
||||||
|
if (null != idObj) {
|
||||||
|
dbo.put("_id", conversionService.convert(idObj, ObjectId.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
introspector.doWithProperties(new MappingIntrospector.PropertyHandler() {
|
||||||
|
public void doWithProperty(PropertyDescriptor descriptor, Field field, Expression spelExpr) {
|
||||||
|
String name = descriptor.getName();
|
||||||
|
try {
|
||||||
|
Object newObj = introspector.getFieldValue(name, o);
|
||||||
|
if (null != newObj) {
|
||||||
|
if (MappingIntrospector.isSimpleType(newObj.getClass())) {
|
||||||
|
dbo.put(name, newObj);
|
||||||
|
} else {
|
||||||
|
if (newObj.getClass().isAssignableFrom(Collection.class)) {
|
||||||
|
BasicDBList dbList = new BasicDBList();
|
||||||
|
write(newObj, dbList);
|
||||||
|
dbo.put(name, dbList);
|
||||||
|
} else {
|
||||||
|
DBObject newDbObj = new BasicDBObject();
|
||||||
|
write(newObj, newDbObj);
|
||||||
|
dbo.put(name, newDbObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (MappingException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle mapping-specific stuff
|
||||||
|
if (introspector.isMappable()) {
|
||||||
|
introspector.doWithAssociations(new MappingIntrospector.AssociationHandler() {
|
||||||
|
public void doWithAssociation(MappingIntrospector.Association association) {
|
||||||
|
log.info("HANDLE ASSOCIATION: " + association);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (MappingException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isTransientField(Field f) {
|
||||||
|
return (Modifier.isTransient(f.getModifiers()) || null != f.getAnnotation(Transient.class) || null != f.getAnnotation(Autowired.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isPersistentProperty(Object obj, PropertyDescriptor descriptor) {
|
||||||
|
try {
|
||||||
|
Field f = obj.getClass().getDeclaredField(descriptor.getName());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initializeConverters() {
|
||||||
|
if (!conversionService.canConvert(ObjectId.class, String.class)) {
|
||||||
|
conversionService.addConverter(ObjectIdToStringConverter.INSTANCE);
|
||||||
|
conversionService.addConverter(StringToObjectIdConverter.INSTANCE);
|
||||||
|
}
|
||||||
|
if (!conversionService.canConvert(ObjectId.class, BigInteger.class)) {
|
||||||
|
conversionService.addConverter(ObjectIdToBigIntegerConverter.INSTANCE);
|
||||||
|
conversionService.addConverter(BigIntegerToIdConverter.INSTANCE);
|
||||||
|
}
|
||||||
|
if (!conversionService.canConvert(ObjectId.class, Integer.class)) {
|
||||||
|
conversionService.addConverter(IntegerToIdConverter.INSTANCE);
|
||||||
|
conversionService.addConverter(IdToIntegerConverter.INSTANCE);
|
||||||
|
}
|
||||||
|
if (!conversionService.canConvert(Object.class, DBObject.class)) {
|
||||||
|
conversionService.addConverter(new ObjectToDBObjectConverter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object getValueInternal(String name, Class<?> type, DBObject dbo, StandardEvaluationContext ctx, Expression spelExpr) {
|
||||||
|
Object o;
|
||||||
|
if (null != spelExpr) {
|
||||||
|
o = spelExpr.getValue(ctx);
|
||||||
|
} else {
|
||||||
|
Object dbObj = dbo.get(name);
|
||||||
|
if (dbObj instanceof DBObject) {
|
||||||
|
// It's a complex object, have to read it in
|
||||||
|
o = read(type, (DBObject) dbObj);
|
||||||
|
} else {
|
||||||
|
o = dbObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static boolean isSimpleType(Class<?> propertyType) {
|
||||||
|
if (propertyType == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (propertyType.isArray()) {
|
||||||
|
return isSimpleType(propertyType.getComponentType());
|
||||||
|
}
|
||||||
|
return SIMPLE_TYPES.contains(propertyType.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple singleton to convert {@link ObjectId}s to their {@link String} representation.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public static enum ObjectIdToStringConverter implements Converter<ObjectId, String> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public String convert(ObjectId id) {
|
||||||
|
return id.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple singleton to convert {@link String}s to their {@link ObjectId} representation.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public static enum StringToObjectIdConverter implements Converter<String, ObjectId> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public ObjectId convert(String source) {
|
||||||
|
return new ObjectId(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple singleton to convert {@link ObjectId}s to their {@link java.math.BigInteger} representation.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public static enum ObjectIdToBigIntegerConverter implements Converter<ObjectId, BigInteger> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public BigInteger convert(ObjectId source) {
|
||||||
|
return new BigInteger(source.toString(), 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple singleton to convert {@link BigInteger}s to their {@link ObjectId} representation.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public static enum BigIntegerToIdConverter implements Converter<BigInteger, ObjectId> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public ObjectId convert(BigInteger source) {
|
||||||
|
return new ObjectId(source.toString(16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum IntegerToIdConverter implements Converter<Integer, ObjectId> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public ObjectId convert(Integer source) {
|
||||||
|
String s = String.valueOf(source);
|
||||||
|
StringBuffer buff = new StringBuffer();
|
||||||
|
for (int i = 0; i < (16 - s.length()); i++) {
|
||||||
|
buff.append("0");
|
||||||
|
}
|
||||||
|
buff.append(s);
|
||||||
|
return new ObjectId(buff.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum IdToIntegerConverter implements Converter<ObjectId, Integer> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public Integer convert(ObjectId source) {
|
||||||
|
return Integer.parseInt(source.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ObjectToDBObjectConverter implements Converter<Object, DBObject> {
|
||||||
|
|
||||||
|
private final DBObject dbo;
|
||||||
|
|
||||||
|
public ObjectToDBObjectConverter() {
|
||||||
|
this.dbo = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectToDBObjectConverter(DBObject dbo) {
|
||||||
|
this.dbo = dbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBObject convert(Object source) {
|
||||||
|
DBObject dbo;
|
||||||
|
if (source instanceof Collection) {
|
||||||
|
Collection c = (Collection) source;
|
||||||
|
dbo = (null == this.dbo ? new BasicDBList() : this.dbo);
|
||||||
|
for (Object o : c) {
|
||||||
|
if (isSimpleType(o.getClass())) {
|
||||||
|
((BasicDBList) dbo).add(o);
|
||||||
|
} else {
|
||||||
|
((BasicDBList) dbo).add(convert(o));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (source instanceof Map) {
|
||||||
|
Map<Object, Object> m = (Map) source;
|
||||||
|
dbo = (null == this.dbo ? new BasicDBObject() : this.dbo);
|
||||||
|
for (Map.Entry<Object, Object> entry : m.entrySet()) {
|
||||||
|
String key = (entry.getKey() instanceof String ? entry.getKey().toString() : conversionService.convert(entry.getKey(), String.class));
|
||||||
|
if (isSimpleType(entry.getValue().getClass())) {
|
||||||
|
dbo.put(key, entry.getValue());
|
||||||
|
} else {
|
||||||
|
dbo.put(key, convert(entry.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dbo = (null == this.dbo ? new BasicDBObject() : this.dbo);
|
||||||
|
if (!fieldsByName.containsKey(source.getClass())) {
|
||||||
|
Map<String, Field> fields = new HashMap<String, Field>();
|
||||||
|
for (Field f : source.getClass().getDeclaredFields()) {
|
||||||
|
if (!"class".equals(f.getName())) {
|
||||||
|
ReflectionUtils.makeAccessible(f);
|
||||||
|
fields.put(f.getName(), f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fieldsByName.put(source.getClass(), fields);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
for (PropertyDescriptor descriptor : Introspector.getBeanInfo(source.getClass()).getPropertyDescriptors()) {
|
||||||
|
Field f = fieldsByName.get(source.getClass()).get(descriptor.getName());
|
||||||
|
if (null != f && !isTransientField(f)) {
|
||||||
|
try {
|
||||||
|
Object o;
|
||||||
|
if (null != descriptor.getReadMethod()) {
|
||||||
|
o = descriptor.getReadMethod().invoke(source);
|
||||||
|
} else {
|
||||||
|
o = f.get(source);
|
||||||
|
}
|
||||||
|
if (null != o && isSimpleType(o.getClass())) {
|
||||||
|
dbo.put(descriptor.getName(), o);
|
||||||
|
} else if (null != o) {
|
||||||
|
dbo.put(descriptor.getName(), convert(o));
|
||||||
|
} else {
|
||||||
|
// Value was NULL, skip it
|
||||||
|
}
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new RuntimeException("Error converting " + source + " to DBObject");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException("Error converting " + source + " to DBObject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IntrospectionException e) {
|
||||||
|
throw new RuntimeException("Error converting " + source + " to DBObject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dbo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.data.document.mongodb;
|
package org.springframework.data.document.mongodb.convert;
|
||||||
|
|
||||||
import static org.springframework.beans.PropertyAccessorFactory.*;
|
import static org.springframework.beans.PropertyAccessorFactory.*;
|
||||||
|
|
||||||
@@ -21,6 +21,7 @@ import org.springframework.beans.BeanWrapper;
|
|||||||
import org.springframework.beans.ConfigurablePropertyAccessor;
|
import org.springframework.beans.ConfigurablePropertyAccessor;
|
||||||
import org.springframework.beans.NotWritablePropertyException;
|
import org.springframework.beans.NotWritablePropertyException;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
|
import org.springframework.data.document.mongodb.MongoPropertyDescriptors;
|
||||||
import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoPropertyDescriptor;
|
import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoPropertyDescriptor;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@@ -13,29 +13,31 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.data.document.mongodb;
|
package org.springframework.data.document.mongodb.convert;
|
||||||
|
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
|
import org.springframework.data.document.mongodb.MongoReader;
|
||||||
|
import org.springframework.data.document.mongodb.MongoWriter;
|
||||||
|
|
||||||
|
|
||||||
public interface MongoConverter extends MongoWriter<Object>, MongoReader<Object> {
|
public interface MongoConverter extends MongoWriter<Object>, MongoReader<Object> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given {@link ObjectId} to the given target type.
|
* Converts the given {@link ObjectId} to the given target type.
|
||||||
*
|
*
|
||||||
* @param <T> the actual type to create
|
* @param <T> the actual type to create
|
||||||
* @param id the source {@link ObjectId}
|
* @param id the source {@link ObjectId}
|
||||||
* @param targetType the target type to convert the {@link ObjectId} to
|
* @param targetType the target type to convert the {@link ObjectId} to
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public <T> T convertObjectId(ObjectId id, Class<T> targetType);
|
public <T> T convertObjectId(ObjectId id, Class<T> targetType);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link ObjectId} instance for the given id.
|
* Returns the {@link ObjectId} instance for the given id.
|
||||||
*
|
*
|
||||||
* @param id
|
* @param id
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public ObjectId convertObjectId(Object id);
|
public ObjectId convertObjectId(Object id);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,546 @@
|
|||||||
|
/*
|
||||||
|
* 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.document.mongodb.convert;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBList;
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
import com.mongodb.DBRef;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.bson.types.CodeWScope;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.core.CollectionFactory;
|
||||||
|
import org.springframework.core.convert.ConversionFailedException;
|
||||||
|
import org.springframework.core.convert.ConversionService;
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||||
|
import org.springframework.core.convert.support.GenericConversionService;
|
||||||
|
import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoPropertyDescriptor;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.comparator.CompoundComparator;
|
||||||
|
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic {@link MongoConverter} implementation to convert between domain classes and {@link DBObject}s.
|
||||||
|
*
|
||||||
|
* @author Mark Pollack
|
||||||
|
* @author Thomas Risberg
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public class SimpleMongoConverter implements MongoConverter {
|
||||||
|
|
||||||
|
private static final Log LOG = LogFactory.getLog(SimpleMongoConverter.class);
|
||||||
|
private static final Set<String> SIMPLE_TYPES;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Set<String> basics = new HashSet<String>();
|
||||||
|
basics.add(boolean.class.getName());
|
||||||
|
basics.add(long.class.getName());
|
||||||
|
basics.add(short.class.getName());
|
||||||
|
basics.add(int.class.getName());
|
||||||
|
basics.add(byte.class.getName());
|
||||||
|
basics.add(float.class.getName());
|
||||||
|
basics.add(double.class.getName());
|
||||||
|
basics.add(char.class.getName());
|
||||||
|
basics.add(Boolean.class.getName());
|
||||||
|
basics.add(Long.class.getName());
|
||||||
|
basics.add(Short.class.getName());
|
||||||
|
basics.add(Integer.class.getName());
|
||||||
|
basics.add(Byte.class.getName());
|
||||||
|
basics.add(Float.class.getName());
|
||||||
|
basics.add(Double.class.getName());
|
||||||
|
basics.add(Character.class.getName());
|
||||||
|
basics.add(String.class.getName());
|
||||||
|
basics.add(java.util.Date.class.getName());
|
||||||
|
// basics.add(Time.class.getName());
|
||||||
|
// basics.add(Timestamp.class.getName());
|
||||||
|
// basics.add(java.sql.Date.class.getName());
|
||||||
|
// basics.add(BigDecimal.class.getName());
|
||||||
|
// basics.add(BigInteger.class.getName());
|
||||||
|
basics.add(Locale.class.getName());
|
||||||
|
// basics.add(Calendar.class.getName());
|
||||||
|
// basics.add(GregorianCalendar.class.getName());
|
||||||
|
// basics.add(java.util.Currency.class.getName());
|
||||||
|
// basics.add(TimeZone.class.getName());
|
||||||
|
// basics.add(Object.class.getName());
|
||||||
|
basics.add(Class.class.getName());
|
||||||
|
// basics.add(byte[].class.getName());
|
||||||
|
// basics.add(Byte[].class.getName());
|
||||||
|
// basics.add(char[].class.getName());
|
||||||
|
// basics.add(Character[].class.getName());
|
||||||
|
// basics.add(Blob.class.getName());
|
||||||
|
// basics.add(Clob.class.getName());
|
||||||
|
// basics.add(Serializable.class.getName());
|
||||||
|
// basics.add(URI.class.getName());
|
||||||
|
// basics.add(URL.class.getName());
|
||||||
|
basics.add(DBRef.class.getName());
|
||||||
|
basics.add(Pattern.class.getName());
|
||||||
|
basics.add(CodeWScope.class.getName());
|
||||||
|
basics.add(ObjectId.class.getName());
|
||||||
|
// TODO check on enums..
|
||||||
|
basics.add(Enum.class.getName());
|
||||||
|
SIMPLE_TYPES = Collections.unmodifiableSet(basics);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final GenericConversionService conversionService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link SimpleMongoConverter}.
|
||||||
|
*/
|
||||||
|
public SimpleMongoConverter() {
|
||||||
|
this.conversionService = ConversionServiceFactory.createDefaultConversionService();
|
||||||
|
initializeConverters();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link SimpleMongoConverter} for the given {@link ConversionService}.
|
||||||
|
*
|
||||||
|
* @param conversionService
|
||||||
|
*/
|
||||||
|
public SimpleMongoConverter(GenericConversionService conversionService) {
|
||||||
|
Assert.notNull(conversionService);
|
||||||
|
this.conversionService = conversionService;
|
||||||
|
initializeConverters();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes additional converters that handle {@link ObjectId} conversion. Will register converters for supported
|
||||||
|
* id types if none are registered for those conversion already. {@link GenericConversionService} is configured.
|
||||||
|
*/
|
||||||
|
protected void initializeConverters() {
|
||||||
|
|
||||||
|
if (!conversionService.canConvert(ObjectId.class, String.class)) {
|
||||||
|
conversionService.addConverter(ObjectIdToStringConverter.INSTANCE);
|
||||||
|
conversionService.addConverter(StringToObjectIdConverter.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!conversionService.canConvert(ObjectId.class, BigInteger.class)) {
|
||||||
|
conversionService.addConverter(ObjectIdToBigIntegerConverter.INSTANCE);
|
||||||
|
conversionService.addConverter(BigIntegerToIdConverter.INSTANCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see org.springframework.data.document.mongodb.MongoWriter#write(java.lang.Object, com.mongodb.DBObject)
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
public void write(Object obj, DBObject dbo) {
|
||||||
|
|
||||||
|
MongoBeanWrapper beanWrapper = createWrapper(obj, false);
|
||||||
|
for (MongoPropertyDescriptor descriptor : beanWrapper.getDescriptors()) {
|
||||||
|
if (descriptor.isMappable()) {
|
||||||
|
Object value = beanWrapper.getValue(descriptor);
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String keyToUse = descriptor.getKeyToMap();
|
||||||
|
// TODO validate Enums...
|
||||||
|
if (descriptor.isEnum()) {
|
||||||
|
writeValue(dbo, keyToUse, ((Enum) value).name());
|
||||||
|
} else if (descriptor.isIdProperty() && descriptor.isOfIdType()) {
|
||||||
|
if (value instanceof String && ObjectId.isValid((String) value)) {
|
||||||
|
try {
|
||||||
|
writeValue(dbo, keyToUse, conversionService.convert(value, ObjectId.class));
|
||||||
|
} catch (ConversionFailedException iae) {
|
||||||
|
LOG.warn("Unable to convert the String " + value + " to an ObjectId");
|
||||||
|
writeValue(dbo, keyToUse, value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we can't convert this id - use as is
|
||||||
|
writeValue(dbo, keyToUse, value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
writeValue(dbo, keyToUse, value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!"class".equals(descriptor.getName())) {
|
||||||
|
LOG.warn("Unable to map property " + descriptor.getName() + ". Skipping.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the given value to the given {@link DBObject}. Will skip {@literal null} values.
|
||||||
|
*
|
||||||
|
* @param dbo
|
||||||
|
* @param keyToUse
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
private void writeValue(DBObject dbo, String keyToUse, Object value) {
|
||||||
|
|
||||||
|
if (!isSimpleType(value.getClass())) {
|
||||||
|
writeCompoundValue(dbo, keyToUse, value);
|
||||||
|
} else {
|
||||||
|
dbo.put(keyToUse, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the given {@link CompoundComparator} value to the given {@link DBObject}.
|
||||||
|
*
|
||||||
|
* @param dbo
|
||||||
|
* @param keyToUse
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void writeCompoundValue(DBObject dbo, String keyToUse, Object value) {
|
||||||
|
if (value instanceof Map) {
|
||||||
|
writeMap(dbo, keyToUse, (Map<String, Object>) value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value instanceof Collection) {
|
||||||
|
// Should write a collection!
|
||||||
|
writeArray(dbo, keyToUse, ((Collection<Object>) value).toArray());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value instanceof Object[]) {
|
||||||
|
// Should write an array!
|
||||||
|
writeArray(dbo, keyToUse, (Object[]) value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DBObject nestedDbo = new BasicDBObject();
|
||||||
|
write(value, nestedDbo);
|
||||||
|
dbo.put(keyToUse, nestedDbo);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the given {@link Map} to the given {@link DBObject}.
|
||||||
|
*
|
||||||
|
* @param dbo
|
||||||
|
* @param mapKey
|
||||||
|
* @param map
|
||||||
|
*/
|
||||||
|
protected void writeMap(DBObject dbo, String mapKey, Map<String, Object> map) {
|
||||||
|
// TODO support non-string based keys as long as there is a Spring Converter obj->string and (optionally)
|
||||||
|
// string->obj
|
||||||
|
DBObject dboToPopulate = null;
|
||||||
|
|
||||||
|
// TODO - Does that make sense? If we create a new object here it's content will never make it out of this
|
||||||
|
// method
|
||||||
|
if (mapKey != null) {
|
||||||
|
dboToPopulate = new BasicDBObject();
|
||||||
|
} else {
|
||||||
|
dboToPopulate = dbo;
|
||||||
|
}
|
||||||
|
if (map != null) {
|
||||||
|
for (Entry<String, Object> entry : map.entrySet()) {
|
||||||
|
|
||||||
|
Object entryValue = entry.getValue();
|
||||||
|
String entryKey = entry.getKey();
|
||||||
|
|
||||||
|
if (!isSimpleType(entryValue.getClass())) {
|
||||||
|
writeCompoundValue(dboToPopulate, entryKey, entryValue);
|
||||||
|
} else {
|
||||||
|
dboToPopulate.put(entryKey, entryValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbo.put(mapKey, dboToPopulate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the given array to the given {@link DBObject}.
|
||||||
|
*
|
||||||
|
* @param dbo
|
||||||
|
* @param keyToUse
|
||||||
|
* @param array
|
||||||
|
*/
|
||||||
|
protected void writeArray(DBObject dbo, String keyToUse, Object[] array) {
|
||||||
|
// TODO
|
||||||
|
Object[] dboValues;
|
||||||
|
if (array != null) {
|
||||||
|
dboValues = new Object[array.length];
|
||||||
|
int i = 0;
|
||||||
|
for (Object o : array) {
|
||||||
|
if (!isSimpleType(o.getClass())) {
|
||||||
|
DBObject dboValue = new BasicDBObject();
|
||||||
|
write(o, dboValue);
|
||||||
|
dboValues[i] = dboValue;
|
||||||
|
} else {
|
||||||
|
dboValues[i] = o;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
dbo.put(keyToUse, dboValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see org.springframework.data.document.mongodb.MongoReader#read(java.lang.Class, com.mongodb.DBObject)
|
||||||
|
*/
|
||||||
|
public <S> S read(Class<S> clazz, DBObject source) {
|
||||||
|
|
||||||
|
if (source == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.notNull(clazz, "Mapped class was not specified");
|
||||||
|
S target = BeanUtils.instantiateClass(clazz);
|
||||||
|
MongoBeanWrapper bw = new MongoBeanWrapper(target, conversionService, true);
|
||||||
|
|
||||||
|
for (MongoPropertyDescriptor descriptor : bw.getDescriptors()) {
|
||||||
|
String keyToUse = descriptor.getKeyToMap();
|
||||||
|
if (source.containsField(keyToUse)) {
|
||||||
|
if (descriptor.isMappable()) {
|
||||||
|
Object value = source.get(keyToUse);
|
||||||
|
if (!isSimpleType(value.getClass())) {
|
||||||
|
if (value instanceof Object[]) {
|
||||||
|
bw.setValue(descriptor, readCollection(descriptor, Arrays.asList((Object[]) value))
|
||||||
|
.toArray());
|
||||||
|
} else if (value instanceof BasicDBList) {
|
||||||
|
bw.setValue(descriptor, readCollection(descriptor, (BasicDBList) value));
|
||||||
|
} else if (value instanceof DBObject) {
|
||||||
|
bw.setValue(descriptor, readCompoundValue(descriptor, (DBObject) value));
|
||||||
|
} else {
|
||||||
|
LOG.warn("Unable to map compound DBObject field " + keyToUse + " to property "
|
||||||
|
+ descriptor.getName()
|
||||||
|
+ ". The field value should have been a 'DBObject.class' but was "
|
||||||
|
+ value.getClass().getName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bw.setValue(descriptor, value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG.warn("Unable to map DBObject field " + keyToUse + " to property " + descriptor.getName()
|
||||||
|
+ ". Skipping.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the given collection values (that are {@link DBObject}s potentially) into a {@link Collection} of domain
|
||||||
|
* objects.
|
||||||
|
*
|
||||||
|
* @param descriptor
|
||||||
|
* @param values
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Collection<Object> readCollection(MongoPropertyDescriptor descriptor, Collection<?> values) {
|
||||||
|
|
||||||
|
Class<?> targetCollectionType = descriptor.getPropertyType();
|
||||||
|
boolean targetIsArray = targetCollectionType.isArray();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Collection<Object> result = targetIsArray ? new ArrayList<Object>(values.size()) : CollectionFactory
|
||||||
|
.createCollection(targetCollectionType, values.size());
|
||||||
|
|
||||||
|
for (Object o : values) {
|
||||||
|
if (o instanceof DBObject) {
|
||||||
|
Class<?> type;
|
||||||
|
if (targetIsArray) {
|
||||||
|
type = targetCollectionType.getComponentType();
|
||||||
|
} else {
|
||||||
|
type = getGenericParameters(descriptor.getTypeToSet()).get(0);
|
||||||
|
}
|
||||||
|
result.add(read(type, (DBObject) o));
|
||||||
|
} else {
|
||||||
|
result.add(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a compound value from the given {@link DBObject} for the given property.
|
||||||
|
*
|
||||||
|
* @param pd
|
||||||
|
* @param dbo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Object readCompoundValue(MongoPropertyDescriptor pd, DBObject dbo) {
|
||||||
|
|
||||||
|
Assert.isTrue(!pd.isCollection(), "Collections not supported!");
|
||||||
|
|
||||||
|
if (pd.isMap()) {
|
||||||
|
return readMap(pd, dbo, getGenericParameters(pd.getTypeToSet()).get(1));
|
||||||
|
} else {
|
||||||
|
return read(pd.getPropertyType(), dbo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a {@link Map} instance. Will return a {@link HashMap} by default. Subclasses might want to override this
|
||||||
|
* method to use a custom {@link Map} implementation.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected Map<String, Object> createMap() {
|
||||||
|
return new HashMap<String, Object>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads every key/value pair from the {@link DBObject} into a {@link Map} instance.
|
||||||
|
*
|
||||||
|
* @param pd
|
||||||
|
* @param dbo
|
||||||
|
* @param targetType
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected Map<?, ?> readMap(MongoPropertyDescriptor pd, DBObject dbo, Class<?> targetType) {
|
||||||
|
Map<String, Object> map = createMap();
|
||||||
|
for (String key : dbo.keySet()) {
|
||||||
|
Object value = dbo.get(key);
|
||||||
|
if (!isSimpleType(value.getClass())) {
|
||||||
|
map.put(key, read(targetType, (DBObject) value));
|
||||||
|
// Can do some reflection tricks here -
|
||||||
|
// throw new RuntimeException("User types not supported yet as values for Maps");
|
||||||
|
} else {
|
||||||
|
map.put(key, conversionService.convert(value, targetType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static boolean isSimpleType(Class<?> propertyType) {
|
||||||
|
if (propertyType == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (propertyType.isArray()) {
|
||||||
|
return isSimpleType(propertyType.getComponentType());
|
||||||
|
}
|
||||||
|
return SIMPLE_TYPES.contains(propertyType.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to allow customizing creation of a {@link MongoBeanWrapper}.
|
||||||
|
*
|
||||||
|
* @param target the target object to wrap
|
||||||
|
* @param fieldAccess whether to use field access or property access
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected MongoBeanWrapper createWrapper(Object target, boolean fieldAccess) {
|
||||||
|
|
||||||
|
return new MongoBeanWrapper(target, conversionService, fieldAccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Class<?>> getGenericParameters(Type genericParameterType) {
|
||||||
|
|
||||||
|
List<Class<?>> actualGenericParameterTypes = new ArrayList<Class<?>>();
|
||||||
|
|
||||||
|
if (genericParameterType instanceof ParameterizedType) {
|
||||||
|
ParameterizedType aType = (ParameterizedType) genericParameterType;
|
||||||
|
Type[] parameterArgTypes = aType.getActualTypeArguments();
|
||||||
|
for (Type parameterArgType : parameterArgTypes) {
|
||||||
|
if (parameterArgType instanceof GenericArrayType) {
|
||||||
|
Class<?> arrayType = (Class<?>) ((GenericArrayType) parameterArgType).getGenericComponentType();
|
||||||
|
actualGenericParameterTypes.add(Array.newInstance(arrayType, 0).getClass());
|
||||||
|
} else {
|
||||||
|
if (parameterArgType instanceof ParameterizedType) {
|
||||||
|
ParameterizedType paramTypeArgs = (ParameterizedType) parameterArgType;
|
||||||
|
actualGenericParameterTypes.add((Class<?>) paramTypeArgs.getRawType());
|
||||||
|
} else {
|
||||||
|
if (parameterArgType instanceof TypeVariable) {
|
||||||
|
throw new RuntimeException("Can not map " + ((TypeVariable<?>) parameterArgType).getName());
|
||||||
|
} else {
|
||||||
|
if (parameterArgType instanceof Class) {
|
||||||
|
actualGenericParameterTypes.add((Class<?>) parameterArgType);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Can not map " + parameterArgType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return actualGenericParameterTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.document.mongodb.convert.MongoConverter#convertObjectId(org.bson.types.ObjectId, java.lang.Class)
|
||||||
|
*/
|
||||||
|
public <T> T convertObjectId(ObjectId id, Class<T> targetType) {
|
||||||
|
return conversionService.convert(id, targetType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.document.mongodb.convert.MongoConverter#convertObjectId(java.lang.Object)
|
||||||
|
*/
|
||||||
|
public ObjectId convertObjectId(Object id) {
|
||||||
|
return conversionService.convert(id, ObjectId.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple singleton to convert {@link ObjectId}s to their {@link String} representation.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public static enum ObjectIdToStringConverter implements Converter<ObjectId, String> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public String convert(ObjectId id) {
|
||||||
|
return id.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple singleton to convert {@link String}s to their {@link ObjectId} representation.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public static enum StringToObjectIdConverter implements Converter<String, ObjectId> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public ObjectId convert(String source) {
|
||||||
|
return new ObjectId(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple singleton to convert {@link ObjectId}s to their {@link BigInteger} representation.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public static enum ObjectIdToBigIntegerConverter implements Converter<ObjectId, BigInteger> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public BigInteger convert(ObjectId source) {
|
||||||
|
return new BigInteger(source.toString(), 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple singleton to convert {@link BigInteger}s to their {@link ObjectId} representation.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
public static enum BigIntegerToIdConverter implements Converter<BigInteger, ObjectId> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public ObjectId convert(BigInteger source) {
|
||||||
|
return new ObjectId(source.toString(16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.convert;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBList;
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
import com.mongodb.DBRef;
|
||||||
|
import org.bson.types.CodeWScope;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.convert.ConversionFailedException;
|
||||||
|
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||||
|
import org.springframework.core.convert.support.GenericConversionService;
|
||||||
|
import org.springframework.data.mapping.annotation.Transient;
|
||||||
|
import org.springframework.data.mapping.reflect.ReflectionUtils;
|
||||||
|
|
||||||
|
import java.beans.IntrospectionException;
|
||||||
|
import java.beans.Introspector;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public class SimplePojoDBObjectConverter {
|
||||||
|
|
||||||
|
protected static final Set<String> SIMPLE_TYPES;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Set<String> basics = new HashSet<String>();
|
||||||
|
basics.add(boolean.class.getName());
|
||||||
|
basics.add(long.class.getName());
|
||||||
|
basics.add(short.class.getName());
|
||||||
|
basics.add(int.class.getName());
|
||||||
|
basics.add(byte.class.getName());
|
||||||
|
basics.add(float.class.getName());
|
||||||
|
basics.add(double.class.getName());
|
||||||
|
basics.add(char.class.getName());
|
||||||
|
basics.add(Boolean.class.getName());
|
||||||
|
basics.add(Long.class.getName());
|
||||||
|
basics.add(Short.class.getName());
|
||||||
|
basics.add(Integer.class.getName());
|
||||||
|
basics.add(Byte.class.getName());
|
||||||
|
basics.add(Float.class.getName());
|
||||||
|
basics.add(Double.class.getName());
|
||||||
|
basics.add(Character.class.getName());
|
||||||
|
basics.add(String.class.getName());
|
||||||
|
basics.add(java.util.Date.class.getName());
|
||||||
|
basics.add(Locale.class.getName());
|
||||||
|
basics.add(Class.class.getName());
|
||||||
|
basics.add(DBRef.class.getName());
|
||||||
|
basics.add(Pattern.class.getName());
|
||||||
|
basics.add(CodeWScope.class.getName());
|
||||||
|
basics.add(ObjectId.class.getName());
|
||||||
|
// TODO check on enums..
|
||||||
|
basics.add(Enum.class.getName());
|
||||||
|
SIMPLE_TYPES = Collections.unmodifiableSet(basics);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static final ConcurrentMap<Class<?>, Map<String, Field>> fieldsByName = new ConcurrentHashMap<Class<?>, Map<String, Field>>();
|
||||||
|
|
||||||
|
protected GenericConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
|
||||||
|
|
||||||
|
public SimplePojoDBObjectConverter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public GenericConversionService getConversionService() {
|
||||||
|
return conversionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConversionService(GenericConversionService conversionService) {
|
||||||
|
this.conversionService = conversionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSimpleType(Class<?> propertyType) {
|
||||||
|
if (propertyType == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (propertyType.isArray()) {
|
||||||
|
return isSimpleType(propertyType.getComponentType());
|
||||||
|
}
|
||||||
|
return SIMPLE_TYPES.contains(propertyType.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isTransientField(Field f) {
|
||||||
|
return (Modifier.isTransient(f.getModifiers()) || null != f.getAnnotation(Transient.class) || null != f.getAnnotation(Autowired.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBObject convert(Object source, DBObject existing) throws Exception {
|
||||||
|
DBObject dbo;
|
||||||
|
if (source instanceof Collection) {
|
||||||
|
Collection c = (Collection) source;
|
||||||
|
dbo = (null == existing ? new BasicDBList() : existing);
|
||||||
|
for (Object o : c) {
|
||||||
|
if (isSimpleType(o.getClass())) {
|
||||||
|
((BasicDBList) dbo).add(o);
|
||||||
|
} else {
|
||||||
|
((BasicDBList) dbo).add(convert(o, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (source instanceof Map) {
|
||||||
|
Map<Object, Object> m = (Map) source;
|
||||||
|
dbo = (null == existing ? new BasicDBObject() : existing);
|
||||||
|
for (Map.Entry<Object, Object> entry : m.entrySet()) {
|
||||||
|
String key = (entry.getKey() instanceof String ? entry.getKey().toString() : conversionService.convert(entry.getKey(), String.class));
|
||||||
|
if (isSimpleType(entry.getValue().getClass())) {
|
||||||
|
dbo.put(key, entry.getValue());
|
||||||
|
} else {
|
||||||
|
dbo.put(key, convert(entry.getValue(), null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dbo = (null == existing ? new BasicDBObject() : existing);
|
||||||
|
if (!fieldsByName.containsKey(source.getClass())) {
|
||||||
|
Map<String, Field> fields = new HashMap<String, Field>();
|
||||||
|
for (Field f : source.getClass().getDeclaredFields()) {
|
||||||
|
if (!"class".equals(f.getName())) {
|
||||||
|
ReflectionUtils.makeAccessible(f);
|
||||||
|
fields.put(f.getName(), f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fieldsByName.put(source.getClass(), fields);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
for (PropertyDescriptor descriptor : Introspector.getBeanInfo(source.getClass()).getPropertyDescriptors()) {
|
||||||
|
Field f = fieldsByName.get(source.getClass()).get(descriptor.getName());
|
||||||
|
if (null != f && !isTransientField(f)) {
|
||||||
|
try {
|
||||||
|
Object o;
|
||||||
|
if (null != descriptor.getReadMethod()) {
|
||||||
|
o = descriptor.getReadMethod().invoke(source);
|
||||||
|
} else {
|
||||||
|
o = f.get(source);
|
||||||
|
}
|
||||||
|
if (null != o && isSimpleType(o.getClass())) {
|
||||||
|
dbo.put(descriptor.getName(), o);
|
||||||
|
} else if (null != o) {
|
||||||
|
dbo.put(descriptor.getName(), convert(o, null));
|
||||||
|
} else {
|
||||||
|
// Value was NULL, skip it
|
||||||
|
}
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new RuntimeException("Error converting " + source + " to DBObject");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException("Error converting " + source + " to DBObject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IntrospectionException e) {
|
||||||
|
throw new RuntimeException("Error converting " + source + " to DBObject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.index;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Target({ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface CompoundIndex {
|
||||||
|
|
||||||
|
String def();
|
||||||
|
|
||||||
|
boolean unique() default false;
|
||||||
|
|
||||||
|
boolean sparse() default false;
|
||||||
|
|
||||||
|
boolean dropDups() default true;
|
||||||
|
|
||||||
|
String name() default "";
|
||||||
|
|
||||||
|
String collection() default "";
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.index;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Target({ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface CompoundIndexes {
|
||||||
|
|
||||||
|
CompoundIndex[] value();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public interface IndexDefinition<T> {
|
||||||
|
|
||||||
|
T getIndexDefinition();
|
||||||
|
|
||||||
|
T getIndexOptions();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public enum IndexDirection {
|
||||||
|
ASCENDING,
|
||||||
|
DESCENDING;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public abstract class IndexPredicate {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private IndexDirection direction = IndexDirection.ASCENDING;
|
||||||
|
private boolean unique = false;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexDirection getDirection() {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDirection(IndexDirection direction) {
|
||||||
|
this.direction = direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUnique() {
|
||||||
|
return unique;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUnique(boolean unique) {
|
||||||
|
this.unique = unique;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.index;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Indexed {
|
||||||
|
boolean unique() default false;
|
||||||
|
|
||||||
|
IndexDirection direction() default IndexDirection.ASCENDING;
|
||||||
|
|
||||||
|
boolean sparse() default false;
|
||||||
|
|
||||||
|
boolean dropDups() default true;
|
||||||
|
|
||||||
|
String name() default "";
|
||||||
|
|
||||||
|
String collection() default "";
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public class MappingException extends Throwable {
|
||||||
|
|
||||||
|
private final Object source;
|
||||||
|
|
||||||
|
public MappingException(Throwable throwable, Object source) {
|
||||||
|
super(String.format("Error encountered mapping object: %s", source), throwable);
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,417 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
import com.mongodb.DBRef;
|
||||||
|
import com.sun.org.apache.xalan.internal.extensions.ExpressionContext;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.bson.types.CodeWScope;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.expression.BeanFactoryResolver;
|
||||||
|
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||||
|
import org.springframework.data.mapping.annotation.*;
|
||||||
|
import org.springframework.expression.EvaluationContext;
|
||||||
|
import org.springframework.expression.Expression;
|
||||||
|
import org.springframework.expression.spel.standard.SpelExpression;
|
||||||
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.beans.BeanInfo;
|
||||||
|
import java.beans.IntrospectionException;
|
||||||
|
import java.beans.Introspector;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public class MappingIntrospector<T> {
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(MappingIntrospector.class);
|
||||||
|
private static final ConcurrentMap<Class<?>, MappingIntrospector<?>> introspectors = new ConcurrentHashMap<Class<?>, MappingIntrospector<?>>();
|
||||||
|
private static final Set<String> SIMPLE_TYPES;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Set<String> basics = new HashSet<String>();
|
||||||
|
basics.add(boolean.class.getName());
|
||||||
|
basics.add(long.class.getName());
|
||||||
|
basics.add(short.class.getName());
|
||||||
|
basics.add(int.class.getName());
|
||||||
|
basics.add(byte.class.getName());
|
||||||
|
basics.add(float.class.getName());
|
||||||
|
basics.add(double.class.getName());
|
||||||
|
basics.add(char.class.getName());
|
||||||
|
basics.add(Boolean.class.getName());
|
||||||
|
basics.add(Long.class.getName());
|
||||||
|
basics.add(Short.class.getName());
|
||||||
|
basics.add(Integer.class.getName());
|
||||||
|
basics.add(Byte.class.getName());
|
||||||
|
basics.add(Float.class.getName());
|
||||||
|
basics.add(Double.class.getName());
|
||||||
|
basics.add(Character.class.getName());
|
||||||
|
basics.add(String.class.getName());
|
||||||
|
basics.add(java.util.Date.class.getName());
|
||||||
|
basics.add(Locale.class.getName());
|
||||||
|
basics.add(Class.class.getName());
|
||||||
|
basics.add(DBRef.class.getName());
|
||||||
|
basics.add(Pattern.class.getName());
|
||||||
|
basics.add(CodeWScope.class.getName());
|
||||||
|
basics.add(ObjectId.class.getName());
|
||||||
|
// TODO check on enums..
|
||||||
|
basics.add(Enum.class.getName());
|
||||||
|
SIMPLE_TYPES = Collections.unmodifiableSet(basics);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Class<T> clazz;
|
||||||
|
private final BeanInfo beanInfo;
|
||||||
|
private final Map<String, PropertyDescriptor> properties;
|
||||||
|
private final Map<String, Field> fields;
|
||||||
|
private final Set<Association> associations;
|
||||||
|
private final Map<String, Method> setters;
|
||||||
|
private final Map<String, Method> getters;
|
||||||
|
private Field idField = null;
|
||||||
|
private List<String> ignoredProperties = new ArrayList<String>() {{
|
||||||
|
add("class");
|
||||||
|
}};
|
||||||
|
private SpelExpressionParser parser = new SpelExpressionParser();
|
||||||
|
private Map<String, Expression> expressions = new HashMap<String, Expression>();
|
||||||
|
private PreferredConstructor preferredConstructor = null;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
private MappingIntrospector(Class<T> clazz) throws MappingException {
|
||||||
|
this.clazz = clazz;
|
||||||
|
try {
|
||||||
|
this.beanInfo = Introspector.getBeanInfo(clazz);
|
||||||
|
} catch (IntrospectionException e) {
|
||||||
|
throw new MappingException(e, clazz);
|
||||||
|
}
|
||||||
|
Map<String, PropertyDescriptor> properties = new HashMap<String, PropertyDescriptor>();
|
||||||
|
Map<String, Field> fields = new HashMap<String, Field>();
|
||||||
|
Set<Association> associations = new HashSet<Association>();
|
||||||
|
Map<String, Method> setters = new HashMap<String, Method>();
|
||||||
|
Map<String, Method> getters = new HashMap<String, Method>();
|
||||||
|
for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) {
|
||||||
|
String name = descriptor.getName();
|
||||||
|
if (!ignoredProperties.contains(name)) {
|
||||||
|
try {
|
||||||
|
Field fld = clazz.getDeclaredField(name);
|
||||||
|
Class<?> fldType = fld.getType();
|
||||||
|
fld.setAccessible(true);
|
||||||
|
if (!isTransientField(fld)) {
|
||||||
|
if (fld.isAnnotationPresent(Id.class)) {
|
||||||
|
if (null != idField) {
|
||||||
|
throw new IllegalStateException("You cannot have two fields in a domain object annotated with Id! " + clazz);
|
||||||
|
}
|
||||||
|
idField = fld;
|
||||||
|
continue;
|
||||||
|
} else if (null == idField && fldType.equals(ObjectId.class)) {
|
||||||
|
// Respect fields of the MongoDB ObjectId type
|
||||||
|
idField = fld;
|
||||||
|
continue;
|
||||||
|
} else if (null == idField
|
||||||
|
&& (fldType.equals(String.class) || fldType.equals(BigInteger.class))
|
||||||
|
&& ("id".equals(name) || "_id".equals(name))) {
|
||||||
|
// Strings and BigIntegers named "id"|"_id" are also valid ID fields
|
||||||
|
idField = fld;
|
||||||
|
continue;
|
||||||
|
} else if (fld.isAnnotationPresent(OneToMany.class)
|
||||||
|
|| fld.isAnnotationPresent(OneToOne.class)
|
||||||
|
|| fld.isAnnotationPresent(ManyToMany.class)) {
|
||||||
|
associations.add(new Association(descriptor, fld));
|
||||||
|
continue;
|
||||||
|
} else if (fld.isAnnotationPresent(Value.class)) {
|
||||||
|
// @Value fields are evaluated at runtime and are the same transient fields
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fields.put(name, fld);
|
||||||
|
properties.put(name, descriptor);
|
||||||
|
setters.put(name, descriptor.getWriteMethod());
|
||||||
|
getters.put(name, descriptor.getReadMethod());
|
||||||
|
if (fld.isAnnotationPresent(Value.class)) {
|
||||||
|
expressions.put(name, parser.parseExpression(fld.getAnnotation(Value.class).value()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
log.warn(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.properties = Collections.unmodifiableMap(properties);
|
||||||
|
this.fields = Collections.unmodifiableMap(fields);
|
||||||
|
this.associations = Collections.unmodifiableSet(associations);
|
||||||
|
this.setters = Collections.unmodifiableMap(setters);
|
||||||
|
this.getters = Collections.unmodifiableMap(getters);
|
||||||
|
|
||||||
|
// Find the right constructor
|
||||||
|
for (Constructor<?> constructor : clazz.getConstructors()) {
|
||||||
|
if (constructor.getParameterTypes().length != 0) {
|
||||||
|
// Non-no-arg constructor
|
||||||
|
if (null == preferredConstructor) {
|
||||||
|
String[] paramNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(constructor);
|
||||||
|
Type[] paramTypes = constructor.getGenericParameterTypes();
|
||||||
|
Class<?>[] paramClassTypes = new Class[paramTypes.length];
|
||||||
|
for (int i = 0; i < paramTypes.length; i++) {
|
||||||
|
Class<?> targetType;
|
||||||
|
if (paramTypes[i] instanceof ParameterizedType) {
|
||||||
|
ParameterizedType ptype = (ParameterizedType) paramTypes[i];
|
||||||
|
Type[] types = ptype.getActualTypeArguments();
|
||||||
|
if (types.length == 1) {
|
||||||
|
targetType = (Class<?>) types[0];
|
||||||
|
} else {
|
||||||
|
targetType = (Class<?>) ptype.getRawType();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
targetType = (Class<?>) paramTypes[i];
|
||||||
|
}
|
||||||
|
paramClassTypes[i] = targetType;
|
||||||
|
}
|
||||||
|
preferredConstructor = new PreferredConstructor((Constructor<T>) constructor, paramNames, paramClassTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
public static <C extends Object> MappingIntrospector<C> getInstance(Class<C> clazz) throws MappingException {
|
||||||
|
MappingIntrospector<C> introspector = (MappingIntrospector<C>) introspectors.get(clazz);
|
||||||
|
if (null == introspector) {
|
||||||
|
introspector = new MappingIntrospector<C>(clazz);
|
||||||
|
introspectors.put(clazz, introspector);
|
||||||
|
}
|
||||||
|
return introspector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<T> getTargetClass() {
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field getField(String name) {
|
||||||
|
return fields.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PropertyDescriptor getPropertyDescriptor(String name) {
|
||||||
|
return properties.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMappable() {
|
||||||
|
return (null != clazz.getAnnotation(Persistent.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field getIdField() {
|
||||||
|
return idField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T createInstance() throws MappingException {
|
||||||
|
return createInstance(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T createInstance(ParameterValueProvider provider) throws MappingException {
|
||||||
|
try {
|
||||||
|
if (null == preferredConstructor || null == provider) {
|
||||||
|
return clazz.newInstance();
|
||||||
|
} else {
|
||||||
|
List<Object> params = new LinkedList<Object>();
|
||||||
|
for (ConstructorParameter<?> p : preferredConstructor.parameters) {
|
||||||
|
Expression x = null;
|
||||||
|
Value v = p.getValueAnnotation();
|
||||||
|
if (null != v) {
|
||||||
|
x = parser.parseExpression(v.value());
|
||||||
|
}
|
||||||
|
params.add(provider.getParameterValue(p.name, p.type, x));
|
||||||
|
}
|
||||||
|
return preferredConstructor.constructor.newInstance(params.toArray());
|
||||||
|
}
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new MappingException(e, clazz);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new MappingException(e, clazz);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new MappingException(e, clazz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getFieldValue(PropertyDescriptor descriptor, Object from) throws MappingException {
|
||||||
|
try {
|
||||||
|
Method getter = descriptor.getReadMethod();
|
||||||
|
if (null != getter) {
|
||||||
|
return getter.invoke(from);
|
||||||
|
} else {
|
||||||
|
Field f = fields.get(descriptor.getName());
|
||||||
|
return f.get(from);
|
||||||
|
}
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new MappingException(e, from);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new MappingException(e, from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getFieldValue(String name, Object from) throws MappingException {
|
||||||
|
PropertyDescriptor descriptor = properties.get(name);
|
||||||
|
if (null != descriptor) {
|
||||||
|
return getFieldValue(descriptor, from);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String name, Object on, Object value) throws MappingException {
|
||||||
|
Field f = fields.get(name);
|
||||||
|
if (null != f) {
|
||||||
|
Method setter = setters.get(name);
|
||||||
|
try {
|
||||||
|
if (null != setter) {
|
||||||
|
setter.invoke(on, value);
|
||||||
|
} else {
|
||||||
|
f.set(on, value);
|
||||||
|
}
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new MappingException(e, value);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new MappingException(e, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void maybeAutowire(Object obj, ApplicationContext applicationContext, boolean autowire) throws MappingException {
|
||||||
|
StandardEvaluationContext evaluationContext = new StandardEvaluationContext(obj);
|
||||||
|
evaluationContext.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||||
|
|
||||||
|
if (autowire) {
|
||||||
|
applicationContext.getAutowireCapableBeanFactory().autowireBean(obj);
|
||||||
|
if (obj instanceof InitializingBean) {
|
||||||
|
try {
|
||||||
|
((InitializingBean) obj).afterPropertiesSet();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new MappingException(e, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, Expression> entry : expressions.entrySet()) {
|
||||||
|
setValue(entry.getKey(), obj, entry.getValue().getValue(evaluationContext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doWithProperties(PropertyHandler handler) {
|
||||||
|
for (Map.Entry<String, PropertyDescriptor> entry : properties.entrySet()) {
|
||||||
|
String name = entry.getKey();
|
||||||
|
handler.doWithProperty(entry.getValue(), fields.get(name), expressions.get(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doWithAssociations(AssociationHandler handler) {
|
||||||
|
for (Association association : associations) {
|
||||||
|
handler.doWithAssociation(association);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSimpleType(Class<?> propertyType) {
|
||||||
|
if (propertyType == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (propertyType.isArray()) {
|
||||||
|
return isSimpleType(propertyType.getComponentType());
|
||||||
|
}
|
||||||
|
return SIMPLE_TYPES.contains(propertyType.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isTransientField(Field f) {
|
||||||
|
return (Modifier.isTransient(f.getModifiers()) || null != f.getAnnotation(Transient.class) || null != f.getAnnotation(Autowired.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Association {
|
||||||
|
|
||||||
|
private final PropertyDescriptor descriptor;
|
||||||
|
private final Field field;
|
||||||
|
|
||||||
|
public Association(PropertyDescriptor descriptor, Field field) {
|
||||||
|
this.descriptor = descriptor;
|
||||||
|
this.field = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PropertyDescriptor getDescriptor() {
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field getField() {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PreferredConstructor {
|
||||||
|
|
||||||
|
Constructor<T> constructor;
|
||||||
|
ConstructorParameter<?>[] parameters;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
public PreferredConstructor(Constructor<T> constructor, String[] names, Class<?>[] types) {
|
||||||
|
this.constructor = constructor;
|
||||||
|
Annotation[][] annos = constructor.getParameterAnnotations();
|
||||||
|
parameters = new ConstructorParameter[names.length];
|
||||||
|
for (int i = 0; i < names.length; i++) {
|
||||||
|
parameters[i] = new ConstructorParameter(names[i], types[i], annos[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ConstructorParameter<V> {
|
||||||
|
String name;
|
||||||
|
Class<V> type;
|
||||||
|
Annotation[] annotations;
|
||||||
|
|
||||||
|
private ConstructorParameter(String name, Class<V> type, Annotation[] annotations) {
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
this.annotations = annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Value getValueAnnotation() {
|
||||||
|
for (Annotation anno : annotations) {
|
||||||
|
if (anno instanceof Value) {
|
||||||
|
return (Value) anno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface AssociationHandler {
|
||||||
|
void doWithAssociation(Association association);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface PropertyHandler {
|
||||||
|
void doWithProperty(PropertyDescriptor descriptor, Field field, Expression spelExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ParameterValueProvider {
|
||||||
|
<T> T getParameterValue(String name, Class<T> type, Expression spelExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.AbstractClassMapping;
|
||||||
|
import org.springframework.data.mapping.model.MappingContext;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
|
||||||
|
public class MongoClassMapping extends AbstractClassMapping<MongoCollection> {
|
||||||
|
|
||||||
|
public MongoClassMapping(PersistentEntity entity, MappingContext context) {
|
||||||
|
super(entity, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MongoCollection getMappedForm() {
|
||||||
|
return (MongoCollection) context.getMappingFactory().createMappedForm(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public class MongoCollection {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public MongoCollection(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,457 @@
|
|||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBCollection;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
import com.mongodb.MongoException;
|
||||||
|
import com.mongodb.util.JSON;
|
||||||
|
import org.springframework.dao.DataAccessException;
|
||||||
|
import org.springframework.data.document.mongodb.index.CompoundIndex;
|
||||||
|
import org.springframework.data.document.mongodb.index.CompoundIndexes;
|
||||||
|
import org.springframework.data.document.mongodb.index.IndexDirection;
|
||||||
|
import org.springframework.data.document.mongodb.index.Indexed;
|
||||||
|
import org.springframework.data.document.mongodb.CollectionCallback;
|
||||||
|
import org.springframework.data.document.mongodb.MongoTemplate;
|
||||||
|
import org.springframework.data.mapping.annotation.*;
|
||||||
|
import org.springframework.data.mapping.model.*;
|
||||||
|
import org.springframework.data.mapping.model.types.Association;
|
||||||
|
import org.springframework.data.mapping.reflect.ClassPropertyFetcher;
|
||||||
|
import org.springframework.expression.EvaluationContext;
|
||||||
|
import org.springframework.expression.common.TemplateParserContext;
|
||||||
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.beans.IntrospectionException;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author J. Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public class MongoMappingConfigurationStrategy implements MappingConfigurationStrategy {
|
||||||
|
|
||||||
|
protected MongoTemplate mongo;
|
||||||
|
protected MongoMappingFactory mappingFactory;
|
||||||
|
protected SpelExpressionParser expressionParser = new SpelExpressionParser();
|
||||||
|
protected TemplateParserContext templateParserContext = new TemplateParserContext();
|
||||||
|
protected Map<Class<?>, PersistenceDescriptor> descriptors = new ConcurrentHashMap<Class<?>, PersistenceDescriptor>();
|
||||||
|
protected Map<Class<?>, Set<PersistentEntity>> owners = new LinkedHashMap<Class<?>, Set<PersistentEntity>>();
|
||||||
|
|
||||||
|
public MongoMappingConfigurationStrategy(MongoTemplate mongo) {
|
||||||
|
this.mongo = mongo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MongoMappingConfigurationStrategy(MongoTemplate mongo, MongoMappingFactory mappingFactory) {
|
||||||
|
this.mongo = mongo;
|
||||||
|
this.mappingFactory = mappingFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpelExpressionParser getExpressionParser() {
|
||||||
|
return expressionParser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpressionParser(SpelExpressionParser expressionParser) {
|
||||||
|
this.expressionParser = expressionParser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemplateParserContext getTemplateParserContext() {
|
||||||
|
return templateParserContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTemplateParserContext(TemplateParserContext templateParserContext) {
|
||||||
|
this.templateParserContext = templateParserContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
public boolean isPersistentEntity(Class aClass) {
|
||||||
|
if (null != aClass) {
|
||||||
|
return (null != aClass.getAnnotation(Persistent.class));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PersistentProperty> getPersistentProperties(Class aClass, MappingContext mappingContext) {
|
||||||
|
return getPersistentProperties(aClass, mappingContext, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PersistentProperty> getPersistentProperties(Class aClass,
|
||||||
|
MappingContext mappingContext,
|
||||||
|
ClassMapping classMapping) {
|
||||||
|
PersistenceDescriptor pd = getPersistenceDescriptor(aClass, mappingContext, classMapping);
|
||||||
|
return (null != pd ? pd.getProperties() : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentProperty getIdentity(Class aClass, MappingContext mappingContext) {
|
||||||
|
PersistenceDescriptor idPd = getPersistenceDescriptor(aClass, mappingContext, null);
|
||||||
|
return (null != idPd ? idPd.getIdProperty() : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdentityMapping getDefaultIdentityMapping(final ClassMapping classMapping) {
|
||||||
|
final PersistentProperty<?> prop = getPersistenceDescriptor(classMapping.getEntity().getJavaClass(),
|
||||||
|
classMapping.getEntity().getMappingContext(),
|
||||||
|
classMapping).getIdProperty();
|
||||||
|
|
||||||
|
return new IdentityMapping() {
|
||||||
|
public String[] getIdentifierName() {
|
||||||
|
return new String[]{prop.getName()};
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassMapping getClassMapping() {
|
||||||
|
return classMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getMappedForm() {
|
||||||
|
return classMapping.getMappedForm();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set getOwningEntities(Class aClass, MappingContext mappingContext) {
|
||||||
|
return owners.get(aClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PersistenceDescriptor getPersistenceDescriptor(Class<?> javaClass,
|
||||||
|
MappingContext context,
|
||||||
|
ClassMapping mapping) {
|
||||||
|
PersistenceDescriptor descriptor = descriptors.get(javaClass);
|
||||||
|
if (null == descriptor) {
|
||||||
|
ClassPropertyFetcher fetcher = ClassPropertyFetcher.forClass(javaClass);
|
||||||
|
PersistentEntity entity = getPersistentEntity(javaClass, context, mapping);
|
||||||
|
|
||||||
|
String collection = javaClass.getSimpleName().toLowerCase();
|
||||||
|
for (Annotation anno : javaClass.getAnnotations()) {
|
||||||
|
if (anno instanceof Persistent) {
|
||||||
|
|
||||||
|
} else if (anno instanceof CompoundIndexes) {
|
||||||
|
CompoundIndexes idxs = (CompoundIndexes) anno;
|
||||||
|
for (CompoundIndex idx : idxs.value()) {
|
||||||
|
String idxColl = collection;
|
||||||
|
if (!"".equals(idx.collection())) {
|
||||||
|
idxColl = idx.collection();
|
||||||
|
}
|
||||||
|
String name = null;
|
||||||
|
if (!"".equals(idx.name())) {
|
||||||
|
name = idx.name();
|
||||||
|
}
|
||||||
|
ensureIndex(idxColl, name, idx.def(), null, idx.unique(), idx.dropDups(), idx.sparse());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EvaluationContext elContext = createElContext();
|
||||||
|
elContext.setVariable("class", javaClass);
|
||||||
|
|
||||||
|
PersistentProperty<?> id = extractIdProperty(entity, context, elContext);
|
||||||
|
|
||||||
|
List<PersistentProperty> properties = new LinkedList<PersistentProperty>();
|
||||||
|
for (PropertyDescriptor propertyDescriptor : fetcher.getPropertyDescriptors()) {
|
||||||
|
if (null == id || !propertyDescriptor.getName().equals(id.getName())) {
|
||||||
|
PersistentProperty<?> p = createPersistentProperty(entity, context, propertyDescriptor, mapping);
|
||||||
|
if (null != p) {
|
||||||
|
properties.add(p);
|
||||||
|
for (Annotation anno : fetcher.getDeclaredField(p.getName()).getDeclaredAnnotations()) {
|
||||||
|
if (anno instanceof Indexed) {
|
||||||
|
Indexed idx = (Indexed) anno;
|
||||||
|
String idxColl = collection;
|
||||||
|
if (!"".equals(idx.collection())) {
|
||||||
|
idxColl = idx.collection();
|
||||||
|
}
|
||||||
|
String name = p.getName();
|
||||||
|
if (!"".equals(idx.name())) {
|
||||||
|
name = idx.name();
|
||||||
|
}
|
||||||
|
ensureIndex(idxColl, name, null, idx.direction(), idx.unique(), idx.dropDups(), idx.sparse());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
descriptor = new PersistenceDescriptor(entity, id, properties);
|
||||||
|
descriptors.put(javaClass, descriptor);
|
||||||
|
}
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PersistentEntity getPersistentEntity(Class<?> javaClass, MappingContext context, ClassMapping mapping) {
|
||||||
|
Assert.notNull(javaClass);
|
||||||
|
if (null != mapping) {
|
||||||
|
return mapping.getEntity();
|
||||||
|
} else {
|
||||||
|
return context.getPersistentEntity(javaClass.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PersistentProperty<?> createPersistentProperty(PersistentEntity entity,
|
||||||
|
MappingContext mappingContext,
|
||||||
|
PropertyDescriptor descriptor,
|
||||||
|
ClassMapping mapping) {
|
||||||
|
ClassPropertyFetcher fetcher = ClassPropertyFetcher.forClass(entity.getJavaClass());
|
||||||
|
Field f = fetcher.getDeclaredField(descriptor.getName());
|
||||||
|
|
||||||
|
if (null != f) {
|
||||||
|
// Handle associations and persistent types
|
||||||
|
PersistentProperty<?> prop = extractChildType(entity, mappingContext, descriptor, mapping);
|
||||||
|
if (null == prop) {
|
||||||
|
// Must be a simple type
|
||||||
|
prop = mappingFactory.createSimple(entity, mappingContext, descriptor);
|
||||||
|
}
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PersistentProperty<?> extractChildType(PersistentEntity entity,
|
||||||
|
MappingContext mappingContext,
|
||||||
|
PropertyDescriptor descriptor,
|
||||||
|
ClassMapping mapping) {
|
||||||
|
|
||||||
|
ClassPropertyFetcher fetcher = ClassPropertyFetcher.forClass(entity.getJavaClass());
|
||||||
|
Field f = fetcher.getDeclaredField(descriptor.getName());
|
||||||
|
|
||||||
|
Class<?> childClass = null;
|
||||||
|
Association<?> assoc = null;
|
||||||
|
if (f.getType().isAssignableFrom(List.class)) {
|
||||||
|
if (null != f.getAnnotation(org.springframework.data.mapping.annotation.OneToMany.class)) {
|
||||||
|
org.springframework.data.mapping.annotation.OneToMany otm = f.getAnnotation(
|
||||||
|
org.springframework.data.mapping.annotation.OneToMany.class);
|
||||||
|
if (Object.class != otm.targetClass()) {
|
||||||
|
childClass = otm.targetClass();
|
||||||
|
} else {
|
||||||
|
childClass = extractType(f);
|
||||||
|
}
|
||||||
|
assoc = mappingFactory.createOneToMany(entity, mappingContext, descriptor);
|
||||||
|
} else if (null != f.getAnnotation(org.springframework.data.mapping.annotation.ManyToMany.class)) {
|
||||||
|
org.springframework.data.mapping.annotation.ManyToMany mtm = f.getAnnotation(
|
||||||
|
org.springframework.data.mapping.annotation.ManyToMany.class);
|
||||||
|
if (Object.class != mtm.targetClass()) {
|
||||||
|
childClass = mtm.targetClass();
|
||||||
|
} else {
|
||||||
|
childClass = extractType(f);
|
||||||
|
}
|
||||||
|
assoc = mappingFactory.createManyToMany(entity, mappingContext, descriptor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (null != f.getAnnotation(OneToOne.class) || null != f.getType().getAnnotation(Persistent.class)) {
|
||||||
|
childClass = f.getType();
|
||||||
|
assoc = mappingFactory.createOneToOne(entity, mappingContext, descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (null != childClass && null != assoc) {
|
||||||
|
if (childClass != entity.getJavaClass()) {
|
||||||
|
PersistentEntity childEntity = getPersistentEntity(childClass, mappingContext, mapping);
|
||||||
|
addOwner(entity.getJavaClass(), childEntity);
|
||||||
|
assoc.setAssociatedEntity(childEntity);
|
||||||
|
} else {
|
||||||
|
addOwner(entity.getJavaClass(), entity);
|
||||||
|
assoc.setAssociatedEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class<?> extractType(Field f) {
|
||||||
|
Type t = f.getGenericType();
|
||||||
|
if (null != t && t instanceof ParameterizedType) {
|
||||||
|
Type[] types = ((ParameterizedType) t).getActualTypeArguments();
|
||||||
|
return ((Class) types[0]);
|
||||||
|
}
|
||||||
|
return f.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IdentifiedBy extractIdentifiedBy(Class<?> clazz, Field field) {
|
||||||
|
Persistent cAnno = clazz.getAnnotation(Persistent.class);
|
||||||
|
Persistent fldAnno = (null != field ? field.getAnnotation(Persistent.class) : null);
|
||||||
|
return (null != fldAnno ? fldAnno.identifiedBy() : cAnno.identifiedBy());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PersistenceStrategy extractPersistenceStrategy(Class<?> clazz, Field field) {
|
||||||
|
Persistent cAnno = clazz.getAnnotation(Persistent.class);
|
||||||
|
Persistent fldAnno = (null != field ? field.getAnnotation(Persistent.class) : null);
|
||||||
|
return (null != fldAnno ? fldAnno.strategy() : cAnno.strategy());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String extractId(Class<?> clazz, Field field) {
|
||||||
|
Persistent cAnno = clazz.getAnnotation(Persistent.class);
|
||||||
|
Persistent fldAnno = (null != field ? field.getAnnotation(Persistent.class) : null);
|
||||||
|
return (null != fldAnno ? fldAnno.id() : cAnno.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addOwner(Class<?> javaClass, PersistentEntity parent) {
|
||||||
|
if (!owners.containsKey(javaClass)) {
|
||||||
|
Set<PersistentEntity> owningEntities = new HashSet<PersistentEntity>();
|
||||||
|
owningEntities.add(parent);
|
||||||
|
owners.put(javaClass, owningEntities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PersistentProperty<?> extractIdProperty(PersistentEntity entity,
|
||||||
|
MappingContext mappingContext,
|
||||||
|
EvaluationContext elContext) {
|
||||||
|
ClassPropertyFetcher fetcher = ClassPropertyFetcher.forClass(entity.getJavaClass());
|
||||||
|
|
||||||
|
// Let field annotation override that on the class
|
||||||
|
IdentifiedBy idBy = extractIdentifiedBy(fetcher.getJavaClass(), null);
|
||||||
|
String id = extractId(fetcher.getJavaClass(), null);
|
||||||
|
Assert.notNull(id);
|
||||||
|
if (id.indexOf("#") > -1) {
|
||||||
|
id = expressionParser.parseExpression(id).getValue(elContext, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyDescriptor idPropDesc = null;
|
||||||
|
switch (idBy) {
|
||||||
|
case DEFAULT:
|
||||||
|
idPropDesc = findIdByAnnotation(fetcher);
|
||||||
|
if (null == idPropDesc) {
|
||||||
|
idPropDesc = fetcher.getPropertyDescriptor(id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ANNOTATION:
|
||||||
|
idPropDesc = findIdByAnnotation(fetcher);
|
||||||
|
break;
|
||||||
|
case PROPERTY:
|
||||||
|
idPropDesc = fetcher.getPropertyDescriptor(id);
|
||||||
|
break;
|
||||||
|
case VALUE:
|
||||||
|
try {
|
||||||
|
idPropDesc = new ValuePropertyDescriptor("id", entity.getJavaClass(), id);
|
||||||
|
} catch (IntrospectionException e) {
|
||||||
|
throw new IllegalStateException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//Assert.notNull(idPropDesc, String.format("No ID property could be found on the entity %s", entity));
|
||||||
|
|
||||||
|
return (null != idPropDesc ? mappingFactory.createIdentity(entity, mappingContext, idPropDesc) : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PropertyDescriptor findIdByAnnotation(ClassPropertyFetcher fetcher) {
|
||||||
|
for (PropertyDescriptor descriptor : fetcher.getPropertyDescriptors()) {
|
||||||
|
Field f = fetcher.getDeclaredField(descriptor.getName());
|
||||||
|
if (null != f && null != f.getAnnotation(Id.class)) {
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected EvaluationContext createElContext() {
|
||||||
|
StandardEvaluationContext elContext = new StandardEvaluationContext(System.getProperties());
|
||||||
|
for (String prop : System.getProperties().stringPropertyNames()) {
|
||||||
|
elContext.setVariable(prop, System.getProperty(prop));
|
||||||
|
}
|
||||||
|
return elContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ensureIndex(String collection,
|
||||||
|
final String name,
|
||||||
|
final String def,
|
||||||
|
final IndexDirection direction,
|
||||||
|
final boolean unique,
|
||||||
|
final boolean dropDups,
|
||||||
|
final boolean sparse) {
|
||||||
|
mongo.execute(collection, new CollectionCallback<Object>() {
|
||||||
|
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||||
|
DBObject defObj;
|
||||||
|
if (null != def) {
|
||||||
|
defObj = (DBObject) JSON.parse(def);
|
||||||
|
} else {
|
||||||
|
defObj = new BasicDBObject();
|
||||||
|
defObj.put(name, (direction == IndexDirection.ASCENDING ? 1 : -1));
|
||||||
|
}
|
||||||
|
DBObject opts = new BasicDBObject();
|
||||||
|
if (!"".equals(name)) {
|
||||||
|
opts.put("name", name);
|
||||||
|
}
|
||||||
|
opts.put("dropDups", dropDups);
|
||||||
|
opts.put("sparse", sparse);
|
||||||
|
opts.put("unique", unique);
|
||||||
|
collection.ensureIndex(defObj, opts);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class PersistenceDescriptor {
|
||||||
|
|
||||||
|
PersistentEntity entity;
|
||||||
|
PersistentProperty idProperty = null;
|
||||||
|
List<PersistentProperty> properties = null;
|
||||||
|
|
||||||
|
PersistenceDescriptor(PersistentEntity entity, PersistentProperty idProperty, List<PersistentProperty> properties) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.idProperty = idProperty;
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentEntity getEntity() {
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentProperty getIdProperty() {
|
||||||
|
return idProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PersistentProperty> getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class ValuePropertyDescriptor extends PropertyDescriptor {
|
||||||
|
|
||||||
|
Object value;
|
||||||
|
|
||||||
|
ValuePropertyDescriptor(String s, Class<?> aClass, Object value) throws IntrospectionException {
|
||||||
|
super(s, aClass);
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(Object value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Method getReadMethod() {
|
||||||
|
try {
|
||||||
|
return getClass().getMethod("getValue", null);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
// IGNORED
|
||||||
|
}
|
||||||
|
return super.getReadMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReadMethod(Method method) throws IntrospectionException {
|
||||||
|
// IGNORED
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Method getWriteMethod() {
|
||||||
|
try {
|
||||||
|
return getClass().getMethod("setValue", Object.class);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
// IGNORED
|
||||||
|
}
|
||||||
|
return super.getWriteMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setWriteMethod(Method method) throws IntrospectionException {
|
||||||
|
// IGNORED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
import org.springframework.data.document.mongodb.MongoTemplate;
|
||||||
|
import org.springframework.data.mapping.model.AbstractMappingContext;
|
||||||
|
import org.springframework.data.mapping.model.MappingConfigurationStrategy;
|
||||||
|
import org.springframework.data.mapping.model.MappingFactory;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public class MongoMappingContext extends AbstractMappingContext {
|
||||||
|
|
||||||
|
private MongoTemplate mongo;
|
||||||
|
private MongoMappingFactory mappingFactory = null;
|
||||||
|
private MappingConfigurationStrategy strategy = null;
|
||||||
|
|
||||||
|
public MongoMappingContext(MongoTemplate mongo) {
|
||||||
|
this.mongo = mongo;
|
||||||
|
this.mappingFactory = new MongoMappingFactory();
|
||||||
|
strategy = new MongoMappingConfigurationStrategy(mongo, mappingFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MongoMappingContext(MongoTemplate mongo, MongoMappingFactory mappingFactory) {
|
||||||
|
this.mongo = mongo;
|
||||||
|
this.mappingFactory = mappingFactory;
|
||||||
|
strategy = new MongoMappingConfigurationStrategy(mongo, mappingFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PersistentEntity createPersistentEntity(Class javaClass) {
|
||||||
|
MongoPersistentEntity entity = new MongoPersistentEntity(javaClass, this);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MappingConfigurationStrategy getMappingSyntaxStrategy() {
|
||||||
|
return strategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MappingFactory getMappingFactory() {
|
||||||
|
return mappingFactory;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
import org.springframework.data.document.mongodb.MongoTemplate;
|
||||||
|
import org.springframework.data.mapping.model.MappingFactory;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
import org.springframework.data.mapping.model.PersistentProperty;
|
||||||
|
import org.springframework.data.mapping.reflect.ClassPropertyFetcher;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public class MongoMappingFactory extends MappingFactory<MongoCollection, MongoProperty> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MongoCollection createMappedForm(PersistentEntity entity) {
|
||||||
|
String name = entity.getJavaClass().getSimpleName().toLowerCase();
|
||||||
|
return new MongoCollection(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MongoProperty createMappedForm(PersistentProperty property) {
|
||||||
|
String name = property.getName();
|
||||||
|
return new MongoProperty(name, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.AbstractPersistentEntity;
|
||||||
|
import org.springframework.data.mapping.model.ClassMapping;
|
||||||
|
import org.springframework.data.mapping.model.MappingContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public class MongoPersistentEntity extends AbstractPersistentEntity {
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
public MongoPersistentEntity(Class<?> javaClass, MappingContext context) {
|
||||||
|
super(javaClass, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
public ClassMapping<MongoCollection> getMapping() {
|
||||||
|
return new MongoClassMapping(this, getMappingContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
super.afterPropertiesSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public class MongoProperty {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public MongoProperty(String name, boolean indexed) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping.index;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
import com.mongodb.util.JSON;
|
||||||
|
import org.springframework.data.document.mongodb.index.IndexDefinition;
|
||||||
|
import org.springframework.data.document.mongodb.index.IndexDirection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public class MongoIndexDefinition implements IndexDefinition<DBObject> {
|
||||||
|
|
||||||
|
private String collection = null;
|
||||||
|
private String name = null;
|
||||||
|
private IndexDirection direction = IndexDirection.ASCENDING;
|
||||||
|
private boolean unique = false;
|
||||||
|
private boolean dropDups = true;
|
||||||
|
private boolean sparse = false;
|
||||||
|
private String definition = null;
|
||||||
|
|
||||||
|
public MongoIndexDefinition() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCollection() {
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCollection(String collection) {
|
||||||
|
this.collection = collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexDirection getDirection() {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDirection(IndexDirection direction) {
|
||||||
|
this.direction = direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUnique() {
|
||||||
|
return unique;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUnique(boolean unique) {
|
||||||
|
this.unique = unique;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDropDups() {
|
||||||
|
return dropDups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDropDups(boolean dropDups) {
|
||||||
|
this.dropDups = dropDups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSparse() {
|
||||||
|
return sparse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSparse(boolean sparse) {
|
||||||
|
this.sparse = sparse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefinition() {
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefinition(String definition) {
|
||||||
|
this.definition = definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBObject getIndexDefinition() {
|
||||||
|
DBObject dbo;
|
||||||
|
if (null != definition) {
|
||||||
|
dbo = (DBObject) JSON.parse(definition);
|
||||||
|
} else {
|
||||||
|
dbo = new BasicDBObject();
|
||||||
|
dbo.put(name, (direction == IndexDirection.ASCENDING ? 1 : -1));
|
||||||
|
}
|
||||||
|
return dbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBObject getIndexOptions() {
|
||||||
|
DBObject dbo = new BasicDBObject();
|
||||||
|
dbo.put("dropDups", dropDups);
|
||||||
|
dbo.put("sparse", sparse);
|
||||||
|
dbo.put("unique", unique);
|
||||||
|
return dbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.springframework.data.document.mongodb.MongoConverter;
|
import org.springframework.data.document.mongodb.convert.MongoConverter;
|
||||||
import org.springframework.data.document.mongodb.MongoTemplate;
|
import org.springframework.data.document.mongodb.MongoTemplate;
|
||||||
import org.springframework.data.document.mongodb.query.Query;
|
import org.springframework.data.document.mongodb.query.Query;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
|||||||
*
|
*
|
||||||
* @see
|
* @see
|
||||||
* org.springframework.data.document.mongodb.repository.AbstractMongoQuery#createQuery(org.springframework.data.
|
* org.springframework.data.document.mongodb.repository.AbstractMongoQuery#createQuery(org.springframework.data.
|
||||||
* repository.query.SimpleParameterAccessor, org.springframework.data.document.mongodb.MongoConverter)
|
* repository.query.SimpleParameterAccessor, org.springframework.data.document.mongodb.support.convert.MongoConverter)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Query createQuery(ConvertingParameterAccessor accessor) {
|
protected Query createQuery(ConvertingParameterAccessor accessor) {
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.mapping.annotation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public @interface Aliases {
|
||||||
|
|
||||||
|
String[] value();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.springframework.data.mapping.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author J. Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.FIELD})
|
||||||
|
public @interface Id {
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.springframework.data.mapping.annotation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author J. Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public enum IdentifiedBy {
|
||||||
|
DEFAULT,
|
||||||
|
ANNOTATION,
|
||||||
|
PROPERTY,
|
||||||
|
VALUE,
|
||||||
|
PARENT
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.springframework.data.mapping.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author J. Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.FIELD})
|
||||||
|
public @interface ManyToMany {
|
||||||
|
|
||||||
|
Class<?> targetClass() default Object.class;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.springframework.data.mapping.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author J. Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.FIELD})
|
||||||
|
public @interface OneToMany {
|
||||||
|
|
||||||
|
Class<?> targetClass() default Object.class;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.springframework.data.mapping.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author J. Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.FIELD})
|
||||||
|
public @interface OneToOne {
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.mapping.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.CONSTRUCTOR)
|
||||||
|
public @interface PersistenceConstructor {
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.springframework.data.mapping.annotation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author J. Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public enum PersistenceStrategy {
|
||||||
|
DEFAULT,
|
||||||
|
KEY_VALUE,
|
||||||
|
DOCUMENT,
|
||||||
|
SERIALIZED
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.mapping.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author J. Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = {ElementType.TYPE, ElementType.FIELD})
|
||||||
|
public @interface Persistent {
|
||||||
|
|
||||||
|
PersistenceStrategy strategy() default PersistenceStrategy.DOCUMENT;
|
||||||
|
|
||||||
|
IdentifiedBy identifiedBy() default IdentifiedBy.DEFAULT;
|
||||||
|
|
||||||
|
String id() default "id";
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.springframework.data.mapping.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author J. Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
public @interface Transient {
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.mapping.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({
|
||||||
|
ElementType.PARAMETER,
|
||||||
|
ElementType.FIELD,
|
||||||
|
ElementType.ANNOTATION_TYPE
|
||||||
|
})
|
||||||
|
public @interface Value {
|
||||||
|
|
||||||
|
String value();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/* Copyright (C) 2010 SpringSource
|
||||||
|
*
|
||||||
|
* 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.mapping.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract implementation of the ClassMapping interface
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractClassMapping<T> implements ClassMapping{
|
||||||
|
protected PersistentEntity entity;
|
||||||
|
protected MappingContext context;
|
||||||
|
|
||||||
|
public AbstractClassMapping(PersistentEntity entity, MappingContext context) {
|
||||||
|
super();
|
||||||
|
this.entity = entity;
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentEntity getEntity() {
|
||||||
|
return this.entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract T getMappedForm();
|
||||||
|
|
||||||
|
public IdentityMapping getIdentifier() {
|
||||||
|
return context.getMappingSyntaxStrategy().getDefaultIdentityMapping(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
/* Copyright (C) 2010 SpringSource
|
||||||
|
*
|
||||||
|
* 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.mapping.model;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConversionService;
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.core.convert.converter.ConverterRegistry;
|
||||||
|
import org.springframework.core.convert.support.GenericConversionService;
|
||||||
|
import org.springframework.validation.Validator;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract implementation of the MappingContext interface
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractMappingContext implements MappingContext {
|
||||||
|
|
||||||
|
protected Collection<PersistentEntity> persistentEntities = new ConcurrentLinkedQueue<PersistentEntity>();
|
||||||
|
protected Map<String, PersistentEntity> persistentEntitiesByName = new ConcurrentHashMap<String, PersistentEntity>();
|
||||||
|
protected Map<PersistentEntity, Map<String, PersistentEntity>> persistentEntitiesByDiscriminator = new ConcurrentHashMap<PersistentEntity, Map<String, PersistentEntity>>();
|
||||||
|
protected Map<PersistentEntity, Validator> entityValidators = new ConcurrentHashMap<PersistentEntity, Validator>();
|
||||||
|
protected Collection<Listener> eventListeners = new ConcurrentLinkedQueue<Listener>();
|
||||||
|
protected GenericConversionService conversionService = new GenericConversionService();
|
||||||
|
|
||||||
|
public ConversionService getConversionService() {
|
||||||
|
return conversionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConverterRegistry getConverterRegistry() {
|
||||||
|
return conversionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMappingContextListener(Listener listener) {
|
||||||
|
if (listener != null)
|
||||||
|
eventListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTypeConverter(Converter converter) {
|
||||||
|
conversionService.addConverter(converter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Validator getEntityValidator(PersistentEntity entity) {
|
||||||
|
if (entity != null) {
|
||||||
|
return entityValidators.get(entity);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEntityValidator(PersistentEntity entity, Validator validator) {
|
||||||
|
if (entity != null && validator != null) {
|
||||||
|
entityValidators.put(entity, validator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentEntity addExternalPersistentEntity(Class javaClass) {
|
||||||
|
if (javaClass == null) throw new IllegalArgumentException("PersistentEntity class cannot be null");
|
||||||
|
|
||||||
|
PersistentEntity entity = persistentEntitiesByName.get(javaClass.getName());
|
||||||
|
|
||||||
|
if (entity == null) {
|
||||||
|
entity = addPersistentEntityInternal(javaClass, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final PersistentEntity addPersistentEntity(Class javaClass) {
|
||||||
|
if (javaClass == null) throw new IllegalArgumentException("PersistentEntity class cannot be null");
|
||||||
|
|
||||||
|
PersistentEntity entity = persistentEntitiesByName.get(javaClass.getName());
|
||||||
|
|
||||||
|
if (entity == null) {
|
||||||
|
entity = addPersistentEntityInternal(javaClass, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PersistentEntity addPersistentEntityInternal(Class javaClass, boolean isExternal) {
|
||||||
|
PersistentEntity entity;
|
||||||
|
entity = createPersistentEntity(javaClass);
|
||||||
|
entity.setExternal(isExternal);
|
||||||
|
|
||||||
|
persistentEntities.remove(entity);
|
||||||
|
persistentEntities.add(entity);
|
||||||
|
persistentEntitiesByName.put(entity.getName(), entity);
|
||||||
|
try {
|
||||||
|
entity.afterPropertiesSet();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(String.format("Error initializing PersistentEntity: %s", entity), e);
|
||||||
|
}
|
||||||
|
if (!entity.isRoot()) {
|
||||||
|
PersistentEntity root = entity.getRootEntity();
|
||||||
|
Map<String, PersistentEntity> children = persistentEntitiesByDiscriminator.get(root);
|
||||||
|
if (children == null) {
|
||||||
|
children = new ConcurrentHashMap<String, PersistentEntity>();
|
||||||
|
persistentEntitiesByDiscriminator.put(root, children);
|
||||||
|
}
|
||||||
|
children.put(entity.getDiscriminator(), entity);
|
||||||
|
}
|
||||||
|
for (Listener eventListener : eventListeners) {
|
||||||
|
eventListener.persistentEntityAdded(entity);
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentEntity getChildEntityByDiscriminator(PersistentEntity root, String discriminator) {
|
||||||
|
final Map<String, PersistentEntity> children = persistentEntitiesByDiscriminator.get(root);
|
||||||
|
if (children != null) {
|
||||||
|
return children.get(discriminator);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract PersistentEntity createPersistentEntity(Class javaClass);
|
||||||
|
|
||||||
|
public Collection<PersistentEntity> getPersistentEntities() {
|
||||||
|
return persistentEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPersistentEntity(Class type) {
|
||||||
|
return type != null && getPersistentEntity(type.getName()) != null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPersistentEntity(Object value) {
|
||||||
|
return value != null && isPersistentEntity(value.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentEntity getPersistentEntity(String name) {
|
||||||
|
final int proxyIndicator = name.indexOf("_$$_");
|
||||||
|
if (proxyIndicator > -1) {
|
||||||
|
name = name.substring(0, proxyIndicator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return persistentEntitiesByName.get(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.model;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.data.mapping.model.types.Association;
|
||||||
|
import org.springframework.data.mapping.model.types.OneToMany;
|
||||||
|
|
||||||
|
import java.beans.Introspector;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract implementation to be subclasses on a per datastore basis
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractPersistentEntity<T> implements PersistentEntity<T> {
|
||||||
|
|
||||||
|
protected Class<T> javaClass;
|
||||||
|
protected List<PersistentProperty> persistentProperties;
|
||||||
|
protected List<Association> associations;
|
||||||
|
protected Map<String, PersistentProperty> propertiesByName = new HashMap<String, PersistentProperty>();
|
||||||
|
protected MappingContext context;
|
||||||
|
protected PersistentProperty identity;
|
||||||
|
protected List<String> persistentPropertyNames;
|
||||||
|
private String decapitalizedName;
|
||||||
|
protected Set owners;
|
||||||
|
private PersistentEntity parentEntity = null;
|
||||||
|
private boolean external;
|
||||||
|
|
||||||
|
public AbstractPersistentEntity(Class<T> javaClass, MappingContext context) {
|
||||||
|
if (javaClass == null) throw new IllegalArgumentException("The argument [javaClass] cannot be null");
|
||||||
|
this.javaClass = javaClass;
|
||||||
|
this.context = context;
|
||||||
|
this.decapitalizedName = Introspector.decapitalize(javaClass.getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExternal() {
|
||||||
|
return external;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setExternal(boolean external) {
|
||||||
|
this.external = external;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MappingContext getMappingContext() {
|
||||||
|
return this.context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
this.identity = context.getMappingSyntaxStrategy().getIdentity(javaClass, context);
|
||||||
|
this.owners = context.getMappingSyntaxStrategy().getOwningEntities(javaClass, context);
|
||||||
|
this.persistentProperties = context.getMappingSyntaxStrategy().getPersistentProperties(javaClass, context);
|
||||||
|
persistentPropertyNames = new ArrayList<String>();
|
||||||
|
associations = new ArrayList();
|
||||||
|
for (PersistentProperty persistentProperty : persistentProperties) {
|
||||||
|
if (!(persistentProperty instanceof OneToMany))
|
||||||
|
persistentPropertyNames.add(persistentProperty.getName());
|
||||||
|
if (persistentProperty instanceof Association) {
|
||||||
|
associations.add((Association) persistentProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (PersistentProperty persistentProperty : persistentProperties) {
|
||||||
|
propertiesByName.put(persistentProperty.getName(), persistentProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?> superClass = javaClass.getSuperclass();
|
||||||
|
if (superClass != null
|
||||||
|
&& !superClass.equals(Object.class)
|
||||||
|
&& !Modifier.isAbstract(superClass.getModifiers())) {
|
||||||
|
this.parentEntity = context.addPersistentEntity(superClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getMapping().getMappedForm(); // initialize mapping
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasProperty(String name, Class type) {
|
||||||
|
final PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(getJavaClass(), name);
|
||||||
|
return pd != null && pd.getPropertyType().equals(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIdentityName(String propertyName) {
|
||||||
|
return getIdentity().getName().equals(propertyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentEntity getParentEntity() {
|
||||||
|
return parentEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDiscriminator() {
|
||||||
|
return getJavaClass().getSimpleName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentEntity getRootEntity() {
|
||||||
|
PersistentEntity root = this;
|
||||||
|
PersistentEntity parent = getParentEntity();
|
||||||
|
while (parent != null) {
|
||||||
|
root = parent;
|
||||||
|
parent = parent.getParentEntity();
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRoot() {
|
||||||
|
return getParentEntity() == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOwningEntity(PersistentEntity owner) {
|
||||||
|
return owner != null && owners.contains(owner.getJavaClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDecapitalizedName() {
|
||||||
|
return this.decapitalizedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getPersistentPropertyNames() {
|
||||||
|
return this.persistentPropertyNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T newInstance() {
|
||||||
|
try {
|
||||||
|
return getJavaClass().newInstance();
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new EntityInstantiationException("Unable to create entity of type [" + getJavaClass() + "]: " + e.getMessage(), e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new EntityInstantiationException("Unable to create entity of type [" + getJavaClass() + "]: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return javaClass.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentProperty getIdentity() {
|
||||||
|
return this.identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<T> getJavaClass() {
|
||||||
|
return this.javaClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInstance(Object obj) {
|
||||||
|
return getJavaClass().isInstance(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PersistentProperty> getPersistentProperties() {
|
||||||
|
return persistentProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Association> getAssociations() {
|
||||||
|
return associations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentProperty getPropertyByName(String name) {
|
||||||
|
return propertiesByName.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return javaClass.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == null || !(o instanceof PersistentEntity)) return false;
|
||||||
|
if (this == o) return true;
|
||||||
|
|
||||||
|
PersistentEntity other = (PersistentEntity) o;
|
||||||
|
return javaClass.equals(other.getJavaClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PersistentEntity[" + javaClass.getName() + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.model;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract implementation of the PersistentProperty interface that
|
||||||
|
* uses the PropertyDescriptor instance to establish name and type
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractPersistentProperty implements PersistentProperty {
|
||||||
|
protected PersistentEntity owner;
|
||||||
|
protected MappingContext context;
|
||||||
|
protected String name;
|
||||||
|
protected Class type;
|
||||||
|
private boolean nullable = false;
|
||||||
|
|
||||||
|
public AbstractPersistentProperty(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) {
|
||||||
|
this.owner = owner;
|
||||||
|
this.context = context;
|
||||||
|
this.name = descriptor.getName();
|
||||||
|
this.type = descriptor.getPropertyType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractPersistentProperty(PersistentEntity owner, MappingContext context, String name, Class type) {
|
||||||
|
this.owner = owner;
|
||||||
|
this.context = context;
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCapitilizedName() {
|
||||||
|
String name = getName();
|
||||||
|
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentEntity getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getName() + ":" + getType().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNullable() {
|
||||||
|
return nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNullable(boolean nullable) {
|
||||||
|
this.nullable = nullable;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package org.springframework.data.mapping.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class mapping is a mapping between a class and some external
|
||||||
|
* form such as a table, column family, or document (depending on the underlying data store)
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public interface ClassMapping<T> {
|
||||||
|
/**
|
||||||
|
* Obtains the PersistentEntity for this class mapping
|
||||||
|
*
|
||||||
|
* @return The PersistentEntity
|
||||||
|
*/
|
||||||
|
PersistentEntity getEntity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the mapped form of the class such as a Table, a Key Space, Document etc.
|
||||||
|
*
|
||||||
|
* @return The mapped representation
|
||||||
|
*/
|
||||||
|
T getMappedForm();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns details of the identifier used for this class
|
||||||
|
*
|
||||||
|
* @return The Identity
|
||||||
|
*/
|
||||||
|
IdentityMapping getIdentifier();
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.springframework.data.mapping.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown when something goes wrong configuring a datastore
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public class DatastoreConfigurationException extends RuntimeException{
|
||||||
|
|
||||||
|
public DatastoreConfigurationException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DatastoreConfigurationException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.mapping.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by IntelliJ IDEA.
|
||||||
|
* User: jbrisbin
|
||||||
|
* Date: 2/25/11
|
||||||
|
* Time: 9:07 AM
|
||||||
|
* To change this template use File | Settings | File Templates.
|
||||||
|
*/
|
||||||
|
public class EntityInstantiationException extends RuntimeException {
|
||||||
|
public EntityInstantiationException(String s, Throwable throwable) {
|
||||||
|
super(s, throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/* Copyright (C) 2010 SpringSource
|
||||||
|
*
|
||||||
|
* 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.mapping.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public interface IdentityMapping extends PropertyMapping{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The identifier property name(s) as an array. Usually there is just one identifier
|
||||||
|
* name, however in the case of a composite or natural identifier there
|
||||||
|
* may be serveral names
|
||||||
|
*
|
||||||
|
* @return A String[] of identifier names that make up the key
|
||||||
|
*/
|
||||||
|
String[] getIdentifierName();
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/* Copyright (C) 2010 SpringSource
|
||||||
|
*
|
||||||
|
* 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.mapping.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when an error occurs reading the mapping between object and datastore
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public class IllegalMappingException extends RuntimeException {
|
||||||
|
|
||||||
|
public IllegalMappingException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package org.springframework.data.mapping.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>This interface defines a strategy for reading how
|
||||||
|
* persistent properties are defined in a persistent entity.</p>
|
||||||
|
* <p/>
|
||||||
|
* <p>Subclasses can implement this interface in order to provide
|
||||||
|
* a different mechanism for mapping entities such as annotations or XML.</p>
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public interface MappingConfigurationStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether the given class is a persistent entity
|
||||||
|
*
|
||||||
|
* @param javaClass The java class
|
||||||
|
* @return true if it is a persistent entity
|
||||||
|
*/
|
||||||
|
<T> boolean isPersistentEntity(Class<T> javaClass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #getPersistentProperties(Class, MappingContext, ClassMapping)
|
||||||
|
*/
|
||||||
|
<T> List<PersistentProperty> getPersistentProperties(Class<T> javaClass, MappingContext context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a List of PersistentProperty instances for the given Mapped class
|
||||||
|
*
|
||||||
|
* @param javaClass The Java class
|
||||||
|
* @param context The MappingContext instance
|
||||||
|
* @param mapping The mapping for this class
|
||||||
|
* @return The PersistentProperty instances
|
||||||
|
*/
|
||||||
|
<T> List<PersistentProperty> getPersistentProperties(Class<T> javaClass, MappingContext context, ClassMapping mapping);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the identity of a persistent entity
|
||||||
|
*
|
||||||
|
* @param javaClass The Java class
|
||||||
|
* @param context The MappingContext
|
||||||
|
* @return A PersistentProperty instance
|
||||||
|
*/
|
||||||
|
<T> PersistentProperty getIdentity(Class<T> javaClass, MappingContext context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the default manner in which identifiers are mapped. In GORM
|
||||||
|
* this is just using a property called 'id', but in other frameworks this
|
||||||
|
* may differ. For example JPA expects an annotated @Id property
|
||||||
|
*
|
||||||
|
* @param classMapping The ClassMapping instance
|
||||||
|
* @return The default identifier mapping
|
||||||
|
*/
|
||||||
|
IdentityMapping getDefaultIdentityMapping(ClassMapping classMapping);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a set of entities that "own" the given entity. Ownership
|
||||||
|
* dictates default cascade strategies. So if entity A owns entity B
|
||||||
|
* then saves, updates and deletes will cascade from A to B
|
||||||
|
*
|
||||||
|
* @param javaClass The Java class
|
||||||
|
* @param context The MappingContext
|
||||||
|
* @return A Set of owning classes
|
||||||
|
*/
|
||||||
|
<T> Set getOwningEntities(Class<T> javaClass, MappingContext context);
|
||||||
|
}
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.model;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConversionService;
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.core.convert.converter.ConverterRegistry;
|
||||||
|
import org.springframework.validation.Validator;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>This interface defines the overall context including all known
|
||||||
|
* PersistentEntity instances and methods to obtain instances on demand</p>
|
||||||
|
* <p/>
|
||||||
|
* <p>This interface is used internally to establish associations
|
||||||
|
* between entities and also at runtime to obtain entities by name</p>
|
||||||
|
* <p/>
|
||||||
|
* <p>The generic type parameters T & R are used to specify the
|
||||||
|
* mapped form of a class (example Table) and property (example Column) respectively.</p>
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public interface MappingContext {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a list of PersistentEntity instances
|
||||||
|
*
|
||||||
|
* @return A list of PersistentEntity instances
|
||||||
|
*/
|
||||||
|
Collection<PersistentEntity> getPersistentEntities();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a PersistentEntity by name
|
||||||
|
*
|
||||||
|
* @param name The name of the entity
|
||||||
|
* @return The entity or null
|
||||||
|
*/
|
||||||
|
PersistentEntity getPersistentEntity(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a child of the given root entity using the given discriminator
|
||||||
|
*
|
||||||
|
* @param root The root entity
|
||||||
|
* @param discriminator The discriminator
|
||||||
|
* @return The child entity or null if non exists
|
||||||
|
*/
|
||||||
|
PersistentEntity getChildEntityByDiscriminator(PersistentEntity root, String discriminator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a PersistentEntity instance
|
||||||
|
*
|
||||||
|
* @param javaClass The Java class representing the entity
|
||||||
|
* @return The PersistentEntity instance
|
||||||
|
*/
|
||||||
|
PersistentEntity addPersistentEntity(Class javaClass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a persistent entity that is not mapped by this MappingContext instance.
|
||||||
|
* Used for cross store persistence
|
||||||
|
*
|
||||||
|
* @param javaClass The Java class
|
||||||
|
* @return The persistent entity
|
||||||
|
*/
|
||||||
|
PersistentEntity addExternalPersistentEntity(Class javaClass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a validator to be used by the entity for validation
|
||||||
|
*
|
||||||
|
* @param entity The PersistentEntity
|
||||||
|
* @param validator The validator
|
||||||
|
*/
|
||||||
|
void addEntityValidator(PersistentEntity entity, Validator validator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a converter used to convert property values to and from the datastore
|
||||||
|
*
|
||||||
|
* @param converter The converter to add
|
||||||
|
*/
|
||||||
|
void addTypeConverter(Converter converter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the ConversionService instance to use for type conversion
|
||||||
|
*
|
||||||
|
* @return The conversion service instance
|
||||||
|
*/
|
||||||
|
ConversionService getConversionService();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the converter registry
|
||||||
|
*
|
||||||
|
* @return The converter registry used for type conversion
|
||||||
|
*/
|
||||||
|
ConverterRegistry getConverterRegistry();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a validator for the given entity
|
||||||
|
*
|
||||||
|
* @param entity The entity
|
||||||
|
* @return A validator or null if none exists for the given entity
|
||||||
|
*/
|
||||||
|
Validator getEntityValidator(PersistentEntity entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the syntax reader used to interpret the entity
|
||||||
|
* mapping syntax
|
||||||
|
*
|
||||||
|
* @return The SyntaxReader
|
||||||
|
*/
|
||||||
|
MappingConfigurationStrategy getMappingSyntaxStrategy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the MappingFactory instance
|
||||||
|
*
|
||||||
|
* @return The mapping factory instance
|
||||||
|
*/
|
||||||
|
MappingFactory getMappingFactory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the specified class is a persistent entity
|
||||||
|
*
|
||||||
|
* @param type The type to check
|
||||||
|
* @return True if it is
|
||||||
|
*/
|
||||||
|
boolean isPersistentEntity(Class<?> type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the specified value is a persistent entity
|
||||||
|
*
|
||||||
|
* @param value The value to check
|
||||||
|
* @return True if it is
|
||||||
|
*/
|
||||||
|
boolean isPersistentEntity(Object value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new mapping context listener instance
|
||||||
|
*
|
||||||
|
* @param listener The listener
|
||||||
|
*/
|
||||||
|
void addMappingContextListener(Listener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementors can register for events when the mapping context changes
|
||||||
|
*/
|
||||||
|
public static interface Listener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired when a new entity is added
|
||||||
|
*
|
||||||
|
* @param entity The entity
|
||||||
|
*/
|
||||||
|
void persistentEntityAdded(PersistentEntity entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,278 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.model;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.types.*;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.sql.Blob;
|
||||||
|
import java.sql.Clob;
|
||||||
|
import java.sql.Time;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>An abstract factory for creating persistent property instances.</p>
|
||||||
|
* <p/>
|
||||||
|
* <p>Subclasses should implement the createMappedForm method in order to
|
||||||
|
* provide a mechanisms for representing the property in a form appropriate
|
||||||
|
* for mapping to the underlying datastore. Example:</p>
|
||||||
|
* <p/>
|
||||||
|
* <pre>
|
||||||
|
* <code>
|
||||||
|
* class RelationalPropertyFactory<Column> extends PropertyFactory {
|
||||||
|
* public Column createMappedForm(PersistentProperty mpp) {
|
||||||
|
* return new Column(mpp)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </code>
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class MappingFactory<R, T> {
|
||||||
|
public static final Set<String> SIMPLE_TYPES;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Set<String> basics = new HashSet<String>();
|
||||||
|
basics.add(boolean.class.getName());
|
||||||
|
basics.add(long.class.getName());
|
||||||
|
basics.add(short.class.getName());
|
||||||
|
basics.add(int.class.getName());
|
||||||
|
basics.add(byte.class.getName());
|
||||||
|
basics.add(float.class.getName());
|
||||||
|
basics.add(double.class.getName());
|
||||||
|
basics.add(char.class.getName());
|
||||||
|
basics.add(Boolean.class.getName());
|
||||||
|
basics.add(Long.class.getName());
|
||||||
|
basics.add(Short.class.getName());
|
||||||
|
basics.add(Integer.class.getName());
|
||||||
|
basics.add(Byte.class.getName());
|
||||||
|
basics.add(Float.class.getName());
|
||||||
|
basics.add(Double.class.getName());
|
||||||
|
basics.add(Character.class.getName());
|
||||||
|
basics.add(String.class.getName());
|
||||||
|
basics.add(java.util.Date.class.getName());
|
||||||
|
basics.add(Time.class.getName());
|
||||||
|
basics.add(Timestamp.class.getName());
|
||||||
|
basics.add(java.sql.Date.class.getName());
|
||||||
|
basics.add(BigDecimal.class.getName());
|
||||||
|
basics.add(BigInteger.class.getName());
|
||||||
|
basics.add(Locale.class.getName());
|
||||||
|
basics.add(Calendar.class.getName());
|
||||||
|
basics.add(GregorianCalendar.class.getName());
|
||||||
|
basics.add(java.util.Currency.class.getName());
|
||||||
|
basics.add(TimeZone.class.getName());
|
||||||
|
basics.add(Object.class.getName());
|
||||||
|
basics.add(Class.class.getName());
|
||||||
|
basics.add(byte[].class.getName());
|
||||||
|
basics.add(Byte[].class.getName());
|
||||||
|
basics.add(char[].class.getName());
|
||||||
|
basics.add(Character[].class.getName());
|
||||||
|
basics.add(Blob.class.getName());
|
||||||
|
basics.add(Clob.class.getName());
|
||||||
|
basics.add(Serializable.class.getName());
|
||||||
|
basics.add(URI.class.getName());
|
||||||
|
basics.add(URL.class.getName());
|
||||||
|
|
||||||
|
SIMPLE_TYPES = Collections.unmodifiableSet(basics);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public MappingFactory() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSimpleType(Class propType) {
|
||||||
|
if (propType == null) return false;
|
||||||
|
if (propType.isArray()) {
|
||||||
|
return isSimpleType(propType.getComponentType());
|
||||||
|
}
|
||||||
|
final String typeName = propType.getName();
|
||||||
|
return isSimpleType(typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSimpleType(final String typeName) {
|
||||||
|
return SIMPLE_TYPES.contains(typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the mapped form of a persistent entity
|
||||||
|
*
|
||||||
|
* @param entity The entity
|
||||||
|
* @return The mapped form
|
||||||
|
*/
|
||||||
|
public abstract R createMappedForm(PersistentEntity entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the mapped form of a PersistentProperty instance
|
||||||
|
*
|
||||||
|
* @param mpp The PersistentProperty instance
|
||||||
|
* @return The mapped form
|
||||||
|
*/
|
||||||
|
public abstract T createMappedForm(PersistentProperty mpp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an identifier property
|
||||||
|
*
|
||||||
|
* @param owner The owner
|
||||||
|
* @param context The context
|
||||||
|
* @param pd The PropertyDescriptor
|
||||||
|
* @return An Identity instance
|
||||||
|
*/
|
||||||
|
public Identity<T> createIdentity(PersistentEntity owner, MappingContext context, PropertyDescriptor pd) {
|
||||||
|
return new Identity<T>(owner, context, pd) {
|
||||||
|
public PropertyMapping<T> getMapping() {
|
||||||
|
return createPropertyMapping(this, owner);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a simple property type used for mapping basic types such as String, long, integer etc.
|
||||||
|
*
|
||||||
|
* @param owner The owner
|
||||||
|
* @param context The MappingContext
|
||||||
|
* @param pd The PropertyDescriptor
|
||||||
|
* @return A Simple property type
|
||||||
|
*/
|
||||||
|
public Simple<T> createSimple(PersistentEntity owner, MappingContext context, PropertyDescriptor pd) {
|
||||||
|
return new Simple<T>(owner, context, pd) {
|
||||||
|
public PropertyMapping<T> getMapping() {
|
||||||
|
return createPropertyMapping(this, owner);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PropertyMapping<T> createPropertyMapping(final PersistentProperty<T> property, final PersistentEntity owner) {
|
||||||
|
return new PropertyMapping<T>() {
|
||||||
|
public ClassMapping getClassMapping() {
|
||||||
|
return owner.getMapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getMappedForm() {
|
||||||
|
return createMappedForm(property);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a one-to-one association type used for mapping a one-to-one association between entities
|
||||||
|
*
|
||||||
|
* @param entity The entity
|
||||||
|
* @param context The context
|
||||||
|
* @param property The property
|
||||||
|
* @return The ToOne instance
|
||||||
|
*/
|
||||||
|
public ToOne createOneToOne(PersistentEntity entity, MappingContext context, PropertyDescriptor property) {
|
||||||
|
return new OneToOne<T>(entity, context, property) {
|
||||||
|
public PropertyMapping getMapping() {
|
||||||
|
return createPropertyMapping(this, owner);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a many-to-one association type used for a mapping a many-to-one association between entities
|
||||||
|
*
|
||||||
|
* @param entity The entity
|
||||||
|
* @param context The context
|
||||||
|
* @param property The property
|
||||||
|
* @return The ToOne instance
|
||||||
|
*/
|
||||||
|
public ToOne createManyToOne(PersistentEntity entity, MappingContext context, PropertyDescriptor property) {
|
||||||
|
return new ManyToOne<T>(entity, context, property) {
|
||||||
|
public PropertyMapping getMapping() {
|
||||||
|
return createPropertyMapping(this, owner);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link OneToMany} type used to model a one-to-many association between entities
|
||||||
|
*
|
||||||
|
* @param entity The entity
|
||||||
|
* @param context The context
|
||||||
|
* @param property The property
|
||||||
|
* @return The {@link OneToMany} instance
|
||||||
|
*/
|
||||||
|
public OneToMany createOneToMany(PersistentEntity entity, MappingContext context, PropertyDescriptor property) {
|
||||||
|
return new OneToMany<T>(entity, context, property) {
|
||||||
|
public PropertyMapping getMapping() {
|
||||||
|
return createPropertyMapping(this, owner);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link ManyToMany} type used to model a many-to-many association between entities
|
||||||
|
*
|
||||||
|
* @param entity The entity
|
||||||
|
* @param context The context
|
||||||
|
* @param property The property
|
||||||
|
* @return The {@link ManyToMany} instance
|
||||||
|
*/
|
||||||
|
public ManyToMany createManyToMany(PersistentEntity entity, MappingContext context, PropertyDescriptor property) {
|
||||||
|
return new ManyToMany<T>(entity, context, property) {
|
||||||
|
public PropertyMapping getMapping() {
|
||||||
|
return createPropertyMapping(this, owner);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an {@link Embedded} type used to model an embedded association (composition)
|
||||||
|
*
|
||||||
|
* @param entity The entity
|
||||||
|
* @param context The context
|
||||||
|
* @param property The property
|
||||||
|
* @return The {@link Embedded} instance
|
||||||
|
*/
|
||||||
|
public Embedded createEmbedded(PersistentEntity entity,
|
||||||
|
MappingContext context, PropertyDescriptor property) {
|
||||||
|
return new Embedded<T>(entity, context, property) {
|
||||||
|
public PropertyMapping getMapping() {
|
||||||
|
return createPropertyMapping(this, owner);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Basic} collection type
|
||||||
|
*
|
||||||
|
* @param entity The entity
|
||||||
|
* @param context The context
|
||||||
|
* @param property The property
|
||||||
|
* @return The Basic collection type
|
||||||
|
*/
|
||||||
|
public Basic createBasicCollection(PersistentEntity entity,
|
||||||
|
MappingContext context, PropertyDescriptor property) {
|
||||||
|
return new Basic(entity, context, property) {
|
||||||
|
public PropertyMapping getMapping() {
|
||||||
|
return createPropertyMapping(this, owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
package org.springframework.data.mapping.model;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.data.mapping.model.types.Association;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a persistent entity
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public interface PersistentEntity<T> extends InitializingBean {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entity name including any package prefix
|
||||||
|
*
|
||||||
|
* @return The entity name
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this PersistentEntity is mapped using a different store. Used for cross store persistence
|
||||||
|
*
|
||||||
|
* @return True if this entity is externally mapped
|
||||||
|
*/
|
||||||
|
boolean isExternal();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this PersistentEntity is mapped using a different store. Used for cross store persistence
|
||||||
|
*
|
||||||
|
* @return True if this entity is externally mapped
|
||||||
|
*/
|
||||||
|
void setExternal(boolean external);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the identity of the instance
|
||||||
|
*
|
||||||
|
* @return The identity
|
||||||
|
*/
|
||||||
|
PersistentProperty getIdentity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of properties to be persisted
|
||||||
|
*
|
||||||
|
* @return A list of PersistentProperty instances
|
||||||
|
*/
|
||||||
|
List<PersistentProperty> getPersistentProperties();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of the associations for this entity. This is typically
|
||||||
|
* a subset of the list returned by {@link #getPersistentProperties()}
|
||||||
|
*
|
||||||
|
* @return A list of associations
|
||||||
|
*/
|
||||||
|
List<Association> getAssociations();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a PersistentProperty instance by name
|
||||||
|
*
|
||||||
|
* @param name The name of the property
|
||||||
|
* @return The PersistentProperty or null if it doesn't exist
|
||||||
|
*/
|
||||||
|
PersistentProperty getPropertyByName(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The underlying Java class for this entity
|
||||||
|
*/
|
||||||
|
Class<T> getJavaClass();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether the given instance is an instance of this persistent entity
|
||||||
|
*
|
||||||
|
* @param obj The object
|
||||||
|
* @return True if it is
|
||||||
|
*/
|
||||||
|
boolean isInstance(Object obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the mapping between this persistent entity
|
||||||
|
* and an external form
|
||||||
|
*
|
||||||
|
* @return The ClassMapping instance
|
||||||
|
*/
|
||||||
|
<M> ClassMapping<M> getMapping();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new instance
|
||||||
|
*
|
||||||
|
* @return The new instnace
|
||||||
|
*/
|
||||||
|
T newInstance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of property names that a persistent
|
||||||
|
*
|
||||||
|
* @return A List of strings
|
||||||
|
*/
|
||||||
|
List<String> getPersistentPropertyNames();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the name of the class decapitalized form
|
||||||
|
*/
|
||||||
|
String getDecapitalizedName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the specified entity asserts ownership over this
|
||||||
|
* entity
|
||||||
|
*
|
||||||
|
* @param owner The owning entity
|
||||||
|
* @return True if it does own this entity
|
||||||
|
*/
|
||||||
|
boolean isOwningEntity(PersistentEntity<?> owner);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the parent entity of this entity
|
||||||
|
*
|
||||||
|
* @return The ParentEntity instance
|
||||||
|
*/
|
||||||
|
PersistentEntity<?> getParentEntity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the root entity of an inheritance hierarchy
|
||||||
|
*
|
||||||
|
* @return The root entity
|
||||||
|
*/
|
||||||
|
PersistentEntity<?> getRootEntity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this entity is a root entity
|
||||||
|
*
|
||||||
|
* @return True if it is a root entity
|
||||||
|
*/
|
||||||
|
boolean isRoot();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The discriminator used when persisting subclasses of an inheritance hierarchy
|
||||||
|
*
|
||||||
|
* @return The discriminator
|
||||||
|
*/
|
||||||
|
String getDiscriminator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the MappingContext where this PersistentEntity is defined
|
||||||
|
*
|
||||||
|
* @return The MappingContext instance
|
||||||
|
*/
|
||||||
|
MappingContext getMappingContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether an entity has a bean property of the given name and type
|
||||||
|
*
|
||||||
|
* @param name The name
|
||||||
|
* @param type The type
|
||||||
|
* @return True if it does
|
||||||
|
*/
|
||||||
|
boolean hasProperty(String name, Class<?> type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the given property is the identifier
|
||||||
|
*
|
||||||
|
* @param propertyName the property name
|
||||||
|
* @return True if it is the identifier
|
||||||
|
*/
|
||||||
|
boolean isIdentityName(String propertyName);
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package org.springframework.data.mapping.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public interface PersistentProperty<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the property
|
||||||
|
*
|
||||||
|
* @return The property name
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name with the first letter in upper case as per Java bean conventions
|
||||||
|
*
|
||||||
|
* @return The capitilized name
|
||||||
|
*/
|
||||||
|
String getCapitilizedName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the property
|
||||||
|
*
|
||||||
|
* @return The property type
|
||||||
|
*/
|
||||||
|
Class<T> getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the mapping between this property and an external form
|
||||||
|
* such as a column, key/value pair etc.
|
||||||
|
*
|
||||||
|
* @return The PropertyMapping instance
|
||||||
|
*/
|
||||||
|
PropertyMapping<T> getMapping();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the owner of this persistent property
|
||||||
|
*
|
||||||
|
* @return The owner
|
||||||
|
*/
|
||||||
|
PersistentEntity<?> getOwner();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the property can be set to null
|
||||||
|
*
|
||||||
|
* @return True if it can
|
||||||
|
*/
|
||||||
|
boolean isNullable();
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package org.springframework.data.mapping.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A marker interface for a property mapping which specifies
|
||||||
|
* what or where a particular property is mapped to
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public interface PropertyMapping<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the ClassMapping instance of the owning class
|
||||||
|
*
|
||||||
|
* @return The ClassMapping instance
|
||||||
|
*/
|
||||||
|
ClassMapping getClassMapping();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the mapped form of the property such as a Column, a Key/Value pair, attribute etc.
|
||||||
|
* @return The mapped representation
|
||||||
|
*/
|
||||||
|
T getMappedForm();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.model.types;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.*;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models an association between one class and another
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class Association<T> extends AbstractPersistentProperty {
|
||||||
|
|
||||||
|
public static final List<CascadeType> DEFAULT_OWNER_CASCADE = new ArrayList<CascadeType>() {{
|
||||||
|
add(CascadeType.ALL);
|
||||||
|
}};
|
||||||
|
|
||||||
|
public static final List<CascadeType> DEFAULT_CHILD_CASCADE = new ArrayList<CascadeType>() {{
|
||||||
|
add(CascadeType.PERSIST);
|
||||||
|
}};
|
||||||
|
|
||||||
|
private PersistentEntity associatedEntity;
|
||||||
|
private String referencedPropertyName;
|
||||||
|
private boolean owningSide;
|
||||||
|
private List<CascadeType> cascadeOperations = new ArrayList<CascadeType>();
|
||||||
|
private FetchType fetchStrategy = FetchType.EAGER;
|
||||||
|
|
||||||
|
public Association(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) {
|
||||||
|
super(owner, context, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Association(PersistentEntity owner, MappingContext context, String name, Class type) {
|
||||||
|
super(owner, context, name, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FetchType getFetchStrategy() {
|
||||||
|
return fetchStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFetchStrategy(FetchType fetchStrategy) {
|
||||||
|
this.fetchStrategy = fetchStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBidirectional() {
|
||||||
|
return getInverseSide() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Association getInverseSide() {
|
||||||
|
final PersistentProperty associatedProperty = associatedEntity.getPropertyByName(referencedPropertyName);
|
||||||
|
if(associatedProperty == null) return null;
|
||||||
|
if(associatedProperty instanceof Association) {
|
||||||
|
return (Association) associatedProperty;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalMappingException("The inverse side ["+associatedEntity.getName()+"." + associatedProperty.getName() +"] of the association ["+getOwner().getName()+"." + this.getName() +"] is not valid. Associations can only map to other entities and collection types.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the this association cascade for the given cascade operation
|
||||||
|
*
|
||||||
|
* @param cascadeOperation The cascadeOperation
|
||||||
|
* @return True if it does
|
||||||
|
*/
|
||||||
|
public boolean doesCascade(CascadeType cascadeOperation) {
|
||||||
|
List<CascadeType> cascades = getCascadeOperations();
|
||||||
|
return cascadeOperation != null && (cascades.contains(CascadeType.ALL) || cascades.contains(cascadeOperation));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<CascadeType> getCascadeOperations() {
|
||||||
|
List<CascadeType> cascades;
|
||||||
|
if(cascadeOperations.isEmpty()) {
|
||||||
|
if(isOwningSide()) cascades = DEFAULT_OWNER_CASCADE;
|
||||||
|
else {
|
||||||
|
cascades = DEFAULT_CHILD_CASCADE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cascades = this.cascadeOperations;
|
||||||
|
}
|
||||||
|
return cascades;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this side owns the relationship. This controls
|
||||||
|
* the default cascading behavior if none is specified
|
||||||
|
*
|
||||||
|
* @return True if this property is the owning side
|
||||||
|
*/
|
||||||
|
public boolean isOwningSide() {
|
||||||
|
return owningSide;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwningSide(boolean owningSide) {
|
||||||
|
this.owningSide = owningSide;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssociatedEntity(PersistentEntity associatedEntity) {
|
||||||
|
this.associatedEntity = associatedEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistentEntity getAssociatedEntity() {
|
||||||
|
return associatedEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReferencedPropertyName(String referencedPropertyName) {
|
||||||
|
this.referencedPropertyName = referencedPropertyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReferencedPropertyName() {
|
||||||
|
return referencedPropertyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getOwner().getName() + "->" + getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isList() {
|
||||||
|
return List.class.isAssignableFrom(getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCircular() {
|
||||||
|
return isBidirectional() && getAssociatedEntity().equals(getOwner());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/* Copyright (C) 2011 SpringSource
|
||||||
|
*
|
||||||
|
* 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.mapping.model.types;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.MappingContext;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
import org.springframework.data.mapping.model.PropertyMapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models a basic collection type such as a list of Strings
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class Basic extends Association {
|
||||||
|
|
||||||
|
public Basic(PersistentEntity owner, MappingContext context,
|
||||||
|
PropertyDescriptor descriptor) {
|
||||||
|
super(owner, context, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Basic(PersistentEntity owner, MappingContext context, String name, Class type) {
|
||||||
|
super(owner, context, name, type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Association getInverseSide() {
|
||||||
|
return null; // basic collection types have no inverse side
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwningSide() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOwningSide(boolean owningSide) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PersistentEntity getAssociatedEntity() {
|
||||||
|
return null; // basic collection types have no associated entity
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
/* Copyright (C) 2010 SpringSource
|
||||||
|
*
|
||||||
|
* 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.mapping.model.types;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.core.convert.converter.ConverterRegistry;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A registrar that registers basic type converters
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public class BasicTypeConverterRegistrar {
|
||||||
|
|
||||||
|
public void register(ConverterRegistry registry) {
|
||||||
|
registry.addConverter(new Converter<Date, String>() {
|
||||||
|
public String convert(Date date) {
|
||||||
|
return String.valueOf(date.getTime());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
registry.addConverter(new Converter<Date, Calendar>() {
|
||||||
|
public Calendar convert(Date date) {
|
||||||
|
final GregorianCalendar calendar = new GregorianCalendar();
|
||||||
|
calendar.setTime(date);
|
||||||
|
return calendar;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
registry.addConverter(new Converter<Integer, Long>() {
|
||||||
|
public Long convert(Integer integer) {
|
||||||
|
return integer.longValue();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
registry.addConverter(new Converter<Integer, Double>() {
|
||||||
|
public Double convert(Integer integer) {
|
||||||
|
return integer.doubleValue();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
registry.addConverter(new Converter<CharSequence, Date>() {
|
||||||
|
|
||||||
|
public Date convert(CharSequence s) {
|
||||||
|
try {
|
||||||
|
final Long time = Long.valueOf(s.toString());
|
||||||
|
return new Date(time);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
registry.addConverter(new Converter<CharSequence, Double>() {
|
||||||
|
|
||||||
|
public Double convert(CharSequence s) {
|
||||||
|
try {
|
||||||
|
return Double.valueOf(s.toString());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return (double) 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
registry.addConverter(new Converter<CharSequence, Integer>() {
|
||||||
|
|
||||||
|
public Integer convert(CharSequence s) {
|
||||||
|
try {
|
||||||
|
return Integer.valueOf(s.toString());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
registry.addConverter(new Converter<CharSequence, Long>() {
|
||||||
|
|
||||||
|
public Long convert(CharSequence s) {
|
||||||
|
try {
|
||||||
|
return Long.valueOf(s.toString());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
registry.addConverter(new Converter<Object, String>() {
|
||||||
|
public String convert(Object o) {
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
registry.addConverter(new Converter<Calendar, String>() {
|
||||||
|
public String convert(Calendar calendar) {
|
||||||
|
return String.valueOf(calendar.getTime().getTime());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
registry.addConverter(new Converter<CharSequence, Calendar>() {
|
||||||
|
|
||||||
|
public Calendar convert(CharSequence s) {
|
||||||
|
try {
|
||||||
|
Date date = new Date(Long.valueOf(s.toString()));
|
||||||
|
Calendar c = new GregorianCalendar();
|
||||||
|
c.setTime(date);
|
||||||
|
return c;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.model.types;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.MappingContext;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models an embedded component
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class Embedded<T> extends ToOne<T> {
|
||||||
|
|
||||||
|
public Embedded(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) {
|
||||||
|
super(owner, context, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Embedded(PersistentEntity owner, MappingContext context, String name, Class type) {
|
||||||
|
super(owner, context, name, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOwningSide() {
|
||||||
|
return true; // embedded instances are always owned
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.model.types;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.AbstractPersistentProperty;
|
||||||
|
import org.springframework.data.mapping.model.MappingContext;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the identity of a persistent entity
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class Identity<T> extends AbstractPersistentProperty {
|
||||||
|
public Identity(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) {
|
||||||
|
super(owner, context, descriptor);
|
||||||
|
}
|
||||||
|
public Identity(PersistentEntity owner, MappingContext context, String name, Class type) {
|
||||||
|
super(owner, context, name, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/* Copyright (C) 2010 SpringSource
|
||||||
|
*
|
||||||
|
* 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.mapping.model.types;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.MappingContext;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models a many-to-many association between one class and another
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class ManyToMany<T> extends Association<T> {
|
||||||
|
public ManyToMany(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) {
|
||||||
|
super(owner, context, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ManyToMany(PersistentEntity owner, MappingContext context, String name, Class type) {
|
||||||
|
super(owner, context, name, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.model.types;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.MappingContext;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models a many-to-one association
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class ManyToOne<T> extends ToOne<T> {
|
||||||
|
public ManyToOne(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) {
|
||||||
|
super(owner, context, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ManyToOne(PersistentEntity owner, MappingContext context, String name, Class type) {
|
||||||
|
super(owner, context, name, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.model.types;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.MappingContext;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models a one-to-many association
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class OneToMany<T> extends Association<T> {
|
||||||
|
public OneToMany(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) {
|
||||||
|
super(owner, context, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OneToMany(PersistentEntity owner, MappingContext context, String name, Class type) {
|
||||||
|
super(owner, context, name, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.model.types;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.MappingContext;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models a one-to-one association
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class OneToOne<T> extends ToOne<T> {
|
||||||
|
public OneToOne(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) {
|
||||||
|
super(owner, context, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OneToOne(PersistentEntity owner, MappingContext context, String name, Class type) {
|
||||||
|
super(owner, context, name, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.model.types;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.AbstractPersistentProperty;
|
||||||
|
import org.springframework.data.mapping.model.MappingContext;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models a simple property type
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public abstract class Simple<T> extends AbstractPersistentProperty {
|
||||||
|
public Simple(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) {
|
||||||
|
super(owner, context, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Simple(PersistentEntity owner, MappingContext context, String name, Class type) {
|
||||||
|
super(owner, context, name, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/* Copyright (C) 2010 SpringSource
|
||||||
|
*
|
||||||
|
* 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.mapping.model.types;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.model.MappingContext;
|
||||||
|
import org.springframework.data.mapping.model.PersistentEntity;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.1
|
||||||
|
*/
|
||||||
|
public abstract class ToOne<T> extends Association<T> {
|
||||||
|
|
||||||
|
private boolean foreignKeyInChild;
|
||||||
|
|
||||||
|
public ToOne(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) {
|
||||||
|
super(owner, context, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ToOne(PersistentEntity owner, MappingContext context, String name, Class type) {
|
||||||
|
super(owner, context, name, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setForeignKeyInChild(boolean foreignKeyInChild) {
|
||||||
|
this.foreignKeyInChild = foreignKeyInChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isForeignKeyInChild() {
|
||||||
|
return foreignKeyInChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,372 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.reflect;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.data.mapping.annotation.PersistenceConstructor;
|
||||||
|
|
||||||
|
import java.beans.IntrospectionException;
|
||||||
|
import java.beans.Introspector;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the properties of a class in an optimized manner avoiding
|
||||||
|
* exceptions
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public class ClassPropertyFetcher {
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(ClassPropertyFetcher.class);
|
||||||
|
|
||||||
|
private final Class clazz;
|
||||||
|
final Map<String, PropertyFetcher> staticFetchers = new HashMap<String, PropertyFetcher>();
|
||||||
|
final Map<String, PropertyFetcher> instanceFetchers = new HashMap<String, PropertyFetcher>();
|
||||||
|
private final ReferenceInstanceCallback callback;
|
||||||
|
private PropertyDescriptor[] propertyDescriptors;
|
||||||
|
private Constructor preferredConstructor;
|
||||||
|
private Map<String, PropertyDescriptor> propertyDescriptorsByName = new HashMap<String, PropertyDescriptor>();
|
||||||
|
private Map<String, Field> fieldsByName = new HashMap<String, Field>();
|
||||||
|
private Map<Class, List<PropertyDescriptor>> typeToPropertyMap = new HashMap<Class, List<PropertyDescriptor>>();
|
||||||
|
|
||||||
|
private static Map<Class, ClassPropertyFetcher> cachedClassPropertyFetchers = new WeakHashMap<Class, ClassPropertyFetcher>();
|
||||||
|
|
||||||
|
public static ClassPropertyFetcher forClass(final Class c) {
|
||||||
|
ClassPropertyFetcher cpf = cachedClassPropertyFetchers.get(c);
|
||||||
|
if (cpf == null) {
|
||||||
|
cpf = new ClassPropertyFetcher(c);
|
||||||
|
cachedClassPropertyFetchers.put(c, cpf);
|
||||||
|
}
|
||||||
|
return cpf;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassPropertyFetcher(final Class clazz) {
|
||||||
|
this.clazz = clazz;
|
||||||
|
this.callback = new ReferenceInstanceCallback() {
|
||||||
|
public Object getReferenceInstance() {
|
||||||
|
try {
|
||||||
|
return ReflectionUtils.instantiate(clazz);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The Java that this ClassPropertyFetcher was constructor for
|
||||||
|
*/
|
||||||
|
public Class getJavaClass() {
|
||||||
|
return this.clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getReference() {
|
||||||
|
if (callback != null)
|
||||||
|
return this.callback.getReferenceInstance();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PropertyDescriptor[] getPropertyDescriptors() {
|
||||||
|
return propertyDescriptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReadableProperty(String name) {
|
||||||
|
return staticFetchers.containsKey(name) || instanceFetchers.containsKey(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
|
||||||
|
List<Class> allClasses = resolveAllClasses(clazz);
|
||||||
|
for (Class c : allClasses) {
|
||||||
|
Field[] fields = c.getDeclaredFields();
|
||||||
|
for (Field field : fields) {
|
||||||
|
processField(field);
|
||||||
|
}
|
||||||
|
Method[] methods = c.getDeclaredMethods();
|
||||||
|
for (Method method : methods) {
|
||||||
|
processMethod(method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.propertyDescriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
|
||||||
|
} catch (IntrospectionException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
if (propertyDescriptors != null) {
|
||||||
|
for (PropertyDescriptor desc : propertyDescriptors) {
|
||||||
|
propertyDescriptorsByName.put(desc.getName(), desc);
|
||||||
|
final Class<?> propertyType = desc.getPropertyType();
|
||||||
|
List<PropertyDescriptor> pds = typeToPropertyMap.get(propertyType);
|
||||||
|
if (pds == null) {
|
||||||
|
pds = new ArrayList<PropertyDescriptor>();
|
||||||
|
typeToPropertyMap.put(propertyType, pds);
|
||||||
|
}
|
||||||
|
pds.add(desc);
|
||||||
|
|
||||||
|
Method readMethod = desc.getReadMethod();
|
||||||
|
if (readMethod != null) {
|
||||||
|
boolean staticReadMethod = Modifier.isStatic(readMethod.getModifiers());
|
||||||
|
if (staticReadMethod) {
|
||||||
|
staticFetchers.put(desc.getName(), new GetterPropertyFetcher(readMethod, staticReadMethod));
|
||||||
|
} else {
|
||||||
|
instanceFetchers.put(desc.getName(), new GetterPropertyFetcher(readMethod, staticReadMethod));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Constructor[] constructors = clazz.getConstructors();
|
||||||
|
if (constructors.length == 1 && constructors[0].getGenericParameterTypes().length > 0) {
|
||||||
|
preferredConstructor = constructors[0];
|
||||||
|
} else {
|
||||||
|
for (Constructor<?> c : constructors) {
|
||||||
|
if (c.isAnnotationPresent(PersistenceConstructor.class)) {
|
||||||
|
preferredConstructor = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> Constructor<T> getPreferredConstructor() {
|
||||||
|
return preferredConstructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processMethod(Method method) {
|
||||||
|
if (method.isSynthetic())
|
||||||
|
return;
|
||||||
|
if (!Modifier.isPublic(method.getModifiers()))
|
||||||
|
return;
|
||||||
|
if (Modifier.isStatic(method.getModifiers())
|
||||||
|
&& method.getReturnType() != Void.class) {
|
||||||
|
if (method.getParameterTypes().length == 0) {
|
||||||
|
String name = method.getName();
|
||||||
|
if (name.indexOf('$') == -1) {
|
||||||
|
if (name.length() > 3 && name.startsWith("get") && Character.isUpperCase(name.charAt(3))) {
|
||||||
|
name = name.substring(3);
|
||||||
|
} else if (name.length() > 2
|
||||||
|
&& name.startsWith("is")
|
||||||
|
&& Character.isUpperCase(name.charAt(2))
|
||||||
|
&& (method.getReturnType() == Boolean.class || method.getReturnType() == boolean.class)) {
|
||||||
|
name = name.substring(2);
|
||||||
|
}
|
||||||
|
PropertyFetcher fetcher = new GetterPropertyFetcher(method, true);
|
||||||
|
staticFetchers.put(name, fetcher);
|
||||||
|
staticFetchers.put(Introspector.decapitalize(name), fetcher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processField(Field field) {
|
||||||
|
if (field.isSynthetic())
|
||||||
|
return;
|
||||||
|
final int modifiers = field.getModifiers();
|
||||||
|
final String name = field.getName();
|
||||||
|
if (!Modifier.isPublic(modifiers)) {
|
||||||
|
if (name.indexOf('$') == -1) {
|
||||||
|
fieldsByName.put(name, field);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (name.indexOf('$') == -1) {
|
||||||
|
boolean staticField = Modifier.isStatic(modifiers);
|
||||||
|
if (staticField) {
|
||||||
|
staticFetchers.put(name, new FieldReaderFetcher(field, staticField));
|
||||||
|
} else {
|
||||||
|
instanceFetchers.put(name, new FieldReaderFetcher(field, staticField));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Class> resolveAllClasses(Class c) {
|
||||||
|
List<Class> list = new ArrayList<Class>();
|
||||||
|
Class currentClass = c;
|
||||||
|
while (currentClass != null) {
|
||||||
|
list.add(currentClass);
|
||||||
|
currentClass = currentClass.getSuperclass();
|
||||||
|
}
|
||||||
|
Collections.reverse(list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getPropertyValue(String name) {
|
||||||
|
return getPropertyValue(name, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getPropertyValue(String name, boolean onlyInstanceProperties) {
|
||||||
|
PropertyFetcher fetcher = resolveFetcher(name, onlyInstanceProperties);
|
||||||
|
return getPropertyValueWithFetcher(name, fetcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getPropertyValueWithFetcher(String name, PropertyFetcher fetcher) {
|
||||||
|
if (fetcher != null) {
|
||||||
|
try {
|
||||||
|
return fetcher.get(callback);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Error fetching property's " + name + " value from class " + clazz.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T getStaticPropertyValue(String name, Class<T> c) {
|
||||||
|
PropertyFetcher fetcher = staticFetchers.get(name);
|
||||||
|
if (fetcher != null) {
|
||||||
|
Object v = getPropertyValueWithFetcher(name, fetcher);
|
||||||
|
return returnOnlyIfInstanceOf(v, c);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T getPropertyValue(String name, Class<T> c) {
|
||||||
|
return returnOnlyIfInstanceOf(getPropertyValue(name, false), c);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T returnOnlyIfInstanceOf(Object value, Class<T> type) {
|
||||||
|
if ((value != null) && (type == Object.class || ReflectionUtils.isAssignableFrom(type, value.getClass()))) {
|
||||||
|
return (T) value;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private PropertyFetcher resolveFetcher(String name,
|
||||||
|
boolean onlyInstanceProperties) {
|
||||||
|
PropertyFetcher fetcher = null;
|
||||||
|
if (!onlyInstanceProperties) {
|
||||||
|
fetcher = staticFetchers.get(name);
|
||||||
|
}
|
||||||
|
if (fetcher == null) {
|
||||||
|
fetcher = instanceFetchers.get(name);
|
||||||
|
}
|
||||||
|
return fetcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getPropertyType(String name) {
|
||||||
|
return getPropertyType(name, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getPropertyType(String name, boolean onlyInstanceProperties) {
|
||||||
|
PropertyFetcher fetcher = resolveFetcher(name, onlyInstanceProperties);
|
||||||
|
if (fetcher != null) {
|
||||||
|
return fetcher.getPropertyType(name);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PropertyDescriptor getPropertyDescriptor(String name) {
|
||||||
|
return propertyDescriptorsByName.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PropertyDescriptor> getPropertiesOfType(Class javaClass) {
|
||||||
|
final List<PropertyDescriptor> propertyDescriptorList = typeToPropertyMap.get(javaClass);
|
||||||
|
if (propertyDescriptorList == null) return Collections.emptyList();
|
||||||
|
return propertyDescriptorList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PropertyDescriptor> getPropertiesAssignableToType(Class assignableType) {
|
||||||
|
List<PropertyDescriptor> properties = new ArrayList<PropertyDescriptor>();
|
||||||
|
for (Class type : typeToPropertyMap.keySet()) {
|
||||||
|
if (assignableType.isAssignableFrom(type)) {
|
||||||
|
properties.addAll(typeToPropertyMap.get(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static interface ReferenceInstanceCallback {
|
||||||
|
public Object getReferenceInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
static interface PropertyFetcher {
|
||||||
|
public Object get(ReferenceInstanceCallback callback)
|
||||||
|
throws IllegalArgumentException, IllegalAccessException,
|
||||||
|
InvocationTargetException;
|
||||||
|
|
||||||
|
public Class getPropertyType(String name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class GetterPropertyFetcher implements PropertyFetcher {
|
||||||
|
private final Method readMethod;
|
||||||
|
private final boolean staticMethod;
|
||||||
|
|
||||||
|
GetterPropertyFetcher(Method readMethod, boolean staticMethod) {
|
||||||
|
this.readMethod = readMethod;
|
||||||
|
this.staticMethod = staticMethod;
|
||||||
|
ReflectionUtils.makeAccessible(readMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object get(ReferenceInstanceCallback callback)
|
||||||
|
throws IllegalArgumentException, IllegalAccessException,
|
||||||
|
InvocationTargetException {
|
||||||
|
if (staticMethod) {
|
||||||
|
return readMethod.invoke(null, (Object[]) null);
|
||||||
|
} else {
|
||||||
|
if (callback != null) {
|
||||||
|
return readMethod.invoke(callback.getReferenceInstance(),
|
||||||
|
(Object[]) null);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getPropertyType(String name) {
|
||||||
|
return readMethod.getReturnType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class FieldReaderFetcher implements PropertyFetcher {
|
||||||
|
private final Field field;
|
||||||
|
private final boolean staticField;
|
||||||
|
|
||||||
|
public FieldReaderFetcher(Field field, boolean staticField) {
|
||||||
|
this.field = field;
|
||||||
|
this.staticField = staticField;
|
||||||
|
ReflectionUtils.makeAccessible(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object get(ReferenceInstanceCallback callback)
|
||||||
|
throws IllegalArgumentException, IllegalAccessException,
|
||||||
|
InvocationTargetException {
|
||||||
|
if (staticField) {
|
||||||
|
return field.get(null);
|
||||||
|
} else {
|
||||||
|
if (callback != null) {
|
||||||
|
return field.get(callback.getReferenceInstance());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getPropertyType(String name) {
|
||||||
|
return field.getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field getDeclaredField(String name) {
|
||||||
|
return fieldsByName.get(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
/* Copyright 2004-2005 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.mapping.reflect;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.lang.Boolean;
|
||||||
|
import java.lang.Byte;
|
||||||
|
import java.lang.Character;
|
||||||
|
import java.lang.Class;
|
||||||
|
import java.lang.Double;
|
||||||
|
import java.lang.Exception;
|
||||||
|
import java.lang.Float;
|
||||||
|
import java.lang.IllegalAccessException;
|
||||||
|
import java.lang.InstantiationException;
|
||||||
|
import java.lang.Integer;
|
||||||
|
import java.lang.Long;
|
||||||
|
import java.lang.NoSuchMethodException;
|
||||||
|
import java.lang.NullPointerException;
|
||||||
|
import java.lang.Object;
|
||||||
|
import java.lang.Short;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides methods to help with reflective operations
|
||||||
|
*
|
||||||
|
* @author Graeme Rocher
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public class ReflectionUtils {
|
||||||
|
|
||||||
|
public static final Map<Class<?>, Class<?>> PRIMITIVE_TYPE_COMPATIBLE_CLASSES = new HashMap<Class<?>, Class<?>>();
|
||||||
|
private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just add two entries to the class compatibility map
|
||||||
|
*
|
||||||
|
* @param left
|
||||||
|
* @param right
|
||||||
|
*/
|
||||||
|
private static void registerPrimitiveClassPair(Class<?> left, Class<?> right) {
|
||||||
|
PRIMITIVE_TYPE_COMPATIBLE_CLASSES.put(left, right);
|
||||||
|
PRIMITIVE_TYPE_COMPATIBLE_CLASSES.put(right, left);
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
registerPrimitiveClassPair(Boolean.class, boolean.class);
|
||||||
|
registerPrimitiveClassPair(Integer.class, int.class);
|
||||||
|
registerPrimitiveClassPair(Short.class, short.class);
|
||||||
|
registerPrimitiveClassPair(Byte.class, byte.class);
|
||||||
|
registerPrimitiveClassPair(Character.class, char.class);
|
||||||
|
registerPrimitiveClassPair(Long.class, long.class);
|
||||||
|
registerPrimitiveClassPair(Float.class, float.class);
|
||||||
|
registerPrimitiveClassPair(Double.class, double.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the given field accessible, explicitly setting it accessible if necessary.
|
||||||
|
* The <code>setAccessible(true)</code> method is only called when actually necessary,
|
||||||
|
* to avoid unnecessary conflicts with a JVM SecurityManager (if active).
|
||||||
|
* <p/>
|
||||||
|
* Based on the same method in Spring core.
|
||||||
|
*
|
||||||
|
* @param field the field to make accessible
|
||||||
|
* @see java.lang.reflect.Field#setAccessible
|
||||||
|
*/
|
||||||
|
public static void makeAccessible(Field field) {
|
||||||
|
if (!Modifier.isPublic(field.getModifiers()) ||
|
||||||
|
!Modifier.isPublic(field.getDeclaringClass().getModifiers())) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the given method accessible, explicitly setting it accessible if necessary.
|
||||||
|
* The <code>setAccessible(true)</code> method is only called when actually necessary,
|
||||||
|
* to avoid unnecessary conflicts with a JVM SecurityManager (if active).
|
||||||
|
* <p/>
|
||||||
|
* Based on the same method in Spring core.
|
||||||
|
*
|
||||||
|
* @param method the method to make accessible
|
||||||
|
* @see java.lang.reflect.Method#setAccessible
|
||||||
|
*/
|
||||||
|
public static void makeAccessible(Method method) {
|
||||||
|
if (!Modifier.isPublic(method.getModifiers()) ||
|
||||||
|
!Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
|
||||||
|
method.setAccessible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Tests whether or not the left hand type is compatible with the right hand type in Groovy
|
||||||
|
* terms, i.e. can the left type be assigned a value of the right hand type in Groovy.</p>
|
||||||
|
* <p>This handles Java primitive type equivalence and uses isAssignableFrom for all other types,
|
||||||
|
* with a bit of magic for native types and polymorphism i.e. Number assigned an int.
|
||||||
|
* If either parameter is null an exception is thrown</p>
|
||||||
|
*
|
||||||
|
* @param leftType The type of the left hand part of a notional assignment
|
||||||
|
* @param rightType The type of the right hand part of a notional assignment
|
||||||
|
* @return True if values of the right hand type can be assigned in Groovy to variables of the left hand type.
|
||||||
|
*/
|
||||||
|
public static boolean isAssignableFrom(final Class<?> leftType, final Class<?> rightType) {
|
||||||
|
if (leftType == null) {
|
||||||
|
throw new NullPointerException("Left type is null!");
|
||||||
|
}
|
||||||
|
if (rightType == null) {
|
||||||
|
throw new NullPointerException("Right type is null!");
|
||||||
|
}
|
||||||
|
if (leftType == Object.class) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (leftType == rightType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// check for primitive type equivalence
|
||||||
|
Class<?> r = PRIMITIVE_TYPE_COMPATIBLE_CLASSES.get(leftType);
|
||||||
|
boolean result = r == rightType;
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
// If no primitive <-> wrapper match, it may still be assignable
|
||||||
|
// from polymorphic primitives i.e. Number -> int (AKA Integer)
|
||||||
|
if (rightType.isPrimitive()) {
|
||||||
|
// see if incompatible
|
||||||
|
r = PRIMITIVE_TYPE_COMPATIBLE_CLASSES.get(rightType);
|
||||||
|
if (r != null) {
|
||||||
|
result = leftType.isAssignableFrom(r);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Otherwise it may just be assignable using normal Java polymorphism
|
||||||
|
result = leftType.isAssignableFrom(rightType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates an object catching any relevant exceptions and rethrowing as a runtime exception
|
||||||
|
*
|
||||||
|
* @param clazz The class
|
||||||
|
* @return The instantiated object or null if the class parameter was null
|
||||||
|
*/
|
||||||
|
public static Object instantiate(Class clazz) throws InstantiationException {
|
||||||
|
if (clazz == null) return null;
|
||||||
|
try {
|
||||||
|
return clazz.getConstructor(EMPTY_CLASS_ARRAY).newInstance();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new InstantiationException(e.getClass().getName() + " error creating instance of class [" + e.getMessage() + "]: " + e.getMessage());
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new InstantiationException(e.getClass().getName() + " error creating instance of class [" + e.getMessage() + "]: " + e.getMessage());
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new InstantiationException(e.getClass().getName() + " error creating instance of class [" + e.getMessage() + "]: " + e.getMessage());
|
||||||
|
} catch (java.lang.InstantiationException e) {
|
||||||
|
throw new InstantiationException(e.getClass().getName() + " error creating instance of class [" + e.getMessage() + "]: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all the properties of the given class for the given type
|
||||||
|
*
|
||||||
|
* @param clazz The class to retrieve the properties from
|
||||||
|
* @param propertyType The type of the properties you wish to retrieve
|
||||||
|
* @return An array of PropertyDescriptor instances
|
||||||
|
*/
|
||||||
|
public static PropertyDescriptor[] getPropertiesOfType(Class<?> clazz, Class<?> propertyType) {
|
||||||
|
if (clazz == null || propertyType == null) {
|
||||||
|
return new PropertyDescriptor[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<PropertyDescriptor> properties = new HashSet<PropertyDescriptor>();
|
||||||
|
try {
|
||||||
|
for (PropertyDescriptor descriptor : BeanUtils.getPropertyDescriptors(clazz)) {
|
||||||
|
Class<?> currentPropertyType = descriptor.getPropertyType();
|
||||||
|
if (isTypeInstanceOfPropertyType(propertyType, currentPropertyType)) {
|
||||||
|
properties.add(descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// if there are any errors in instantiating just return null for the moment
|
||||||
|
return new PropertyDescriptor[0];
|
||||||
|
}
|
||||||
|
return properties.toArray(new PropertyDescriptor[properties.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isTypeInstanceOfPropertyType(Class<?> type, Class<?> propertyType) {
|
||||||
|
return propertyType.isAssignableFrom(type) && !propertyType.equals(Object.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@ import org.springframework.dao.DataAccessException;
|
|||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
|
import org.springframework.data.document.mongodb.convert.MongoConverter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for unit tests to specify behaviour we expect from {@link MongoOperations}. Subclasses return
|
* Abstract base class for unit tests to specify behaviour we expect from {@link MongoOperations}. Subclasses return
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import org.springframework.data.document.mongodb.query.Index.Duplicates;
|
|||||||
import org.springframework.data.document.mongodb.query.Order;
|
import org.springframework.data.document.mongodb.query.Order;
|
||||||
import org.springframework.data.document.mongodb.query.Query;
|
import org.springframework.data.document.mongodb.query.Query;
|
||||||
import org.springframework.data.document.mongodb.query.Update;
|
import org.springframework.data.document.mongodb.query.Update;
|
||||||
|
import org.springframework.data.document.mongodb.convert.MongoConverter;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
|
import org.springframework.data.document.mongodb.convert.SimpleMongoConverter;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
|
||||||
import com.mongodb.DB;
|
import com.mongodb.DB;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.data.document.mongodb.SomeEnumTest.NumberEnum;
|
import org.springframework.data.document.mongodb.SomeEnumTest.NumberEnum;
|
||||||
import org.springframework.data.document.mongodb.SomeEnumTest.StringEnum;
|
import org.springframework.data.document.mongodb.SomeEnumTest.StringEnum;
|
||||||
|
import org.springframework.data.document.mongodb.convert.SimpleMongoConverter;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
import org.springframework.data.mapping.annotation.Id;
|
||||||
|
import org.springframework.data.mapping.annotation.Persistent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Persistent
|
||||||
|
public class Account {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String id;
|
||||||
|
private Float balance;
|
||||||
|
|
||||||
|
public Float getBalance() {
|
||||||
|
return balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBalance(Float balance) {
|
||||||
|
this.balance = balance;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
public class Address implements Serializable {
|
||||||
|
|
||||||
|
private String[] lines;
|
||||||
|
private String city;
|
||||||
|
private String provinceOrState;
|
||||||
|
private Integer postalCode;
|
||||||
|
private String country;
|
||||||
|
|
||||||
|
public String[] getLines() {
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLines(String[] lines) {
|
||||||
|
this.lines = lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCity() {
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCity(String city) {
|
||||||
|
this.city = city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProvinceOrState() {
|
||||||
|
return provinceOrState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProvinceOrState(String provinceOrState) {
|
||||||
|
this.provinceOrState = provinceOrState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPostalCode() {
|
||||||
|
return postalCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPostalCode(Integer postalCode) {
|
||||||
|
this.postalCode = postalCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCountry() {
|
||||||
|
return country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountry(String country) {
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
import com.mongodb.DBObject;
|
||||||
|
import com.mongodb.util.JSON;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.document.mongodb.MongoTemplate;
|
||||||
|
import org.springframework.data.document.mongodb.convert.MongoConverter;
|
||||||
|
import org.springframework.data.document.mongodb.query.Criteria;
|
||||||
|
import org.springframework.data.document.mongodb.query.Index;
|
||||||
|
import org.springframework.data.document.mongodb.query.IndexDefinition;
|
||||||
|
import org.springframework.data.document.mongodb.query.Query;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration("classpath:mapping.xml")
|
||||||
|
public class MappingTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
MongoTemplate template;
|
||||||
|
@Autowired
|
||||||
|
MongoMappingContext mappingContext;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ExpectedException thrown = ExpectedException.none();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setUp() {
|
||||||
|
template.dropCollection(template.getDefaultCollectionName());
|
||||||
|
mappingContext.addPersistentEntity(Person.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWrite() {
|
||||||
|
Person p = new Person(123456789, "John", "Doe", 37);
|
||||||
|
|
||||||
|
Address addr = new Address();
|
||||||
|
addr.setLines(new String[]{"1234 W. 1st Street", "Apt. 12"});
|
||||||
|
addr.setCity("Anytown");
|
||||||
|
addr.setPostalCode(12345);
|
||||||
|
addr.setCountry("USA");
|
||||||
|
p.setAddress(addr);
|
||||||
|
|
||||||
|
Account acct = new Account();
|
||||||
|
acct.setBalance(1000.00f);
|
||||||
|
List<Account> accounts = new ArrayList<Account>();
|
||||||
|
accounts.add(acct);
|
||||||
|
p.setAccounts(accounts);
|
||||||
|
|
||||||
|
template.insert(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRead() {
|
||||||
|
MongoConverter converter = template.getConverter();
|
||||||
|
|
||||||
|
List<Person> result = template.find(new Query(Criteria.where("ssn").is(123456789)), Person.class);
|
||||||
|
assertThat(result.size(), is(1));
|
||||||
|
assertThat(result.get(0).getAddress().getCountry(), is("USA"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by the original author(s).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.data.document.mongodb.mapping;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.document.mongodb.MongoTemplate;
|
||||||
|
import org.springframework.data.document.mongodb.index.CompoundIndex;
|
||||||
|
import org.springframework.data.document.mongodb.index.CompoundIndexes;
|
||||||
|
import org.springframework.data.document.mongodb.index.Indexed;
|
||||||
|
import org.springframework.data.mapping.annotation.*;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||||
|
*/
|
||||||
|
@Persistent
|
||||||
|
@CompoundIndexes({
|
||||||
|
@CompoundIndex(name = "age_idx", def = "{'lastName': 1, 'age': -1}")
|
||||||
|
})
|
||||||
|
public class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String id;
|
||||||
|
@Indexed(unique = true)
|
||||||
|
private Integer ssn;
|
||||||
|
private String firstName;
|
||||||
|
@Indexed
|
||||||
|
private String lastName;
|
||||||
|
private Integer age;
|
||||||
|
@Transient
|
||||||
|
private Integer accountTotal;
|
||||||
|
@OneToMany
|
||||||
|
private List<Account> accounts;
|
||||||
|
private Address address;
|
||||||
|
|
||||||
|
public Person(Integer ssn, String firstName, String lastName, Integer age) {
|
||||||
|
this.ssn = ssn;
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PersistenceConstructor
|
||||||
|
public Person(Integer ssn, String firstName, String lastName, Integer age, List<Account> accounts, Address address) {
|
||||||
|
this.ssn = ssn;
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
this.age = age;
|
||||||
|
this.accounts = accounts;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSsn() {
|
||||||
|
return ssn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge(Integer age) {
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAccountTotal() {
|
||||||
|
return accountTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountTotal(Integer accountTotal) {
|
||||||
|
this.accountTotal = accountTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Account> getAccounts() {
|
||||||
|
return accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccounts(List<Account> accounts) {
|
||||||
|
this.accounts = accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddress(Address address) {
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
import org.springframework.data.document.mongodb.MongoConverter;
|
import org.springframework.data.document.mongodb.convert.MongoConverter;
|
||||||
import org.springframework.data.document.mongodb.Person;
|
import org.springframework.data.document.mongodb.Person;
|
||||||
import org.springframework.data.repository.query.parser.PartTree;
|
import org.springframework.data.repository.query.parser.PartTree;
|
||||||
|
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
import org.springframework.data.document.mongodb.MongoConverter;
|
import org.springframework.data.document.mongodb.convert.MongoConverter;
|
||||||
import org.springframework.data.document.mongodb.MongoTemplate;
|
import org.springframework.data.document.mongodb.MongoTemplate;
|
||||||
import org.springframework.data.document.mongodb.SimpleMongoConverter;
|
import org.springframework.data.document.mongodb.convert.SimpleMongoConverter;
|
||||||
import org.springframework.data.document.mongodb.query.BasicQuery;
|
import org.springframework.data.document.mongodb.query.BasicQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
||||||
|
|
||||||
<bean id="mongo" class="org.springframework.data.document.mongodb.MongoFactoryBean">
|
<bean id="mongo" class="org.springframework.data.document.mongodb.MongoFactoryBean">
|
||||||
<property name="host" value="localhost" />
|
<property name="host" value="localhost"/>
|
||||||
<property name="port" value="27017" />
|
<property name="port" value="27017"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
|
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
|
||||||
<constructor-arg ref="mongo" />
|
<constructor-arg ref="mongo"/>
|
||||||
<constructor-arg value="database" />
|
<constructor-arg value="database"/>
|
||||||
<property name="defaultCollectionName" value="springdata" />
|
<property name="defaultCollectionName" value="springdata"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean class="org.springframework.data.document.mongodb.MongoExceptionTranslator" />
|
<bean class="org.springframework.data.document.mongodb.MongoExceptionTranslator"/>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
|||||||
29
spring-data-mongodb/src/test/resources/mapping.xml
Normal file
29
spring-data-mongodb/src/test/resources/mapping.xml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
||||||
|
|
||||||
|
<bean id="mongo" class="org.springframework.data.document.mongodb.MongoFactoryBean">
|
||||||
|
<property name="host" value="localhost"/>
|
||||||
|
<property name="port" value="27017"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="mongoConverter" class="org.springframework.data.document.mongodb.convert.MappingMongoConverter">
|
||||||
|
<property name="mappingContext" ref="mappingContext"/>
|
||||||
|
<property name="autowirePersistentBeans" value="true"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
|
||||||
|
<constructor-arg ref="mongo"/>
|
||||||
|
<constructor-arg value="database"/>
|
||||||
|
<constructor-arg value="person"/>
|
||||||
|
<constructor-arg ref="mongoConverter"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="mappingContext" class="org.springframework.data.document.mongodb.mapping.MongoMappingContext">
|
||||||
|
<constructor-arg ref="mongoTemplate"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean class="org.springframework.data.document.mongodb.MongoExceptionTranslator"/>
|
||||||
|
|
||||||
|
</beans>
|
||||||
@@ -15,11 +15,17 @@ Import-Template:
|
|||||||
org.springframework.data.domain.*;version="[1.0.0, 2.0.0)",
|
org.springframework.data.domain.*;version="[1.0.0, 2.0.0)",
|
||||||
org.springframework.data.document.*;version="[1.0.0, 2.0.0)",
|
org.springframework.data.document.*;version="[1.0.0, 2.0.0)",
|
||||||
org.springframework.data.repository.*;version="[1.0.0, 2.0.0)",
|
org.springframework.data.repository.*;version="[1.0.0, 2.0.0)",
|
||||||
|
org.springframework.expression.*;version="[3.0.0, 4.0.0)",
|
||||||
|
org.springframework.expression.common.*;version="[3.0.0, 4.0.0)",
|
||||||
|
org.springframework.expression.spel.standard.*;version="[3.0.0, 4.0.0)",
|
||||||
|
org.springframework.expression.spel.support.*;version="[3.0.0, 4.0.0)",
|
||||||
|
org.springframework.validation.*;version="[3.0.0, 4.0.0)",
|
||||||
com.mongodb.*;version="0",
|
com.mongodb.*;version="0",
|
||||||
org.bson.*;version="0",
|
org.bson.*;version="0",
|
||||||
org.aopalliance.*;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.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||||
org.slf4j.*;version="[1.5.0,1.6.0)",
|
org.slf4j.*;version="[1.5.0,1.6.0)",
|
||||||
org.w3c.dom.*;version="0"
|
org.w3c.dom.*;version="0",
|
||||||
|
javax.persistence.*;version="0"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user