DATACMNS-266 - Use new common Maven build infrastructure.

Simplified project setup to be a single module build again. Using Spring Data Build parent POM to simplify project setup. See https://github.com/SpringSource/spring-data-build#spring-data-build-infrastructure
This commit is contained in:
Oliver Gierke
2013-01-11 12:13:47 +01:00
parent c908d0e023
commit ac256f9921
375 changed files with 215 additions and 3092 deletions

View File

@@ -1,48 +0,0 @@
<?xml version="1.0"?>
<project name="upload-dist-tasks">
<!-- can be run independent of maven as follows
- classpath must be uncommented below. when run from maven,
- the classpath is set up for you
ant -f src/ant/upload-dist.xml \
-Ddist.id=spring-data-commons \
-Ddist.name='Spring Datas Commons' \
-Ddist.key=DATADOC \
-Ddist.releaseType=milestone \
-Ddist.accessKey=<access key> \
-Ddist.secretKey=<secret key> \
-Ddist.bucketName=dist.springframework.org \
-Ddist.fileName=spring-data-commons-1.0.0.M1.zip \
-Ddist.filePath=../../spring-data-commons-1.0.0.M1.zip \
-Ddist.version=1.0.0.M1 \
upload-dist
-->
<taskdef resource="org/springframework/build/aws/ant/antlib.xml">
<!-- see comment above
<classpath>
<pathelement location="/Users/cbeams/Desktop/org.springframework.build.aws.ant-3.0.5.RELEASE.jar"/>
<pathelement location="/Users/cbeams/.m2/repository/net/java/dev/jets3t/jets3t/0.7.2/jets3t-0.7.2.jar"/>
<pathelement location="/Users/cbeams/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar"/>
<pathelement location="/Users/cbeams/.m2/repository/commons-httpclient/commons-httpclient/3.1/commons-httpclient-3.1.jar"/>
<pathelement location="/Users/cbeams/.m2/repository/commons-codec/commons-codec/1.3/commons-codec-1.3.jar"/>
</classpath>
-->
</taskdef>
<target name="upload-dist">
<checksum file="${dist.filePath}" algorithm="sha1"/>
<s3 accessKey="${dist.accessKey}" secretKey="${dist.secretKey}">
<upload bucketName="${dist.bucketName}" file="${dist.filePath}"
toFile="${dist.releaseType}/${dist.key}/${dist.fileName}" publicRead="true">
<metadata name="project.name" value="${dist.name}"/>
<metadata name="release.type" value="${dist.releaseType}"/>
<metadata name="bundle.version" value="${dist.version}"/>
<metadata name="package.file.name" value="${dist.fileName}"/>
</upload>
<upload bucketName="${dist.bucketName}" file="${dist.filePath}.sha1"
toFile="${dist.releaseType}/${dist.key}/${dist.fileName}.sha1" publicRead="true">
</upload>
</s3>
</target>
</project>

View File

@@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<assembly>
<!-- distribution assembly descriptor. packages up jars, source jars, documentation,
dependencies and other resources into a single archive suitable for download and
standalone use.
see pom.xml 'maven-assembly-plugin' declaration
see src/main/scripts/build-distribution.sh
see http://www.sonatype.com/books/mvnref-book/reference/assemblies-set-dist-assemblies.html -->
<id>distribution</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<!-- adds readme and other textfiles to the root of the distribution archive -->
<directory>src/main/resources</directory>
<includes>
<include>readme.txt</include>
<include>license.txt</include>
<include>notice.txt</include>
<include>changelog.txt</include>
</includes>
<outputDirectory/>
<lineEnding>dos</lineEnding>
</fileSet>
<fileSet>
<!-- adds reference manual (html and pdf) to the distribution archive under the
'docs/reference' directory
see pom.xml 'maven-javadoc-plugin' declaration -->
<directory>target/site/reference</directory>
<outputDirectory>docs/reference</outputDirectory>
</fileSet>
<fileSet>
<!-- adds javadoc html to the distribution archive under the 'docs/javadoc' directory
see pom.xml 'maven-javadoc-plugin' declaration -->
<directory>target/site/apidocs</directory>
<outputDirectory>docs/javadoc</outputDirectory>
</fileSet>
</fileSets>
<moduleSets>
<moduleSet>
<!-- adds module jars to the distribution archive under the 'dist' directory -->
<includes>
<include>org.springframework.data:spring-data-commons-core</include>
</includes>
<binaries>
<outputDirectory>dist</outputDirectory>
<includeDependencies>false</includeDependencies>
<unpack>false</unpack>
</binaries>
</moduleSet>
<moduleSet>
<!-- adds module source jars to the distribution archive under the 'src' directory
see pom.xml 'maven-source-plugin' declaration -->
<includes>
<include>org.springframework.data:spring-data-commons-core</include>
</includes>
<binaries>
<attachmentClassifier>sources</attachmentClassifier>
<outputDirectory>src</outputDirectory>
<includeDependencies>false</includeDependencies>
<unpack>false</unpack>
</binaries>
</moduleSet>
</moduleSets>
</assembly>

View File

@@ -1,35 +0,0 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -1,421 +0,0 @@
body {
text-align: justify;
margin-right: 2em;
margin-left: 2em;
}
a,
a[accesskey^
=
"h"
]
,
a[accesskey^
=
"n"
]
,
a[accesskey^
=
"u"
]
,
a[accesskey^
=
"p"
]
{
font-family: Verdana, Arial, helvetica, sans-serif
;
font-size:
12
px
;
color: #003399
;
}
a:active {
color: #003399;
}
a:visited {
color: #888888;
}
p {
font-family: Verdana, Arial, sans-serif;
}
dt {
font-family: Verdana, Arial, sans-serif;
font-size: 12px;
}
p, dl, dt, dd, blockquote {
color: #000000;
margin-bottom: 3px;
margin-top: 3px;
padding-top: 0px;
}
ol, ul, p {
margin-top: 6px;
margin-bottom: 6px;
}
p, blockquote {
font-size: 90%;
}
p.releaseinfo {
font-size: 100%;
font-weight: bold;
font-family: Verdana, Arial, helvetica, sans-serif;
padding-top: 10px;
}
p.pubdate {
font-size: 120%;
font-weight: bold;
font-family: Verdana, Arial, helvetica, sans-serif;
}
td {
font-size: 80%;
}
td, th, span {
color: #000000;
}
td[width^
=
"40%"
]
{
font-family: Verdana, Arial, helvetica, sans-serif
;
font-size:
12
px
;
color: #003399
;
}
table[summary^
=
"Navigation header"
]
tbody tr th[colspan^
=
"3"
]
{
font-family: Verdana, Arial, helvetica, sans-serif
;
}
blockquote {
margin-right: 0px;
}
h1, h2, h3, h4, h6, H6 {
color: #000000;
font-weight: 500;
margin-top: 0px;
padding-top: 14px;
font-family: Verdana, Arial, helvetica, sans-serif;
margin-bottom: 0px;
}
h2.title {
font-weight: 800;
margin-bottom: 8px;
}
h2.subtitle {
font-weight: 800;
margin-bottom: 20px;
}
.firstname, .surname {
font-size: 12px;
font-family: Verdana, Arial, helvetica, sans-serif;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px black;
empty-cells: hide;
margin: 10px 0px 30px 50px;
width: 90%;
}
div.table {
margin: 30px 0px 30px 0px;
border: 1px dashed gray;
padding: 10px;
}
div .table-contents table {
border: 1px solid black;
}
div.table > p.title {
padding-left: 10px;
}
table[summary^
=
"Navigation footer"
]
{
border-collapse: collapse
;
border-spacing:
0
;
border:
1
px black
;
empty-cells: hide
;
margin:
0
px
;
width:
100
%
;
}
table[summary^
=
"Note"
]
,
table[summary^
=
"Warning"
]
,
table[summary^
=
"Tip"
]
{
border-collapse: collapse
;
border-spacing:
0
;
border:
1
px black
;
empty-cells: hide
;
margin:
10
px
0
px
10
px
-
20
px
;
width:
100
%
;
}
td {
padding: 4pt;
font-family: Verdana, Arial, helvetica, sans-serif;
}
div.warning TD {
text-align: justify;
}
h1 {
font-size: 150%;
}
h2 {
font-size: 110%;
}
h3 {
font-size: 100%;
font-weight: bold;
}
h4 {
font-size: 90%;
font-weight: bold;
}
h5 {
font-size: 90%;
font-style: italic;
}
h6 {
font-size: 100%;
font-style: italic;
}
tt {
font-size: 110%;
font-family: "Courier New", Courier, monospace;
color: #000000;
}
.navheader, .navfooter {
border: none;
}
div.navfooter table {
border: dashed gray;
border-width: 1px 1px 1px 1px;
background-color: #cde48d;
}
pre {
font-size: 110%;
padding: 5px;
border-style: solid;
border-width: 1px;
border-color: #CCCCCC;
background-color: #f3f5e9;
}
ul, ol, li {
list-style: disc;
}
hr {
width: 100%;
height: 1px;
background-color: #CCCCCC;
border-width: 0px;
padding: 0px;
}
.variablelist {
padding-top: 10px;
padding-bottom: 10px;
margin: 0;
}
.term {
font-weight: bold;
}
.mediaobject {
padding-top: 30px;
padding-bottom: 30px;
}
.legalnotice {
font-family: Verdana, Arial, helvetica, sans-serif;
font-size: 12px;
font-style: italic;
}
.sidebar {
float: right;
margin: 10px 0px 10px 30px;
padding: 10px 20px 20px 20px;
width: 33%;
border: 1px solid black;
background-color: #F4F4F4;
font-size: 14px;
}
.property {
font-family: "Courier New", Courier, monospace;
}
a code {
font-family: Verdana, Arial, monospace;
font-size: 12px;
}
td code {
font-size: 110%;
}
div.note * td,
div.tip * td,
div.warning * td,
div.calloutlist * td {
text-align: justify;
font-size: 100%;
}
.programlisting .interfacename,
.programlisting .literal,
.programlisting .classname {
font-size: 95%;
}
.title .interfacename,
.title .literal,
.title .classname {
font-size: 130%;
}
/* everything in a <lineannotation/> is displayed in a coloured, comment-like font */
.programlisting * .lineannotation,
.programlisting * .lineannotation * {
color: green;
}

View File

