diff --git a/pom.xml b/pom.xml index 78cfc622b..c4f54df1a 100644 --- a/pom.xml +++ b/pom.xml @@ -168,6 +168,65 @@ 1.5 + + com.agilejava.docbkx + docbkx-maven-plugin + 2.0.7 + + + + generate-html + generate-pdf + + pre-site + + + + + org.docbook + docbook-xml + 4.4 + runtime + + + + index.xml + true + ${project.basedir}/src/docbkx/resources/xsl/fopdf.xsl + css/html.css + false + ${project.basedir}/src/docbkx/resources/xsl/html.xsl + 1 + 1 + + + + + version + ${pom.version} + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docbkx/appendix/faq.xml b/src/docbkx/appendix/faq.xml new file mode 100644 index 000000000..3dfca50bf --- /dev/null +++ b/src/docbkx/appendix/faq.xml @@ -0,0 +1,92 @@ + + + + Frequently asked questions + + + + Common + + + + I'd like to get more detailled logging information on what + methods are called inside + JpaRepository, e.g. How can I gain + them? + + + + You can make use of + CustomizableTraceInterceptor provided by + Spring: + + <bean id="customizableTraceInterceptor" class=" + org.springframework.aop.interceptor.CustomizableTraceInterceptor"> + <property name="enterMessage" value="Entering $[methodName]($[arguments])"/> + <property name="exitMessage" value="Leaving $[methodName](): $[returnValue]"/> +</bean> + +<aop:config> + <aop:advisor advice-ref="customizableTraceInterceptor" + pointcut="execution(public * org.sfw.data.jpa.repository.JpaRepository+.*(..))"/> +</aop:config> + + + + + + Infrastructure + + + + Currently I have implemented a repository layer based on + HibernateDaoSupport. I create a + SessionFactory by using Spring's + AnnotationSessionFactoryBean. How do I get + Hades DAOs working in this environment. + + + + You have to replace + AnnotationSessionFactoryBean with the + LocalContainerEntityManagerFactoryBean. + Supposed you have registered it under + entityManagerFactory you can reference it in you + repositories based on HibernateDaoSupport as + follows: + + + Looking up a SessionFactory from an + HibernateEntityManagerFactory + + <bean class="com.acme.YourDaoBasedOnHibernateDaoSupport"> + <property name="sessionFactory"> + <bean factory-bean="entityManagerFactory" + factory-method="getSessionFactory" /> + </property> +</bean> + + + + + + + Auditing + + + + I want to use Spring Data JPA auditing capabilities but have + my database already set up to set modification and creation date on + entities. How to prevent Hades to set the date + programmatically. + + + + Just use the set-dates attribute of the + auditing namespace element to false. + + + + + \ No newline at end of file diff --git a/src/docbkx/appendix/glossary.xml b/src/docbkx/appendix/glossary.xml new file mode 100644 index 000000000..b4df26fd9 --- /dev/null +++ b/src/docbkx/appendix/glossary.xml @@ -0,0 +1,114 @@ + + + + + A + + + AOP + + + Aspect oriented programming + + + + + + C + + + Commons DBCP + + + Commons DataBase Connection Pools - Library of the Apache + foundation offering pooling implementations of the + DataSource interface. + + + + + CRUD + + + Create, Read, Update, Delete - Basic persistence + operations + + + + + + D + + + DAO + + + Data Access Object - Pattern to separate persisting logic from + the object to be persisted + + + + + Dependency Injection + + + Pattern to hand a component's dependency to the component from + outside, freeing the component to lookup the dependant itself. For + more information see http://en.wikipedia.org/wiki/Dependency_Injection. + + + + + + E + + + EclipseLink + + + Object relational mapper implementing JPA - http://www.eclipselink.org + + + + + + H + + + Hibernate + + + Object relational mapper implementing JPA - http://www.hibernate.org + + + + + + J + + + JPA + + + Java Persistence Api + + + + + + S + + + Spring + + + Java application framework - http://www.springframework.org + + + + \ No newline at end of file diff --git a/src/docbkx/index.xml b/src/docbkx/index.xml new file mode 100644 index 000000000..a87073c81 --- /dev/null +++ b/src/docbkx/index.xml @@ -0,0 +1,77 @@ + + + + + Spring Data JPA - Reference Documentation + + 1.0.0.BUILD-SNAPSHOT + + + + Oliver + + Gierke + + + Senior Consultant + + SpringSource - a division of VMware + + + ogierke@vmware.com + + + + + Copies of this document may be made for your own use and for + distribution to others, provided that you do not charge any fee for such + copies and further provided that each copy contains this Copyright + Notice, whether distributed in print or electronically. + + + + + + 2008-2011 + + The original authors + + + + + 09.02.2011 + + + Oliver + + Gierke + + + Initial port from Hades documentation + + + + + + + + + + Reference Documentation + + + + + + + + Appendix + + + + + + + + \ No newline at end of file diff --git a/src/docbkx/preface.xml b/src/docbkx/preface.xml new file mode 100644 index 000000000..7c3ca258f --- /dev/null +++ b/src/docbkx/preface.xml @@ -0,0 +1,38 @@ + + + + Preface + +
+ Project metadata + + + + Version control - git://github.com/SpringSource/spring-data-jpa.git + + + + Bugtracker - https://jira.springsource.org/browse/DATAJPA + + + + Release repository - http://maven.springframework.org/release + + + + Milestone repsitory - http://maven.springframework.org/milestone + + + + Snapshot repsitory - http://maven.springframework.org/snapshot + + +
+
\ No newline at end of file diff --git a/src/docbkx/reference/core-concepts.xml b/src/docbkx/reference/core-concepts.xml new file mode 100644 index 000000000..7a156018f --- /dev/null +++ b/src/docbkx/reference/core-concepts.xml @@ -0,0 +1,673 @@ + + + + Repositories + +
+ Introduction + + Implementing a data access layer of an application has been + cumbersome for quite a while. Too much boilerplate code had to be written. + Domain classes were anemic and haven't been designed in a real object + oriented or domain driven manner. + + Using both of these technologies makes developers life a lot easier + regarding rich domain model's persistence. Nevertheless the amount of + boilerplate code to implement repositories especially is still quite high. + So the goal of the repository abstraction of Spring Data is to reduce the + effort to implement data access layers for various persistence stores + significantly + + The following chapters will introduce the core concepts and + interfaces of Spring Data repositories. +
+ +
+ Core concepts + + The central interface in Spring Data repository abstraction is + Repository (probably not that much of a + surprise). It is typeable to the domain class to manage as well as the id + type of the domain class and provides some sophisticated functionality + around CRUD for the entity managed. + + + Repository interface + + + + + + + + + + + + + + + + + + + public interface Repository<T, ID extends Serializable> { + + T save(T entity); + + T findById(ID primaryKey); + + List<T> findAll(); + + Page<T> findAll(Pageable pageable); + + Long count(); + + void delete(T entity); + + boolean exists(ID primaryKey); + + // … more functionality omitted. +} + + + + Saves the given entity. + + + + Returns the entity identified by the given id. + + + + Returns all entities. + + + + Returns a page of entities. + + + + Returns the number of entities. + + + + Deletes the given entity. + + + + Returns whether an entity with the given id exists. + + + + + + Usually we will have persistence technology specific sub-interfaces + to include additional technology specific methods. We will now ship + implementations for a variety of Spring Data modules that implement that + interface. +
+ +
+ Query methods + + Next to standard CRUD functionality repositories are usually query + the underlying datastore. With Spring Data declaring those queries becomes + a four-step process (we use the JPA based module as example but that works + the same way for other stores): + + + + Declare an interface extending the technology specific + Repository sub-interface and type it to the domain class it shall + handle. + + public interface PersonRepository extends JpaRepository<User, Long> { … } + + + + Declare query methods on the interface. + + List<Person> findByLastname(String lastname); + + + + Setup Spring to create proxy instances for those + interfaces. + + <?xml version="1.0" encoding="UTF-8"?> +<beans:beans xmlns:beans="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://www.springframework.org/schema/data/jpa + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/data/jpa + http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> + + <repositories base-package="com.acme.repositories" /> + +</beans> + + + + Get the repository instance injected and use it. + + public class SomeClient { + + @Autowired private PersonRepoyitory repository; + + public void doSomething() { + List<Person> persons = repository.findByLastname("Matthews"); + } + + + + At this stage we barely scratched the surface of what's possible + with the repositories but the general approach should be clear. Let's go + through each of these steps and and figure out details and various options + that you have at each stage. + +
+ Defining repository interfaces + + As a very first step you define a domain class specific repository + interface to start with. It's got to be typed to the domain class and an + ID type so that you get CRUD methods of the + Repository interface tailored to + it. +
+ +
+ Defining query methods + +
+ Query lookup strategies + + The next thing we have to discuss is the definition of query + methods. There's roughly two main ways how the repository proxy is + generally able to come up with the store specific query from the + method name. The first option is to derive the quer from the method + name directly, the second is using some kind of additionally created + query. What detailed options are available pretty much depends on the + actual store. However there's got to be some algorithm the decision + which actual query to is made. + + There's three strategies for the repository infrastructure to + resolve the query. The strategy to be used can be configured at the + namespace through the query-lookup-strategy attribute. + However might be the case that some of the strategies are not + supported for the specific datastore. Here are your options: + + + CREATE + + This strategy will try to construct a store specific query + from the query method's name. The general approach is to remove a + given set of well-known prefixes from the method name and parse the + rest of the method. Read more about query construction in . + + + + USE_DECLARED_QUERY + + This strategy tries to find a declared query which will be + used for execution first. The query could be defined by an + annotation somwhere or declared by other means. Please consult the + documentation of the specific store to find out what options are + available for that store. If the repository infrastructure does not + find a declared query for the method at bootstrap time it will + fail. + + + + CREATE_IF_NOT_FOUND (default) + + This strategy is actually a combination of the both mentioned + above. It will try to lookup a declared query first but create a + custom method name based query if no declared query was found. This + is default lookup strategy and thus will be used if you don't + configure anything explicitly. It allows quick query definition by + method names but also custom tuning of these queries by introducing + declared queries for those who need explicit tuning. + +
+ +
+ Query creation + + The query builder mechanism built into Spring Data repository + infrastructue is useful to build constraining queries over entities of + the repository. We will strip the prefixes findBy, + find, readBy, read, + getBy as well as get from the method and + start parsing the rest of it. At a very basic level you can define + conditions on entity properties and concatenate them with + AND and OR. + + + Query creation from method names + + public interface PersonRepository extends JpaRepository<User, Long> { + + List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname); +} + + + The actual result of parsing that method will of course depend + on the persistence store we create the query for. However there are + some general things to notice. The expression are usually property + traversals combined with operators that can be concatenated. As you + can see in the example you can combine property expressions with And + and Or. Beyond that you will get support for various operators like + Between, LessThan, GreaterThan, Like for the property expressions. As + the operators supported can vary from datastore to datastore please + consult the according part of the reference documentation. + +
+ Property expressions + + Property expressions can just refer to a direct property of + the managed entity (as you just saw in the example above. On query + creation time we already make sure that the parsed property is at a + property of the managed domain class. However you can also traverse + nested properties to define constraints on. Assume + Persons have Addresses + with ZipCodes. In that case a method name + of + + List<Person> findByAddressZipCode(ZipCode zipCode); + + will create the property traversal + x.address.zipCode. The resolution algorithm starts with + interpreting the entire part (AddressZipCode) as + property and checks the domain class for a property with that name + (uncapitalized). If it succeeds it just uses that. If not it starts + splitting up the source at the camel case parts from the right side + into a head and a tail and tries to find the according property, + e.g. AddressZip and Code. If + we find a property with that head we take the tail and continue + building the tree down from there. As in our case the first split + does not match we move the split point to the left + (Address, ZipCode). + + Now although this should work for most cases, there might be + cases where the algorithm could select the wrong property. Suppose + our Person class has a + addressZip property as well. Then our algorithm would + match in the first split round already and essentially choose the + wrong property and finally fail (as the type of + addressZip probably has no code property). To + resolve this ambiguity you can use _ inside your + method name to manually define traversal points. So our method name + would end up like so: + + List<Person> findByAddress_ZipCode(ZipCode zipCode); + +
+
+ +
+ Special parameter handling + + To hand parameters to your query you simply define method + parameters as already seen in in examples above. Besides that we will + recognizes certain specific types to apply pagination and sorting to + your queries dynamically. + + + Using Pageable and Sort in query methods + + Page<User> findByLastname(String lastname, Pageable pageable); + +List<User> findByLastname(String lastname, Sort sort); + +List<User> findByLastname(String lastname, Pageable pageable); + + + The first method allows you to pass a Pageable + instance to the query method to dynamically add paging to your + statically defined query. Sorting options are handed via + the Pageable instance, too. If you only + need sorting, simply add a Sort parameter to your method. + As you also can see, simply returning a + List is possible as well. We will then + not retrieve the additional metadata required to build the actual + Page instance but rather simply + restrict the query to lookup only the given range of entities. + + + To find out how many pages you get for a query entirely we + have to trigger an additional count query. This will be derived from + the query you actually trigger by default. + +
+
+ +
+ Creating repository instances + + So now the question is how to create instances and bean + definitions for the repository interfaces defined. + +
+ Spring + + The easiest way to do so is by using the Spring namespace that + is shipped with each Spring Data module that supports the repository + mechanism. Each of those includes a repositories element that allows + you to simply define a base packge Spring shall scan for you. + + <?xml version="1.0" encoding="UTF-8"?> +<beans:beans xmlns:beans="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://www.springframework.org/schema/data/jpa + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/data/jpa + http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> + + <repositories base-package="com.acme.repositories" /> + +</beans:beans> + + In this case we instruct Spring to scan + com.acme.repositories and all it's sub packages for + interfaces extending the appropriate + Repository sub-interface (in this case + JpaRepository). For each interface + found it will register the presistence technology specific + FactoryBean to create the according + proxies that handle invocations of the query methods. Each of these + beans will be registered under a bean name that is derived from the + interface name, so an interface of + UserRepository would be registered + under userRepository. The base-package + attribute allows to use wildcards, so that you can have a pattern of + packages parsed. + + + Using filters + + By default we will pick up every interface extending the + persistence technology specific + Repository sub-interface located + underneath the configured base package and create a bean instance + for it. However, you might want to gain finer grained control over + which interfaces bean instances get created for. To do this we + support the use of <include-filter /> and + <exclude-filter /> elements inside + <repositories />. The semantics are exactly + equivalent to the elements in Spring's context namespace. For + details see Spring reference documentation on these + elements. + + E.g. to exclude certain interfaces from instantiation as + repository, you could use the following configuration: + + + Using exclude-filter element + + <repositories base-package="com.acme.repositories"> + <context:exclude-filter type="regex" expression=".*SomeRepository" /> +</repositories> + + + This would exclude all interface ending on + SomeRepository from being + instantiated. + + + + + Manual configuration + + If you'd rather like to manually define which repository + instances to create you can do this with nested <repository + /> elements. + + <repositories base-package="com.acme.repositories"> + <repository id="userRepository" /> +</repositories> + + +
+ +
+ Standalone usage + + You can also use the repository infrastructure outside of a + Spring container usage. You will still need to have some of the Spring + libraries on your classpath but you can generally setup repositories + programatically as well. The Spring Data modules providing repository + support ship a persistence technology specific RepositoryFactory that + can be used as follows: + + + Standalone usage of repository factory + + RepositoryFactorySupport factory = … // Instantiate factory here +UserRepository repository = factory.getRepository(UserRepository.class + +
+
+
+ +
+ Custom implementations + +
+ Adding behaviour to single repositories + + Often it is necessary to provide a custom implementation for a few + repository methods. Spring Data repositories easily allow provide custom + repository code and integrate it with generic CRUD abstraction and query + method functionality. To enrich a repository with custom functionality + you have to define an interface and an implementation for that + functionality first and let the repository interface you provided so far + extend that custom interface. + + + Interface for custom repository functionality + + interface UserRepositoryCustom { + + public void someCustomMethod(User user); +} + + + + Implementation of custom repository functionality + + class UserRepositoryImpl implements UserRepositoryCustom { + + public void someCustomMethod(User user) { + // Your custom implementation + } +}Note that the implementation itself does not depend on + Spring Data and can be a regular Spring bean. So you can either use + standard dependency injection behaviour to inject references to other + beans, take part in aspects and so on. + + + + Changes to the your basic repository interface + + public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom { + + // Declare query methods here +}Let your standard repository interface extend the custom + one. This makes CRUD and custom functionality available to + clients. + + + + Configuration + + If you use namespace configuration the repository infrastructure + tries to autodetect custom implementations by looking up classes in + the package we found a repository using the naming conventions + appending the namespace element's attribute + repository-impl-postfix to the classname. This suffix + defaults to Impl. + + + Configuration example + + <repositories base-package="com.acme.repository"> + <repository id="userRepository" /> +</repositories> + +<repositories base-package="com.acme.repository" repository-impl-postfix="FooBar"> + <repository id="userRepository" /> +</repositories> + + + The first configuration example will try to lookup a class + com.acme.repository.UserRepositoryImpl to act + as custom repository implementation, where the second example will try + to lookup + com.acme.repository.UserRepositoryFooBar. + + + + Manual wiring + + The approach above works perfectly well if your custom + implementation uses annotation based configuration and autowring + entirely as will be trated as any other Spring bean. If your customly + implemented bean needs some special wiring you simply declare the bean + and name it after the conventions just descibed. We will then pick up + the custom bean by name rather than creating an own instance. + + + Manual wiring of custom implementations (I) + + <repositories base-package="com.acme.repository"> + <repository id="userRepository" /> +</repositories> + +<beans:bean id="userRepositoryImpl" class="…"> + <!-- further configuration --> +</beans:bean> + + This also works if you use automatic repository lookup without + defining single <repository /> elements. + + + In case you are not in control of the implementation bean name + (e.g. if you wrap a generic repository facade around an existing + repository implementation) you can explicitly tell the + <repository /> element which bean to use as custom + implementation by using the repository-impl-ref + attribute. + + + Manual wiring of custom implementations (II) + + <repositories base-package="com.acme.repository"> + <repository id="userRepository" repository-impl-ref="customRepositoryImplementation" /> +</repositories> + +<bean id="customRepositoryImplementation" class="…"> + <!-- further configuration --> +</bean> + + +
+ +
+ Adding custom behaviour to all repositories + + In other cases you might want to add a single method to all of + your repository interfaces. So the approach just shown is not feasible. + The first step to achieve this is adding and intermediate interface to + declare the shared behaviour + + + An interface declaring custom shared behaviour + + public interface MyRepository<T, ID extends Serializable> + extends JpaRepository<T, ID> { + + void sharedCustomMethod(ID id); +} + + + Now your individual repository interfaces will extend this + intermediate interface to include the functionality declared. The second + step is to create an implementation of this interface that extends the + persistence technology specific repository base class which will act as + custom base class for the repository proxies then. + + + If you're using automatic repository interface detection using + the Spring namespace using the interface just as is will cause Spring + trying to create an instance of + MyRepository. This is of course not + desired as it just acts as indermediate between + Repository and the actual repository + interfaces you want to define for each entity. To exclude an interface + extending Repository from being + instantiated as repository instance annotate it with + @NoRepositoryBean. + + + + Custom repository base class + + public class MyRepositoryImpl<T, ID extends Serializable> + extends SimpleJpaRepository<T, ID> implements MyRepository<T, ID> { + + public void sharedCustomMethod(ID id) { + // implementation goes here + } +} + + + The last step to get this implementation used as base class for + Spring Data repositores is replacing the standard + RepositoryFactoryBean with a custom one using a + custom RepositoryFactory that in turn creates + instances of your MyRepositoryImpl class. + + + Custom repository factory bean + + public class MyRepositoryFactoryBean<T extends JpaRepository<?, ?> + extends JpaRepositoryFactoryBean<T> { + + protected RepositoryFactorySupport getRepositoryFactory(…) { + return new MyRepositoryFactory(…); + } + + private static class MyRepositoryFactory extends JpaRepositoryFactory{ + + public MyRepositoryImpl getTargetRepository(…) { + return new MyRepositoryImpl(…); + } + + public Class<? extends RepositorySupport> getRepositoryClass() { + return MyRepositoryImpl.class; + } + } +} + + + Finally you can either declare beans of the custom factory + directly or use the factory-class attribute of the Spring + namespace to tell the repository infrastructure to use your custom + factory implementation. + + + Using the custom factory with the namespace + + <repositories base-package="com.acme.repository" + factory-class="com.acme.MyRepositoryFactoryBean" /> + +
+
+
\ No newline at end of file diff --git a/src/docbkx/reference/jpa.xml b/src/docbkx/reference/jpa.xml new file mode 100644 index 000000000..5d1988cc1 --- /dev/null +++ b/src/docbkx/reference/jpa.xml @@ -0,0 +1,680 @@ + + + + JPA Repositories + + + This chapter includes details of the JPA repository + implementation. + + +
+ Query methods + +
+ Query lookup strategies + + The JPA module supports defining a query manually as String or + have it being derived from the method name. + + + Declared queries + + Although getting a query derived from the method name is quite + convenient one might face the situation in which either the method + name parser does not support the keyword one wants to use or the + method name would get unnecessarily ugly. So you can either use JPA + named queries through a naming convention (see for more information) or + rather annotate your query method with + @Query (see as for details). + + + + Strategies + + This strategy tries to find a declared query that can either be + defined using JPA @NamedQuery means or Hades + @Query annotation (see and for details). If no declared + query is found execution of the query will fail. + + + + CREATE_IF_NOT_FOUND (default) + + This strategy is actually a combination of the both mentioned + above. It will try to lookup a declared query first but create a + custom method name based query if no named query was found. This is + default lookup strategy and thus will be used if you don't configure + anything explicitly. It allows quick query definition by method names + but also custom tuning of these queries by introducing declared + queries for those who need explicit tuning. + +
+ +
+ Query creation + + Generally the query creation mechanism for JPA works as described + in . Here's a short example + of what a JPA query method translates into: + Query creation from method names + + public interface UserRepository extends Repository<User, Long> { + + List<User> findByEmailAddressAndLastname(String emailAddress, String lastname); +}We will create a query using the JPA criteria API from this + but essentially this translates into the following query: + + select u from User u where u.emailAddress = ?1 and u.lastname = ?2 + + Spring Data JPA will do a property check and traverse nested + properties like described in . Here's + an overview of the keywords supported for JPA and what a method + containing that keyword essentially translates to. + + + + Supported keywords inside method names + + + + + + + + + + + Keyword + + Sample + + JPQL snippet + + + + + + And + + findByLastnameAndFirstname + + … where x.lastname = ?1 and x.firstname = + ?2 + + + + Or + + findByLastnameOrFirstname + + … where x.lastname = ?1 or x.firstname = + ?2 + + + + Between + + findByStartDateBetween + + … where x.startDate between 1? and + ?2 + + + + LessThan + + findByAgeLessThan + + … where x.age < ?1 + + + + GreaterThan + + findByAgeGreaterThan + + … where x.age > ?1 + + + + IsNull + + findByAgeIsNull + + … where x.age is null + + + + IsNotNull,NotNull + + findByAge(Is)NotNull + + … where x.age not null + + + + Like + + findByFirstnameLike + + … where x.firstname like ?1 + + + + NotLike + + findByFirstnameNotLike + + … where x.firstname not like ?1 + + + + OrderBy + + findByAgeOrderByLastnameDesc + + … where x.age > ?1 order by x.lastname + desc + + + + Not + + findByLastnameNot + + … where x.lastname <> ?1 + + + +
+
+ +
+ Using JPA NamedQueries + + + The examples use simple <named-query /> + element and @NamedQuery annotation. The queries for these + configuration elements have to be defined in JPA query language. Of + course you can use <named-native-query /> or + @NamedNativeQuery, too. These elements allow you to + define the query in native SQL by losing the database platform + independence. + + + + XML named query definition + + To use XML configuration simply add the necessary + <named-query /> element to the + orm.xml JPA configuration file located in + META-INF folder of your classpath. Automatic + invocation of named queries is enabled by using some defined naming + convention. For more details see below. + + + XML named query configuration + + <named-query name="User.findByLastname"> + <query>select u from User u where u.lastname = ?1</query> +</named-query> + + + As you can see the query has a special name which will be used + to resolve it at runtime. + + + + Annotation configuration + + Annotation configuration has the advantage not to need another + config file to be edited, probably lowering maintenance cost. You pay + for that benefit by the need to recompile your domain class for every + new query declaration. + + + Annotation based named query configuration + + @Entity +@NamedQuery(name = "User.findByEmailAddress", + query = "select u from User u where u.emailAddress = ?1") +public class User { + +} + + + + + Declaring interfaces + + To allow execution of this named query all you need to do is to + specify the UserRepository as + follows: + + + Query method declaration in UserRepository + + public interface UserRepository extends JpaRepository<User, Long> { + + List<User> findByLastname(String lastname); + + User findByEmailAddress(String emailAddress); +} + + + Declaring this method we will try to resolve a call to this + method to a named query starting with the simple name of the + configured domain class followed by the method name separated by a + dot. So the example here would use the named queries defined above + instead of trying to create a query from the method name. + +
+ +
+ Using @Query + + Using named queries to declare queries for entities is a valid + approach and works fine for a small number amount of queries. As the + queries themselves are tied to a Java method to execute them you + actually can bind them to the query executing methods using Spring Data + JPA @Query annotation rather than annotating them to the + domain class. This will free the domain class from persistence specific + information and colocate the query to the repository interface. + + Querys annotated to the query method will trump queries defined + using @NamedQuery or named queries declared in in + orm.xml. + + + Declare query at the query method using @Query + + public interface UserRepository extends JpaRepository<User, Long> { + + @Query("select u from User u where u.emailAddress = ?1") + User findByEmailAddress(String emailAddress); +} + +
+ +
+ Using named parameters + + By default Sprign Data JPA will use position based parameter + binding as described in all the samples above. This makes query methods + a little error prone to refactorings regarding the parameter position. + To solve this issue you can use @Param annotation to give a + method parameter a concrete name and bind the name in the query: + + + Using named parameters + + public interface UserRepository extends JpaRepository<User, Long> { + + @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname") + User findByLastnameOrFirstname(@Param("lastname") String lastname, + @Param("firstname") String firstname); +} + + Note that the method parameters are switched according to the + occurrence in the query defined. + +
+ +
+ Modifying queries + + All the sections before described how to declare queries to access + a given entity or collection of entitites. Of course you can add custom + modifying behaviour by using facilities described in . As this approach is feasible for + comprehensive custom functionality, you can achieve the execution of + modifying queries that actually only need parameter binding by + annotating the query method with @Modifying: + + + Declaring manipulating queries + + @Modifying +@Query("update User u set u.firstname = ?1 where u.lastname = ?2") +int setFixedFirstnameFor(String firstname, String lastname); + + + This will trigger the query annotated to the method as updating + query instead of a selecting one. As the + EntityManager might contain outdated + entities after the execution of the modifying query, we automatically + clear it (see JavaDoc of + EntityManager.clear() + for details). This will effectively drop all non-flushed changes still + pending in the EntityManager. If you + don't wish the EntityManager to be + cleared automatically you can set + @Modifying annotation's + clearAutomatically attribute to + false; +
+
+ +
+ Specifications + + JPA 2 introduces a criteria API that can be used to build queries + programatically. Writing a criteria you actually define the where-clause + of a query for a query of the handled domain class. Taking another step + back these criterias can be regarded as predicate over the entity that is + verbalized by the JPA criteria API constraints. + + Spring Data JPA now takes the concept of a specification from Eric + Evans' book Domain Driven Design, that carries the same semantics and + provides an API to define such + Specifications using the JPA criteria API. + Thus you find methods like this in + JpaRepository: + + List<T> readAll(Specification<T> spec); + + The Specification interface now looks + as follows: + + public interface Specification<T> { + Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, + CriteriaBuilder builder); +} + + Okay, so what is the typical use case? + Specifications can easily be used to build + an extensible set of predicates on top of an entity that then can be + combined and used with JpaRepository + without the need of declaring a query (method) for every needed + combination of those. Here's an example: + + + Specifications for a Customer + + public class CustomerSpecs { + + public static Specification<Customer> isLongTermCustomer() { + return new Specification<Customer>() { + Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, + CriteriaBuilder builder) { + + LocalDate date = new LocalDate().minusYears(2); + return builder.lessThan(root.get(Customer_.createdAt), date); + } + }; + } + + + public static Specification<Customer> hasSalesOfMoreThan(MontaryAmount value) { + return new Specification<Customer>() { + Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, + CriteriaBuilder builder) { + + // build query here + } + }; + } +} + + + Admittedly the amount of boilerplate leaves room for improvement + (that will hopefully be reduced by Java 8 closures) but the client side + becomes much nicer as you will see below. Besides that we have expressed + some criteria on a business requirement abstraction level and created + executable Specifications. So a client + might use a Specification as + follows: + + + Using a simple Specification + + List<Customer> customers = customerRepository.findAll(isLongTermCustomer()); + + + Okay, why not simply creating a query for this kind of data access? + You're right. Using a single Specification + does not gain a lot of benefit over a plain query declaration. The power + of Specifications really shines when you + combine them to create new Specification + objects. You can achieve this through the + Specifications helper class we provide to build + expressions like this: + + + Combined Specifications + + MonetaryAmount amount = new MonetaryAmount(200.0, Currencies.DOLLAR); +List<Customer> customers = customerRepository.readAll( + where(isLongTermCustomer()).or(hasSalesOfMoreThan(amount)));As + you can see, Specifications offers some gluecode + methods to chain and combine + Specifications. Thus extending your data + access layer is just a matter of creating new + Specification implementations and + combining them with ones already existing. + +
+ +
+ Transactionality + + CRUD methods on repository instances are transactional by default. + For reading operations the transaction configuration readOnly + flag is set to true, all others are configured with a plain + @Transactional so that default transaction + configuration applies. For details see JavaDoc of + Repository. If you need to tweak transaction + configuration for one of the methods declared in + Repository simply redeclare the method in + your repository interface as follows: + + + Custom transaction configuration for CRUD + + public interface UserRepository extends JpaRepository<User, Long> { + + @Override + @Transactional(timeout = 10) + public List<User> findAll(); + + // Further query method declarations +} + + This will cause the findAll() method to + be executed with a timeout of 10 seconds and without the + readOnly flag. + + + Another possibility to alter transactional behaviour is using a + facade or service implementation that typically covers more than one + repository. Its purpose is to define transactional boundaries for non-CRUD + operations: + + + Using a facade to define transactions for multiple repository + calls + + @Service +class UserManagementImpl implements UserManagement { + + private final UserRepository userRepository; + private final RoleRepository roleRepository; + + @Autowired + public UserManagementImpl(UserRepository userRepository, + RoleRepository roleRepository) { + this.userRepository = userRepository; + this.roleRepository = roleRepository; + } + + @Transactional + public void addRoleToAllUsers(String roleName) { + + Role role = roleRepository.findByName(roleName); + + for (User user : userRepository.readAll()) { + user.addRole(role); + userRepository.save(user); + } +} + + This will cause call to + addRoleToAllUsers(…) to run inside a + transaction (participating in an existing one or create a new one if + none already running). The transaction configuration at the repositories + will be neglected then as the outer transaction configuration determines + the actual one used. Note that you will have to activate + <tx:annotation-driven /> explicitly to get annotation + based configuration at facades working. The example above assumes you're + using component scanning. + + +
+ Transactional query methods + + To let your query methods be transactional simply use + @Transactional at the repository + interface you define. + + + Using @Transactional at query methods + + @Transactional(readOnly = true) +public interface UserRepository extends JpaRepository<User, Long> { + + List<User> findByLastname(String lastname); + + @Modifying + @Transactional + @Query("delete from User u where u.active = false") + void deleteInactiveUsers(); +} + + Typically you will use the readOnly flag set to + true as most of the query methods will be reading ones. In contrast to + that deleteInactiveUsers() makes use of the + @Modifying annotation and overrides the + transaction configuration. Thus the method will be executed with + readOnly flag set to false. + + + + It's definitely reasonable to use transactions for read only + queries as we can mark them as such by setting the + readOnly flag. This will not act as check that you do not + trigger a manipulating query nevertheless (although some databases + reject e.g. INSERT or UPDATE + statements inside a transaction set to be read only) but gets + propagated as hint to the underlying JDBC driver to do performance + optimizations. Furthermore Spring will do some optimizations to the + underlying JPA provider. E.g. when used with Hibernate the flush mode + is set to NEVER when you configure a transaction as read + only which causes Hibernate to skip dirty checks that gets quite + noticeable on large object trees. + +
+
+ +
+ Auditing + + Most applications will require some auditability for entities + allowing to track creation date and user and modification date and user. + Spring Data JPA provides facilities to add this audition information to + entity transparently by AOP means. To take part in this functionality your + domain classes have to implement a more advanced interface: + + + <interfacename>Auditable</interfacename> interface + + public interface Auditable<U, ID extends Serializable> + extends Persistable<ID> { + + U getCreatedBy(); + + void setCreatedBy(U createdBy); + + DateTime getCreatedDate(); + + void setCreated(Date creationDate); + + U getLastModifiedBy(); + + void setLastModifiedBy(U lastModifiedBy); + + DateTime getLastModifiedDate(); + + void setLastModified(Date lastModifiedDate); +} + + + As you can see the modifying entity itself only has to be an entity. + Mostly this will be some sort of User entity, so we chose U as parameter + type. + + + To minimize boilerplate code Spring Data JPA offers + AbstractPersistable and + AbstractAuditable base classes that implement and + preconfigure entities. Thus you can decide to only implement the + interface or enjoy more sophisticated support by extending the base + class. + + + + General auditing configuration + + Spring Data JPA ships with an entity listener that can be used to + trigger capturing auditing information. So first you have to register + the AuditingEntityListener inside your + orm.xml to be used for all entities in your + persistence contexts: + + + Auditing configuration orm.xml + + <persistence-unit-metadata> + <persistence-unit-defaults> + <entity-listeners> + <entity-listener class="….data.jpa.domain.support.AuditingEntityListener" /> + </entity-listeners> + </persistence-unit-defaults> +</persistence-unit-metadata> + + + Now activating auditing functionlity is just a matter of adding + the Spring Data JPA auditing namespace element to + your configuration: + + + Activating auditing in the Spring configuration + + <jpa:auditing auditor-aware-ref="yourAuditorAwareBean" /> + + + As you can see you have to provide a bean that implements the + AuditorAware interface which looks as + follows: + + + <interfacename>AuditorAware</interfacename> interface + + public interface AuditorAware<T, ID extends Serializable> { + + T getCurrentAuditor(); +} + + + Usually you will have some kind of authentication component in + your application that tracks the user currently working with the system. + This component should be AuditorAware and + thus allow seemless tracking of the auditor. + +
+
\ No newline at end of file diff --git a/src/docbkx/resources/css/highlight.css b/src/docbkx/resources/css/highlight.css new file mode 100644 index 000000000..ffefef72d --- /dev/null +++ b/src/docbkx/resources/css/highlight.css @@ -0,0 +1,35 @@ +/* + 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; +} \ No newline at end of file diff --git a/src/docbkx/resources/css/html.css b/src/docbkx/resources/css/html.css new file mode 100644 index 000000000..10936f337 --- /dev/null +++ b/src/docbkx/resources/css/html.css @@ -0,0 +1,421 @@ +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 is displayed in a coloured, comment-like font */ +.programlisting * .lineannotation, + .programlisting * .lineannotation * { + color: green; +} diff --git a/src/docbkx/resources/css/stylesheet.css b/src/docbkx/resources/css/stylesheet.css new file mode 100644 index 000000000..77569070a --- /dev/null +++ b/src/docbkx/resources/css/stylesheet.css @@ -0,0 +1,99 @@ +@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; +} diff --git a/src/docbkx/resources/images/admons/blank.png b/src/docbkx/resources/images/admons/blank.png new file mode 100644 index 000000000..764bf4f0c Binary files /dev/null and b/src/docbkx/resources/images/admons/blank.png differ diff --git a/src/docbkx/resources/images/admons/caution.gif b/src/docbkx/resources/images/admons/caution.gif new file mode 100644 index 000000000..d9f5e5b1b Binary files /dev/null and b/src/docbkx/resources/images/admons/caution.gif differ diff --git a/src/docbkx/resources/images/admons/caution.png b/src/docbkx/resources/images/admons/caution.png new file mode 100644 index 000000000..5b7809ca4 Binary files /dev/null and b/src/docbkx/resources/images/admons/caution.png differ diff --git a/src/docbkx/resources/images/admons/caution.tif b/src/docbkx/resources/images/admons/caution.tif new file mode 100644 index 000000000..4a282948c Binary files /dev/null and b/src/docbkx/resources/images/admons/caution.tif differ diff --git a/src/docbkx/resources/images/admons/draft.png b/src/docbkx/resources/images/admons/draft.png new file mode 100644 index 000000000..0084708c9 Binary files /dev/null and b/src/docbkx/resources/images/admons/draft.png differ diff --git a/src/docbkx/resources/images/admons/home.gif b/src/docbkx/resources/images/admons/home.gif new file mode 100644 index 000000000..6784f5bb0 Binary files /dev/null and b/src/docbkx/resources/images/admons/home.gif differ diff --git a/src/docbkx/resources/images/admons/home.png b/src/docbkx/resources/images/admons/home.png new file mode 100644 index 000000000..cbb711de7 Binary files /dev/null and b/src/docbkx/resources/images/admons/home.png differ diff --git a/src/docbkx/resources/images/admons/important.gif b/src/docbkx/resources/images/admons/important.gif new file mode 100644 index 000000000..6795d9a81 Binary files /dev/null and b/src/docbkx/resources/images/admons/important.gif differ diff --git a/src/docbkx/resources/images/admons/important.png b/src/docbkx/resources/images/admons/important.png new file mode 100644 index 000000000..ad57f6f72 Binary files /dev/null and b/src/docbkx/resources/images/admons/important.png differ diff --git a/src/docbkx/resources/images/admons/important.tif b/src/docbkx/resources/images/admons/important.tif new file mode 100644 index 000000000..184de6371 Binary files /dev/null and b/src/docbkx/resources/images/admons/important.tif differ diff --git a/src/docbkx/resources/images/admons/next.gif b/src/docbkx/resources/images/admons/next.gif new file mode 100644 index 000000000..aa1516e69 Binary files /dev/null and b/src/docbkx/resources/images/admons/next.gif differ diff --git a/src/docbkx/resources/images/admons/next.png b/src/docbkx/resources/images/admons/next.png new file mode 100644 index 000000000..45835bf89 Binary files /dev/null and b/src/docbkx/resources/images/admons/next.png differ diff --git a/src/docbkx/resources/images/admons/note.gif b/src/docbkx/resources/images/admons/note.gif new file mode 100644 index 000000000..f329d359e Binary files /dev/null and b/src/docbkx/resources/images/admons/note.gif differ diff --git a/src/docbkx/resources/images/admons/note.png b/src/docbkx/resources/images/admons/note.png new file mode 100644 index 000000000..ad57f6f72 Binary files /dev/null and b/src/docbkx/resources/images/admons/note.png differ diff --git a/src/docbkx/resources/images/admons/note.tif b/src/docbkx/resources/images/admons/note.tif new file mode 100644 index 000000000..08644d6b5 Binary files /dev/null and b/src/docbkx/resources/images/admons/note.tif differ diff --git a/src/docbkx/resources/images/admons/prev.gif b/src/docbkx/resources/images/admons/prev.gif new file mode 100644 index 000000000..64ca8f3c7 Binary files /dev/null and b/src/docbkx/resources/images/admons/prev.gif differ diff --git a/src/docbkx/resources/images/admons/prev.png b/src/docbkx/resources/images/admons/prev.png new file mode 100644 index 000000000..cf24654f8 Binary files /dev/null and b/src/docbkx/resources/images/admons/prev.png differ diff --git a/src/docbkx/resources/images/admons/tip.gif b/src/docbkx/resources/images/admons/tip.gif new file mode 100644 index 000000000..823f2b417 Binary files /dev/null and b/src/docbkx/resources/images/admons/tip.gif differ diff --git a/src/docbkx/resources/images/admons/tip.png b/src/docbkx/resources/images/admons/tip.png new file mode 100644 index 000000000..ad57f6f72 Binary files /dev/null and b/src/docbkx/resources/images/admons/tip.png differ diff --git a/src/docbkx/resources/images/admons/tip.tif b/src/docbkx/resources/images/admons/tip.tif new file mode 100644 index 000000000..4a3d8c75f Binary files /dev/null and b/src/docbkx/resources/images/admons/tip.tif differ diff --git a/src/docbkx/resources/images/admons/toc-blank.png b/src/docbkx/resources/images/admons/toc-blank.png new file mode 100644 index 000000000..6ffad17a0 Binary files /dev/null and b/src/docbkx/resources/images/admons/toc-blank.png differ diff --git a/src/docbkx/resources/images/admons/toc-minus.png b/src/docbkx/resources/images/admons/toc-minus.png new file mode 100644 index 000000000..abbb020c8 Binary files /dev/null and b/src/docbkx/resources/images/admons/toc-minus.png differ diff --git a/src/docbkx/resources/images/admons/toc-plus.png b/src/docbkx/resources/images/admons/toc-plus.png new file mode 100644 index 000000000..941312ce0 Binary files /dev/null and b/src/docbkx/resources/images/admons/toc-plus.png differ diff --git a/src/docbkx/resources/images/admons/up.gif b/src/docbkx/resources/images/admons/up.gif new file mode 100644 index 000000000..aabc2d016 Binary files /dev/null and b/src/docbkx/resources/images/admons/up.gif differ diff --git a/src/docbkx/resources/images/admons/up.png b/src/docbkx/resources/images/admons/up.png new file mode 100644 index 000000000..07634de26 Binary files /dev/null and b/src/docbkx/resources/images/admons/up.png differ diff --git a/src/docbkx/resources/images/admons/warning.gif b/src/docbkx/resources/images/admons/warning.gif new file mode 100644 index 000000000..c6acdec60 Binary files /dev/null and b/src/docbkx/resources/images/admons/warning.gif differ diff --git a/src/docbkx/resources/images/admons/warning.png b/src/docbkx/resources/images/admons/warning.png new file mode 100644 index 000000000..ef3e10f40 Binary files /dev/null and b/src/docbkx/resources/images/admons/warning.png differ diff --git a/src/docbkx/resources/images/admons/warning.tif b/src/docbkx/resources/images/admons/warning.tif new file mode 100644 index 000000000..7b6611ec7 Binary files /dev/null and b/src/docbkx/resources/images/admons/warning.tif differ diff --git a/src/docbkx/resources/images/callouts/1.png b/src/docbkx/resources/images/callouts/1.png new file mode 100644 index 000000000..7d473430b Binary files /dev/null and b/src/docbkx/resources/images/callouts/1.png differ diff --git a/src/docbkx/resources/images/callouts/10.png b/src/docbkx/resources/images/callouts/10.png new file mode 100644 index 000000000..997bbc824 Binary files /dev/null and b/src/docbkx/resources/images/callouts/10.png differ diff --git a/src/docbkx/resources/images/callouts/11.png b/src/docbkx/resources/images/callouts/11.png new file mode 100644 index 000000000..ce47dac3f Binary files /dev/null and b/src/docbkx/resources/images/callouts/11.png differ diff --git a/src/docbkx/resources/images/callouts/12.png b/src/docbkx/resources/images/callouts/12.png new file mode 100644 index 000000000..31daf4e2f Binary files /dev/null and b/src/docbkx/resources/images/callouts/12.png differ diff --git a/src/docbkx/resources/images/callouts/13.png b/src/docbkx/resources/images/callouts/13.png new file mode 100644 index 000000000..14021a89c Binary files /dev/null and b/src/docbkx/resources/images/callouts/13.png differ diff --git a/src/docbkx/resources/images/callouts/14.png b/src/docbkx/resources/images/callouts/14.png new file mode 100644 index 000000000..64014b75f Binary files /dev/null and b/src/docbkx/resources/images/callouts/14.png differ diff --git a/src/docbkx/resources/images/callouts/15.png b/src/docbkx/resources/images/callouts/15.png new file mode 100644 index 000000000..0d65765fc Binary files /dev/null and b/src/docbkx/resources/images/callouts/15.png differ diff --git a/src/docbkx/resources/images/callouts/2.png b/src/docbkx/resources/images/callouts/2.png new file mode 100644 index 000000000..5d09341b2 Binary files /dev/null and b/src/docbkx/resources/images/callouts/2.png differ diff --git a/src/docbkx/resources/images/callouts/3.png b/src/docbkx/resources/images/callouts/3.png new file mode 100644 index 000000000..ef7b70047 Binary files /dev/null and b/src/docbkx/resources/images/callouts/3.png differ diff --git a/src/docbkx/resources/images/callouts/4.png b/src/docbkx/resources/images/callouts/4.png new file mode 100644 index 000000000..adb8364eb Binary files /dev/null and b/src/docbkx/resources/images/callouts/4.png differ diff --git a/src/docbkx/resources/images/callouts/5.png b/src/docbkx/resources/images/callouts/5.png new file mode 100644 index 000000000..4d7eb4600 Binary files /dev/null and b/src/docbkx/resources/images/callouts/5.png differ diff --git a/src/docbkx/resources/images/callouts/6.png b/src/docbkx/resources/images/callouts/6.png new file mode 100644 index 000000000..0ba694af6 Binary files /dev/null and b/src/docbkx/resources/images/callouts/6.png differ diff --git a/src/docbkx/resources/images/callouts/7.png b/src/docbkx/resources/images/callouts/7.png new file mode 100644 index 000000000..472e96f8a Binary files /dev/null and b/src/docbkx/resources/images/callouts/7.png differ diff --git a/src/docbkx/resources/images/callouts/8.png b/src/docbkx/resources/images/callouts/8.png new file mode 100644 index 000000000..5e60973c2 Binary files /dev/null and b/src/docbkx/resources/images/callouts/8.png differ diff --git a/src/docbkx/resources/images/callouts/9.png b/src/docbkx/resources/images/callouts/9.png new file mode 100644 index 000000000..a0676d26c Binary files /dev/null and b/src/docbkx/resources/images/callouts/9.png differ diff --git a/src/docbkx/resources/images/logo.png b/src/docbkx/resources/images/logo.png new file mode 100644 index 000000000..a9f6d959e Binary files /dev/null and b/src/docbkx/resources/images/logo.png differ diff --git a/src/docbkx/resources/images/xdev-spring_logo.jpg b/src/docbkx/resources/images/xdev-spring_logo.jpg new file mode 100644 index 000000000..622962ee3 Binary files /dev/null and b/src/docbkx/resources/images/xdev-spring_logo.jpg differ diff --git a/src/docbkx/resources/xsl/fopdf.xsl b/src/docbkx/resources/xsl/fopdf.xsl new file mode 100644 index 000000000..7eb91b1e4 --- /dev/null +++ b/src/docbkx/resources/xsl/fopdf.xsl @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copyright © 2010 + + + , + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -5em + -5em + + + + + + + + + + + Spring Data JPA ( + + ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 0 + 1 + + 1 + + + + + + book toc + + + + 2 + + + + + + + + + + 0 + 0 + 0 + + + 5mm + 10mm + 10mm + + 15mm + 10mm + 0mm + + 18mm + 18mm + + + 0pc + + + + + justify + false + + + 11 + 8 + + + 1.4 + + + + + + + 0.8em + + + + + + 17.4cm + + + + 4pt + 4pt + 4pt + 4pt + + + + 0.1pt + 0.1pt + + + + + 1 + + + + + + + + left + bold + + + pt + + + + + + + + + + + + + + + 0.8em + 0.8em + 0.8em + + + pt + + 0.1em + 0.1em + 0.1em + + + 0.6em + 0.6em + 0.6em + + + pt + + 0.1em + 0.1em + 0.1em + + + 0.4em + 0.4em + 0.4em + + + pt + + 0.1em + 0.1em + 0.1em + + + + + bold + + + pt + + false + 0.4em + 0.6em + 0.8em + + + + + + + + + pt + + + + + 1em + 1em + 1em + #444444 + solid + 0.1pt + 0.5em + 0.5em + 0.5em + 0.5em + 0.5em + 0.5em + + + + 1 + + #F0F0F0 + + + + + + 0 + 1 + + + 90 + + + + + '1' + + + + + + + figure after + example before + equation before + table before + procedure before + + + + 1 + + + + 0.8em + 0.8em + 0.8em + 0.1em + 0.1em + 0.1em + + + + + + + + + + + + + + + + + diff --git a/src/docbkx/resources/xsl/html.xsl b/src/docbkx/resources/xsl/html.xsl new file mode 100644 index 000000000..aa7930bab --- /dev/null +++ b/src/docbkx/resources/xsl/html.xsl @@ -0,0 +1,91 @@ + + + + + + + + + html.css + + + 1 + 0 + 1 + 0 + + + + + + book toc + + + + 3 + + + + + 1 + + + + + + + 0 + + + 90 + + + + + 0 + + + + + figure after + example before + equation before + table before + procedure before + + + + , + + + + + + + + +
+

Authors

+

+ +

+
+ +
diff --git a/src/docbkx/resources/xsl/html/html_chunk.xsl b/src/docbkx/resources/xsl/html/html_chunk.xsl new file mode 100644 index 000000000..81e6ab235 --- /dev/null +++ b/src/docbkx/resources/xsl/html/html_chunk.xsl @@ -0,0 +1,136 @@ + + + + + + + '5' + + + + 1 + 0 + 1 + + + + images/ + .gif + + 120 + images/callouts/ + .gif + + + css/stylesheet.css + text/css + book toc,title + + text-align: left + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Begin Google Analytics code + + + End Google Analytics code + + + + + Begin LoopFuse code + + + End LoopFuse code + + + \ No newline at end of file diff --git a/src/docbkx/resources/xsl/html/titlepage.xml b/src/docbkx/resources/xsl/html/titlepage.xml new file mode 100644 index 000000000..09539c068 --- /dev/null +++ b/src/docbkx/resources/xsl/html/titlepage.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + <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> diff --git a/src/docbkx/resources/xsl/html_chunk.xsl b/src/docbkx/resources/xsl/html_chunk.xsl new file mode 100644 index 000000000..59016d819 --- /dev/null +++ b/src/docbkx/resources/xsl/html_chunk.xsl @@ -0,0 +1,208 @@ +<?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) > 0 + or count($up) > 0 + or count($next) > 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> </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> | </xsl:text> + </xsl:if> + </xsl:when> + <xsl:otherwise> </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> </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> </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> </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> diff --git a/src/docbkx/resources/xsl/pdf/fopdf.xsl b/src/docbkx/resources/xsl/pdf/fopdf.xsl new file mode 100644 index 000000000..2905ee3c2 --- /dev/null +++ b/src/docbkx/resources/xsl/pdf/fopdf.xsl @@ -0,0 +1,518 @@ +<?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. %t"/> + <l:template name="section" text="%n %t"/> + </l:context> + <l:context name="title"> + <l:template name="example" text="Example %n %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> \ No newline at end of file diff --git a/src/docbkx/resources/xsl/pdf/titlepage.xml b/src/docbkx/resources/xsl/pdf/titlepage.xml new file mode 100644 index 000000000..dc18e1e0d --- /dev/null +++ b/src/docbkx/resources/xsl/pdf/titlepage.xml @@ -0,0 +1,101 @@ +<?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>