@@ -1,99 +0,0 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
margin-left: 10%;
margin-right: 10%;
font-family: Arial, Sans-serif;
}
div {
margin: 0pt;
}
p {
text-align: justify;
}
hr {
border: 1px solid gray;
background: gray;
}
h1,h2,h3,h4 {
color: #234623;
font-family: Arial, Sans-serif;
}
pre {
line-height: 1.0;
color: black;
}
pre.programlisting {
font-size: 10pt;
padding: 7pt 3pt;
border: 1pt solid black;
background: #eeeeee;
clear: both;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
float: right;
margin: 10px 0 10px 30px;
padding: 10px 20px 20px 20px;
width: 33%;
border: 1px solid black;
background-color: #F4F4F4;
font-size: 14px;
}
.mediaobject {
padding-top: 30px;
padding-bottom: 30px;
}
.legalnotice {
font-family: Verdana, Arial, helvetica, sans-serif;
font-size: 12px;
font-style: italic;
}
p.releaseinfo {
font-size: 100%;
font-weight: bold;
font-family: Verdana, Arial, helvetica, sans-serif;
padding-top: 10px;
}
p.pubdate {
font-size: 120%;
font-weight: bold;
font-family: Verdana, Arial, helvetica, sans-serif;
}
span.productname {
font-size: 200%;
font-weight: bold;
font-family: Verdana, Arial, helvetica, sans-serif;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 623 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -1,418 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This is the XSL FO (PDF) stylesheet for the Spring reference
documentation.
Thanks are due to Christian Bauer of the Hibernate project
team for writing the original stylesheet upon which this one
is based.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="1.0">
<xsl:import href="urn:docbkx:stylesheet"/>
<!--###################################################
Custom Title Page
################################################### -->
<xsl:template name="book.titlepage.recto">
<fo:block>
<fo:table table-layout="fixed" width="175mm">
<fo:table-column column-width="175mm"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell text-align="center">
<fo:block>
<fo:block font-family="Helvetica" font-size="24pt" padding-before="10mm">
<xsl:value-of select="bookinfo/title"/>
</fo:block>
</fo:block>
<fo:block font-family="Helvetica" font-size="22pt" padding-before="10mm">
<xsl:value-of select="bookinfo/subtitle"/>
</fo:block>
<fo:block font-family="Helvetica" font-size="12pt" padding="10mm">
<xsl:value-of select="bookinfo/releaseinfo"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell text-align="center">
<fo:block font-family="Helvetica" font-size="14pt" padding="10mm">
<xsl:value-of select="bookinfo/pubdate"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell text-align="center">
<fo:block font-family="Helvetica" font-size="12pt" padding="10mm">
<xsl:text>Copyright &#xA9; 2010 </xsl:text>
<xsl:for-each select="bookinfo/authorgroup/author">
<xsl:if test="position() > 1">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:value-of select="firstname"/>
<xsl:text> </xsl:text>
<xsl:value-of select="surname"/>
</xsl:for-each>
</fo:block>
<fo:block font-family="Helvetica" font-size="10pt" padding="1mm">
<xsl:value-of select="bookinfo/legalnotice"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</xsl:template>
<!-- Prevent blank pages in output -->
<xsl:template name="book.titlepage.before.verso">
</xsl:template>
<xsl:template name="book.titlepage.verso">
</xsl:template>
<xsl:template name="book.titlepage.separator">
</xsl:template>
<!--###################################################
Header
################################################### -->
<!-- More space in the center header for long text -->
<xsl:attribute-set name="header.content.properties">
<xsl:attribute name="font-family">
<xsl:value-of select="$body.font.family"/>
</xsl:attribute>
<xsl:attribute name="margin-left">-5em</xsl:attribute>
<xsl:attribute name="margin-right">-5em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Custom Footer
################################################### -->
<xsl:template name="footer.content">
<xsl:param name="pageclass" select="''"/>
<xsl:param name="sequence" select="''"/>
<xsl:param name="position" select="''"/>
<xsl:param name="gentext-key" select="''"/>
<xsl:variable name="Version">
<xsl:if test="//releaseinfo">
<xsl:text>Spring Data Commons (</xsl:text>
<xsl:value-of select="//releaseinfo"/>
<xsl:text>)</xsl:text>
</xsl:if>
</xsl:variable>
<xsl:choose>
<xsl:when test="$sequence='blank'">
<xsl:if test="$position = 'center'">
<xsl:value-of select="$Version"/>
</xsl:if>
</xsl:when>
<!-- for double sided printing, print page numbers on alternating sides (of the page) -->
<xsl:when test="$double.sided != 0">
<xsl:choose>
<xsl:when test="$sequence = 'even' and $position='left'">
<fo:page-number/>
</xsl:when>
<xsl:when test="$sequence = 'odd' and $position='right'">
<fo:page-number/>
</xsl:when>
<xsl:when test="$position='center'">
<xsl:value-of select="$Version"/>
</xsl:when>
</xsl:choose>
</xsl:when>
<!-- for single sided printing, print all page numbers on the right (of the page) -->
<xsl:when test="$double.sided = 0">
<xsl:choose>
<xsl:when test="$position='center'">
<xsl:value-of select="$Version"/>
</xsl:when>
<xsl:when test="$position='right'">
<fo:page-number/>
</xsl:when>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:template>
<!--###################################################
Extensions
################################################### -->
<!-- These extensions are required for table printing and other stuff -->
<xsl:param name="use.extensions">1</xsl:param>
<xsl:param name="tablecolumns.extension">0</xsl:param>
<xsl:param name="callout.extensions">1</xsl:param>
<!-- FOP provide only PDF Bookmarks at the moment -->
<xsl:param name="fop.extensions">1</xsl:param>
<!--###################################################
Table Of Contents
################################################### -->
<!-- Generate the TOCs for named components only -->
<xsl:param name="generate.toc">
book toc
</xsl:param>
<!-- Show only Sections up to level 3 in the TOCs -->
<xsl:param name="toc.section.depth">2</xsl:param>
<!-- Dot and Whitespace as separator in TOC between Label and Title-->
<xsl:param name="autotoc.label.separator" select="'. '"/>
<!--###################################################
Paper & Page Size
################################################### -->
<!-- Paper type, no headers on blank pages, no double sided printing -->
<xsl:param name="paper.type" select="'A4'"/>
<xsl:param name="double.sided">0</xsl:param>
<xsl:param name="headers.on.blank.pages">0</xsl:param>
<xsl:param name="footers.on.blank.pages">0</xsl:param>
<!-- Space between paper border and content (chaotic stuff, don't touch) -->
<xsl:param name="page.margin.top">5mm</xsl:param>
<xsl:param name="region.before.extent">10mm</xsl:param>
<xsl:param name="body.margin.top">10mm</xsl:param>
<xsl:param name="body.margin.bottom">15mm</xsl:param>
<xsl:param name="region.after.extent">10mm</xsl:param>
<xsl:param name="page.margin.bottom">0mm</xsl:param>
<xsl:param name="page.margin.outer">18mm</xsl:param>
<xsl:param name="page.margin.inner">18mm</xsl:param>
<!-- No intendation of Titles -->
<xsl:param name="title.margin.left">0pc</xsl:param>
<!--###################################################
Fonts & Styles
################################################### -->
<!-- Left aligned text and no hyphenation -->
<xsl:param name="alignment">justify</xsl:param>
<xsl:param name="hyphenate">false</xsl:param>
<!-- Default Font size -->
<xsl:param name="body.font.master">11</xsl:param>
<xsl:param name="body.font.small">8</xsl:param>
<!-- Line height in body text -->
<xsl:param name="line-height">1.4</xsl:param>
<!-- Monospaced fonts are smaller than regular text -->
<xsl:attribute-set name="monospace.properties">
<xsl:attribute name="font-family">
<xsl:value-of select="$monospace.font.family"/>
</xsl:attribute>
<xsl:attribute name="font-size">0.8em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Tables
################################################### -->
<!-- The table width should be adapted to the paper size -->
<xsl:param name="default.table.width">17.4cm</xsl:param>
<!-- Some padding inside tables -->
<xsl:attribute-set name="table.cell.padding">
<xsl:attribute name="padding-left">4pt</xsl:attribute>
<xsl:attribute name="padding-right">4pt</xsl:attribute>
<xsl:attribute name="padding-top">4pt</xsl:attribute>
<xsl:attribute name="padding-bottom">4pt</xsl:attribute>
</xsl:attribute-set>
<!-- Only hairlines as frame and cell borders in tables -->
<xsl:param name="table.frame.border.thickness">0.1pt</xsl:param>
<xsl:param name="table.cell.border.thickness">0.1pt</xsl:param>
<!--###################################################
Labels
################################################### -->
<!-- Label Chapters and Sections (numbering) -->
<xsl:param name="chapter.autolabel">1</xsl:param>
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="section.label.includes.component.label" select="1"/>
<!--###################################################
Titles
################################################### -->
<!-- Chapter title size -->
<xsl:attribute-set name="chapter.titlepage.recto.style">
<xsl:attribute name="text-align">left</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.8"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
</xsl:attribute-set>
<!-- Why is the font-size for chapters hardcoded in the XSL FO templates?
Let's remove it, so this sucker can use our attribute-set only... -->
<xsl:template match="title" mode="chapter.titlepage.recto.auto.mode">
<fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format"
xsl:use-attribute-sets="chapter.titlepage.recto.style">
<xsl:call-template name="component.title">
<xsl:with-param name="node" select="ancestor-or-self::chapter[1]"/>
</xsl:call-template>
</fo:block>
</xsl:template>
<!-- Sections 1, 2 and 3 titles have a small bump factor and padding -->
<xsl:attribute-set name="section.title.level1.properties">
<xsl:attribute name="space-before.optimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.8em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.5"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="section.title.level2.properties">
<xsl:attribute name="space-before.optimum">0.6em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.6em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.6em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.25"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="section.title.level3.properties">
<xsl:attribute name="space-before.optimum">0.4em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.4em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.4em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.0"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<!-- Titles of formal objects (tables, examples, ...) -->
<xsl:attribute-set name="formal.title.properties" use-attribute-sets="normal.para.spacing">
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="hyphenate">false</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.4em</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.6em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.8em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Programlistings
################################################### -->
<!-- Verbatim text formatting (programlistings) -->
<xsl:attribute-set name="monospace.verbatim.properties">
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.small * 1.0"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="verbatim.properties">
<xsl:attribute name="space-before.minimum">1em</xsl:attribute>
<xsl:attribute name="space-before.optimum">1em</xsl:attribute>
<xsl:attribute name="space-before.maximum">1em</xsl:attribute>
<xsl:attribute name="border-color">#444444</xsl:attribute>
<xsl:attribute name="border-style">solid</xsl:attribute>
<xsl:attribute name="border-width">0.1pt</xsl:attribute>
<xsl:attribute name="padding-top">0.5em</xsl:attribute>
<xsl:attribute name="padding-left">0.5em</xsl:attribute>
<xsl:attribute name="padding-right">0.5em</xsl:attribute>
<xsl:attribute name="padding-bottom">0.5em</xsl:attribute>
<xsl:attribute name="margin-left">0.5em</xsl:attribute>
<xsl:attribute name="margin-right">0.5em</xsl:attribute>
</xsl:attribute-set>
<!-- Shade (background) programlistings -->
<xsl:param name="shade.verbatim">1</xsl:param>
<xsl:attribute-set name="shade.verbatim.style">
<xsl:attribute name="background-color">#F0F0F0</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Callouts
################################################### -->
<!-- Use images for callouts instead of (1) (2) (3) -->
<xsl:param name="callout.graphics">0</xsl:param>
<xsl:param name="callout.unicode">1</xsl:param>
<!-- Place callout marks at this column in annotated areas -->
<xsl:param name="callout.defaultcolumn">90</xsl:param>
<!--###################################################
Admonitions
################################################### -->
<!-- Use nice graphics for admonitions -->
<xsl:param name="admon.graphics">'1'</xsl:param>
<!-- <xsl:param name="admon.graphics.path">&admon_gfx_path;</xsl:param> -->
<!--###################################################
Misc
################################################### -->
<!-- Placement of titles -->
<xsl:param name="formal.title.placement">
figure after
example before
equation before
table before
procedure before
</xsl:param>
<!-- Format Variable Lists as Blocks (prevents horizontal overflow) -->
<xsl:param name="variablelist.as.blocks">1</xsl:param>
<!-- The horrible list spacing problems -->
<xsl:attribute-set name="list.block.spacing">
<xsl:attribute name="space-before.optimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.8em</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
colored and hyphenated links
################################################### -->
<xsl:template match="ulink">
<fo:basic-link external-destination="{@url}"
xsl:use-attribute-sets="xref.properties"
text-decoration="underline"
color="blue">
<xsl:choose>
<xsl:when test="count(child::node())=0">
<xsl:value-of select="@url"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</fo:basic-link>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,91 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This is the XSL HTML configuration file for the Spring
Reference Documentation.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="1.0">
<xsl:import href="urn:docbkx:stylesheet"/>
<!--###################################################
HTML Settings
################################################### -->
<xsl:param name="html.stylesheet">html.css</xsl:param>
<!-- These extensions are required for table printing and other stuff -->
<xsl:param name="use.extensions">1</xsl:param>
<xsl:param name="tablecolumns.extension">0</xsl:param>
<xsl:param name="callout.extensions">1</xsl:param>
<xsl:param name="graphicsize.extension">0</xsl:param>
<!--###################################################
Table Of Contents
################################################### -->
<!-- Generate the TOCs for named components only -->
<xsl:param name="generate.toc">
book toc
</xsl:param>
<!-- Show only Sections up to level 3 in the TOCs -->
<xsl:param name="toc.section.depth">3</xsl:param>
<!--###################################################
Labels
################################################### -->
<!-- Label Chapters and Sections (numbering) -->
<xsl:param name="chapter.autolabel">1</xsl:param>
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="section.label.includes.component.label" select="1"/>
<!--###################################################
Callouts
################################################### -->
<!-- Use images for callouts instead of (1) (2) (3) -->
<xsl:param name="callout.graphics">0</xsl:param>
<!-- Place callout marks at this column in annotated areas -->
<xsl:param name="callout.defaultcolumn">90</xsl:param>
<!--###################################################
Admonitions
################################################### -->
<!-- Use nice graphics for admonitions -->
<xsl:param name="admon.graphics">0</xsl:param>
<!--###################################################
Misc
################################################### -->
<!-- Placement of titles -->
<xsl:param name="formal.title.placement">
figure after
example before
equation before
table before
procedure before
</xsl:param>
<xsl:template match="author" mode="titlepage.mode">
<xsl:if test="name(preceding-sibling::*[1]) = 'author'">
<xsl:text>, </xsl:text>
</xsl:if>
<span class="{name(.)}">
<xsl:call-template name="person.name"/>
<xsl:apply-templates mode="titlepage.mode" select="./contrib"/>
<xsl:apply-templates mode="titlepage.mode" select="./affiliation"/>
</span>
</xsl:template>
<xsl:template match="authorgroup" mode="titlepage.mode">
<div class="{name(.)}">
<h2>Authors</h2>
<p/>
<xsl:apply-templates mode="titlepage.mode"/>
</div>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,136 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xslthl="http://xslthl.sf.net"
exclude-result-prefixes="xslthl"
version='1.0'>
<xsl:param name="chunk.section.depth">'5'</xsl:param>
<xsl:param name="use.id.as.filename" select="1"/>
<!-- Extensions -->
<xsl:param name="use.extensions">1</xsl:param>
<xsl:param name="tablecolumns.extension">0</xsl:param>
<xsl:param name="callout.extensions">1</xsl:param>
<!-- Activate Graphics -->
<xsl:param name="admon.graphics" select="1"/>
<xsl:param name="admon.graphics.path">images/</xsl:param>
<xsl:param name="admon.graphics.extension">.gif</xsl:param>
<xsl:param name="callout.graphics" select="1" />
<xsl:param name="callout.defaultcolumn">120</xsl:param>
<xsl:param name="callout.graphics.path">images/callouts/</xsl:param>
<xsl:param name="callout.graphics.extension">.gif</xsl:param>
<xsl:param name="table.borders.with.css" select="1"/>
<xsl:param name="html.stylesheet">css/stylesheet.css</xsl:param>
<xsl:param name="html.stylesheet.type">text/css</xsl:param>
<xsl:param name="generate.toc">book toc,title</xsl:param>
<xsl:param name="admonition.title.properties">text-align: left</xsl:param>
<!-- Label Chapters and Sections (numbering) -->
<xsl:param name="chapter.autolabel" select="1"/>
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="section.autolabel.max.depth" select="3"/>
<xsl:param name="section.label.includes.component.label" select="1"/>
<xsl:param name="table.footnote.number.format" select="'1'"/>
<!-- Show only Sections up to level 3 in the TOCs -->
<xsl:param name="toc.section.depth">3</xsl:param>
<!-- Remove "Chapter" from the Chapter titles... -->
<xsl:param name="local.l10n.xml" select="document('')"/>
<l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">
<l:l10n language="en">
<l:context name="title-numbered">
<l:template name="chapter" text="%n.&#160;%t"/>
<l:template name="section" text="%n&#160;%t"/>
</l:context>
</l:l10n>
</l:i18n>
<!-- Use code syntax highlighting -->
<xsl:param name="highlight.source" select="1"/>
<xsl:template match='xslthl:keyword'>
<span class="hl-keyword"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:comment'>
<span class="hl-comment"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:oneline-comment'>
<span class="hl-comment"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:multiline-comment'>
<span class="hl-multiline-comment"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:tag'>
<span class="hl-tag"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:attribute'>
<span class="hl-attribute"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:value'>
<span class="hl-value"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:string'>
<span class="hl-string"><xsl:value-of select='.'/></span>
</xsl:template>
<!-- Google Analytics -->
<xsl:template name="user.head.content">
<xsl:comment>Begin Google Analytics code</xsl:comment>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-2728886-3");
pageTracker._setDomainName("none");
pageTracker._setAllowLinker(true);
pageTracker._trackPageview();
</script>
<xsl:comment>End Google Analytics code</xsl:comment>
</xsl:template>
<!-- Loopfuse -->
<xsl:template name="user.footer.content">
<xsl:comment>Begin LoopFuse code</xsl:comment>
<script src="http://loopfuse.net/webrecorder/js/listen.js" type="text/javascript">
</script>
<script type="text/javascript">
_lf_cid = "LF_48be82fa";
_lf_remora();
</script>
<xsl:comment>End LoopFuse code</xsl:comment>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
-->
<t:templates xmlns:t="http://nwalsh.com/docbook/xsl/template/1.0"
xmlns:param="http://nwalsh.com/docbook/xsl/template/1.0/param"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- ==================================================================== -->
<t:titlepage t:element="book" t:wrapper="div" class="titlepage">
<t:titlepage-content t:side="recto">
<productname/>
<title/>
<subtitle/>
<!-- <corpauthor/>
<authorgroup/>
<author/>
<mediaobject/> -->
<othercredit/>
<releaseinfo/>
<copyright/>
<legalnotice/>
<pubdate/>
<revision/>
<revhistory/>
<abstract/>
</t:titlepage-content>
<t:titlepage-content t:side="verso">
</t:titlepage-content>
<t:titlepage-separator>
<hr/>
</t:titlepage-separator>
<t:titlepage-before t:side="recto">
</t:titlepage-before>
<t:titlepage-before t:side="verso">
</t:titlepage-before>
</t:titlepage>
</t:templates>

View File

@@ -1,208 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This is the XSL HTML configuration file for the Spring Reference Documentation.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="1.0">
<xsl:import href="urn:docbkx:stylesheet"/>
<!--###################################################
HTML Settings
################################################### -->
<xsl:param name="chunk.section.depth">'5'</xsl:param>
<xsl:param name="use.id.as.filename">'1'</xsl:param>
<!-- These extensions are required for table printing and other stuff -->
<xsl:param name="use.extensions">1</xsl:param>
<xsl:param name="tablecolumns.extension">0</xsl:param>
<xsl:param name="callout.extensions">1</xsl:param>
<xsl:param name="graphicsize.extension">0</xsl:param>
<!--###################################################
Table Of Contents
################################################### -->
<!-- Generate the TOCs for named components only -->
<xsl:param name="generate.toc">
book toc
</xsl:param>
<!-- Show only Sections up to level 3 in the TOCs -->
<xsl:param name="toc.section.depth">3</xsl:param>
<!--###################################################
Labels
################################################### -->
<!-- Label Chapters and Sections (numbering) -->
<xsl:param name="chapter.autolabel">1</xsl:param>
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="section.label.includes.component.label" select="1"/>
<!--###################################################
Callouts
################################################### -->
<!-- Place callout marks at this column in annotated areas -->
<xsl:param name="callout.graphics">1</xsl:param>
<xsl:param name="callout.defaultcolumn">90</xsl:param>
<!--###################################################
Misc
################################################### -->
<!-- Placement of titles -->
<xsl:param name="formal.title.placement">
figure after
example before
equation before
table before
procedure before
</xsl:param>
<xsl:template match="author" mode="titlepage.mode">
<xsl:if test="name(preceding-sibling::*[1]) = 'author'">
<xsl:text>, </xsl:text>
</xsl:if>
<span class="{name(.)}">
<xsl:call-template name="person.name"/>
<xsl:apply-templates mode="titlepage.mode" select="./contrib"/>
<xsl:apply-templates mode="titlepage.mode" select="./affiliation"/>
</span>
</xsl:template>
<xsl:template match="authorgroup" mode="titlepage.mode">
<div class="{name(.)}">
<h2>Authors</h2>
<p/>
<xsl:apply-templates mode="titlepage.mode"/>
</div>
</xsl:template>
<!--###################################################
Headers and Footers
################################################### -->
<!-- let's have a Spring and SpringSource banner across the top of each page -->
<xsl:template name="user.header.navigation">
<div style="background-color:white;border:none;height:73px;border:1px solid black;">
<a style="border:none;" href="http://static.springframework.org/spring-ws/site/"
title="The Spring Framework - Spring Web Services">
<img style="border:none;" src="images/xdev-spring_logo.jpg"/>
</a>
<a style="border:none;" href="http://www.springsource.com/" title="SpringSource">
<img style="border:none;position:absolute;padding-top:5px;right:42px;" src="images/s2_box_logo.png"/>
</a>
</div>
</xsl:template>
<!-- no other header navigation (prev, next, etc.) -->
<xsl:template name="header.navigation"/>
<xsl:param name="navig.showtitles">1</xsl:param>
<!-- let's have a 'Sponsored by SpringSource' strapline (or somesuch) across the bottom of each page -->
<xsl:template name="footer.navigation">
<xsl:param name="prev" select="/foo"/>
<xsl:param name="next" select="/foo"/>
<xsl:param name="nav.context"/>
<xsl:variable name="home" select="/*[1]"/>
<xsl:variable name="up" select="parent::*"/>
<xsl:variable name="row1" select="count($prev) &gt; 0
or count($up) &gt; 0
or count($next) &gt; 0"/>
<xsl:variable name="row2" select="($prev and $navig.showtitles != 0)
or (generate-id($home) != generate-id(.)
or $nav.context = 'toc')
or ($chunk.tocs.and.lots != 0
and $nav.context != 'toc')
or ($next and $navig.showtitles != 0)"/>
<xsl:if test="$suppress.navigation = '0' and $suppress.footer.navigation = '0'">
<div class="navfooter">
<xsl:if test="$footer.rule != 0">
<hr/>
</xsl:if>
<xsl:if test="$row1 or $row2">
<table width="100%" summary="Navigation footer">
<xsl:if test="$row1">
<tr>
<td width="40%" align="left">
<xsl:if test="count($prev)>0">
<a accesskey="p">
<xsl:attribute name="href">
<xsl:call-template name="href.target">
<xsl:with-param name="object" select="$prev"/>
</xsl:call-template>
</xsl:attribute>
<xsl:call-template name="navig.content">
<xsl:with-param name="direction" select="'prev'"/>
</xsl:call-template>
</a>
</xsl:if>
<xsl:text>&#160;</xsl:text>
</td>
<td width="20%" align="center">
<xsl:choose>
<xsl:when test="$home != . or $nav.context = 'toc'">
<a accesskey="h">
<xsl:attribute name="href">
<xsl:call-template name="href.target">
<xsl:with-param name="object" select="$home"/>
</xsl:call-template>
</xsl:attribute>
<xsl:call-template name="navig.content">
<xsl:with-param name="direction" select="'home'"/>
</xsl:call-template>
</a>
<xsl:if test="$chunk.tocs.and.lots != 0 and $nav.context != 'toc'">
<xsl:text>&#160;|&#160;</xsl:text>
</xsl:if>
</xsl:when>
<xsl:otherwise>&#160;</xsl:otherwise>
</xsl:choose>
<xsl:if test="$chunk.tocs.and.lots != 0 and $nav.context != 'toc'">
<a accesskey="t">
<xsl:attribute name="href">
<xsl:apply-templates select="/*[1]" mode="recursive-chunk-filename">
<xsl:with-param name="recursive" select="true()"/>
</xsl:apply-templates>
<xsl:text>-toc</xsl:text>
<xsl:value-of select="$html.ext"/>
</xsl:attribute>
<xsl:call-template name="gentext">
<xsl:with-param name="key" select="'nav-toc'"/>
</xsl:call-template>
</a>
</xsl:if>
</td>
<td width="40%" align="right">
<xsl:text>&#160;</xsl:text>
<xsl:if test="count($next)>0">
<a accesskey="n">
<xsl:attribute name="href">
<xsl:call-template name="href.target">
<xsl:with-param name="object" select="$next"/>
</xsl:call-template>
</xsl:attribute>
<xsl:call-template name="navig.content">
<xsl:with-param name="direction" select="'next'"/>
</xsl:call-template>
</a>
</xsl:if>
</td>
</tr>
</xsl:if>
<xsl:if test="$row2">
<tr>
<td width="40%" align="left" valign="top">
<xsl:if test="$navig.showtitles != 0">
<xsl:apply-templates select="$prev" mode="object.title.markup"/>
</xsl:if>
<xsl:text>&#160;</xsl:text>
</td>
<td width="20%" align="center">
<span style="color:white;font-size:90%;">
<a href="http://www.springsource.com/"
title="SpringSource">Sponsored by SpringSource
</a>
</span>
</td>
<td width="40%" align="right" valign="top">
<xsl:text>&#160;</xsl:text>
<xsl:if test="$navig.showtitles != 0">
<xsl:apply-templates select="$next" mode="object.title.markup"/>
</xsl:if>
</td>
</tr>
</xsl:if>
</table>
</xsl:if>
</div>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,518 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xslthl="http://xslthl.sf.net"
exclude-result-prefixes="xslthl"
version='1.0'>
<!-- Use nice graphics for admonitions -->
<xsl:param name="admon.graphics">'1'</xsl:param>
<xsl:param name="admon.graphics.path">@file.prefix@@dbf.xsl@/images/</xsl:param>
<xsl:param name="draft.watermark.image" select="'@file.prefix@@dbf.xsl@/images/draft.png'"/>
<xsl:param name="paper.type" select="'@paper.type@'"/>
<xsl:param name="page.margin.top" select="'1cm'"/>
<xsl:param name="region.before.extent" select="'1cm'"/>
<xsl:param name="body.margin.top" select="'1.5cm'"/>
<xsl:param name="body.margin.bottom" select="'1.5cm'"/>
<xsl:param name="region.after.extent" select="'1cm'"/>
<xsl:param name="page.margin.bottom" select="'1cm'"/>
<xsl:param name="title.margin.left" select="'0cm'"/>
<!--###################################################
Header
################################################### -->
<!-- More space in the center header for long text -->
<xsl:attribute-set name="header.content.properties">
<xsl:attribute name="font-family">
<xsl:value-of select="$body.font.family"/>
</xsl:attribute>
<xsl:attribute name="margin-left">-5em</xsl:attribute>
<xsl:attribute name="margin-right">-5em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Table of Contents
################################################### -->
<xsl:param name="generate.toc">
book toc,title
</xsl:param>
<!--###################################################
Custom Header
################################################### -->
<xsl:template name="header.content">
<xsl:param name="pageclass" select="''"/>
<xsl:param name="sequence" select="''"/>
<xsl:param name="position" select="''"/>
<xsl:param name="gentext-key" select="''"/>
<xsl:variable name="Version">
<xsl:choose>
<xsl:when test="//productname">
<xsl:value-of select="//productname"/><xsl:text> </xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>please define productname in your docbook file!</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="$sequence='blank'">
<xsl:choose>
<xsl:when test="$position='center'">
<xsl:value-of select="$Version"/>
</xsl:when>
<xsl:otherwise>
<!-- nop -->
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="$pageclass='titlepage'">
<!-- nop: other titlepage sequences have no header -->
</xsl:when>
<xsl:when test="$position='center'">
<xsl:value-of select="$Version"/>
</xsl:when>
<xsl:otherwise>
<!-- nop -->
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!--###################################################
Custom Footer
################################################### -->
<xsl:template name="footer.content">
<xsl:param name="pageclass" select="''"/>
<xsl:param name="sequence" select="''"/>
<xsl:param name="position" select="''"/>
<xsl:param name="gentext-key" select="''"/>
<xsl:variable name="Version">
<xsl:choose>
<xsl:when test="//releaseinfo">
<xsl:value-of select="//releaseinfo"/>
</xsl:when>
<xsl:otherwise>
<!-- nop -->
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="Title">
<xsl:value-of select="//title"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="$sequence='blank'">
<xsl:choose>
<xsl:when test="$double.sided != 0 and $position = 'left'">
<xsl:value-of select="$Version"/>
</xsl:when>
<xsl:when test="$double.sided = 0 and $position = 'center'">
<!-- nop -->
</xsl:when>
<xsl:otherwise>
<fo:page-number/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="$pageclass='titlepage'">
<!-- nop: other titlepage sequences have no footer -->
</xsl:when>
<xsl:when test="$double.sided != 0 and $sequence = 'even' and $position='left'">
<fo:page-number/>
</xsl:when>
<xsl:when test="$double.sided != 0 and $sequence = 'odd' and $position='right'">
<fo:page-number/>
</xsl:when>
<xsl:when test="$double.sided = 0 and $position='right'">
<fo:page-number/>
</xsl:when>
<xsl:when test="$double.sided != 0 and $sequence = 'odd' and $position='left'">
<xsl:value-of select="$Version"/>
</xsl:when>
<xsl:when test="$double.sided != 0 and $sequence = 'even' and $position='right'">
<xsl:value-of select="$Version"/>
</xsl:when>
<xsl:when test="$double.sided = 0 and $position='left'">
<xsl:value-of select="$Version"/>
</xsl:when>
<xsl:when test="$position='center'">
<xsl:value-of select="$Title"/>
</xsl:when>
<xsl:otherwise>
<!-- nop -->
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="processing-instruction('hard-pagebreak')">
<fo:block break-before='page'/>
</xsl:template>
<!--###################################################
Extensions
################################################### -->
<!-- These extensions are required for table printing and other stuff -->
<xsl:param name="use.extensions">1</xsl:param>
<xsl:param name="tablecolumns.extension">0</xsl:param>
<xsl:param name="callout.extensions">1</xsl:param>
<xsl:param name="fop.extensions">1</xsl:param>
<!--###################################################
Paper & Page Size
################################################### -->
<!-- Paper type, no headers on blank pages, no double sided printing -->
<xsl:param name="double.sided">0</xsl:param>
<xsl:param name="headers.on.blank.pages">0</xsl:param>
<xsl:param name="footers.on.blank.pages">0</xsl:param>
<!--###################################################
Fonts & Styles
################################################### -->
<xsl:param name="hyphenate">false</xsl:param>
<!-- Default Font size -->
<xsl:param name="body.font.master">11</xsl:param>
<xsl:param name="body.font.small">8</xsl:param>
<!-- Line height in body text -->
<xsl:param name="line-height">1.4</xsl:param>
<!-- Chapter title size -->
<xsl:attribute-set name="chapter.titlepage.recto.style">
<xsl:attribute name="text-align">left</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.8"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
</xsl:attribute-set>
<!-- Why is the font-size for chapters hardcoded in the XSL FO templates?
Let's remove it, so this sucker can use our attribute-set only... -->
<xsl:template match="title" mode="chapter.titlepage.recto.auto.mode">
<fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format"
xsl:use-attribute-sets="chapter.titlepage.recto.style">
<xsl:call-template name="component.title">
<xsl:with-param name="node" select="ancestor-or-self::chapter[1]"/>
</xsl:call-template>
</fo:block>
</xsl:template>
<!-- Sections 1, 2 and 3 titles have a small bump factor and padding -->
<xsl:attribute-set name="section.title.level1.properties">
<xsl:attribute name="space-before.optimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.8em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.5"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="section.title.level2.properties">
<xsl:attribute name="space-before.optimum">0.6em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.6em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.6em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.25"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="section.title.level3.properties">
<xsl:attribute name="space-before.optimum">0.4em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.4em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.4em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.0"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="section.title.level4.properties">
<xsl:attribute name="space-before.optimum">0.3em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.3em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.3em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 0.9"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<!-- Use code syntax highlighting -->
<xsl:param name="highlight.source" select="1"/>
<xsl:param name="highlight.default.language" select="xml" />
<xsl:template match='xslthl:keyword'>
<fo:inline font-weight="bold" color="#7F0055"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:comment'>
<fo:inline font-style="italic" color="#3F5F5F"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:oneline-comment'>
<fo:inline font-style="italic" color="#3F5F5F"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:multiline-comment'>
<fo:inline font-style="italic" color="#3F5FBF"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:tag'>
<fo:inline color="#3F7F7F"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:attribute'>
<fo:inline color="#7F007F"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:value'>
<fo:inline color="#2A00FF"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:string'>
<fo:inline color="#2A00FF"><xsl:apply-templates/></fo:inline>
</xsl:template>
<!--###################################################
Tables
################################################### -->
<!-- Some padding inside tables -->
<xsl:attribute-set name="table.cell.padding">
<xsl:attribute name="padding-left">4pt</xsl:attribute>
<xsl:attribute name="padding-right">4pt</xsl:attribute>
<xsl:attribute name="padding-top">4pt</xsl:attribute>
<xsl:attribute name="padding-bottom">4pt</xsl:attribute>
</xsl:attribute-set>
<!-- Only hairlines as frame and cell borders in tables -->
<xsl:param name="table.frame.border.thickness">0.1pt</xsl:param>
<xsl:param name="table.cell.border.thickness">0.1pt</xsl:param>
<!--###################################################
Labels
################################################### -->
<!-- Label Chapters and Sections (numbering) -->
<xsl:param name="chapter.autolabel" select="1"/>
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="section.autolabel.max.depth" select="1"/>
<xsl:param name="section.label.includes.component.label" select="1"/>
<xsl:param name="table.footnote.number.format" select="'1'"/>
<!--###################################################
Programlistings
################################################### -->
<!-- Verbatim text formatting (programlistings) -->
<xsl:attribute-set name="monospace.verbatim.properties">
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.small * 1.0"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="verbatim.properties">
<xsl:attribute name="space-before.minimum">1em</xsl:attribute>
<xsl:attribute name="space-before.optimum">1em</xsl:attribute>
<xsl:attribute name="space-before.maximum">1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
<xsl:attribute name="border-color">#444444</xsl:attribute>
<xsl:attribute name="border-style">solid</xsl:attribute>
<xsl:attribute name="border-width">0.1pt</xsl:attribute>
<xsl:attribute name="padding-top">0.5em</xsl:attribute>
<xsl:attribute name="padding-left">0.5em</xsl:attribute>
<xsl:attribute name="padding-right">0.5em</xsl:attribute>
<xsl:attribute name="padding-bottom">0.5em</xsl:attribute>
<xsl:attribute name="margin-left">0.5em</xsl:attribute>
<xsl:attribute name="margin-right">0.5em</xsl:attribute>
</xsl:attribute-set>
<!-- Shade (background) programlistings -->
<xsl:param name="shade.verbatim">1</xsl:param>
<xsl:attribute-set name="shade.verbatim.style">
<xsl:attribute name="background-color">#F0F0F0</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="list.block.spacing">
<xsl:attribute name="space-before.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="example.properties">
<xsl:attribute name="space-before.minimum">0.5em</xsl:attribute>
<xsl:attribute name="space-before.optimum">0.5em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.5em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
<xsl:attribute name="keep-together.within-column">always</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Title information for Figures, Examples etc.
################################################### -->
<xsl:attribute-set name="formal.title.properties" use-attribute-sets="normal.para.spacing">
<xsl:attribute name="font-weight">normal</xsl:attribute>
<xsl:attribute name="font-style">italic</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="hyphenate">false</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-before.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Callouts
################################################### -->
<!-- don't use images for callouts -->
<xsl:param name="callout.graphics">0</xsl:param>
<xsl:param name="callout.unicode">1</xsl:param>
<!-- Place callout marks at this column in annotated areas -->
<xsl:param name="callout.defaultcolumn">90</xsl:param>
<!--###################################################
Misc
################################################### -->
<!-- Placement of titles -->
<xsl:param name="formal.title.placement">
figure after
example after
equation before
table before
procedure before
</xsl:param>
<!-- Format Variable Lists as Blocks (prevents horizontal overflow) -->
<xsl:param name="variablelist.as.blocks">1</xsl:param>
<xsl:param name="body.start.indent">0pt</xsl:param>
<!-- Show only Sections up to level 3 in the TOCs -->
<xsl:param name="toc.section.depth">3</xsl:param>
<!-- Remove "Chapter" from the Chapter titles... -->
<xsl:param name="local.l10n.xml" select="document('')"/>
<l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">
<l:l10n language="en">
<l:context name="title-numbered">
<l:template name="chapter" text="%n.&#160;%t"/>
<l:template name="section" text="%n&#160;%t"/>
</l:context>
<l:context name="title">
<l:template name="example" text="Example&#160;%n&#160;%t"/>
</l:context>
</l:l10n>
</l:i18n>
<!--###################################################
colored and hyphenated links
################################################### -->
<xsl:template match="ulink">
<fo:basic-link external-destination="{@url}"
xsl:use-attribute-sets="xref.properties"
text-decoration="underline"
color="blue">
<xsl:choose>
<xsl:when test="count(child::node())=0">
<xsl:value-of select="@url"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</fo:basic-link>
</xsl:template>
<xsl:template match="link">
<fo:basic-link internal-destination="{@linkend}"
xsl:use-attribute-sets="xref.properties"
text-decoration="underline"
color="blue">
<xsl:choose>
<xsl:when test="count(child::node())=0">
<xsl:value-of select="@linkend"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</fo:basic-link>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,101 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
-->
<!DOCTYPE t:templates [
<!ENTITY hsize0 "10pt">
<!ENTITY hsize1 "12pt">
<!ENTITY hsize2 "14.4pt">
<!ENTITY hsize3 "17.28pt">
<!ENTITY hsize4 "20.736pt">
<!ENTITY hsize5 "24.8832pt">
<!ENTITY hsize0space "7.5pt"> <!-- 0.75 * hsize0 -->
<!ENTITY hsize1space "9pt"> <!-- 0.75 * hsize1 -->
<!ENTITY hsize2space "10.8pt"> <!-- 0.75 * hsize2 -->
<!ENTITY hsize3space "12.96pt"> <!-- 0.75 * hsize3 -->
<!ENTITY hsize4space "15.552pt"> <!-- 0.75 * hsize4 -->
<!ENTITY hsize5space "18.6624pt"> <!-- 0.75 * hsize5 -->
]>
<t:templates xmlns:t="http://nwalsh.com/docbook/xsl/template/1.0"
xmlns:param="http://nwalsh.com/docbook/xsl/template/1.0/param"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<t:titlepage t:element="book" t:wrapper="fo:block">
<t:titlepage-content t:side="recto">
<title
t:named-template="division.title"
param:node="ancestor-or-self::book[1]"
text-align="center"
font-size="&hsize5;"
space-before="&hsize5space;"
font-weight="bold"
font-family="{$title.fontset}"/>
<subtitle
text-align="center"
font-size="&hsize4;"
space-before="&hsize4space;"
font-family="{$title.fontset}"/>
<!-- <corpauthor space-before="0.5em"
font-size="&hsize2;"/>
<authorgroup space-before="0.5em"
font-size="&hsize2;"/>
<author space-before="0.5em"
font-size="&hsize2;"/> -->
<mediaobject space-before="2em" space-after="2em"/>
<releaseinfo space-before="5em" font-size="&hsize2;"/>
<copyright space-before="1.5em"
font-weight="normal"
font-size="8"/>
<legalnotice space-before="5em"
font-weight="normal"
font-style="italic"
font-size="8"/>
<othercredit space-before="2em"
font-weight="normal"
font-size="8"/>
<pubdate space-before="0.5em"/>
<revision space-before="0.5em"/>
<revhistory space-before="0.5em"/>
<abstract space-before="0.5em"
text-align="start"
margin-left="0.5in"
margin-right="0.5in"
font-family="{$body.fontset}"/>
</t:titlepage-content>
<t:titlepage-content t:side="verso">
</t:titlepage-content>
<t:titlepage-separator>
</t:titlepage-separator>
<t:titlepage-before t:side="recto">
</t:titlepage-before>
<t:titlepage-before t:side="verso">
</t:titlepage-before>
</t:titlepage>
<!-- ==================================================================== -->
</t:templates>

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Declares a field as the one representing the principal that created the entity containing the field.
*
* @author Ranie Jade Ramiso
* @author Oliver Gierke
* @since 1.5
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.ANNOTATION_TYPE })
public @interface CreatedBy {
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Declares a field as the one representing the date the entity containing the field was created.
*
* @author Ranie Jade Ramiso
* @author Oliver Gierke
* @since 1.5
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.ANNOTATION_TYPE })
public @interface CreatedDate {
}

View File

@@ -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.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 {
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Declares a field as the one representing the principal that recently modified the entity containing the field.
*
* @author Ranie Jade Ramiso
* @author Oliver Gierke
* @since 1.5
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.ANNOTATION_TYPE })
public @interface LastModifiedBy {
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Declares a field as the one representing the date the entity containing the field was recently modified.
*
* @author Ranie Jade Ramiso
* @author Oliver Gierke
* @since 1.5
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.ANNOTATION_TYPE })
public @interface LastModifiedDate {
}

View File

@@ -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.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 {
}

View File

@@ -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.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.ANNOTATION_TYPE, ElementType.FIELD, ElementType.PARAMETER })
public @interface Persistent {
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Meta-annotation to be used to annotate annotations that mark references to other objects.
*
* @author Oliver Gierke
* @author Jon Brisbin
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD })
public @interface Reference {
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 20011-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks a field to be transient for the mapping framework. Thus the property will not be persisted and not further
* inspected by the mapping framework.
*
* @author Oliver Gierke
* @author Jon Brisbin
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Transient {
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2011 by the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.data.mapping.PersistentEntity;
/**
* Annotation to allow {@link String} based type aliases to be used when writing type information for
* {@link PersistentEntity}s.
*
* @author Oliver Gierke
*/
@Documented
@Inherited
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface TypeAlias {
/**
* The type alias to be used when persisting
*
* @return
*/
String value();
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.annotation;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Demarcates a property to be used as version field to implement optimistic locking on entities.
*
* @since 1.5
* @author Patryk Wasik
* @author Oliver Gierke
*/
@Documented
@Target({ FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface Version {
}

View File

@@ -0,0 +1,4 @@
/**
* Core annotations being used by Spring Data.
*/
package org.springframework.data.annotation;

View File

@@ -0,0 +1,139 @@
package org.springframework.data.auditing;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.joda.time.DateTime;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.data.util.ReflectionUtils.AnnotationFieldFilter;
import org.springframework.util.Assert;
/**
* Inspects the given {@link Class} for fields annotated by {@link CreatedBy}, {@link CreatedDate},
* {@link LastModifiedBy} , and {@link LastModifiedDate}. Only one field per annotation is stored.
*
* @author Ranie Jade Ramiso
* @author Oliver Gierke
* @since 1.5
*/
class AnnotationAuditingMetadata {
private static final AnnotationFieldFilter CREATED_BY_FILTER = new AnnotationFieldFilter(CreatedBy.class);
private static final AnnotationFieldFilter CREATED_DATE_FILTER = new AnnotationFieldFilter(CreatedDate.class);
private static final AnnotationFieldFilter LAST_MODIFIED_BY_FILTER = new AnnotationFieldFilter(LastModifiedBy.class);
private static final AnnotationFieldFilter LAST_MODIFIED_DATE_FILTER = new AnnotationFieldFilter(
LastModifiedDate.class);
private static final Map<Class<?>, AnnotationAuditingMetadata> METADATA_CACHE = new ConcurrentHashMap<Class<?>, AnnotationAuditingMetadata>();
static final List<Class<?>> SUPPORTED_DATE_TYPES;
static {
List<Class<?>> types = new ArrayList<Class<?>>(4);
types.add(DateTime.class);
types.add(Date.class);
types.add(Long.class);
types.add(long.class);
SUPPORTED_DATE_TYPES = Collections.unmodifiableList(types);
}
private final Field createdByField;
private final Field createdDateField;
private final Field lastModifiedByField;
private final Field lastModifiedDateField;
private AnnotationAuditingMetadata(Class<?> type) {
Assert.notNull(type, "Given type must not be null!");
this.createdByField = ReflectionUtils.findField(type, CREATED_BY_FILTER);
this.createdDateField = ReflectionUtils.findField(type, CREATED_DATE_FILTER);
this.lastModifiedByField = ReflectionUtils.findField(type, LAST_MODIFIED_BY_FILTER);
this.lastModifiedDateField = ReflectionUtils.findField(type, LAST_MODIFIED_DATE_FILTER);
assertValidDateFieldType(createdDateField);
assertValidDateFieldType(lastModifiedDateField);
}
/**
* Checks whether the given field has a type that is a supported date type.
*
* @param field
*/
private void assertValidDateFieldType(Field field) {
if (field == null || SUPPORTED_DATE_TYPES.contains(field.getType())) {
return;
}
throw new IllegalStateException(String.format(
"Found created/modified date field with type %s but only %s are supported!", field.getType(),
SUPPORTED_DATE_TYPES));
}
/**
* Return a {@link AnnotationAuditingMetadata} for the given {@link Class}.
*
* @param type the type to inspect, must not be {@literal null}.
*/
public static AnnotationAuditingMetadata getMetadata(Class<?> type) {
if (METADATA_CACHE.containsKey(type)) {
return METADATA_CACHE.get(type);
}
AnnotationAuditingMetadata metadata = new AnnotationAuditingMetadata(type);
METADATA_CACHE.put(type, metadata);
return metadata;
}
/**
* Returns whether the {@link Class} represented in this instance is auditable or not.
*/
public boolean isAuditable() {
if (createdByField == null && createdDateField == null && lastModifiedByField == null
&& lastModifiedDateField == null) {
return false;
}
return true;
}
/**
* Return the field annotated by {@link CreatedBy}, or {@literal null}.
*/
public Field getCreatedByField() {
return createdByField;
}
/**
* Return the field annotated by {@link CreatedDate}, or {@literal null}.
*/
public Field getCreatedDateField() {
return createdDateField;
}
/**
* Return the field annotated by {@link LastModifiedBy}, or {@literal null}.
*/
public Field getLastModifiedByField() {
return lastModifiedByField;
}
/**
* Return the field annotated by {@link LastModifiedDate}, or {@literal null}.
*/
public Field getLastModifiedDateField() {
return lastModifiedDateField;
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.auditing;
import org.joda.time.DateTime;
/**
* Interface to abstract the ways setting the auditing information can be implemented.
*
* @author Oliver Gierke
* @since 1.5
*/
public interface AuditableBeanWrapper {
/**
* Set the creator of the object.
*
* @param value
*/
void setCreatedBy(Object value);
/**
* Set the date the object was created.
*
* @param value
*/
void setCreatedDate(DateTime value);
/**
* Set the last modifier of the object.
*
* @param value
*/
void setLastModifiedBy(Object value);
/**
* Set the last modification date.
*
* @param value
*/
void setLastModifiedDate(DateTime value);
}

View File

@@ -0,0 +1,220 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.auditing;
import java.lang.reflect.Field;
import java.util.Date;
import org.joda.time.DateTime;
import org.springframework.data.domain.Auditable;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.util.Assert;
/**
* A factory class to {@link AuditableBeanWrapper} instances.
*
* @author Oliver Gierke
* @since 1.5
*/
class AuditableBeanWrapperFactory {
/**
* Returns an {@link AuditableBeanWrapper} if the given object is capable of being equipped with auditing information.
*
* @param source the auditing candidate.
* @return
*/
@SuppressWarnings("unchecked")
public AuditableBeanWrapper getBeanWrapperFor(Object source) {
if (source == null) {
return null;
}
if (source instanceof Auditable) {
return new AuditableInterfaceBeanWrapper((Auditable<Object, ?>) source);
}
AnnotationAuditingMetadata metadata = AnnotationAuditingMetadata.getMetadata(source.getClass());
if (metadata.isAuditable()) {
return new ReflectionAuditingBeanWrapper(source);
}
return null;
}
/**
* An {@link AuditableBeanWrapper} that works with objects implementing
*
* @author Oliver Gierke
*/
static class AuditableInterfaceBeanWrapper implements AuditableBeanWrapper {
private final Auditable<Object, ?> auditable;
public AuditableInterfaceBeanWrapper(Auditable<Object, ?> auditable) {
this.auditable = auditable;
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedBy(java.lang.Object)
*/
public void setCreatedBy(Object value) {
auditable.setCreatedBy(value);
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedDate(org.joda.time.DateTime)
*/
public void setCreatedDate(DateTime value) {
auditable.setCreatedDate(value);
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedBy(java.lang.Object)
*/
public void setLastModifiedBy(Object value) {
auditable.setLastModifiedBy(value);
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedDate(org.joda.time.DateTime)
*/
public void setLastModifiedDate(DateTime value) {
auditable.setLastModifiedDate(value);
}
}
/**
* An {@link AuditableBeanWrapper} implementation that sets values on the target object using refelction.
*
* @author Oliver Gierke
*/
static class ReflectionAuditingBeanWrapper implements AuditableBeanWrapper {
private final AnnotationAuditingMetadata metadata;
private final Object target;
/**
* Creates a new {@link ReflectionAuditingBeanWrapper} to set auditing data on the given target object.
*
* @param target must not be {@literal null}.
*/
public ReflectionAuditingBeanWrapper(Object target) {
Assert.notNull(target, "Target object must not be null!");
this.metadata = AnnotationAuditingMetadata.getMetadata(target.getClass());
this.target = target;
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedBy(java.lang.Object)
*/
public void setCreatedBy(Object value) {
setField(metadata.getCreatedByField(), value);
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedDate(org.joda.time.DateTime)
*/
public void setCreatedDate(DateTime value) {
setDateField(metadata.getCreatedDateField(), value);
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedBy(java.lang.Object)
*/
public void setLastModifiedBy(Object value) {
setField(metadata.getLastModifiedByField(), value);
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedDate(org.joda.time.DateTime)
*/
public void setLastModifiedDate(DateTime value) {
setDateField(metadata.getLastModifiedDateField(), value);
}
/**
* Sets the given field to the given value if the field is not {@literal null}.
*
* @param field
* @param value
*/
private void setField(Field field, Object value) {
if (field != null) {
ReflectionUtils.setField(field, target, value);
}
}
/**
* Sets the given field to the given value if the field is not {@literal null}.
*
* @param field
* @param value
*/
private void setDateField(Field field, DateTime value) {
if (field == null) {
return;
}
ReflectionUtils.setField(field, target, getDateValueToSet(value, field));
}
/**
* Returns the {@link DateTime} in a type compatible to the given field.
*
* @param value
* @param field must not be {@literal null}.
* @return
*/
private Object getDateValueToSet(DateTime value, Field field) {
if (value == null) {
return null;
}
Class<?> targetType = field.getType();
if (DateTime.class.equals(targetType)) {
return value;
}
if (Date.class.equals(targetType)) {
return value.toDate();
}
if (Long.class.equals(targetType) || long.class.equals(targetType)) {
return value.getMillis();
}
throw new IllegalArgumentException(String.format("Invalid date type for field %s! Supported types are %s.",
field, AnnotationAuditingMetadata.SUPPORTED_DATE_TYPES));
}
}
}

View File

@@ -0,0 +1,174 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.auditing;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.domain.Auditable;
import org.springframework.data.domain.AuditorAware;
import org.springframework.util.Assert;
/**
* Auditing handler to mark entity objects created and modified.
*
* @author Oliver Gierke
* @since 1.5
*/
public class AuditingHandler<T> implements InitializingBean {
private static final Logger LOGGER = LoggerFactory.getLogger(AuditingHandler.class);
private final AuditableBeanWrapperFactory factory = new AuditableBeanWrapperFactory();
private DateTimeProvider dateTimeProvider = CurrentDateTimeProvider.INSTANCE;
private AuditorAware<T> auditorAware;
private boolean dateTimeForNow = true;
private boolean modifyOnCreation = true;
/**
* Setter to inject a {@code AuditorAware} component to retrieve the current auditor.
*
* @param auditorAware the auditorAware to set
*/
public void setAuditorAware(final AuditorAware<T> auditorAware) {
Assert.notNull(auditorAware);
this.auditorAware = auditorAware;
}
/**
* Setter do determine if {@link Auditable#setCreatedDate(DateTime)} and
* {@link Auditable#setLastModifiedDate(DateTime)} shall be filled with the current Java time. Defaults to
* {@code true}. One might set this to {@code false} to use database features to set entity time.
*
* @param dateTimeForNow the dateTimeForNow to set
*/
public void setDateTimeForNow(boolean dateTimeForNow) {
this.dateTimeForNow = dateTimeForNow;
}
/**
* Set this to false if you want to treat entity creation as modification and thus set the current date as
* modification date, too. Defaults to {@code true}.
*
* @param modifyOnCreation if modification information shall be set on creation, too
*/
public void setModifyOnCreation(boolean modifyOnCreation) {
this.modifyOnCreation = modifyOnCreation;
}
/**
* Sets the {@link DateTimeProvider} to be used to determine the dates to be set.
*
* @param dateTimeProvider
*/
public void setDateTimeProvider(DateTimeProvider dateTimeProvider) {
this.dateTimeProvider = dateTimeProvider == null ? CurrentDateTimeProvider.INSTANCE : dateTimeProvider;
}
/**
* Marks the given object as created.
*
* @param source
*/
public void markCreated(Object source) {
touch(source, true);
}
/**
* Marks the given object as modified.
*
* @param source
*/
public void markModified(Object source) {
touch(source, false);
}
private void touch(Object target, boolean isNew) {
AuditableBeanWrapper wrapper = factory.getBeanWrapperFor(target);
if (wrapper == null) {
return;
}
T auditor = touchAuditor(wrapper, isNew);
DateTime now = dateTimeForNow ? touchDate(wrapper, isNew) : null;
Object defaultedNow = now == null ? "not set" : now;
Object defaultedAuditor = auditor == null ? "unknown" : auditor;
LOGGER.debug("Touched {} - Last modification at {} by {}", new Object[] { target, defaultedNow, defaultedAuditor });
}
/**
* Sets modifying and creating auditioner. Creating auditioner is only set on new auditables.
*
* @param auditable
* @return
*/
private T touchAuditor(AuditableBeanWrapper wrapper, boolean isNew) {
if (null == auditorAware) {
return null;
}
T auditor = auditorAware.getCurrentAuditor();
if (isNew) {
wrapper.setCreatedBy(auditor);
if (!modifyOnCreation) {
return auditor;
}
}
wrapper.setLastModifiedBy(auditor);
return auditor;
}
/**
* Touches the auditable regarding modification and creation date. Creation date is only set on new auditables.
*
* @param wrapper
* @return
*/
private DateTime touchDate(AuditableBeanWrapper wrapper, boolean isNew) {
DateTime now = dateTimeProvider.getDateTime();
if (isNew) {
wrapper.setCreatedDate(now);
if (!modifyOnCreation) {
return now;
}
}
wrapper.setLastModifiedDate(now);
return now;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() {
if (auditorAware == null) {
LOGGER.debug("No AuditorAware set! Auditing will not be applied!");
}
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.auditing;
import org.joda.time.DateTime;
/**
* Default {@link DateTimeProvider} simply creating new {@link DateTime} instances for each method call.
*
* @author Oliver Gierke
* @since 1.5
*/
public enum CurrentDateTimeProvider implements DateTimeProvider {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.data.jpa.domain.support.DateTimeProvider#getDateTime()
*/
public DateTime getDateTime() {
return new DateTime();
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.auditing;
import org.joda.time.DateTime;
/**
* SPI to calculate the {@link DateTime} instance to be used when auditing.
*
* @author Oliver Gierke
* @since 1.5
*/
public interface DateTimeProvider {
/**
* Returns the {@link DateTime} to be used as modification date.
*
* @return
*/
DateTime getDateTime();
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.auditing;
import org.springframework.data.support.IsNewStrategy;
import org.springframework.data.support.IsNewStrategyFactory;
import org.springframework.util.Assert;
/**
* {@link AuditingHandler} extension that uses an {@link IsNewStrategyFactory} to expose a generic
* {@link #markAudited(Object)} method that will route calls to {@link #markCreated(Object)} or
* {@link #markModified(Object)} based on the {@link IsNewStrategy} determined from the factory.
*
* @author Oliver Gierke
* @since 1.5
*/
public class IsNewAwareAuditingHandler<T> extends AuditingHandler<T> {
private final IsNewStrategyFactory isNewStrategyFactory;
/**
* Creates a new {@link IsNewAwareAuditingHandler} using the given {@link IsNewStrategyFactory}.
*
* @param isNewStrategyFactory must not be {@literal null}.
*/
public IsNewAwareAuditingHandler(IsNewStrategyFactory isNewStrategyFactory) {
Assert.notNull(isNewStrategyFactory, "IsNewStrategy must not be null!");
this.isNewStrategyFactory = isNewStrategyFactory;
}
/**
* Marks the given object created or modified based on the {@link IsNewStrategy} returned by the
* {@link IsNewStrategyFactory} configured. Will rout the calls to {@link #markCreated(Object)} and
* {@link #markModified(Object)} accordingly.
*
* @param object
*/
public void markAudited(Object object) {
if (object == null) {
return;
}
IsNewStrategy strategy = isNewStrategyFactory.getIsNewStrategy(object.getClass());
if (strategy.isNew(object)) {
markCreated(object);
} else {
markModified(object);
}
}
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.authentication;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* Class used to provide credentials for username/password authentication
*
* @author Thomas Risberg
* @author Oliver Gierke
*/
public class UserCredentials {
public static final UserCredentials NO_CREDENTIALS = new UserCredentials(null, null);
private final String username;
private final String password;
/**
* Creates a new {@link UserCredentials} instance from the given username and password. Empty {@link String}s provided
* will be treated like no username or password set.
*
* @param username
* @param password
*/
public UserCredentials(String username, String password) {
this.username = StringUtils.hasText(username) ? username : null;
this.password = StringUtils.hasText(password) ? password : null;
}
/**
* Get the username to use for authentication.
*
* @return the username
*/
public String getUsername() {
return username;
}
/**
* Get the password to use for authentication.
*
* @return the password
*/
public String getPassword() {
return password;
}
/**
* Returns whether the credentials contain a username.
*
* @return
*/
public boolean hasUsername() {
return this.username != null;
}
/**
* Returns whether the credentials contain a password.
*
* @return
*/
public boolean hasPassword() {
return this.password != null;
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || !getClass().equals(obj.getClass())) {
return false;
}
UserCredentials that = (UserCredentials) obj;
return ObjectUtils.nullSafeEquals(this.username, that.username)
&& ObjectUtils.nullSafeEquals(this.password, that.password);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result += 31 * ObjectUtils.nullSafeHashCode(username);
result += 31 * ObjectUtils.nullSafeHashCode(password);
return result;
}
}

View File

@@ -0,0 +1,4 @@
/**
* Types to abstract authentication concepts.
*/
package org.springframework.data.authentication;

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.config;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.target.LazyInitTargetSource;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.data.auditing.AuditingHandler;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* {@link BeanDefinitionParser} that parses an {@link AuditingHandler} {@link BeanDefinition}
*
* @author Oliver Gierke
* @since 1.5
*/
public class AuditingHandlerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
private static final String AUDITOR_AWARE_REF = "auditor-aware-ref";
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
*/
@Override
protected Class<?> getBeanClass(Element element) {
return AuditingHandler.class;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#shouldGenerateId()
*/
@Override
protected boolean shouldGenerateId() {
return true;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.support.BeanDefinitionBuilder)
*/
@Override
protected void doParse(Element element, BeanDefinitionBuilder builder) {
String auditorAwareRef = element.getAttribute(AUDITOR_AWARE_REF);
if (StringUtils.hasText(auditorAwareRef)) {
builder.addPropertyValue("auditorAware", createLazyInitTargetSourceBeanDefinition(auditorAwareRef));
}
ParsingUtils.setPropertyValue(builder, element, "set-dates", "dateTimeForNow");
ParsingUtils.setPropertyReference(builder, element, "date-time-provider-ref", "dateTimeProvider");
}
private BeanDefinition createLazyInitTargetSourceBeanDefinition(String auditorAwareRef) {
BeanDefinitionBuilder targetSourceBuilder = rootBeanDefinition(LazyInitTargetSource.class);
targetSourceBuilder.addPropertyValue("targetBeanName", auditorAwareRef);
BeanDefinitionBuilder builder = rootBeanDefinition(ProxyFactoryBean.class);
builder.addPropertyValue("targetSource", targetSourceBuilder.getBeanDefinition());
return builder.getBeanDefinition();
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.config;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Helper to create {@link BeanComponentDefinition} more easily.
*
* @author Oliver Gierke
*/
public class BeanComponentDefinitionBuilder {
private final Element defaultSource;
private final ParserContext context;
/**
* Creates a new {@link BeanComponentDefinitionBuilder} using the given {@link Element} as default source and the
* given {@link ParserContext}.
*
* @param defaultSource must not be {@literal null}.
* @param context must not be {@literal null}.
*/
public BeanComponentDefinitionBuilder(Element defaultSource, ParserContext context) {
Assert.notNull(defaultSource);
Assert.notNull(context);
this.defaultSource = defaultSource;
this.context = context;
}
/**
* Creates a {@link BeanComponentDefinition} from the given {@link BeanDefinitionBuilder}. Will generate a bean name.
*
* @param builder must not be {@literal null}.
* @return
*/
public BeanComponentDefinition getComponent(BeanDefinitionBuilder builder) {
Assert.notNull(builder);
AbstractBeanDefinition definition = builder.getRawBeanDefinition();
String name = BeanDefinitionReaderUtils.generateBeanName(definition, context.getRegistry(), context.isNested());
return getComponent(builder, name);
}
/**
* Creates a {@link BeanComponentDefinition} from the given {@link BeanDefinitionBuilder} and inspects the backing
* {@link Element}s id attribute for a name. It will use this one if found or the given fallback if not.
*
* @param builder must not be {@literal null}.
* @param fallback must not be {@literal null} or empty.
* @return
*/
public BeanComponentDefinition getComponentIdButFallback(BeanDefinitionBuilder builder, String fallback) {
Assert.hasText(fallback);
String id = defaultSource.getAttribute("id");
return getComponent(builder, StringUtils.hasText(id) ? id : fallback);
}
/**
* Creates a {@link BeanComponentDefinition} from the given {@link BeanDefinitionBuilder} using the given name.
*
* @param builder must not be {@literal null}.
* @param name must not be {@literal null} or empty.
* @return
*/
public BeanComponentDefinition getComponent(BeanDefinitionBuilder builder, String name) {
return getComponent(builder, name, defaultSource);
}
/**
* Creates a new {@link BeanComponentDefinition} from the given {@link BeanDefinitionBuilder} using the given name and
* raw source object.
*
* @param builder must not be {@literal null}.
* @param name must not be {@literal null}.
* @param rawSource
* @return
*/
public BeanComponentDefinition getComponent(BeanDefinitionBuilder builder, String name, Object rawSource) {
Assert.notNull(builder);
Assert.hasText(name);
AbstractBeanDefinition definition = builder.getRawBeanDefinition();
definition.setSource(context.extractSource(rawSource));
return new BeanComponentDefinition(definition, name);
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.data.auditing.IsNewAwareAuditingHandler;
import org.springframework.util.Assert;
import org.w3c.dom.Element;
/**
* {@link AuditingHandlerBeanDefinitionParser} that will register am {@link IsNewAwareAuditingHandler}. Needs to get the
* bean id of the
*
* @author Oliver Gierke
*/
public class IsNewAwareAuditingHandlerBeanDefinitionParser extends AuditingHandlerBeanDefinitionParser {
private final String isNewStrategyFactoryBeanId;
/**
* Creates a new {@link IsNewAwareAuditingHandlerBeanDefinitionParser}.
*
* @param isNewStrategyFactoryBeanId must not be {@literal null} or empty.
*/
public IsNewAwareAuditingHandlerBeanDefinitionParser(String isNewStrategyFactoryBeanId) {
Assert.hasText(isNewStrategyFactoryBeanId);
this.isNewStrategyFactoryBeanId = isNewStrategyFactoryBeanId;
}
/*
* (non-Javadoc)
* @see org.springframework.data.config.AuditingHandlerBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
*/
@Override
protected Class<?> getBeanClass(Element element) {
return IsNewAwareAuditingHandler.class;
}
/*
* (non-Javadoc)
* @see org.springframework.data.config.AuditingHandlerBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.support.BeanDefinitionBuilder)
*/
@Override
protected void doParse(Element element, BeanDefinitionBuilder builder) {
builder.addConstructorArgReference(isNewStrategyFactoryBeanId);
super.doParse(element, builder);
}
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Utility methods for {@link BeanDefinitionParser} implementations.
*
* @author Oliver Gierke
*/
public abstract class ParsingUtils {
private ParsingUtils() {
}
/**
* Configures a property value for the given property name reading the attribute of the given name from the given
* {@link Element} if the attribute is configured.
*
* @param builder must not be {@literal null}.
* @param element must not be {@literal null}.
* @param attrName must not be {@literal null} or empty.
* @param propertyName must not be {@literal null} or empty.
*/
public static void setPropertyValue(BeanDefinitionBuilder builder, Element element, String attrName,
String propertyName) {
Assert.notNull(builder, "BeanDefinitionBuilder must not be null!");
Assert.notNull(element, "Element must not be null!");
Assert.hasText(attrName, "Attribute name must not be null!");
Assert.hasText(propertyName, "Property name must not be null!");
String attr = element.getAttribute(attrName);
if (StringUtils.hasText(attr)) {
builder.addPropertyValue(propertyName, attr);
}
}
/**
* Sets the property with the given attribute name on the given {@link BeanDefinitionBuilder} to the value of the
* attribute with the given name if the attribute is configured.
*
* @param builder must not be {@literal null}.
* @param element must not be {@literal null}.
* @param attribute must not be {@literal null} or empty.
*/
public static void setPropertyValue(BeanDefinitionBuilder builder, Element element, String attribute) {
setPropertyValue(builder, element, attribute, attribute);
}
/**
* Configures a bean property reference with the value of the attribute of the given name if it is configured.
*
* @param builder must not be {@literal null}.
* @param element must not be {@literal null}.
* @param attribute must not be {@literal null} or empty.
* @param property must not be {@literal null}or empty.
*/
public static void setPropertyReference(BeanDefinitionBuilder builder, Element element, String attribute,
String property) {
Assert.notNull(builder, "BeanDefinitionBuilder must not be null!");
Assert.notNull(element, "Element must not be null!");
Assert.hasText(attribute, "Attribute name must not be null!");
Assert.hasText(property, "Property name must not be null!");
String value = element.getAttribute(attribute);
if (StringUtils.hasText(value)) {
builder.addPropertyReference(property, value);
}
}
/**
* Returns the {@link BeanDefinition} built by the given {@link BeanDefinitionBuilder} enriched with source
* information derived from the given {@link Element}.
*
* @param builder must not be {@literal null}.
* @param context must not be {@literal null}.
* @param element must not be {@literal null}.
* @return
*/
public static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, ParserContext context,
Element element) {
Assert.notNull(element, "Element must not be null!");
Assert.notNull(context, "ParserContext must not be null!");
return getSourceBeanDefinition(builder, context.extractSource(element));
}
/**
* Returns the {@link AbstractBeanDefinition} built by the given builder with the given extracted source applied.
*
* @param builder must not be {@literal null}.
* @param source
* @return
*/
public static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, Object source) {
Assert.notNull(builder, "Builder must not be null!");
AbstractBeanDefinition definition = builder.getRawBeanDefinition();
definition.setSource(source);
return definition;
}
}

View File

@@ -0,0 +1,239 @@
/*
* Copyright 2010-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.config;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.HashSet;
import java.util.regex.Pattern;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.parsing.ReaderContext;
import org.springframework.beans.factory.xml.XmlReaderContext;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AspectJTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.RegexPatternTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.Assert;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Parser to populate the given {@link ClassPathScanningCandidateComponentProvider} with {@link TypeFilter}s parsed from
* the given {@link Element}'s children.
*
* @author Oliver Gierke
*/
public class TypeFilterParser {
private static final String FILTER_TYPE_ATTRIBUTE = "type";
private static final String FILTER_EXPRESSION_ATTRIBUTE = "expression";
private final ReaderContext readerContext;
private final ClassLoader classLoader;
/**
* Creates a new {@link TypeFilterParser} with the given {@link ReaderContext}.
*
* @param readerContext must not be {@literal null}.
*/
public TypeFilterParser(XmlReaderContext readerContext) {
this(readerContext, readerContext.getResourceLoader().getClassLoader());
}
/**
* Constructor to ease testing as {@link XmlReaderContext#getBeanClassLoader()} is final and thus cannot be mocked
* easily.
*
* @param readerContext must not be {@literal null}.
* @param classLoader must not be {@literal null}.
*/
TypeFilterParser(ReaderContext readerContext, ClassLoader classLoader) {
Assert.notNull(readerContext, "ReaderContext must not be null!");
Assert.notNull(classLoader, "ClassLoader must not be null!");
this.readerContext = readerContext;
this.classLoader = classLoader;
}
/**
* Returns all {@link TypeFilter} declared in nested elements of the given {@link Element}. Allows to selectively
* retrieve including or excluding filters based on the given {@link Type}.
*
* @param element must not be {@literal null}.
* @param type must not be {@literal null}.
* @return
*/
public Iterable<TypeFilter> parseTypeFilters(Element element, Type type) {
NodeList nodeList = element.getChildNodes();
Collection<TypeFilter> filters = new HashSet<TypeFilter>();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
Element childElement = type.getElement(node);
if (childElement != null) {
try {
filters.add(createTypeFilter(childElement, classLoader));
} catch (RuntimeException e) {
readerContext.error(e.getMessage(), readerContext.extractSource(element), e.getCause());
}
}
}
return filters;
}
/**
* Createsa a {@link TypeFilter} instance from the given {@link Element} and {@link ClassLoader}.
*
* @param element must not be {@literal null}.
* @param classLoader must not be {@literal null}.
* @return
*/
protected TypeFilter createTypeFilter(Element element, ClassLoader classLoader) {
String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE);
String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE);
try {
FilterType filter = FilterType.fromString(filterType);
return filter.getFilter(expression, classLoader);
} catch (ClassNotFoundException ex) {
throw new FatalBeanException("Type filter class not found: " + expression, ex);
}
}
/**
* Enum representing all the filter types available for {@code include} and {@code exclude} elements. This acts as
* factory for {@link TypeFilter} instances.
*
* @author Oliver Gierke
* @see #getFilter(String, ClassLoader)
*/
private static enum FilterType {
ANNOTATION {
@Override
@SuppressWarnings("unchecked")
public TypeFilter getFilter(String expression, ClassLoader classLoader) throws ClassNotFoundException {
return new AnnotationTypeFilter((Class<Annotation>) classLoader.loadClass(expression));
}
},
ASSIGNABLE {
@Override
public TypeFilter getFilter(String expression, ClassLoader classLoader) throws ClassNotFoundException {
return new AssignableTypeFilter(classLoader.loadClass(expression));
}
},
ASPECTJ {
@Override
public TypeFilter getFilter(String expression, ClassLoader classLoader) {
return new AspectJTypeFilter(expression, classLoader);
}
},
REGEX {
@Override
public TypeFilter getFilter(String expression, ClassLoader classLoader) {
return new RegexPatternTypeFilter(Pattern.compile(expression));
}
},
CUSTOM {
@Override
public TypeFilter getFilter(String expression, ClassLoader classLoader) throws ClassNotFoundException {
Class<?> filterClass = classLoader.loadClass(expression);
if (!TypeFilter.class.isAssignableFrom(filterClass)) {
throw new IllegalArgumentException("Class is not assignable to [" + TypeFilter.class.getName() + "]: "
+ expression);
}
return (TypeFilter) BeanUtils.instantiateClass(filterClass);
}
};
/**
* Returns the {@link TypeFilter} for the given expression and {@link ClassLoader}.
*
* @param expression
* @param classLoader
* @return
* @throws ClassNotFoundException
*/
abstract TypeFilter getFilter(String expression, ClassLoader classLoader) throws ClassNotFoundException;
/**
* Returns the {@link FilterType} for the given type as {@link String}.
*
* @param typeString
* @return
* @throws IllegalArgumentException if no {@link FilterType} could be found for the given argument.
*/
static FilterType fromString(String typeString) {
for (FilterType filter : FilterType.values()) {
if (filter.name().equalsIgnoreCase(typeString)) {
return filter;
}
}
throw new IllegalArgumentException("Unsupported filter type: " + typeString);
}
}
public static enum Type {
INCLUDE("include-filter"), EXCLUDE("exclude-filter");
private String elementName;
private Type(String elementName) {
this.elementName = elementName;
}
/**
* Returns the {@link Element} if the given {@link Node} is an {@link Element} and it's name equals the one of the
* type.
*
* @param node
* @return
*/
Element getElement(Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
String localName = node.getLocalName();
if (elementName.equals(localName)) {
return (Element) node;
}
}
return null;
}
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2011-12 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.convert;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**
* {@link TypeInformationMapper} implementation that can be either set up using a {@link MappingContext} or manually set
* up {@link Map} of {@link String} aliases to types. If a {@link MappingContext} is used the {@link Map} will be build
* inspecting the {@link PersistentEntity} instances for type alias information.
*
* @author Oliver Gierke
*/
public class ConfigurableTypeInformationMapper implements TypeInformationMapper {
private final Map<TypeInformation<?>, Object> typeMap;
/**
* Creates a new {@link ConfigurableTypeMapper} for the given type map.
*
* @param sourceTypeMap must not be {@literal null}.
*/
public ConfigurableTypeInformationMapper(Map<? extends Class<?>, String> sourceTypeMap) {
Assert.notNull(sourceTypeMap);
this.typeMap = new HashMap<TypeInformation<?>, Object>(sourceTypeMap.size());
for (Entry<? extends Class<?>, String> entry : sourceTypeMap.entrySet()) {
TypeInformation<?> key = ClassTypeInformation.from(entry.getKey());
String value = entry.getValue();
if (typeMap.containsValue(value)) {
throw new IllegalArgumentException(String.format(
"Detected mapping ambiguity! String %s cannot be mapped to more than one type!", value));
}
this.typeMap.put(key, value);
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeInformationMapper#createAliasFor(org.springframework.data.util.TypeInformation)
*/
public Object createAliasFor(TypeInformation<?> type) {
return typeMap.get(type);
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(java.lang.Object)
*/
public TypeInformation<?> resolveTypeFrom(Object alias) {
if (alias == null) {
return null;
}
for (Entry<TypeInformation<?>, Object> entry : typeMap.entrySet()) {
if (entry.getValue().equals(alias)) {
return entry.getKey();
}
}
return null;
}
}

View File

@@ -0,0 +1,184 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.convert;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**
* Default implementation of {@link MongoTypeMapper} allowing configuration of the key to lookup and store type
* information in {@link DBObject}. The key defaults to {@link #DEFAULT_TYPE_KEY}. Actual type-to-{@link String}
* conversion and back is done in {@link #getTypeString(TypeInformation)} or {@link #getTypeInformation(String)}
* respectively.
*
* @author Oliver Gierke
*/
public class DefaultTypeMapper<S> implements TypeMapper<S> {
private final TypeAliasAccessor<S> accessor;
private final List<? extends TypeInformationMapper> mappers;
/**
* Creates a new {@link DefaultTypeMapper} using the given {@link TypeAliasAccessor}. It will use a
* {@link SimpleTypeInformationMapper} to calculate type aliases.
*
* @param accessor must not be {@literal null}.
*/
public DefaultTypeMapper(TypeAliasAccessor<S> accessor) {
this(accessor, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
}
/**
* Creates a new {@link DefaultTypeMapper} using the given {@link TypeAliasAccessor} and {@link TypeInformationMapper}
* s.
*
* @param accessor must not be {@literal null}.
* @param mappers must not be {@literal null}.
*/
public DefaultTypeMapper(TypeAliasAccessor<S> accessor, List<? extends TypeInformationMapper> mappers) {
this(accessor, null, mappers);
}
/**
* Creates a new {@link DefaultTypeMapper} using the given {@link TypeAliasAccessor}, {@link MappingContext} and
* additional {@link TypeInformationMapper}s. Will register a {@link MappingContextTypeInformationMapper} before the
* given additional mappers.
*
* @param accessor must not be {@literal null}.
* @param mappingContext
* @param additionalMappers must not be {@literal null}.
*/
public DefaultTypeMapper(TypeAliasAccessor<S> accessor,
MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext,
List<? extends TypeInformationMapper> additionalMappers) {
Assert.notNull(accessor);
Assert.notNull(additionalMappers);
List<TypeInformationMapper> mappers = new ArrayList<TypeInformationMapper>(additionalMappers.size() + 1);
if (mappingContext != null) {
mappers.add(new MappingContextTypeInformationMapper(mappingContext));
}
mappers.addAll(additionalMappers);
this.mappers = Collections.unmodifiableList(mappers);
this.accessor = accessor;
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeMapper#readType(java.lang.Object)
*/
public TypeInformation<?> readType(S source) {
Assert.notNull(source);
Object alias = accessor.readAliasFrom(source);
if (alias == null) {
return null;
}
for (TypeInformationMapper mapper : mappers) {
TypeInformation<?> type = mapper.resolveTypeFrom(alias);
if (type != null) {
return type;
}
}
return null;
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeMapper#readType(java.lang.Object, org.springframework.data.util.TypeInformation)
*/
@SuppressWarnings("unchecked")
public <T> TypeInformation<? extends T> readType(S source, TypeInformation<T> basicType) {
Assert.notNull(source);
Class<?> documentsTargetType = getDefaultedTypeToBeUsed(source);
if (documentsTargetType == null) {
return basicType;
}
Class<T> rawType = basicType == null ? null : basicType.getType();
boolean isMoreConcreteCustomType = rawType == null ? true : rawType.isAssignableFrom(documentsTargetType)
&& !rawType.equals(documentsTargetType);
return isMoreConcreteCustomType ? (TypeInformation<? extends T>) ClassTypeInformation.from(documentsTargetType)
: basicType;
}
/**
* Returns the type discovered through {@link #readType(Object)} but defaulted to the one returned by
* {@link #getFallbackTypeFor(Object)}.
*
* @param source
* @return
*/
private Class<?> getDefaultedTypeToBeUsed(S source) {
TypeInformation<?> documentsTargetTypeInformation = readType(source);
documentsTargetTypeInformation = documentsTargetTypeInformation == null ? getFallbackTypeFor(source)
: documentsTargetTypeInformation;
return documentsTargetTypeInformation == null ? null : documentsTargetTypeInformation.getType();
}
/**
* Returns the type fallback {@link TypeInformation} in case none could be extracted from the given source.
*
* @param source will never be {@literal null}.
* @return
*/
protected TypeInformation<?> getFallbackTypeFor(S source) {
return null;
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeMapper#writeType(java.lang.Class, java.lang.Object)
*/
public void writeType(Class<?> type, S dbObject) {
writeType(ClassTypeInformation.from(type), dbObject);
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeMapper#writeType(org.springframework.data.util.TypeInformation, java.lang.Object)
*/
public void writeType(TypeInformation<?> info, S sink) {
Assert.notNull(info);
for (TypeInformationMapper mapper : mappers) {
Object alias = mapper.createAliasFor(info);
if (alias != null) {
accessor.writeTypeTo(sink, alias);
return;
}
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.convert;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.context.MappingContext;
/**
* Combined {@link EntityReader} and {@link EntityWriter} and add the ability to access a {@link MappingContext} and
* {@link ConversionService}.
*
* @param <E> the concrete {@link PersistentEntity} implementation the converter is based on.
* @param <P> the concrete {@link PersistentProperty} implementation the converter is based on.
* @param <T> the most common type the {@link EntityConverter} can actually convert.
* @param <S> the store specific source and sink an {@link EntityConverter} can deal with.
* @author Oliver Gierke
*/
public interface EntityConverter<E extends PersistentEntity<?, P>, P extends PersistentProperty<P>, T, S> extends
EntityReader<T, S>, EntityWriter<T, S> {
/**
* Returns the underlying {@link MappingContext} used by the converter.
*
* @return never {@literal null}
*/
MappingContext<? extends E, P> getMappingContext();
/**
* Returns the underlying {@link ConversionService} used by the converter.
*
* @return never {@literal null}.
*/
ConversionService getConversionService();
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2012-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.convert;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.model.ParameterValueProvider;
/**
* SPI to abstract strategies to create instances for {@link PersistentEntity}s.
*
* @author Oliver Gierke
*/
public interface EntityInstantiator {
/**
* Creates a new instance of the given entity using the given source to pull data from.
*
* @param entity will not be {@literal null}.
* @param provider will not be {@literal null}.
* @return
*/
<T, E extends PersistentEntity<? extends T, P>, P extends PersistentProperty<P>> T createInstance(E entity,
ParameterValueProvider<P> provider);
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.convert;
import java.util.Collections;
import java.util.Map;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.util.Assert;
/**
* Simple value object allowing access to {@link EntityInstantiator} instances for a given type falling back to a
* default one.
*
* @author Oliver Gierke
*/
public class EntityInstantiators {
private final EntityInstantiator fallback;
private final Map<Class<?>, EntityInstantiator> customInstantiators;
/**
* Creates a new {@link EntityInstantiators} using the default fallback instantiator and no custom ones.
*/
public EntityInstantiators() {
this(Collections.<Class<?>, EntityInstantiator> emptyMap());
}
/**
* Creates a new {@link EntityInstantiators} using the given {@link EntityInstantiator} as fallback.
*
* @param fallback must not be {@literal null}.
*/
public EntityInstantiators(EntityInstantiator fallback) {
this(fallback, Collections.<Class<?>, EntityInstantiator> emptyMap());
}
/**
* Creates a new {@link EntityInstantiators} using the default fallback instantiator and the given custom ones.
*
* @param customInstantiators must not be {@literal null}.
*/
public EntityInstantiators(Map<Class<?>, EntityInstantiator> customInstantiators) {
this(ReflectionEntityInstantiator.INSTANCE, customInstantiators);
}
/**
* Creates a new {@link EntityInstantiator} using the given fallback {@link EntityInstantiator} and the given custom
* ones.
*
* @param fallback must not be {@literal null}.
* @param customInstantiators must not be {@literal null}.
*/
public EntityInstantiators(EntityInstantiator defaultInstantiator,
Map<Class<?>, EntityInstantiator> customInstantiators) {
Assert.notNull(defaultInstantiator);
Assert.notNull(customInstantiators);
this.fallback = defaultInstantiator;
this.customInstantiators = customInstantiators;
}
/**
* Returns the {@link EntityInstantiator} to be used to create the given {@link PersistentEntity}.
*
* @param entity must not be {@literal null}.
* @return will never be {@literal null}.
*/
public EntityInstantiator getInstantiatorFor(PersistentEntity<?, ?> entity) {
Assert.notNull(entity);
Class<?> type = entity.getType();
if (!customInstantiators.containsKey(type)) {
return fallback;
}
EntityInstantiator instantiator = customInstantiators.get(entity.getType());
return instantiator == null ? fallback : instantiator;
}
}

View File

@@ -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.convert;
/**
* Interface to read object from store specific sources.
*
* @author Oliver Gierke
*/
public interface EntityReader<T, S> {
/**
* Reads the given source into the given type.
*
* @param type they type to convert the given source to.
* @param source the source to create an object of the given type from.
* @return
*/
<R extends T> R read(Class<R> type, S source);
}

View File

@@ -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.convert;
/**
* Interface to write objects into store specific sinks.
*
* @param <T> the entity type the converter can handle
* @param <S> the store specific sink the converter is able to write to
* @author Oliver Gierke
*/
public interface EntityWriter<T, S> {
void write(T source, S sink);
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.convert;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**
* {@link TypeInformationMapper} implementation that can be either set up using a {@link MappingContext} or manually set
* up {@link Map} of {@link String} aliases to types. If a {@link MappingContext} is used the {@link Map} will be build
* inspecting the {@link PersistentEntity} instances for type alias information.
*
* @author Oliver Gierke
*/
public class MappingContextTypeInformationMapper implements TypeInformationMapper {
private final Map<TypeInformation<?>, Object> typeMap;
private final MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext;
/**
* Creates a {@link MappingContextTypeInformationMapper} from the given {@link MappingContext}. Inspects all
* {@link PersistentEntity} instances for alias information and builds a {@link Map} of aliases to types from it.
*
* @param mappingContext must not be {@literal null}.
*/
public MappingContextTypeInformationMapper(MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext) {
Assert.notNull(mappingContext);
this.typeMap = new HashMap<TypeInformation<?>, Object>();
this.mappingContext = mappingContext;
for (PersistentEntity<?, ?> entity : mappingContext.getPersistentEntities()) {
safelyAddToCache(entity.getTypeInformation(), entity.getTypeAlias());
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeInformationMapper#createAliasFor(org.springframework.data.util.TypeInformation)
*/
public Object createAliasFor(TypeInformation<?> type) {
Object key = typeMap.get(type);
if (key != null) {
return key;
}
PersistentEntity<?, ?> entity = mappingContext.getPersistentEntity(type);
if (entity == null) {
return null;
}
Object alias = entity.getTypeAlias();
safelyAddToCache(type, alias);
return alias;
}
/**
* Adds the given alias to the cache in a {@literal null}-safe manner.
*
* @param key must not be {@literal null}.
* @param alias can be {@literal null}.
*/
private void safelyAddToCache(TypeInformation<?> key, Object alias) {
if (alias == null) {
return;
}
if (typeMap.containsValue(alias)) {
throw new IllegalArgumentException(String.format(
"Detected mapping ambiguity! String %s cannot be mapped to more than one type!", alias));
}
typeMap.put(key, alias);
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(java.lang.Object)
*/
public TypeInformation<?> resolveTypeFrom(Object alias) {
if (alias == null) {
return null;
}
for (Entry<TypeInformation<?>, Object> entry : typeMap.entrySet()) {
if (entry.getValue().equals(alias)) {
return entry.getKey();
}
}
for (PersistentEntity<?, ?> entity : mappingContext.getPersistentEntities()) {
if (alias.equals(entity.getTypeAlias())) {
return entity.getTypeInformation();
}
}
return null;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.convert;
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.convert.converter.Converter;
/**
* Annotation to clarify intended usage of a {@link Converter} as reading converter in case the conversion types leave
* room for disambiguation.
*
* @author Oliver Gierke
*/
@Target(TYPE)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface ReadingConverter {
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2012-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.convert;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PreferredConstructor;
import org.springframework.data.mapping.PreferredConstructor.Parameter;
import org.springframework.data.mapping.model.MappingInstantiationException;
import org.springframework.data.mapping.model.ParameterValueProvider;
/**
* {@link EntityInstantiator} that uses the {@link PersistentEntity}'s {@link PreferredConstructor} to instantiate an
* instance of the entity via reflection.
*
* @author Oliver Gierke
*/
public enum ReflectionEntityInstantiator implements EntityInstantiator {
INSTANCE;
@SuppressWarnings("unchecked")
public <T, E extends PersistentEntity<? extends T, P>, P extends PersistentProperty<P>> T createInstance(E entity,
ParameterValueProvider<P> provider) {
PreferredConstructor<? extends T, P> constructor = entity.getPersistenceConstructor();
if (constructor == null) {
try {
Class<?> clazz = entity.getType();
if (clazz.isArray()) {
Class<?> ctype = clazz;
int dims = 0;
while (ctype.isArray()) {
ctype = ctype.getComponentType();
dims++;
}
return (T) Array.newInstance(clazz, dims);
} else {
return BeanUtils.instantiateClass(entity.getType());
}
} catch (BeanInstantiationException e) {
throw new MappingInstantiationException(e.getMessage(), e);
}
}
List<Object> params = new ArrayList<Object>();
if (null != provider && constructor.hasParameters()) {
for (Parameter<?, P> parameter : constructor.getParameters()) {
params.add(provider.getParameterValue(parameter));
}
}
try {
return BeanUtils.instantiateClass(constructor.getConstructor(), params.toArray());
} catch (BeanInstantiationException e) {
throw new MappingInstantiationException(e.getMessage(), e);
}
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.convert;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Basic {@link TypeInformationMapper} implementation that interprets the alias handles as fully qualified class name
* and tries to load a class with the given name to build {@link TypeInformation}. Returns the fully qualified class
* name for alias creation.
*
* @author Oliver Gierke
*/
public class SimpleTypeInformationMapper implements TypeInformationMapper {
public static final SimpleTypeInformationMapper INSTANCE = new SimpleTypeInformationMapper();
/**
* Returns the {@link TypeInformation} that shall be used when the given {@link String} value is found as type hint.
* The implementation will simply interpret the given value as fully-qualified class name and try to load the class.
* Will return {@literal null} in case the given {@link String} is empty.
*
* @param value the type to load, must not be {@literal null}.
* @return the type to be used for the given {@link String} representation or {@literal null} if nothing found or the
* class cannot be loaded.
*/
public TypeInformation<?> resolveTypeFrom(Object alias) {
if (!(alias instanceof String)) {
return null;
}
String value = (String) alias;
if (!StringUtils.hasText(value)) {
return null;
}
try {
return ClassTypeInformation.from(ClassUtils.forName(value, null));
} catch (ClassNotFoundException e) {
return null;
}
}
/**
* Turn the given type information into the String representation that shall be stored. Default implementation simply
* returns the fully-qualified class name.
*
* @param typeInformation must not be {@literal null}.
* @return the String representation to be stored or {@literal null} if no type information shall be stored.
*/
public String createAliasFor(TypeInformation<?> type) {
return type.getType().getName();
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.convert;
/**
* Interface to abstract implementations of how to access a type alias from a given source or sink.
*
* @author Oliver Gierke
*/
public interface TypeAliasAccessor<S> {
/**
* Reads the type alias to be used from the given source.
*
* @param source
* @return can be {@literal null} in case no alias was found.
*/
Object readAliasFrom(S source);
/**
* Writes the given type alias to the given sink.
*
* @param sink
* @param alias
*/
void writeTypeTo(S sink, Object alias);
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.convert;
import org.springframework.data.util.TypeInformation;
/**
* Interface to abstract the mapping from a type alias to the actual type.
*
* @author Oliver Gierke
*/
public interface TypeInformationMapper {
/**
* Returns the actual {@link TypeInformation} to be used for the given alias.
*
* @param alias can be {@literal null}.
* @return
*/
TypeInformation<?> resolveTypeFrom(Object alias);
/**
* Returns the alias to be used for the given {@link TypeInformation}.
*
* @param type
* @return
*/
Object createAliasFor(TypeInformation<?> type);
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.convert;
import org.springframework.data.util.TypeInformation;
/**
* Interface to define strategies how to store type information in a store specific sink or source.
*
* @author Oliver Gierke
*/
public interface TypeMapper<S> {
/**
* Reads the {@link TypeInformation} from the given source.
*
* @param source must not be {@literal null}.
* @return
*/
TypeInformation<?> readType(S source);
/**
* Returns the {@link TypeInformation} from the given source if it is a more concrete type than the given default one.
*
* @param source must not be {@literal null}.
* @param defaultType
* @return
*/
<T> TypeInformation<? extends T> readType(S source, TypeInformation<T> defaultType);
/**
* Writes type information for the given type into the given sink.
*
* @param type must not be {@literal null}.
* @param dbObject must not be {@literal null}.
*/
void writeType(Class<?> type, S dbObject);
/**
* Writes type information for the given {@link TypeInformation} into the given sink.
*
* @param type must not be {@literal null}.
* @param dbObject must not be {@literal null}.
*/
void writeType(TypeInformation<?> type, S dbObject);
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.convert;
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.convert.converter.Converter;
/**
* Annotation to clarify intended usage of a {@link Converter} as writing converter in case the conversion types leave
* room for disambiguation.
*
* @author Oliver Gierke
*/
@Target(TYPE)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface WritingConverter {
}

View File

@@ -0,0 +1,6 @@
/**
* General purpose conversion framework to read objects from a data store abstraction and write it back.
*
* @see org.springframework.data.convert.EntityConverter
*/
package org.springframework.data.convert;

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.crossstore;
import java.util.Map;
import org.springframework.core.convert.ConversionService;
/**
* Interface representing the set of changes in an entity.
*
* @author Rod Johnson
* @author Thomas Risberg
*/
public interface ChangeSet {
<T> T get(String key, Class<T> requiredClass, ConversionService cs);
void set(String key, Object o);
Map<String, Object> getValues();
Object removeProperty(String k);
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.crossstore;
/**
* Interface introduced to objects exposing ChangeSet information
*
* @author Rod Johnson
* @author Thomas Risberg
*/
public interface ChangeSetBacked {
ChangeSet getChangeSet();
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.crossstore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.support.TransactionSynchronization;
public class ChangeSetBackedTransactionSynchronization implements TransactionSynchronization {
protected final Logger log = LoggerFactory.getLogger(getClass());
private final ChangeSetPersister<Object> changeSetPersister;
private final ChangeSetBacked entity;
private int changeSetTxStatus = -1;
public ChangeSetBackedTransactionSynchronization(ChangeSetPersister<Object> changeSetPersister, ChangeSetBacked entity) {
this.changeSetPersister = changeSetPersister;
this.entity = entity;
}
public void afterCommit() {
log.debug("After Commit called for " + entity);
changeSetPersister.persistState(entity, entity.getChangeSet());
changeSetTxStatus = 0;
}
public void afterCompletion(int status) {
log.debug("After Completion called with status = " + status);
if (changeSetTxStatus == 0) {
if (status == STATUS_COMMITTED) {
// this is good
log.debug("ChangedSetBackedTransactionSynchronization completed successfully for " + this.entity);
} else {
// this could be bad - TODO: compensate
log.error("ChangedSetBackedTransactionSynchronization failed for " + this.entity);
}
}
}
public void beforeCommit(boolean readOnly) {
}
public void beforeCompletion() {
}
public void flush() {
}
public void resume() {
throw new IllegalStateException(
"ChangedSetBackedTransactionSynchronization does not support transaction suspension currently.");
}
public void suspend() {
throw new IllegalStateException(
"ChangedSetBackedTransactionSynchronization does not support transaction suspension currently.");
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.crossstore;
import org.springframework.dao.DataAccessException;
/**
* Interface to be implemented by classes that can synchronize between data stores and ChangeSets.
*
* @param <K> entity key
* @author Rod Johnson
*/
public interface ChangeSetPersister<K> {
String ID_KEY = "_id";
String CLASS_KEY = "_class";
/**
* TODO how to tell when not found? throw exception?
*/
void getPersistentState(Class<? extends ChangeSetBacked> entityClass, K key, ChangeSet changeSet)
throws DataAccessException, NotFoundException;
/**
* Return id
*
* @param entity
* @param cs
* @return
* @throws DataAccessException
*/
K getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException;
/**
* Return key
*
* @param entity
* @param cs Key may be null if not persistent
* @return
* @throws DataAccessException
*/
K persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException;
/**
* Exception thrown in alternate control flow if getPersistentState finds no entity data.
*/
class NotFoundException extends Exception {
private static final long serialVersionUID = -8604207973816331140L;
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.crossstore;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.springframework.core.convert.ConversionService;
/**
* Simple ChangeSet implementation backed by a HashMap.
*
* @author Thomas Risberg
* @author Rod Johnson
*/
public class HashMapChangeSet implements ChangeSet {
private final Map<String, Object> values;
public HashMapChangeSet(Map<String, Object> values) {
this.values = values;
}
public HashMapChangeSet() {
this(new HashMap<String, Object>());
}
public void set(String key, Object o) {
values.put(key, o);
}
public String toString() {
return "HashMapChangeSet: values=[" + values + "]";
}
public Map<String, Object> getValues() {
return Collections.unmodifiableMap(values);
}
public Object removeProperty(String k) {
return this.values.remove(k);
}
public <T> T get(String key, Class<T> requiredClass, ConversionService conversionService) {
return conversionService.convert(values.get(key), requiredClass);
}
}

View File

@@ -0,0 +1,4 @@
/**
* Support for cross-store persistence.
*/
package org.springframework.data.crossstore;

View File

@@ -0,0 +1,87 @@
/*
* Copyright 2008-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.domain;
import java.io.Serializable;
import org.joda.time.DateTime;
/**
* Interface for auditable entities. Allows storing and retrieving creation and modification information. The changing
* instance (typically some user) is to be defined by a generics definition.
*
* @param <U> the auditing type. Typically some kind of user.
* @param <ID> the type of the audited type's identifier
* @author Oliver Gierke
*/
public interface Auditable<U, ID extends Serializable> extends Persistable<ID> {
/**
* Returns the user who created this entity.
*
* @return the createdBy
*/
U getCreatedBy();
/**
* Sets the user who created this entity.
*
* @param createdBy the creating entity to set
*/
void setCreatedBy(final U createdBy);
/**
* Returns the creation date of the entity.
*
* @return the createdDate
*/
DateTime getCreatedDate();
/**
* Sets the creation date of the entity.
*
* @param creationDate the creation date to set
*/
void setCreatedDate(final DateTime creationDate);
/**
* Returns the user who modified the entity lastly.
*
* @return the lastModifiedBy
*/
U getLastModifiedBy();
/**
* Sets the user who modified the entity lastly.
*
* @param lastModifiedBy the last modifying entity to set
*/
void setLastModifiedBy(final U lastModifiedBy);
/**
* Returns the date of the last modification.
*
* @return the lastModifiedDate
*/
DateTime getLastModifiedDate();
/**
* Sets the date of the last modification.
*
* @param lastModifiedDate the date of the last modification to set
*/
void setLastModifiedDate(final DateTime lastModifiedDate);
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2008-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.domain;
/**
* Interface for components that are aware of the application's current auditor. This will be some kind of user mostly.
*
* @param <T> the type of the auditing instance
* @author Oliver Gierke
*/
public interface AuditorAware<T> {
/**
* Returns the current auditor of the application.
*
* @return the current auditor
*/
T getCurrentAuditor();
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright 2008-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.domain;
import java.util.Iterator;
import java.util.List;
/**
* A page is a sublist of a list of objects. It allows gain information about the position of it in the containing
* entire list.
*
* @param <T>
* @author Oliver Gierke
*/
public interface Page<T> extends Iterable<T> {
/**
* Returns the number of the current page. Is always positive and less that {@code Page#getTotalPages()}.
*
* @return the number of the current page
*/
int getNumber();
/**
* Returns the size of the page.
*
* @return the size of the page
*/
int getSize();
/**
* Returns the number of total pages.
*
* @return the number of toral pages
*/
int getTotalPages();
/**
* Returns the number of elements currently on this page.
*
* @return the number of elements currently on this page
*/
int getNumberOfElements();
/**
* Returns the total amount of elements.
*
* @return the total amount of elements
*/
long getTotalElements();
/**
* Returns if there is a previous page.
*
* @return if there is a previous page
*/
boolean hasPreviousPage();
/**
* Returns whether the current page is the first one.
*
* @return
*/
boolean isFirstPage();
/**
* Returns if there is a next page.
*
* @return if there is a next page
*/
boolean hasNextPage();
/**
* Returns whether the current page is the last one.
*
* @return
*/
boolean isLastPage();
/*
* (non-Javadoc)
*
* @see java.lang.Iterable#iterator()
*/
Iterator<T> iterator();
/**
* Returns the page content as {@link List}.
*
* @return
*/
List<T> getContent();
/**
* Returns whether the {@link Page} has content at all.
*
* @return
*/
boolean hasContent();
/**
* Returns the sorting parameters for the page.
*
* @return
*/
Sort getSort();
}

View File

@@ -0,0 +1,255 @@
/*
* Copyright 2008-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Basic {@code Page} implementation.
*
* @param <T> the type of which the page consists.
* @author Oliver Gierke
*/
public class PageImpl<T> implements Page<T>, Serializable {
private static final long serialVersionUID = 867755909294344406L;
private final List<T> content = new ArrayList<T>();
private final Pageable pageable;
private final long total;
/**
* Constructor of {@code PageImpl}.
*
* @param content the content of this page
* @param pageable the paging information
* @param total the total amount of items available
*/
public PageImpl(List<T> content, Pageable pageable, long total) {
if (null == content) {
throw new IllegalArgumentException("Content must not be null!");
}
this.content.addAll(content);
this.total = total;
this.pageable = pageable;
}
/**
* Creates a new {@link PageImpl} with the given content. This will result in the created {@link Page} being identical
* to the entire {@link List}.
*
* @param content
*/
public PageImpl(List<T> content) {
this(content, null, (null == content) ? 0 : content.size());
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#getNumber()
*/
public int getNumber() {
return pageable == null ? 0 : pageable.getPageNumber();
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#getSize()
*/
public int getSize() {
return pageable == null ? 0 : pageable.getPageSize();
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#getTotalPages()
*/
public int getTotalPages() {
return getSize() == 0 ? 0 : (int) Math.ceil((double) total / (double) getSize());
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#getNumberOfElements()
*/
public int getNumberOfElements() {
return content.size();
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#getTotalElements()
*/
public long getTotalElements() {
return total;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#hasPreviousPage()
*/
public boolean hasPreviousPage() {
return getNumber() > 0;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#isFirstPage()
*/
public boolean isFirstPage() {
return !hasPreviousPage();
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#hasNextPage()
*/
public boolean hasNextPage() {
return ((getNumber() + 1) * getSize()) < total;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#isLastPage()
*/
public boolean isLastPage() {
return !hasNextPage();
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#iterator()
*/
public Iterator<T> iterator() {
return content.iterator();
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#asList()
*/
public List<T> getContent() {
return Collections.unmodifiableList(content);
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#hasContent()
*/
public boolean hasContent() {
return !content.isEmpty();
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#getSort()
*/
public Sort getSort() {
return pageable == null ? null : pageable.getSort();
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
String contentType = "UNKNOWN";
if (content.size() > 0) {
contentType = content.get(0).getClass().getName();
}
return String.format("Page %s of %d containing %s instances", getNumber(), getTotalPages(), contentType);
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof PageImpl<?>)) {
return false;
}
PageImpl<?> that = (PageImpl<?>) obj;
boolean totalEqual = this.total == that.total;
boolean contentEqual = this.content.equals(that.content);
boolean pageableEqual = this.pageable == null ? that.pageable == null : this.pageable.equals(that.pageable);
return totalEqual && contentEqual && pageableEqual;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result = 31 * result + (int) (total ^ total >>> 32);
result = 31 * result + (pageable == null ? 0 : pageable.hashCode());
result = 31 * result + content.hashCode();
return result;
}
}

View File

@@ -0,0 +1,164 @@
/*
* Copyright 2008-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.domain;
import java.io.Serializable;
import org.springframework.data.domain.Sort.Direction;
/**
* Basic Java Bean implementation of {@code Pageable}.
*
* @author Oliver Gierke
*/
public class PageRequest implements Pageable, Serializable {
private static final long serialVersionUID = 8280485938848398236L;
private final int page;
private final int size;
private final Sort sort;
/**
* Creates a new {@link PageRequest}. Pages are zero indexed, thus providing 0 for {@code page} will return the first
* page.
*
* @param size
* @param page
*/
public PageRequest(int page, int size) {
this(page, size, null);
}
/**
* Creates a new {@link PageRequest} with sort parameters applied.
*
* @param page
* @param size
* @param direction
* @param properties
*/
public PageRequest(int page, int size, Direction direction, String... properties) {
this(page, size, new Sort(direction, properties));
}
/**
* Creates a new {@link PageRequest} with sort parameters applied.
*
* @param page
* @param size
* @param sort
*/
public PageRequest(int page, int size, Sort sort) {
if (0 > page) {
throw new IllegalArgumentException("Page index must not be less than zero!");
}
if (0 >= size) {
throw new IllegalArgumentException("Page size must not be less than or equal to zero!");
}
this.page = page;
this.size = size;
this.sort = sort;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Pageable#getPageSize()
*/
public int getPageSize() {
return size;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Pageable#getPageNumber()
*/
public int getPageNumber() {
return page;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Pageable#getFirstItem()
*/
public int getOffset() {
return page * size;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Pageable#getSort()
*/
public Sort getSort() {
return sort;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof PageRequest)) {
return false;
}
PageRequest that = (PageRequest) obj;
boolean pageEqual = this.page == that.page;
boolean sizeEqual = this.size == that.size;
boolean sortEqual = this.sort == null ? that.sort == null : this.sort.equals(that.sort);
return pageEqual && sizeEqual && sortEqual;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result = 31 * result + page;
result = 31 * result + size;
result = 31 * result + (null == sort ? 0 : sort.hashCode());
return result;
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2008-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.domain;
/**
* Abstract interface for pagination information.
*
* @author Oliver Gierke
*/
public interface Pageable {
/**
* Returns the page to be returned.
*
* @return the page to be returned.
*/
int getPageNumber();
/**
* Returns the number of items to be returned.
*
* @return the number of items of that page
*/
int getPageSize();
/**
* Returns the offset to be taken according to the underlying page and page size.
*
* @return the offset to be taken
*/
int getOffset();
/**
* Returns the sorting parameters.
*
* @return
*/
Sort getSort();
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2008-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.domain;
import java.io.Serializable;
/**
* Simple interface for entities.
*
* @param <ID> the type of the identifier
* @author Oliver Gierke
*/
public interface Persistable<ID extends Serializable> extends Serializable {
/**
* Returns the id of the entity.
*
* @return the id
*/
ID getId();
/**
* Returns if the {@code Persistable} is new or was persisted already.
*
* @return if the object is new
*/
boolean isNew();
}

View File

@@ -0,0 +1,359 @@
/*
* Copyright 2008-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import org.springframework.util.StringUtils;
/**
* Sort option for queries. You have to provide at least a list of properties to sort for that must not include
* {@literal null} or empty strings. The direction defaults to {@link Sort#DEFAULT_DIRECTION}.
*
* @author Oliver Gierke
*/
public class Sort implements Iterable<org.springframework.data.domain.Sort.Order>, Serializable {
private static final long serialVersionUID = 5737186511678863905L;
public static final Direction DEFAULT_DIRECTION = Direction.ASC;
private final List<Order> orders;
/**
* Creates a new {@link Sort} instance using the given {@link Order}s.
*
* @param orders must not be {@literal null}.
*/
public Sort(Order... orders) {
this(Arrays.asList(orders));
}
/**
* Creates a new {@link Sort} instance.
*
* @param orders must not be {@literal null} or contain {@literal null}.
*/
public Sort(List<Order> orders) {
if (null == orders || orders.isEmpty()) {
throw new IllegalArgumentException("You have to provide at least one sort property to sort by!");
}
this.orders = orders;
}
/**
* Creates a new {@link Sort} instance. Order defaults to {@value Direction#ASC}.
*
* @param properties must not be {@literal null} or contain {@literal null} or empty strings
*/
public Sort(String... properties) {
this(DEFAULT_DIRECTION, properties);
}
/**
* Creates a new {@link Sort} instance.
*
* @param direction defaults to {@linke Sort#DEFAULT_DIRECTION} (for {@literal null} cases, too)
* @param properties must not be {@literal null} or contain {@literal null} or empty strings
*/
public Sort(Direction direction, String... properties) {
this(direction, properties == null ? new ArrayList<String>() : Arrays.asList(properties));
}
/**
* Creates a new {@link Sort} instance.
*
* @param direction
* @param properties
*/
public Sort(Direction direction, List<String> properties) {
if (properties == null || properties.isEmpty()) {
throw new IllegalArgumentException("You have to provide at least one property to sort by!");
}
this.orders = new ArrayList<Order>(properties.size());
for (String property : properties) {
this.orders.add(new Order(direction, property));
}
}
/**
* Returns a new {@link Sort} consisting of the {@link Order}s of the current {@link Sort} combined with the given
* ones.
*
* @param sort can be {@literal null}.
* @return
*/
public Sort and(Sort sort) {
if (sort == null) {
return this;
}
ArrayList<Order> these = new ArrayList<Order>(this.orders);
for (Order order : sort) {
these.add(order);
}
return new Sort(these);
}
/**
* Returns the order registered for the given property.
*
* @param property
* @return
*/
public Order getOrderFor(String property) {
for (Order order : this) {
if (order.getProperty().equals(property)) {
return order;
}
}
return null;
}
/*
* (non-Javadoc)
* @see java.lang.Iterable#iterator()
*/
public Iterator<Order> iterator() {
return this.orders.iterator();
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Sort)) {
return false;
}
Sort that = (Sort) obj;
return this.orders.equals(that.orders);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result = 31 * result + orders.hashCode();
return result;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return StringUtils.collectionToCommaDelimitedString(orders);
}
/**
* Enumeration for sort directions.
*
* @author Oliver Gierke
*/
public static enum Direction {
ASC, DESC;
/**
* Returns the {@link Direction} enum for the given {@link String} value.
*
* @param value
* @return
*/
public static Direction fromString(String value) {
try {
return Direction.valueOf(value.toUpperCase(Locale.US));
} catch (Exception e) {
throw new IllegalArgumentException(String.format(
"Invalid value '%s' for orders given! Has to be either 'desc' or 'asc' (case insensitive).", value), e);
}
}
}
/**
* PropertyPath implements the pairing of an {@link Direction} and a property. It is used to provide input for
* {@link Sort}
*
* @author Oliver Gierke
*/
public static class Order implements Serializable {
private static final long serialVersionUID = 1522511010900108987L;
private final Direction direction;
private final String property;
/**
* Creates a new {@link Order} instance. if order is {@literal null} then order defaults to
* {@link Sort#DEFAULT_DIRECTION}
*
* @param direction can be {@literal null}, will default to {@link Sort#DEFAULT_DIRECTION}
* @param property must not be {@literal null} or empty.
*/
public Order(Direction direction, String property) {
if (!StringUtils.hasText(property)) {
throw new IllegalArgumentException("Property must not null or empty!");
}
this.direction = direction == null ? DEFAULT_DIRECTION : direction;
this.property = property;
}
/**
* Creates a new {@link Order} instance. Takes a single property. Direction defaults to
* {@link Sort#DEFAULT_DIRECTION}.
*
* @param property must not be {@literal null} or empty.
*/
public Order(String property) {
this(DEFAULT_DIRECTION, property);
}
/**
* @deprecated use {@link Sort#Sort(Direction, List)} instead.
*/
@Deprecated
public static List<Order> create(Direction direction, Iterable<String> properties) {
List<Order> orders = new ArrayList<Sort.Order>();
for (String property : properties) {
orders.add(new Order(direction, property));
}
return orders;
}
/**
* Returns the order the property shall be sorted for.
*
* @return
*/
public Direction getDirection() {
return direction;
}
/**
* Returns the property to order for.
*
* @return
*/
public String getProperty() {
return property;
}
/**
* Returns whether sorting for this property shall be ascending.
*
* @return
*/
public boolean isAscending() {
return this.direction.equals(Direction.ASC);
}
/**
* Returns a new {@link Order} with the given {@link Order}.
*
* @param order
* @return
*/
public Order with(Direction order) {
return new Order(order, this.property);
}
/**
* Returns a new {@link Sort} instance for the given properties.
*
* @param properties
* @return
*/
public Sort withProperties(String... properties) {
return new Sort(this.direction, properties);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result = 31 * result + direction.hashCode();
result = 31 * result + property.hashCode();
return result;
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Order)) {
return false;
}
Order that = (Order) obj;
return this.direction.equals(that.direction) && this.property.equals(that.property);
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return String.format("%s: %s", property, direction);
}
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.domain.jaxb;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.domain.jaxb.SpringDataJaxb.OrderDto;
/**
* XmlAdapter to convert {@link Order} instances into {@link OrderDto}s and vice versa.
*
* @author Oliver Gierke
*/
public class OrderAdapter extends XmlAdapter<OrderDto, Order> {
public static final OrderAdapter INSTANCE = new OrderAdapter();
/*
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object)
*/
@Override
public OrderDto marshal(Order order) throws Exception {
if (order == null) {
return null;
}
OrderDto dto = new OrderDto();
dto.direction = order.getDirection();
dto.property = order.getProperty();
return dto;
}
/*
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object)
*/
@Override
public Order unmarshal(OrderDto source) throws Exception {
return source == null ? null : new Order(source.direction, source.property);
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.domain.jaxb;
import java.util.Collections;
import java.util.List;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.jaxb.SpringDataJaxb.PageDto;
import org.springframework.hateoas.Link;
/**
* {@link XmlAdapter} to convert {@link Page} instances into {@link PageDto} instances and vice versa.
*
* @author Oliver Gierke
*/
public class PageAdapter extends XmlAdapter<PageDto, Page<Object>> {
/*
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object)
*/
@Override
public PageDto marshal(Page<Object> source) throws Exception {
if (source == null) {
return null;
}
PageDto dto = new PageDto();
dto.content = source.getContent();
dto.add(getLinks(source));
return dto;
}
/*
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object)
*/
@Override
public Page<Object> unmarshal(PageDto v) throws Exception {
return null;
}
/**
* Return additional links that shall be added to the {@link PageDto}.
*
* @param source the source {@link Page}.
* @return
*/
protected List<Link> getLinks(Page<?> source) {
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.domain.jaxb;
import java.util.Collections;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.jaxb.SpringDataJaxb.OrderDto;
import org.springframework.data.domain.jaxb.SpringDataJaxb.PageRequestDto;
import org.springframework.data.domain.jaxb.SpringDataJaxb.SortDto;
/**
* {@link XmlAdapter} to convert {@link Pageable} instances int a {@link PageRequestDto} and vice versa.
*
* @author Oliver Gierke
*/
class PageableAdapter extends XmlAdapter<PageRequestDto, Pageable> {
/*
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object)
*/
@Override
public PageRequestDto marshal(Pageable request) throws Exception {
SortDto sortDto = SortAdapter.INSTANCE.marshal(request.getSort());
PageRequestDto dto = new PageRequestDto();
dto.orders = sortDto == null ? Collections.<OrderDto> emptyList() : sortDto.orders;
dto.page = request.getPageNumber();
dto.size = request.getPageSize();
return dto;
}
/*
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object)
*/
@Override
public Pageable unmarshal(PageRequestDto v) throws Exception {
if (v.orders.isEmpty()) {
return new PageRequest(v.page, v.size);
}
SortDto sortDto = new SortDto();
sortDto.orders = v.orders;
Sort sort = SortAdapter.INSTANCE.unmarshal(sortDto);
return new PageRequest(v.page, v.size, sort);
}
}

View File

@@ -0,0 +1,42 @@
package org.springframework.data.domain.jaxb;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.jaxb.SpringDataJaxb.SortDto;
/**
* {@link XmlAdapter} to convert {@link Sort} instances into {@link SortDto} instances and vice versa.
*
* @author Oliver Gierke
*/
public class SortAdapter extends XmlAdapter<SortDto, Sort> {
public static final SortAdapter INSTANCE = new SortAdapter();
/*
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object)
*/
@Override
public SortDto marshal(Sort source) throws Exception {
if (source == null) {
return null;
}
SortDto dto = new SortDto();
dto.orders = SpringDataJaxb.marshal(source, OrderAdapter.INSTANCE);
return dto;
}
/*
* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object)
*/
@Override
public Sort unmarshal(SortDto source) throws Exception {
return source == null ? null : new Sort(SpringDataJaxb.unmarshal(source.orders, OrderAdapter.INSTANCE));
}
}

View File

@@ -0,0 +1,153 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.domain.jaxb;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.hateoas.ResourceSupport;
import org.springframework.util.Assert;
/**
* Helper class containing utility methods to implement JAXB {@link XmlAdapter}s as well as the DTO types to be
* marshalled by JAXB.
*
* @author Oliver Gierke
*/
public class SpringDataJaxb {
public static final String NAMESPACE = "http://www.springframework.org/schema/data/jaxb";
/**
* The DTO for {@link Pageable}s/{@link PageRequest}s.
*
* @author Oliver Gierke
*/
@XmlRootElement(name = "page-request", namespace = NAMESPACE)
@XmlAccessorType(XmlAccessType.FIELD)
public static class PageRequestDto {
@XmlAttribute
int page, size;
@XmlElement(name = "order", namespace = NAMESPACE)
List<OrderDto> orders = new ArrayList<OrderDto>();
}
/**
* The DTO for {@link Sort}.
*
* @author Oliver Gierke
*/
@XmlRootElement(name = "sort", namespace = NAMESPACE)
@XmlAccessorType(XmlAccessType.FIELD)
public static class SortDto {
@XmlElement(name = "order", namespace = SpringDataJaxb.NAMESPACE)
List<OrderDto> orders = new ArrayList<OrderDto>();
}
/**
* The DTO for {@link Order}.
*
* @author Oliver Gierke
*/
@XmlRootElement(name = "order", namespace = NAMESPACE)
@XmlAccessorType(XmlAccessType.FIELD)
public static class OrderDto {
@XmlAttribute
String property;
@XmlAttribute
Direction direction;
}
/**
* The DTO for {@link Page}.
*
* @author Oliver Gierke
*/
@XmlRootElement(name = "page", namespace = NAMESPACE)
@XmlAccessorType(XmlAccessType.FIELD)
public static class PageDto extends ResourceSupport {
@XmlAnyElement
@XmlElementWrapper(name = "content")
List<Object> content;
}
/**
* Unmarshals each element of the given {@link Collection} using the given {@link XmlAdapter}.
*
* @param source
* @param adapter must not be {@literal null}.
* @return
* @throws Exception
*/
public static <T, S> List<T> unmarshal(Collection<S> source, XmlAdapter<S, T> adapter) throws Exception {
Assert.notNull(adapter);
if (source == null || source.isEmpty()) {
return Collections.emptyList();
}
List<T> result = new ArrayList<T>(source.size());
for (S element : source) {
result.add(adapter.unmarshal(element));
}
return result;
}
/**
* Marshals each of the elements of the given {@link Iterable} using the given {@link XmlAdapter}.
*
* @param source
* @param adapter must not be {@literal null}.
* @return
* @throws Exception
*/
public static <T, S> List<S> marshal(Iterable<T> source, XmlAdapter<S, T> adapter) throws Exception {
Assert.notNull(adapter);
if (source == null) {
return Collections.emptyList();
}
List<S> result = new ArrayList<S>();
for (T element : source) {
result.add(adapter.marshal(element));
}
return result;
}
}

View File

@@ -0,0 +1,21 @@
/**
* Central domain abstractions especially to be used in combination with the {@link org.springframework.data.repository.Repository} abstraction.
*
* @see org.springframework.data.repository.Repository
*/
@XmlSchema(xmlns = { @XmlNs(prefix = "sd", namespaceURI = org.springframework.data.domain.jaxb.SpringDataJaxb.NAMESPACE) })
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(value = org.springframework.data.domain.jaxb.PageableAdapter.class, type = Pageable.class),
@XmlJavaTypeAdapter(value = org.springframework.data.domain.jaxb.SortAdapter.class, type = Sort.class),
@XmlJavaTypeAdapter(value = org.springframework.data.domain.jaxb.PageAdapter.class, type = Page.class) })
package org.springframework.data.domain.jaxb;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlSchema;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

View File

@@ -0,0 +1,7 @@
/**
* Central domain abstractions especially to be used in combination with the {@link org.springframework.data.repository.Repository} abstraction.
*
* @see org.springframework.data.repository.Repository
*/
package org.springframework.data.domain;

View File

@@ -0,0 +1,93 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.history;
import java.lang.annotation.Annotation;
import org.joda.time.DateTime;
import org.springframework.data.util.AnnotationDetectionFieldCallback;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* A {@link RevisionMetadata} implementation that inspects the given object for fields with the configured annotations
* and returns the field's values on calls to {@link #getRevisionDate()} and {@link #getRevisionNumber()}.
*
* @author Oliver Gierke
*/
public class AnnotationRevisionMetadata<N extends Number & Comparable<N>> implements RevisionMetadata<N> {
private final Object entity;
private final N revisionNumber;
private final DateTime revisionDate;
/**
* Creates a new {@link AnnotationRevisionMetadata} inspecing the given entity for the given annotations. If no
* annotations will be provided these values will not be looked up from the entity and return {@literal null}.
*
* @param entity must not be {@literal null}.
* @param revisionNumberAnnotation
* @param revisionTimeStampAnnotation
*/
public AnnotationRevisionMetadata(final Object entity, Class<? extends Annotation> revisionNumberAnnotation,
Class<? extends Annotation> revisionTimeStampAnnotation) {
Assert.notNull(entity);
this.entity = entity;
if (revisionNumberAnnotation != null) {
AnnotationDetectionFieldCallback numberCallback = new AnnotationDetectionFieldCallback(revisionNumberAnnotation);
ReflectionUtils.doWithFields(entity.getClass(), numberCallback);
this.revisionNumber = numberCallback.getValue(entity);
} else {
this.revisionNumber = null;
}
if (revisionTimeStampAnnotation != null) {
AnnotationDetectionFieldCallback revisionCallback = new AnnotationDetectionFieldCallback(
revisionTimeStampAnnotation);
ReflectionUtils.doWithFields(entity.getClass(), revisionCallback);
this.revisionDate = new DateTime(revisionCallback.getValue(entity));
} else {
this.revisionDate = null;
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.history.RevisionMetadata#getRevisionNumber()
*/
public N getRevisionNumber() {
return revisionNumber;
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.history.RevisionMetadata#getRevisionDate()
*/
public DateTime getRevisionDate() {
return revisionDate;
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.history.RevisionMetadata#getDelegate()
*/
@SuppressWarnings("unchecked")
public <T> T getDelegate() {
return (T) entity;
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.history;
import org.joda.time.DateTime;
import org.springframework.util.Assert;
/**
* Wrapper to contain {@link RevisionMetadata} as well as the revisioned entity.
*
* @author Oliver Gierke
* @author Philipp Huegelmeyer
*/
public final class Revision<N extends Number & Comparable<N>, T> implements Comparable<Revision<N, ?>> {
private final RevisionMetadata<N> metadata;
private final T entity;
/**
* Creates a new {@link Revision} consisting of the given {@link RevisionMetadata} and entity.
*
* @param metadata must not be {@literal null}.
* @param entity must not be {@literal null}.
*/
public Revision(RevisionMetadata<N> metadata, T entity) {
Assert.notNull(metadata);
Assert.notNull(entity);
this.metadata = metadata;
this.entity = entity;
}
/**
* Returns the revision number of the revision.
*
* @return the revision number.
*/
public N getRevisionNumber() {
return metadata.getRevisionNumber();
}
/**
* Returns the revision date of the revision.
*
* @return
*/
public DateTime getRevisionDate() {
return metadata.getRevisionDate();
}
/**
* Returns the underlying entity.
*
* @return the entity
*/
public T getEntity() {
return entity;
}
/**
* Returns the {@link RevisionMetadata} for the current {@link Revision}.
*
* @return the metadata
*/
public RevisionMetadata<N> getMetadata() {
return metadata;
}
/*
* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(Revision<N, ?> that) {
return getRevisionNumber().compareTo(that.getRevisionNumber());
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@SuppressWarnings("unchecked")
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Revision)) {
return false;
}
Revision<N, T> that = (Revision<N, T>) obj;
boolean sameRevisionNumber = this.metadata.getRevisionNumber().equals(that.metadata.getRevisionNumber());
return !sameRevisionNumber ? false : this.entity.equals(that.entity);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result += 31 * metadata.hashCode();
result += 31 * entity.hashCode();
return result;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return String.format("Revision %s of entity %s - Revision metadata %s", getRevisionNumber(), entity, metadata);
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.history;
import org.joda.time.DateTime;
/**
* Metadata about a revision.
*
* @author Philipp Huegelmeyer
* @author Oliver Gierke
*/
public interface RevisionMetadata<N extends Number & Comparable<N>> {
/**
* Returns the revision number of the revision.
*
* @return
*/
N getRevisionNumber();
/**
* Returns the date of the revision.
*
* @return
*/
DateTime getRevisionDate();
/**
* Returns the underlying revision metadata which might provider more detailed implementation specific information.
*
* @return
*/
<T> T getDelegate();
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.history;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.springframework.util.Assert;
/**
* Simple wrapper class for a {@link List} of {@link Revisions} allowing to canonically access the latest revision.
* Allows iterating over the underlying {@link Revisions} starting with older revisions.
*
* @author Oliver Gierke
*/
public class Revisions<N extends Number & Comparable<N>, T> implements Iterable<Revision<N, T>> {
private final List<Revision<N, T>> revisions;
private final boolean latestLast;
/**
* Creates a new {@link Revisions} instance containing the given revisions. Will make sure they are ordered
* ascendingly.
*
* @param revisions must not be {@literal null}.
*/
public Revisions(List<? extends Revision<N, T>> revisions) {
this(revisions, true);
}
/**
* Creates a new {@link Revisions} instance using the given revisions.
*
* @param revisions must not be {@literal null}.
* @param latestLast
*/
private Revisions(List<? extends Revision<N, T>> revisions, boolean latestLast) {
Assert.notNull(revisions);
this.revisions = new ArrayList<Revision<N, T>>(revisions);
this.latestLast = latestLast;
Collections.sort(this.revisions);
if (!latestLast) {
Collections.reverse(this.revisions);
}
}
/**
* Returns the latest revision of the revisions backing the wrapper independently of the order.
*
* @return
*/
public Revision<N, T> getLatestRevision() {
int index = latestLast ? revisions.size() - 1 : 0;
return revisions.get(index);
}
/**
* Reverses the current {@link Revisions}. By default this will return the revisions with the latest revision first.
*
* @return
*/
public Revisions<N, T> reverse() {
List<Revision<N, T>> result = new ArrayList<Revision<N, T>>(revisions);
Collections.reverse(result);
return new Revisions<N, T>(result, !latestLast);
}
/*
* (non-Javadoc)
* @see java.lang.Iterable#iterator()
*/
public Iterator<Revision<N, T>> iterator() {
return revisions.iterator();
}
/**
* Returns the content of the {@link Revisions} instance.
*
* @return
*/
public List<Revision<N, T>> getContent() {
return Collections.unmodifiableList(revisions);
}
}

View File

@@ -0,0 +1,5 @@
/**
* Basic interfaces and value objects for historiography API.
*/
package org.springframework.data.history;

View File

@@ -0,0 +1,48 @@
/*
* 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;
/**
* Value object to capture {@link Association}s.
*
* @param the {@link PersistentProperty}s the association connects.
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class Association<P extends PersistentProperty<P>> {
private final P inverse;
private final P obverse;
/**
* Creates a new {@link Association} between the two given {@link PersistentProperty}s.
*
* @param inverse
* @param obverse
*/
public Association(P inverse, P obverse) {
this.inverse = inverse;
this.obverse = obverse;
}
public P getInverse() {
return inverse;
}
public P getObverse() {
return obverse;
}
}

View File

@@ -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.mapping;
/**
* Callback interface to implement functionality to be applied to a collection of {@link Association}s.
*
* @author Jon Brisbin <jbrisbin@vmware.com>
* @author Oliver Gierke
*/
public interface AssociationHandler<P extends PersistentProperty<P>> {
/**
* Processes the given {@link Association}.
*
* @param association
*/
void doWithAssociation(Association<P> association);
}

View File

@@ -0,0 +1,149 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mapping;
import org.springframework.data.convert.EntityInstantiator;
import org.springframework.data.util.TypeInformation;
/**
* Represents a persistent entity.
*
* @author Oliver Gierke
* @author Graeme Rocher
* @author Jon Brisbin
* @author Patryk Wasik
*/
public interface PersistentEntity<T, P extends PersistentProperty<P>> {
/**
* The entity name including any package prefix.
*
* @return must never return {@literal null}
*/
String getName();
/**
* Returns the {@link PreferredConstructor} to be used to instantiate objects of this {@link PersistentEntity}.
*
* @return {@literal null} in case no suitable constructor for automatic construction can be found. This usually
* indicates that the instantiation of the object of tthat persistent entity is done through either a customer
* {@link EntityInstantiator} or handled by custom conversion mechanisms entirely.
*/
PreferredConstructor<T, P> getPersistenceConstructor();
/**
* Returns whether the given {@link PersistentProperty} is referred to by a constructor argument of the
* {@link PersistentEntity}.
*
* @param property
* @return true if the given {@link PersistentProperty} is referred to by a constructor argument or {@literal false}
* if not or {@literal null}.
*/
boolean isConstructorArgument(PersistentProperty<?> property);
/**
* Returns whether the given {@link PersistentProperty} is the id property of the entity.
*
* @param property
* @return
*/
boolean isIdProperty(PersistentProperty<?> property);
/**
* Returns whether the given {@link PersistentProperty} is the version property of the entity.
*
* @param property
* @return
*/
boolean isVersionProperty(PersistentProperty<?> property);
/**
* Returns the id property of the {@link PersistentEntity}. Can be {@literal null} in case this is an entity
* completely handled by a custom conversion.
*
* @return the id property of the {@link PersistentEntity}.
*/
P getIdProperty();
/**
* Returns the version property of the {@link PersistentEntity}. Can be {@literal null} in case no version property is
* available on the entity.
*
* @return the version property of the {@link PersistentEntity}.
*/
P getVersionProperty();
/**
* Obtains a {@link PersistentProperty} instance by name.
*
* @param name The name of the property
* @return the {@link PersistentProperty} or {@literal null} if it doesn't exist.
*/
P getPersistentProperty(String name);
/**
* Returns whether the {@link PersistentEntity} has an id property. If this call returns {@literal true},
* {@link #getIdProperty()} will return a non-{@literal null} value.
*
* @return
*/
boolean hasIdProperty();
/**
* Returns whether the {@link PersistentEntity} has a version property. If this call returns {@literal true},
* {@link #getVersionProperty()} will return a non-{@literal null} value.
*
* @return
*/
boolean hasVersionProperty();
/**
* Returns the resolved Java type of this entity.
*
* @return The underlying Java class for this entity
*/
Class<T> getType();
/**
* Returns the alias to be used when storing type information. Might be {@literal null} to indicate that there was no
* alias defined through the mapping metadata.
*
* @return
*/
Object getTypeAlias();
/**
* Returns the {@link TypeInformation} backing this {@link PersistentEntity}.
*
* @return
*/
TypeInformation<T> getTypeInformation();
/**
* Applies the given {@link PropertyHandler} to all {@link PersistentProperty}s contained in this
* {@link PersistentEntity}.
*
* @param handler must not be {@literal null}.
*/
void doWithProperties(PropertyHandler<P> handler);
/**
* Applies the given {@link AssociationHandler} to all {@link Association} contained in this {@link PersistentEntity}.
*
* @param handler must not be {@literal null}.
*/
void doWithAssociations(AssociationHandler<P> handler);
}

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