http://git-wip-us.apache.org/repos/asf/cayenne/blob/cde78f0b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/customize.adoc
----------------------------------------------------------------------
diff --git 
a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/customize.adoc
 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/customize.adoc
new file mode 100644
index 0000000..42504d2
--- /dev/null
+++ 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/customize.adoc
@@ -0,0 +1,473 @@
+// 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.
+
+[[customize]]
+=== Customizing Cayenne Runtime
+
+==== Dependency Injection Container
+
+Cayenne runtime is built around a small powerful dependency injection (DI) 
container. Just like other popular DI technologies, such as Spring or Guice, 
Cayenne DI container manages sets of interdependent objects and allows users to 
configure them. These objects are regular Java objects. We are calling them 
"services" in this document to distinguish from all other objects that are not 
configured in the container and are not managed. DI container is responsible 
for service instantiation, injecting correct dependencies, maintaining service 
instances scope, and dispatching scope events to services.
+
+The services are configured in special Java classes called "modules". Each 
module defines binding of service interfaces to implementation instances, 
implementation types or providers of implementation instances. There are no XML 
configuration files, and all the bindings are type-safe. The container supports 
injection into instance variables and constructor parameters based on the 
@Inject annotation. This mechanism is very close to Google Guice.
+
+The discussion later in this chapter demonstrates a standalone DI container. 
But keep in mind that Cayenne already has a built-in Injector, and a set of 
default modules. A Cayenne user would normally only use the API below to write 
custom extension modules that will be loaded in that existing container when 
creating ServerRuntime. See "Starting and Stopping ServerRuntime" chapter for 
an example of passing an extension module to Cayenne.
+
+Cayenne DI probably has ~80% of the features expected in a DI container and 
has no dependency on the rest of Cayenne, so in theory can be used as an 
application-wide DI engine. But it's primary purpose is still to serve Cayenne. 
Hence there are no plans to expand it beyond Cayenne needs. It is an ideal 
"embedded" DI that does not interfere with Spring, Guice or any other such 
framework present elsewhere in the application.
+
+===== DI Bindings API
+
+To have a working DI container, we need three things: service interfaces and 
classes, a module that describes service bindings, a container that loads the 
module, and resolves the depedencies. Let's start with service interfaces and 
classes:
+
+[source, Java]
+----
+public interface Service1 {
+    public String getString();
+}
+----
+
+[source, Java]
+----
+public interface Service2 {
+    public int getInt();
+}
+----
+
+A service implementation using instance variable injection:
+
+[source, Java]
+----
+public class Service1Impl implements Service1 {
+    @Inject
+    private Service2 service2;
+
+    public String getString() {
+        return service2.getInt() + "_Service1Impl";
+    }
+}
+----
+
+Same thing, but using constructor injection:
+
+[source, Java]
+----
+public class Service1Impl implements Service1 {
+
+    private Service2 service2;
+
+    public Service1Impl(@Inject Service2 service2) {
+        this.service2 = service2;
+    }
+
+    public String getString() {
+        return service2.getInt() + "_Service1Impl";
+    }
+}
+----
+
+[source, Java]
+----
+public class Service2Impl implements Service2 {
+    private int i;
+
+    public int getInt() {
+        return i++;
+    }
+}
+----
+
+Now let's create a module implementing `org.apache.cayenne.tutorial.di.Module` 
interface that will contain DI configuration. A module binds service objects to 
keys that are reference. Binder provided by container implements fluent API to 
connect the key to implementation, and to configure various binding options 
(the options, such as scope, are demonstrated later in this chapter). The 
simplest form of a key is a Java Class object representing service interface. 
Here is a module that binds Service1 and Service2 to corresponding default 
implementations:
+
+[source, Java]
+----
+public class Module1 implements Module {
+
+    public void configure(Binder binder) {
+        binder.bind(Service1.class).to(Service1Impl.class);
+        binder.bind(Service2.class).to(Service2Impl.class);
+    }
+}
+----
+
+Once we have at least one module, we can create a DI container. 
`org.apache.cayenne.di.Injector` is the container class in Cayenne:
+
+[source, Java]
+----
+Injector injector = DIBootstrap.createInjector(new Module1());
+----
+
+Now that we have created the container, we can obtain services from it and 
call their methods:
+
+[source, Java]
+----
+Service1 s1 = injector.getInstance(Service1.class);
+for (int i = 0; i < 5; i++) {
+    System.out.println("S1 String: " + s1.getString());
+}
+----
+
+This outputs the following lines, demonstrating that s1 was Service1Impl and 
Service2 injected into it was Service2Impl:
+
+----
+0_Service1Impl
+1_Service1Impl
+2_Service1Impl
+3_Service1Impl
+4_Service1Impl
+----
+
+There are more flavors of bindings:
+
+[source, Java]
+----
+// binding to instance - allowing user to create and configure instance
+// inside the module class
+binder.bind(Service2.class).toInstance(new Service2Impl());
+
+// binding to provider - delegating instance creation to a special
+// provider class
+binder.bind(Service1.class).toProvider(Service1Provider.class);
+
+// binding to provider instance
+binder.bind(Service1.class).toProviderInstance(new Service1Provider());
+
+// multiple bindings of the same type using Key
+// injection can reference the key name in annotation:
+// @Inject("i1")
+// private Service2 service2;
+binder.bind(Key.get(Service2.class, "i1")).to(Service2Impl.class);
+binder.bind(Key.get(Service2.class, "i2")).to(Service2Impl.class);
+----
+
+
+Another types of confiuguration that can be bound in the container are lists 
and maps. They will be discussed in the following chapters.
+
+===== Service Lifecycle
+
+An important feature of the Cayenne DI container is instance scope. The 
default scope (implicitly used in all examples above) is "singleton", meaning 
that a binding would result in creation of only one service instance, that will 
be repeatedly returned from `Injector.getInstance(..)`, as well as injected 
into classes that declare it as a dependency.
+
+Singleton scope dispatches a "BeforeScopeEnd" event to interested services. 
This event occurs before the scope is shutdown, i.e. when `Injector.shutdown()` 
is called. Note that the built-in Cayenne injector is shutdown behind the 
scenes when `ServerRuntime.shutdown()` is invoked. Services may register as 
listeners for this event by annotating a no-argument method with 
`@BeforeScopeEnd` annotation. Such method should be implemented if a service 
needs to clean up some resources, stop threads, etc.
+
+Another useful scope is "no scope", meaning that every time a container is 
asked to provide a service instance for a given key, a new instance will be 
created and returned:
+
+[source, Java]
+----
+binder.bind(Service2.class).to(Service2Impl.class).withoutScope();
+----
+
+Users can also create their own scopes, e.g. a web application request scope 
or a session scope. Most often than not custom scopes can be created as 
instances of `org.apache.cayenne.di.spi.DefaultScope` with startup and shutdown 
managed by the application (e.g. singleton scope is a DefaultScope managed by 
the Injector) .
+
+===== Overriding Services
+
+Cayenne DI allows to override services already definied in the current module, 
or more commonly - some other module in the the same container. Actually 
there's no special API to override a service, you'd just bind the service key 
again with a new implementation or provider. The last binding for a key takes 
precedence. This means that the order of modules is important when configuring 
a container. The built-in Cayenne injector ensures that Cayenne standard 
modules are loaded first, followed by optional user extension modules. This way 
the application can override the standard services in Cayenne.
+
+==== Customization Strategies
+
+The previous section discussed how Cayenne DI works in general terms. Since 
Cayenne users will mostly be dealing with an existing Injector provided by 
ServerRuntime, it is important to understand how to build custom extensions to 
a preconfigured container. As shown in "Starting and Stopping ServerRuntime" 
chapter, custom extensions are done by writing an aplication DI module (or 
multiple modules) that configures service overrides. This section shows all the 
configuration possibilities in detail, including changing properties of the 
existing services, contributing services to standard service lists and maps, 
and overriding service implementations. All the code examples later in this 
section are assumed to be placed in an application module "configure" method:
+
+[source, Java]
+----
+public class MyExtensionsModule implements Module {
+    public void configure(Binder binder) {
+        // customizations go here...
+    }
+}
+----
+
+[source, Java]
+----
+Module extensions = new MyExtensionsModule();
+ServerRuntime runtime = ServerRuntime.builder()
+        .addConfig("com/example/cayenne-mydomain.xml")
+        .addModule(extensions)
+        .build();
+----
+
+===== Changing Properties of Existing Services
+
+Many built-in Cayenne services change their behavior based on a value of some 
environment property. A user may change Cayenne behavior without even knowing 
which services are responsible for it, but setting a specific value of a known 
property. Supported property names are listed in "Appendix A".
+
+There are two ways to set service properties. The most obvious one is to pass 
it to the JVM with -D flag on startup. E.g.
+
+----
+$ java -Dcayenne.server.contexts_sync_strategy=false ...
+----
+
+A second one is to contribute a property to 
`org.apache.cayenne.configuration.DefaultRuntimeProperties.properties` map (see 
the next section on how to do that). This map contains the default property 
values and can accept application-specific values, overrding the defaults.
+
+Note that if a property value is a name of a Java class, when this Java class 
is instantiated by Cayenne, the container performs injection of instance 
variables. So even the dynamically specified Java classes can use @Inject 
annotation to get a hold of other Cayenne services.
+
+If the same property is specified both in the command line and in the 
properties map, the command-line value takes precedence. The map value will be 
ignored. This way Cayenne runtime can be reconfigured during deployment.
+
+===== Contributing to Service Collections
+
+Cayenne can be extended by adding custom objects to named maps or lists bound 
in DI. We are calling these lists/maps "service collections". A service 
collection allows things like appending a custom strategy to a list of built-in 
strategies. E.g. an application that needs to install a custom DbAdapter for 
some database type may contribute an instance of custom DbAdapterDetector to a 
`org.apache.cayenne.configuration.server.DefaultDbAdapterFactory.detectors` 
list:
+
+[source, Java]
+----
+public class MyDbAdapterDetector implements DbAdapterDetector {
+    public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
+        // check if we support this database and retun custom adapter
+        ...
+    }
+}
+----
+
+[source, Java]
+----
+// since build-in list for this key is a singleton, repeated
+// calls to 'bindList' will return the same instance
+binder.bindList(DefaultDbAdapterFactory.DETECTORS_LIST)
+       .add(MyDbAdapterDetector.class);
+----
+
+Maps are customized using a similar `"bindMap"` method.
+
+The names of built-in collections are listed in "Appendix B".
+
+===== Alternative Service Implementations
+
+As mentioned above, custom modules are loaded by ServerRuntime after the 
built-in modules. So it is easy to redefine a built-in service in Cayenne by 
rebinding desired implementations or providers. To do that, first we need to 
know what those services to redefine are. While we describe some of them in the 
following sections, the best way to get a full list is to check the source code 
of the Cayenne version you are using and namely look in 
`org.apache.cayenne.configuration.server.ServerModule` - the main built-in 
module in Cayenne.
+
+Now an example of overriding `QueryCache` service. The default implementation 
of this service is provided by `MapQueryCacheProvider`. But if we want to use 
`EhCacheQueryCache` (a Cayenne wrapper for the EhCache framework), we can 
define it like this:
+
+[source, Java]
+----
+binder.bind(QueryCache.class).to(EhCacheQueryCache.class);
+----
+
+==== Using custom data types
+
+===== Value object type
+
+`ValueObjectType` is a new and lightweight alternative to the Extended Types 
API described in the following section. In most cases is should be preferred as 
is it easier to understand and use. Currently only one case is known when 
`ExtendedType` should be used: when your value object can be mapped on 
different JDBC types.
+
+In order to use your custom data type you should implement `ValueObjectType` 
describing it in terms of some type already known to Cayenne (e.g. backed by 
system or user ExtendedType). Let's assume we want to support some data type 
called `Money`:
+
+[source, Java]
+----
+public class Money {
+    private BigDecimal value;
+
+    public Money(BigDecimal value) {
+        this.value = value;
+    }
+
+    public BigDecimal getValue() {
+        return value;
+    }
+
+    // .. some other business logic ..
+}
+----
+
+Here is how `ValueObjectType` that will allow to store our `Money` class as 
`BigDecimal` can be implemented:
+
+[source, Java]
+----
+public class MoneyValueObjectType implements ValueObjectType<Money, 
BigDecimal> {
+
+    @Override
+    public Class<BigDecimal> getTargetType() {
+        return BigDecimal.class;
+    }
+
+    @Override
+    public Class<Money> getValueType() {
+        return Money.class;
+    }
+
+    @Override
+    public Money toJavaObject(BigDecimal value) {
+        return new Money(value);
+    }
+
+    @Override
+    public BigDecimal fromJavaObject(Money object) {
+        return object.getValue();
+    }
+
+    @Override
+    public String toCacheKey(Money object) {
+        return object.getValue().toString();
+    }
+}
+----
+
+Last step is to register this new type in `ServerRuntime`:
+
+[source, Java]
+----
+ServerRuntime runtime = ServerRuntime.builder()
+    .addConfig("cayenne-project.xml")
+    .addModule(binder -> 
ServerModule.contributeValueObjectTypes(binder).add(MoneyValueObjectType.class))
+    .build();
+----
+
+More examples of implementation you can find in 
https://github.com/apache/cayenne/tree/master/cayenne-joda[cayenne-joda module].
+
+===== Extended Types
+
+JDBC specification defines a set of "standard" database column types (defined 
in java.sql.Types class) and a very specific mapping of these types to Java 
Object Types, such as java.lang.String, java.math.BigDecimal, etc. Sometimes 
there is a need to use a custom Java type not known to JDBC driver and Cayenne 
allows to configure it. For this Cayenne needs to know how to instantiate this 
type from a database "primitive" value, and conversely, how to transform an 
object of the custom type to a JDBC-compatible object.
+
+====== Supporting Non-Standard Types
+
+For supporting non-standard type you should define it via an interface 
`org.apache.cayenne.access.types.ExtendedType`. An implementation must provide 
`ExtendedType.getClassName()` method that returns a fully qualified Java class 
name for the supported custom type, and a number of methods that convert data 
between JDBC and custom type. The following example demonstrates how to add a 
custom DoubleArrayType to store `java.lang.Double[]` as a custom string in a 
database:
+
+[source, Java]
+----
+/**
+* Defines methods to read Java objects from JDBC ResultSets and write as 
parameters of
+* PreparedStatements.
+*/
+public class DoubleArrayType implements ExtendedType {
+
+    private final String SEPARATOR = ",";
+
+    /**
+    * Returns a full name of Java class that this ExtendedType supports.
+    */
+    @Override
+    public String getClassName() {
+        return Double[].class.getCanonicalName();
+    }
+
+    /**
+    * Initializes a single parameter of a PreparedStatement with object value.
+    */
+    @Override
+    public void setJdbcObject(PreparedStatement statement, Object value,
+            int pos, int type, int scale) throws Exception {
+
+        String str = StringUtils.join((Double[]) value, SEPARATOR);
+        statement.setString(pos, str);
+    }
+
+
+    /**
+    * Reads an object from JDBC ResultSet column, converting it to class 
returned by
+    * 'getClassName' method.
+    *
+    * @throws Exception if read error occurred, or an object can't be 
converted to a
+    *             target Java class.
+    */
+    @Override
+    public Object materializeObject(ResultSet rs, int index, int type) throws 
Exception {
+        String[] str = rs.getString(index).split(SEPARATOR);
+        Double[] res = new Double[str.length];
+
+        for (int i = 0; i < str.length; i++) {
+            res[i] = Double.valueOf(str[i]);
+        }
+
+        return res;
+    }
+
+    /**
+    * Reads an object from a stored procedure OUT parameter, converting it to 
class
+    * returned by 'getClassName' method.
+    *
+    * @throws Exception if read error ocurred, or an object can't be converted 
to a
+    *             target Java class.
+    */
+    @Override
+    public Object materializeObject(CallableStatement rs, int index, int type) 
throws Exception {
+        String[] str = rs.getString(index).split(SEPARATOR);
+        Double[] res = new Double[str.length];
+
+        for (int i = 0; i < str.length; i++) {
+            res[i] = Double.valueOf(str[i]);
+        }
+
+        return res;
+    }
+}
+----
+
+For Java7
+
+[source, Java]
+----
+// add DoubleArrayType to list of user types
+ServerRuntime runtime = ServerRuntime.builder()
+                .addConfig("cayenne-project.xml")
+                .addModule(new Module() {
+                    @Override
+                    public void configure(Binder binder) {
+                        ServerModule.contributeUserTypes(binder).add(new 
DoubleArrayType());
+                    }
+                })
+                .build();
+----
+
+For Java8
+
+[source, Java]
+----
+// add DoubleArrayType to list of user types
+ServerRuntime runtime = ServerRuntime.builder()
+                .addConfig("cayenne-project.xml")
+                .addModule(binder -> 
ServerModule.contributeUserTypes(binder).add(new DoubleArrayType()))
+                .build();
+----
+
+====== DbAdapters and Extended Types
+
+As shown in the example above, ExtendedTypes are stored by DbAdapter. In fact 
DbAdapters often install their own extended types to address incompatibilities, 
incompleteness and differences between JDBC drivers in handling "standard" JDBC 
types. For instance some drivers support reading large character columns (CLOB) 
as java.sql.Clob, but some other - as "character stream", etc. Adapters 
provided with Cayenne override `configureExtendedTypes()` method to install 
their own types, possibly substituting Cayenne defaults. Custom DbAdapters can 
use the same technique.
+
+==== Noteworthy Built-in Services
+
+===== JdbcEventLogger
+
+`org.apache.cayenne.log.JdbcEventLogger` is the service that defines logging 
API for Cayenne internals. It provides facilities for logging queries, commits, 
transactions, etc. The default implementation is 
`org.apache.cayenne.log.Slf4jJdbcEventLogger` that performs logging via 
slf4j-api library. Cayenne library includes another potentially useful logger - 
`org.apache.cayenne.log.FormattedSlf4jJdbcEventLogger` that produces formatted 
multiline SQL output that can be easier to read.
+
+===== DataSourceFactory
+
+Factory that returns `javax.sql.DataSource` object based on the configuration 
provided in the "nodeDescriptor".
+
+===== DataChannelFilter
+
+An interface of a filter that allows to intercept DataChannel operations. 
Filters allow to implement chains of custom processors around a DataChannel, 
that can be used for security, monitoring, business logic, providing context to 
lifecycle event listeners, etc.
+
+===== QueryCache
+
+Defines API of a cache that stores query results.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

http://git-wip-us.apache.org/repos/asf/cayenne/blob/cde78f0b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/expressions.adoc
----------------------------------------------------------------------
diff --git 
a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/expressions.adoc
 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/expressions.adoc
new file mode 100644
index 0000000..4d41f1d
--- /dev/null
+++ 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/expressions.adoc
@@ -0,0 +1,279 @@
+// 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.
+[[expressions]]
+=== Expressions
+
+==== Expressions Overview
+
+Cayenne provides a simple yet powerful object-based expression language. The 
most common use of expressions are to build qualifiers and orderings of queries 
that are later converted to SQL by Cayenne and to evaluate in-memory against 
specific objects (to access certain values in the object graph or to perform 
in-memory object filtering and sorting). Cayenne provides API to build 
expressions in the code and a parser to create expressions from strings.
+
+==== Path Expressions
+
+Before discussing how to build expressions, it is important to understand one 
group of expressions widely used in Cayenne - path expressions. There are two 
types of path expressions - object and database, used for navigating graphs of 
connected objects or joined DB tables respectively. Object paths are much more 
commonly used, as after all Cayenne is supposed to provide a degree of 
isolation of the object model from the database. However database paths are 
helpful in certain situations. General structure of path expressions is the 
following:
+
+----
+ [db:]segment[+][.segment[+]...]
+----
+
+- `db:` is an optional prefix indicating that the following path is a DB path. 
Otherwise it is an object path.
+
+- `segment` is a name of a property (relationship or attribute in Cayenne 
terms) in the path. Path must have at least one segment; segments are separated 
by dot (".").
+
+- `+` An "OUTER JOIN" path component. Currently "+" only has effect when 
translated to SQL as OUTER JOIN. When evaluating expressions in memory, it is 
ignored.
+
+An object path expression represents a chain of property names rooted in a 
certain (unspecified during expression creation) object and "navigating" to its 
related value. E.g. a path expression "artist.name" might be a property path 
starting from a Painting object, pointing to the related Artist object, and 
then to its name attribute. A few more examples:
+
+- `name` - can be used to navigate (read) the "name" property of a Person (or 
any other type of object that has a "name" property).
+
+- `artist.exhibits.closingDate` - can be used to navigate to a closing date of 
any of the exhibits of a Painting's Artist object.
+
+- `artist.exhibits+.closingDate` - same as the previous example, but when 
translated into SQL, an OUTER JOIN will be used for "exhibits".
+
+Similarly a database path expression is a dot-separated path through DB table 
joins and columns. In Cayenne joins are mapped as DbRelationships with some 
symbolic names (the closest concept to DbRelationship name in the DB world is a 
named foreign key constraint. But DbRelationship names are usually chosen 
arbitrarily, without regard to constraints naming or even constraints 
presence). A database path therefore might look like this - 
`db:dbrelationshipX.dbrelationshipY.COLUMN_Z`. More specific examples:
+
+- `db:NAME` - can be used to navigate to the value of "NAME" column of some 
unspecified table.
+
+- `db:artist.artistExhibits.exhibit.CLOSING_DATE` - can be used to match a 
closing date of any of the exhibits of a related artist record.
+
+Cayenne supports "aliases" in path Expressions. E.g. the same expression can 
be written using explicit path or an alias:
+
+- `artist.exhibits.closingDate` - full path
+
+- `e.closingDate` - alias `e` is used for `artist.exhibits`.
+
+SelectQuery using the second form of the path expression must be made aware of 
the alias via `SelectQuery.aliasPathSplits(..)`, otherwise an Exception will be 
thrown. The main use of aliases is to allow users to control how SQL joins are 
generated if the same path is encountered more than once in any given 
Expression. Each alias for any given path would result in a separate join. 
Without aliases, a single join will be used for a group of matching paths.
+
+==== Creating Expressions from Strings
+
+While in most cases users are likely to rely on API from the following section 
for expression creation, we'll start by showing String expressions, as this 
will help to understand the semantics. A Cayenne expression can be represented 
as a String, which can be converted to an expression object using 
`ExpressionFactory.exp` static method. Here is an example:
+
+
+[source, java]
+----
+String expString = "name like 'A%' and price < 1000";
+Expression exp = ExpressionFactory.exp(expString);
+----
+
+This particular expression may be used to match Paintings whose names that 
start with "A" and whose price is less than $1000. While this example is pretty 
self-explanatory, there are a few points worth mentioning. "name" and "price" 
here are object paths discussed earlier. As always, paths themselves are not 
attached to a specific root entity and can be applied to any entity that has 
similarly named attributes or relationships. So when we are saying that this 
expression "may be used to match Paintings", we are implying that there may be 
other entities, for which this expression is valid. Now the expression 
details...
+
+Character constants that are not paths or numeric values should be enclosed in 
single or double quotes. Two of the expressions below are equivalent:
+
+[source, java]
+----
+name = 'ABC'
+
+// double quotes are escaped inside Java Strings of course
+name = \"ABC\"
+----
+
+Case sensitivity. Expression operators are case sensitive and are usually 
lowercase. Complex words follow the Java camel-case style:
+
+[source, java]
+----
+// valid
+name likeIgnoreCase 'A%'
+
+// invalid - will throw a parse exception
+name LIKEIGNORECASE 'A%'
+----
+
+Grouping with parenthesis:
+
+
+[source, java]
+----
+value = (price + 250.00) * 3
+----
+
+Path prefixes. Object expressions are unquoted strings, optionally prefixed by 
"obj:" (usually they are not prefixed at all actually). Database expressions 
are always prefixed with "db:". A special kind of prefix, not discussed yet is 
"enum:" that prefixes an enumeration constant:
+
+[source, java]
+----
+// object path
+name = 'Salvador Dali'
+
+// same object path - a rarely used form
+obj:name = 'Salvador Dali'
+
+// multi-segment object path
+artist.name = 'Salvador Dali'
+
+// db path
+db:NAME = 'Salvador Dali'
+
+// enumeration constant
+name = enum:org.foo.EnumClass.VALUE1
+----
+
+Binary conditions are expressions that contain a path on the left, a value on 
the right, and some operation between them, such as equals, like, etc. They can 
be used as qualifiers in SelectQueries:
+
+[source, java]
+----
+name like 'A%'
+----
+
+
+Parameters. Expressions can contain named parameters (names that start with 
"$") that can be substituted with values either by name or by position. 
Parameterized expressions allow to create reusable expression templates. Also 
if an Expression contains a complex object that doesn't have a simple String 
representation (e.g. a Date, a DataObject, an ObjectId), parameterizing such 
expression is the only way to represent it as String. Here are the examples of 
both positional and named parameter bindings:
+
+[source, java]
+----
+Expression template = ExpressionFactory.exp("name = $name");
+...
+// name binding
+Map p1 = Collections.singletonMap("name", "Salvador Dali");
+Expression qualifier1 = template.params(p1);
+...
+// positional binding
+Expression qualifier2 = template.paramsArray("Monet");
+----
+
+Positional binding is usually shorter. You can pass positional bindings to the 
`"exp(..)"` factory method (its second argument is a params vararg):
+
+[source, java]
+----
+Expression qualifier = ExpressionFactory.exp("name = $name", "Monet");
+----
+
+In parameterized expressions with LIKE clause, SQL wildcards must be part of 
the values in the Map and not the expression string itself:
+
+[source, java]
+----
+Expression qualifier = ExpressionFactory.exp("name like $name", "Salvador%");
+----
+
+When matching on a relationship, the value parameter must be either a 
Persistent object, an `org.apache.cayenne.ObjectId`, or a numeric ID value (for 
single column IDs). E.g.:
+
+[source, java]
+----
+Artist dali = ... // asume we fetched this one already
+Expression qualifier = ExpressionFactory.exp("artist = $artist", dali);
+----
+
+When using positional binding, Cayenne would expect values for all parameters 
to be present. Binding by name offers extra flexibility: subexpressions with 
uninitialized parameters are automatically pruned from the expression. So e.g. 
if certain parts of the expression criteria are not provided to the 
application, you can still build a valid expression:
+
+
+[source, java]
+----
+Expression template = ExpressionFactory.exp("name like $name and dateOfBirth > 
$date");
+...
+Map p1 = Collections.singletonMap("name", "Salvador%");
+Expression qualifier1 = template.params(p1);
+
+// "qualifier1" is now "name like 'Salvador%'".
+// 'dateOfBirth > $date' condition was pruned, as no value was specified for
+// the $date parameter
+----
+
+Null handling. Handling of Java nulls as operands is no different from normal 
values. Instead of using special conditional operators, like SQL does (IS NULL, 
IS NOT NULL), "=" and "!=" expressions are used directly with null values. It 
is up to Cayenne to translate expressions with nulls to the valid SQL.
+
+NOTE: A formal definition of the expression grammar is provided in Appendix C
+
+==== Creating Expressions via API
+
+Creating expressions from Strings is a powerful and dynamic approach, however 
a safer alternative is to use Java API. It provides compile-time checking of 
expressions validity. The API in question is provided by `ExpressionFactory` 
class (that we've seen already), Property class and Expression class itself. 
`ExpressionFactory` contains a number of self-explanatory static methods that 
can be used to build expressions. E.g.:
+
+[source, java]
+----
+// String expression: name like 'A%' and price < 1000
+Expression e1 = ExpressionFactory.likeExp("name", "A%");
+Expression e2 = ExpressionFactory.lessExp("price", 1000);
+Expression finalExp = e1.andExp(e2);
+----
+
+NOTE: The last line in the example above shows how to create a new expression 
by "chaining" two other epxressions. A common error when chaining expressions 
is to assume that "andExp" and "orExp" append another expression to the current 
expression. In fact a new expression is created. I.e. Expression API treats 
existing expressions as immutable.
+
+As discussed earlier, Cayenne supports aliases in path Expressions, allowing 
to control how SQL joins are generated if the same path is encountered more 
than once in the same Expression. Two ExpressionFactory methods allow to 
implicitly generate aliases to "split" match paths into individual joins if 
needed:
+
+[source, java]
+----
+Expression matchAllExp(String path, Collection values)
+Expression matchAllExp(String path, Object... values)
+----
+
+"Path" argument to both of these methods can use a split character (a pipe 
symbol '|') instead of dot to indicate that relationship following a path 
should be split into a separate set of joins, one per collection value. There 
can only be one split at most in any given path. Split must always precede a 
relationship. E.g. `"|exhibits.paintings"`, `"exhibits|paintings"`, etc. 
Internally Cayenne would generate distinct aliases for each of the split 
expressions, forcing separate joins.
+
+While ExpressionFactory is pretty powerful, there's an even easier way to 
create expression using static Property objects generated by Cayenne for each 
persistent class. Some examples:
+
+[source, java]
+----
+// Artist.NAME is generated by Cayenne and has a type of Property<String>
+Expression e1 = Artist.NAME.eq("Pablo");
+
+// Chaining multiple properties into a path..
+// Painting.ARTIST is generated by Cayenne and has a type of Property<Artist>
+Expression e2 = Painting.ARTIST.dot(Artist.NAME).eq("Pablo");
+----
+
+Property objects provide the API mostly analogius to ExpressionFactory, though 
it is significantly shorter and is aware of the value types. It provides 
compile-time checks of both property names and types of arguments in 
conditions. We will use Property-based API in further examples.
+
+[[evaluate]]
+==== Evaluating Expressions in Memory
+
+When used in a query, an expression is converted to SQL WHERE clause (or ORDER 
BY clause) by Cayenne during query execution. Thus the actual evaluation 
against the data is done by the database engine. However the same expressions 
can also be used for accessing object properties, calculating values, in-memory 
filtering.
+
+
+Checking whether an object satisfies an expression:
+
+[source, java]
+----
+Expression e = Artist.NAME.in("John", "Bob");
+Artist artist = ...
+if(e.match(artist)) {
+   ...
+}
+----
+
+Reading property value:
+
+
+[source, java]
+----
+String name = Artist.NAME.path().evaluate(artist);
+----
+
+Filtering a list of objects:
+
+[source, java]
+----
+Expression e = Artist.NAME.in("John", "Bob");
+List<Artist> unfiltered = ...
+List<Artist> filtered = e.filterObjects(unfiltered);
+----
+
+NOTE: Current limitation of in-memory expressions is that no collections are 
permitted in the property path.
+
+==== Translating Expressions to EJBQL
+
+xref:ejbql[EJBQL] is a textual query language that can be used with Cayenne. 
In some situations, it is convenient to be able to convert Expression instances 
into EJBQL. Expressions support this conversion. An example is shown below.
+
+[source, java]
+----
+String serial = ...
+Expression e = Pkg.SERIAL.eq(serial);
+List<Object> params = new ArrayList<Object>();
+EJBQLQuery query = new EJBQLQuery("SELECT p FROM Pkg p WHERE " + 
e.toEJBQL(params,"p");
+
+for(int i=0;i<params.size();i++) {
+  query.setParameter(i+1, params.get(i));
+}
+----
+
+This would be equivalent to the following purely EJBQL querying logic;
+
+[source, java]
+----
+EJBQLQuery query = new EJBQLQuery("SELECT p FROM Pkg p WHERE p.serial = ?1");
+query.setParameter(1,serial);
+----
+

http://git-wip-us.apache.org/repos/asf/cayenne/blob/cde78f0b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/including.adoc
----------------------------------------------------------------------
diff --git 
a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/including.adoc
 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/including.adoc
new file mode 100644
index 0000000..b60cc2e
--- /dev/null
+++ 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/including.adoc
@@ -0,0 +1,662 @@
+// 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.
+
+include::../var.adoc[]
+
+[[include]]
+=== Including Cayenne in a Project
+
+==== Jar Files
+
+This is an overview of Cayenne jars that is agnostic of the build tool used. 
The following are the important libraries:
+
+- `cayenne-di-{version}.jar` - Cayenne dependency injection (DI) container 
library. All applications will require this file.
+
+- `cayenne-server-{version}.jar` - contains main Cayenne runtime (adapters, DB 
access classes, etc.). Most applications will require this file.
+
+- `cayenne-client-{version}.jar` - a client-side runtime for xref:rop[ROP 
applications].
+
+- Other cayenne-* jars - various Cayenne tools extensions.
+
+==== Dependencies
+
+With modern build tools like Maven and Gradle, you should not worry about 
tracking dependencies. If you have one of those, you can skip this section and 
go straight to the Maven section below. However if your environment requires 
manual dependency resolution (like Ant), the distribution provides all of 
Cayenne jars plus a minimal set of third-party dependencies to get you started 
in a default configuration. Check lib and `lib/third-party` folders for those.
+
+Dependencies for non-standard configurations will need to be figured out by 
the users on their own. Check `pom.xml` files of the corresponding Cayenne 
modules in one of the searchable Maven archives out there to get an idea of 
those dependencies (e.g. http://search.maven.org).
+
+==== Maven Projects
+
+If you are using Maven, you won't have to deal with figuring out the 
dependencies. You can simply include cayenne-server artifact in your POM:
+
+[source,xml,subs="verbatim,attributes"]
+----
+<dependency>
+   <groupId>org.apache.cayenne</groupId>
+   <artifactId>cayenne-server</artifactId>
+   <version>{version}</version>
+</dependency>
+----
+
+Additionally Cayenne provides a Maven plugin with a set of goals to perform 
various project tasks, such as synching generated Java classes with the 
mapping, described in the following subsection. The full plugin name is 
`org.apache.cayenne.plugins:cayenne-maven-plugin`.
+
+[[cgen]]
+===== cgen
+
+`cgen` is a `cayenne-maven-plugin` goal that generates and maintains source 
(.java) files of persistent objects based on a DataMap. By default, it is bound 
to the generate-sources phase. If "makePairs" is set to "true" (which is the 
recommended default), this task will generate a pair of classes 
(superclass/subclass) for each ObjEntity in the DataMap. Superclasses should 
not be changed manually, since they are always overwritten. Subclasses are 
never overwritten and may be later customized by the user. If "makePairs" is 
set to "false", a single class will be generated for each ObjEntity.
+
+By creating custom templates, you can use cgen to generate other output (such 
as web pages, reports, specialized code templates) based on DataMap information.
+
+[#tablecgen.table.table-bordered]
+.cgen required parameters
+[cols="1,1,4"]
+|===
+|Name |Type|Description
+
+.^|map
+.^|File
+a|DataMap XML file which serves as a source of metadata for class generation. 
E.g.
+----
+${project.basedir}/src/main/resources/my.map.xml
+----
+|===
+
+
+[#cgenOptional.table.table-bordered]
+.cgen optional parameters
+[cols="2,1,5"]
+|===
+|Name |Type|Description
+
+.^|additionalMaps
+.^|File
+.^|A directory that contains additional DataMap XML files that may be needed 
to resolve cross-DataMap relationships for the the main DataMap, for which 
class generation occurs.
+
+.^|client
+.^|boolean
+.^|Whether we are generating classes for the client tier in a Remote Object 
Persistence application. "False" by default.
+
+.^|destDir
+.^|File
+.^|Root destination directory for Java classes (ignoring their package names). 
The default is "src/main/java".
+
+.^|embeddableTemplate
+.^|String
+.^|Location of a custom Velocity template file for Embeddable class 
generation. If omitted, default template is used.
+
+.^|embeddableSuperTemplate
+.^|String
+.^|Location of a custom Velocity template file for Embeddable superclass 
generation. Ignored unless "makepairs" set to "true". If omitted, default 
template is used.
+
+.^|encoding
+.^|String
+.^|Generated files encoding if different from the default on current platform. 
Target encoding must be supported by the JVM running the build. Standard 
encodings supported by Java on all platforms are US-ASCII, ISO-8859-1, UTF-8, 
UTF-16BE, UTF-16LE, UTF-16. See javadocs for java.nio.charset.Charset for more 
information.
+
+.^|excludeEntities
+.^|String
+.^|A comma-separated list of ObjEntity patterns (expressed as a perl5 regex) 
to exclude from template generation. By default none of the DataMap entities 
are excluded.
+
+.^|includeEntities
+.^|String
+.^|A comma-separated list of ObjEntity patterns (expressed as a perl5 regex) 
to include from template generation. By default all DataMap entities are 
included.
+
+.^|makePairs
+.^|boolean
+.^|If "true" (a recommended default), will generate subclass/superclass pairs, 
with all generated code placed in superclass.
+
+.^|mode
+.^|String
+.^|Specifies class generator iteration target. There are three possible 
values: "entity" (default), "datamap", "all". "entity" performs one generator 
iteration for each included ObjEntity, applying either standard to custom 
entity templates. "datamap" performs a single iteration, applying DataMap 
templates. "All" is a combination of entity and datamap.
+
+.^|overwrite
+.^|boolean
+.^|Only has effect when "makePairs" is set to "false". If "overwrite" is 
"true", will overwrite older versions of generated classes.
+
+.^|superPkg
+.^|String
+.^|Java package name of all generated superclasses. If omitted, each 
superclass will be placed in the subpackage of its subclass called "auto". 
Doesn't have any effect if either "makepairs" or "usePkgPath" are false (both 
are true by default).
+
+.^|superTemplate
+.^|String
+.^|Location of a custom Velocity template file for ObjEntity superclass 
generation. Only has effect if "makepairs" set to "true". If omitted, default 
template is used.
+
+.^|template
+.^|String
+.^|Location of a custom Velocity template file for ObjEntity class generation. 
If omitted, default template is used.
+
+.^|usePkgPath
+.^|boolean
+.^|If set to "true" (default), a directory tree will be generated in "destDir" 
corresponding to the class package structure, if set to "false", classes will 
be generated in "destDir" ignoring their package.
+
+.^|createPropertyNames
+.^|boolean
+.^|If set to "true", will generate String Property names. Default is "false"
+|===
+
+Example - a typical class generation scenario, where pairs of classes are 
generated with default Maven source destination and superclass package:
+
+[source,xml,subs="verbatim,attributes"]
+----
+<plugin>
+    <groupId>org.apache.cayenne.plugins</groupId>
+    <artifactId>cayenne-maven-plugin</artifactId>
+    <version>{version}</version>
+
+    <configuration>
+        <map>${project.basedir}/src/main/resources/my.map.xml</map>
+    </configuration>
+
+    <executions>
+        <execution>
+            <goals>
+                <goal>cgen</goal>
+            </goals>
+        </execution>
+    </executions>
+</plugin>
+----
+
+===== cdbgen
+
+`cdbgen` is a `cayenne-maven-plugin` goal that drops and/or generates tables 
in a database on Cayenne DataMap. By default, it is bound to the 
pre-integration-test phase.
+
+[#cdbgenTable.table.table-bordered]
+.cdbgen required parameters
+[cols="1,1,4"]
+|===
+|Name |Type|Description
+
+.^|map
+.^|File
+a|DataMap XML file which serves as a source of metadata for class generation. 
E.g.
+----
+${project.basedir}/src/main/resources/my.map.xml
+----
+
+.^|dataSource
+.^|XML
+.^|An object that contains Data Source parameters
+|===
+
+
+[#dataSourceParameteres.table.table-bordered]
+.<dataSource> parameters
+[cols="2,1,2,5"]
+|===
+|Name |Type |Required |Description
+
+.^|driver
+.^|String
+.^|Yes
+.^|A class of JDBC driver to use for the target database.
+
+.^|url
+.^|String
+.^|Yes
+.^|JDBC URL of a target database.
+
+.^|username
+.^|String
+.^|No
+.^|Database user name.
+
+.^|password
+.^|String
+.^|No
+.^|Database user password.
+|===
+
+[#cdbgenOptionl.table.table-bordered]
+.cdbgen optional parameters
+[cols="1,1,4"]
+|===
+|Name |Type|Description
+
+.^|adapter
+.^|String
+.^|Java class name implementing org.apache.cayenne.dba.DbAdapter. While this 
attribute is optional (a generic JdbcAdapter is used if not set), it is highly 
recommended to specify correct target adapter.
+
+
+.^|createFK
+.^|boolean
+.^|Indicates whether cdbgen should create foreign key constraints. Default is 
"true".
+
+.^|createPK
+.^|boolean
+.^|Indicates whether cdbgen should create Cayenne-specific auto PK objects. 
Default is "true".
+
+.^|createTables
+.^|boolean
+.^|Indicates whether cdbgen should create new tables. Default is "true".
+
+.^|dropPK
+.^|boolean
+.^|Indicates whether cdbgen should drop Cayenne primary key support objects. 
Default is "false".
+
+.^|dropTables
+.^|boolean
+.^|Indicates whether cdbgen should drop the tables before attempting to create 
new ones. Default is "false".
+|===
+
+Example - creating a DB schema on a local HSQLDB database:
+
+[source,xml, subs="verbatim,attributes"]
+----
+<plugin>
+    <groupId>org.apache.cayenne.plugins</groupId>
+    <artifactId>cayenne-maven-plugin</artifactId>
+    <version>{version}</version>
+    <executions>
+        <execution>
+            <configuration>
+                <map>${project.basedir}/src/main/resources/my.map.xml</map>
+                <adapter>org.apache.cayenne.dba.hsqldb.HSQLDBAdapter</adapter>
+                <dataSource>
+                    <url>jdbc:hsqldb:hsql://localhost/testdb</url>
+                    <driver>org.hsqldb.jdbcDriver</driver>
+                    <username>sa</username>
+                </dataSource>
+            </configuration>
+            <goals>
+                <goal>cdbgen</goal>
+            </goals>
+        </execution>
+    </executions>
+</plugin>
+----
+
+[[mavenCdbimort]]
+===== cdbimport
+
+`cdbimport` is a `cayenne-maven-plugin` goal that generates a DataMap based on 
an existing database schema. By default, it is bound to the generate-sources 
phase. This allows you to generate your DataMap prior to building your project, 
possibly followed by "cgen" execution to generate the classes. CDBImport plugin 
described in details in chapter xref:dbFirstFlow["DB-First Flow"]
+[#cdbimportTable.table.table-bordered]
+.cdbimport parameters
+[cols="2,1,2,5"]
+|===
+|Name |Type |Required |Description
+
+.^|map
+.^|File
+.^|Yes
+.^|DataMap XML file which is the destination of the schema import. Can be an 
existing file. If this file does not exist, it is created when cdbimport is 
executed. E.g. `${project.basedir}/src/main/resources/my.map.xml`. If 
"overwrite" is true (the default), an existing DataMap will be used as a 
template for the new imported DataMap, i.e. all its entities will be cleared 
and recreated, but its common settings, such as default Java package, will be 
preserved (unless changed explicitly in the plugin configuration).
+
+.^|adapter
+.^|String
+.^|No
+.^|A Java class name implementing org.apache.cayenne.dba.DbAdapter. This 
attribute is optional. If not specified, AutoAdapter is used, which will 
attempt to guess the DB type.
+
+.^|dataSource
+.^|XML
+.^|Yes
+.^|An object that contains Data Source parameters.
+
+.^|dbimport
+.^|XML
+.^|No
+.^|An object that contains detailed reverse engineering rules about what DB 
objects should be processed. For full information about this parameter see 
xref:dbFirstFlow["DB-First Flow"] chapter.
+|===
+
+[#cdbimportDataSource.table.table-bordered]
+.<dataSource> parameters
+[cols="2,1,2,5"]
+|===
+|Name |Type |Required |Description
+
+.^|driver
+.^|String
+.^|Yes
+.^|A class of JDBC driver to use for the target database.
+
+.^|url
+.^|String
+.^|Yes
+.^|JDBC URL of a target database.
+
+.^|username
+.^|String
+.^|No
+.^|Database user name.
+
+.^|password
+.^|String
+.^|No
+.^|Database user password.
+|===
+
+[#dbimportParameters.table.table-bordered]
+.<dbimport> parameters
+[cols="3,1,4"]
+|===
+|Name |Type|Description
+
+.^|defaultPackage
+.^|String
+.^|A Java package that will be set as the imported DataMap default and a 
package of all the persistent Java classes. This is a required attribute if the 
"map" itself does not already contain a default package, as otherwise all the 
persistent classes will be mapped with no package, and will not compile.
+
+.^|forceDataMapCatalog
+.^|boolean
+.^|Automatically tagging each DbEntity with the actual DB catalog/schema 
(default behavior) may sometimes be undesirable. If this is the case then 
setting `forceDataMapCatalog` to `true` will set DbEntity catalog to one in the 
DataMap. Default value is `false`.
+
+.^|forceDataMapSchema
+.^|boolean
+.^|Automatically tagging each DbEntity with the actual DB catalog/schema 
(default behavior) may sometimes be undesirable. If this is the case then 
setting `forceDataMapSchema` to `true` will set DbEntity schema to one in the 
DataMap. Default value is `false`.
+
+.^|meaningfulPkTables
+.^|String
+.^|A comma-separated list of Perl5 patterns that defines which imported tables 
should have their primary key columns mapped as ObjAttributes. "*" would 
indicate all tables.
+
+.^|namingStrategy
+.^|String
+.^|The naming strategy used for mapping database names to object entity names. 
Default is `org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator`.
+
+.^|skipPrimaryKeyLoading
+.^|boolean
+.^|Whether to load primary keys. Default "false".
+
+.^|skipRelationshipsLoading
+.^|boolean
+.^|Whether to load relationships. Default "false".
+
+.^|stripFromTableNames
+.^|String
+a|Regex that matches the part of the table name that needs to be stripped off 
when generating ObjEntity name. Here are some examples:
+[source,XML]
+----
+<!-- Strip prefix -->
+<stripFromTableNames>^myt_</stripFromTableNames>
+
+<!-- Strip suffix -->
+<stripFromTableNames>_s$</stripFromTableNames>
+
+<!-- Strip multiple occurrences in the middle -->
+<stripFromTableNames>_abc</stripFromTableNames>
+----
+
+.^|usePrimitives
+.^|boolean
+.^|Whether numeric and boolean data types should be mapped as Java primitives 
or Java classes. Default is "true", i.e. primitives will be used.
+
+.^|useJava7Types
+.^|boolean
+.^|Whether `DATE`, `TIME` and `TIMESTAMP` data types should be mapped as 
`java.util.Date` or `java.time.* classes`. Default is "false", i.e. 
`java.time.*` will be used.
+
+.^|filters configuration
+.^|XML
+a|Detailed reverse engineering rules about what DB objects should be 
processed. For full information about this parameter see  
xref:dbFirstFlow["DB-First Flow"] chapter. Here is some simple example:
+[source,XML]
+----
+<dbimport>
+       <catalog name="test_catalog">
+               <schema name="test_schema">
+                       <includeTable>.*</includeTable>
+                       <excludeTable>test_table</excludeTable>
+               </schema>
+       </catalog>
+
+       <includeProcedure pattern=".*"/>
+</dbimport>
+----
+
+
+|===
+
+Example - loading a DB schema from a local HSQLDB database (essentially a 
reverse operation compared to the cdbgen example above) :
+
+[source, XML, subs="verbatim,attributes"]
+----
+<plugin>
+    <groupId>org.apache.cayenne.plugins</groupId>
+    <artifactId>cayenne-maven-plugin</artifactId>
+    <version>{version}</version>
+
+    <executions>
+        <execution>
+            <configuration>
+                <map>${project.basedir}/src/main/resources/my.map.xml</map>
+                <dataSource>
+                    <url>jdbc:mysql://127.0.0.1/mydb</url>
+                    <driver>com.mysql.jdbc.Driver</driver>
+                    <username>sa</username>
+                </dataSource>
+                <dbimport>
+                    <defaultPackage>com.example.cayenne</defaultPackage>
+                </dbimport>
+            </configuration>
+            <goals>
+                <goal>cdbimport</goal>
+            </goals>
+        </execution>
+    </executions>
+</plugin>
+----
+
+==== Gradle Projects
+
+To include Cayenne into your Gradle project you have two options:
+
+- Simply add Cayenne as a dependency:
+
+[source, Groovy, subs="verbatim,attributes"]
+----
+compile 'org.apache.cayenne:cayenne-server:{version}'
+----
+
+- Or you can use Cayenne Gradle plugin
+
+===== Gradle Plugin
+
+Cayenne Gradle plugin provides several tasks, such as synching generated Java 
classes with the mapping or synching mapping with the database. Plugin also 
provides `cayenne` extension that have some useful utility methods. Here is 
example of how to include Cayenne plugin into your project:
+
+[source, Groovy, subs="verbatim,attributes"]
+----
+buildscript {
+    // add Maven Central repository
+    repositories {
+        mavenCentral()
+    }
+    // add Cayenne Gradle Plugin
+    dependencies {
+        classpath group: 'org.apache.cayenne.plugins', name: 
'cayenne-gradle-plugin', version: '{version}'
+    }
+}
+
+// apply plugin
+apply plugin: 'org.apache.cayenne'
+
+// set default DataMap
+cayenne.defaultDataMap 'datamap.map.xml'
+
+// add Cayenne dependencies to your project
+dependencies {
+    // this is a shortcut for 
'org.apache.cayenne:cayenne-server:VERSION_OF_PLUGIN'
+    compile cayenne.dependency('server')
+    compile cayenne.dependency('java8')
+}
+----
+
+====== Warning
+
+Cayenne Gradle plugin is experimental and it's API can change later.
+
+===== cgen
+
+Cgen task generates Java classes based on your DataMap, it has same 
configuration parameters as in Maven Plugin version, described in 
xref:tablecgen[Table, “cgen required parameters”.]. If you provided default 
DataMap via `cayenne.defaultDataMap`, you can skip `cgen` configuration as 
default settings will suffice in common case.
+
+Here is how you can change settings of the default `cgen` task:
+
+[source, Groovy]
+----
+cgen {
+    client = false
+    mode = 'all'
+    overwrite = true
+    createPropertiesNames = true
+}
+----
+
+And here is example of how to define additional cgen task (e.g. for client 
classes if you are using ROP):
+
+
+[source, Groovy]
+----
+task clientCgen(type: cayenne.cgen) {
+    client = true
+}
+----
+
+===== cdbimport
+
+This task is for creating and synchronizing your Cayenne model from database 
schema. Full list of parameters are same as in Maven Plugin version, described 
in xref:cdbimportTable[Table, “cdbimport parameters”], with exception that 
Gradle version will use Groovy instead of XML.
+
+Here is example of configuration for cdbimport task:
+
+[source, Groovy]
+----
+cdbimport {
+    // map can be skipped if it is defined in cayenne.defaultDataMap
+    map 'datamap.map.xml'
+
+    dataSource {
+        driver 'com.mysql.cj.jdbc.Driver'
+        url 'jdbc:mysql://127.0.0.1:3306/test?useSSL=false'
+        username 'root'
+        password ''
+    }
+
+    dbImport
+        // additional settings
+        usePrimitives false
+        defaultPackage 'org.apache.cayenne.test'
+
+        // DB filter configuration
+        catalog 'catalog-1'
+        schema 'schema-1'
+
+        catalog {
+            name 'catalog-2'
+
+            includeTable 'table0', {
+                excludeColumns '_column_'
+            }
+
+            includeTables 'table1', 'table2', 'table3'
+
+            includeTable 'table4', {
+                includeColumns 'id', 'type', 'data'
+            }
+
+            excludeTable '^GENERATED_.*'
+        }
+
+        catalog {
+            name 'catalog-3'
+            schema {
+                name 'schema-2'
+                includeTable 'test_table'
+                includeTable 'test_table2', {
+                    excludeColumn '__excluded'
+                }
+            }
+        }
+
+        includeProcedure 'procedure_test_1'
+
+        includeColumns 'id', 'version'
+
+        tableTypes 'TABLE', 'VIEW'
+    }
+}
+----
+
+===== cdbgen
+
+Cdbgen task drops and/or generates tables in a database on Cayenne DataMap. 
Full list of parameters are same as in Maven Plugin version, described in 
xref:cdbgenTable[Table , “cdbgen required parameters”]
+
+Here is example of how to configure default `cdbgen` task:
+
+[source, Groovy]
+----
+cdbgen {
+
+    adapter 'org.apache.cayenne.dba.derby.DerbyAdapter'
+
+    dataSource {
+        driver 'org.apache.derby.jdbc.EmbeddedDriver'
+        url 'jdbc:derby:build/testdb;create=true'
+        username 'sa'
+        password ''
+    }
+
+    dropTables true
+    dropPk true
+
+    createTables true
+    createPk true
+    createFk true
+}
+----
+
+===== Link tasks to Gradle build lifecycle
+
+With gradle you can easily connect Cayenne tasks to default build lifecycle. 
Here is short example of how to connect defaut `cgen` and `cdbimport` tasks 
with `compileJava` task:
+
+[source, Groovy]
+----
+cgen.dependsOn cdbimport
+compileJava.dependsOn cgen
+----
+
+NOTE: Running `cdbimport` automatically with build not always a good choice, 
e.g. in case of complex model that you need to alter in the Cayenne Modeler 
after import.
+
+==== Ant Projects
+
+Ant tasks are the same as Maven plugin goals described above, namely "cgen", 
"cdbgen", "cdbimport". Configuration parameters are also similar (except Maven 
can guess many defaults that Ant can't). To include Ant tasks in the project, 
use the following Antlib:
+
+[source, XML]
+----
+<typedef resource="org/apache/cayenne/tools/antlib.xml">
+   <classpath>
+               <fileset dir="lib" >
+                       <include name="cayenne-ant-*.jar" />
+                       <include name="cayenne-cgen-*.jar" />
+                       <include name="cayenne-dbsync-*.jar" />
+                       <include name="cayenne-di-*.jar" />
+                       <include name="cayenne-project-*.jar" />
+                       <include name="cayenne-server-*.jar" />
+                       <include name="commons-collections-*.jar" />
+                       <include name="commons-lang-*.jar" />
+                       <include name="slf4j-api-*.jar" />
+                       <include name="velocity-*.jar" />
+                       <include name="vpp-2.2.1.jar" />
+               </fileset>
+   </classpath>
+</typedef>
+----
+
+===== cgen
+
+===== cdbgen
+
+===== cdbimport
+
+This is an Ant counterpart of "cdbimport" goal of cayenne-maven-plugin 
described above. It has exactly the same properties. Here is a usage example:
+
+[source, XML]
+----
+ <cdbimport map="${context.dir}/WEB-INF/my.map.xml"
+    driver="com.mysql.jdbc.Driver"
+    url="jdbc:mysql://127.0.0.1/mydb"
+    username="sa"
+    defaultPackage="com.example.cayenne"/>
+----
+

http://git-wip-us.apache.org/repos/asf/cayenne/blob/cde78f0b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc
----------------------------------------------------------------------
diff --git 
a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc
 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc
new file mode 100644
index 0000000..9305723
--- /dev/null
+++ 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc
@@ -0,0 +1,273 @@
+// 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.
+
+=== Lifecycle Events
+
+An application might be interested in getting notified when a Persistent 
object moves through its lifecycle (i.e. fetched from DB, created, modified, 
committed). E.g. when a new object is created, the application may want to 
initialize its default properties (this can't be done in constructor, as 
constructor is also called when an object is fetched from DB). Before save, the 
application may perform validation and/or set some properties (e.g. 
"updatedTimestamp"). After save it may want to create an audit record for each 
saved object, etc., etc.
+
+All this can be achieved by declaring callback methods either in Persistent 
objects or in non-persistent listener classes defined by the application 
(further simply called "listeners"). There are eight types of lifecycle events 
supported by Cayenne, listed later in this chapter. When any such event occurs 
(e.g. an object is committed), Cayenne would invoke all appropriate callbacks. 
Persistent objects would receive their own events, while listeners would 
receive events from any objects.
+
+Cayenne allows to build rather powerful and complex "workflows" or 
"processors" tied to objects lifecycle, especially with listeners, as they have 
full access to the application evnironment outside Cayenne. This power comes 
from such features as filtering which entity events are sent to a given 
listener and the ability to create a common operation context for multiple 
callback invocations. All of these are discussed later in this chapter.
+
+==== Types of Lifecycle Events
+
+Cayenne defines the following 8 types of lifecycle events for which callbacks 
can be regsitered:
+
+[#lifecycleEvent.table.table-bordered]
+.Lifecycle Event Types
+[cols="1,4"]
+|===
+|Event |Occurs...
+
+.^|PostAdd
+.^|right after a new object is created inside `ObjectContext.newObject()`. 
When this event is fired the object is already registered with its 
ObjectContext and has its ObjectId and ObjectContext properties set.
+
+.^|PrePersist
+.^|right before a new object is committed, inside 
`ObjectContext.commitChanges()` and `ObjectContext.commitChangesToParent()` 
(and after `"validateForInsert()"`).
+
+.^|PreUpdate
+.^|right before a modified object is committed, inside 
`ObjectContext.commitChanges()` and `ObjectContext.commitChangesToParent()` 
(and after `"validateForUpdate()"`).
+
+.^|PreRemove
+.^|right before an object is deleted, inside `ObjectContext.deleteObjects()`. 
The event is also generated for each object indirectly deleted as a result of 
CASCADE delete rule.
+
+.^|PostPersist
+.^|right after a commit of a new object is done, inside 
`ObjectContext.commitChanges()`.
+
+.^|PostUpdate
+.^|right after a commit of a modified object is done, inside 
`ObjectContext.commitChanges()`.
+
+.^|PostRemove
+.^|right after a commit of a deleted object is done, inside 
`ObjectContext.commitChanges()`.
+
+.^|PostLoad
+a|
+- After an object is fetched inside ObjectContext.performQuery().
+- After an object is reverted inside ObjectContext.rollbackChanges().
+- Anytime a faulted object is resolved (i.e. if a relationship is fetched).
+|===
+
+==== Callbacks on Persistent Objects
+
+Callback methods on Persistent classes are mapped in CayenneModeler for each 
ObjEntity. Empty callback methods are automatically created as a part of class 
generation (either with Maven, Ant or the Modeler) and are later filled with 
appropriate logic by the programmer. E.g. assuming we mapped a 'post-add' 
callback called 'onNewOrder' in ObjEntity 'Order', the following code will be 
generated:
+
+[source, Java]
+----
+public abstract class _Order extends CayenneDataObject {
+    protected abstract void onNewOrder();
+}
+
+public class Order extends _Order {
+
+    @Override
+    protected void onNewOrder() {
+        //TODO: implement onNewOrder
+    }
+}
+----
+
+As `onNewOrder()` is already declared in the mapping, it does not need to be 
registered explicitly. Implementing the method in subclass to do something 
meaningful is all that is required at this point.
+
+As a rule callback methods do not have any knowledge of the outside 
application, and can only access the state of the object itself and possibly 
the state of other persistent objects via object's own ObjectContext.
+
+NOTE: Validation and callbacks: There is a clear overlap in functionality 
between object callbacks and `DataObject.validateForX()` methods. In the future 
validation may be completely superceeded by callbacks. It is a good idea to use 
"validateForX" strictly for validation (or not use it at all). Updating the 
state before commit should be done via callbacks.
+
+==== Callbacks on Non-Persistent Listeners
+
+A listener is simply some application class that has one or more annotated 
callback methods. A callback method signature should be `void 
someMethod(SomePersistentType object)`. It can be public, private, protected or 
use default access:
+
+[source, Java]
+----
+ public class OrderListener {
+
+   @PostAdd(Order.class)
+   public void setDefaultsForNewOrder(Order o) {
+      o.setCreatedOn(new Date());
+   }
+}
+----
+
+Notice that the example above contains an annotation on the callback method 
that defines the type of the event this method should be called for. Before we 
go into annotation details, we'll show how to create and register a listener 
with Cayenne. It is always a user responsibility to register desired 
application listeners, usually right after ServerRuntime is started. Here is an 
example:
+
+First let's define 2 simple listeners.
+
+[source, Java]
+----
+public class Listener1 {
+
+    @PostAdd(MyEntity.class)
+    void postAdd(Persistent object) {
+        // do something
+    }
+}
+
+public class Listener2 {
+
+    @PostRemove({ MyEntity1.class, MyEntity2.class })
+    void postRemove(Persistent object) {
+        // do something
+    }
+
+    @PostUpdate({ MyEntity1.class, MyEntity2.class })
+    void postUpdate(Persistent object) {
+        // do something
+    }
+}
+----
+
+Ignore the annotations for a minute. The important point here is that the 
listeners are arbitrary classes unmapped and unknown to Cayenne, that contain 
some callback methods. Now let's register them with runtime:
+
+[source, Java]
+----
+ServerRuntime runtime = ...
+
+runtime.getDataDomain().addListener(new Listener1());
+runtime.getDataDomain().addListener(new Listener2());
+----
+
+
+Listeners in this example are very simple. However they don't have to be. 
Unlike Persistent objects, normally listeners initialization is managed by the 
application code, not Cayenne, so listeners may have knowledge of various 
application services, operation transactional context, etc. Besides a single 
listener can apply to multiple entities. As a consequence their callbacks can 
do more than just access a single ObjectContext.
+
+Now let's discuss the annotations. There are eight annotations exactly 
matching the names of eight lifecycle events. A callback method in a listener 
should be annotated with at least one, but possibly with more than one of them. 
Annotation itself defines what event the callback should react to. Annotation 
parameters are essentially an entity filter, defining a subset of ObjEntities 
whose events we are interested in:
+
+[source, Java]
+----
+// this callback will be invoked on PostRemove event of any object
+// belonging to MyEntity1, MyEntity2 or their subclasses
+@PostRemove({ MyEntity1.class, MyEntity2.class })
+void postRemove(Persistent object) {
+    ...
+}
+----
+
+[source, Java]
+----
+// similar example with multipe annotations on a single method
+// each matching just one entity
+@PostPersist(MyEntity1.class)
+@PostRemove(MyEntity1.class)
+@PostUpdate(MyEntity1.class)
+void postCommit(MyEntity1 object) {
+    ...
+}
+----
+
+As shown above, "value" (the implicit annotation parameter) can contain one or 
more entity classes. Only these entities' events will result in callback 
invocation. There's also another way to match entities - via custom 
annotations. This allows to match any number of entities without even knowing 
what they are. Here is an example. We'll first define a custom annotation:
+
+[source, Java]
+----
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Tag {
+
+}
+----
+
+Now we can define a listener that will react to events from ObjEntities 
annotated with this annotation:
+
+[source, Java]
+----
+public class Listener3 {
+
+    @PostAdd(entityAnnotations = Tag.class)
+    void postAdd(Persistent object) {
+        // do something
+    }
+}
+----
+
+As you see we don't have any entities yet, still we can define a listener that 
does something useful. Now let's annotate some entities:
+
+[source, Java]
+----
+@Tag
+public class MyEntity1 extends _MyEntity1 {
+
+}
+
+@Tag
+public class MyEntity2 extends _MyEntity2 {
+
+}
+----
+
+
+==== Combining Listeners with DataChannelFilters
+
+A final touch in the listeners design is preserving the state of the listener 
within a single select or commit, so that events generated by multiple objects 
can be collected and processed all together. To do that you will need to 
implement a `DataChannelFilter`, and add some callback methods to it. They will 
store their state in a ThreadLocal variable of the filter. Here is an example 
filter that does something pretty meaningless - counts how many total objects 
were committed. However it demonstrates the important pattern of aggregating 
multiple events and presenting a combined result:
+
+[source, Java]
+----
+public class CommittedObjectCounter implements DataChannelFilter {
+
+    private ThreadLocal<int[]> counter;
+
+    @Override
+    public void init(DataChannel channel) {
+        counter = new ThreadLocal<int[]>();
+    }
+
+    @Override
+    public QueryResponse onQuery(ObjectContext originatingContext, Query 
query, DataChannelFilterChain filterChain) {
+        return filterChain.onQuery(originatingContext, query);
+    }
+
+    @Override
+    public GraphDiff onSync(ObjectContext originatingContext, GraphDiff 
changes, int syncType,
+            DataChannelFilterChain filterChain) {
+
+        // init the counter for the current commit
+        counter.set(new int[1]);
+
+        try {
+            return filterChain.onSync(originatingContext, changes, syncType);
+        } finally {
+
+            // process aggregated result and release the counter
+            System.out.println("Committed " + counter.get()[0] + " object(s)");
+            counter.set(null);
+        }
+    }
+
+    @PostPersist(entityAnnotations = Tag.class)
+    @PostUpdate(entityAnnotations = Tag.class)
+    @PostRemove(entityAnnotations = Tag.class)
+    void afterCommit(Persistent object) {
+        counter.get()[0]++;
+    }
+}
+----
+
+Now since this is both a filter and a listener, it needs to be registered as 
such:
+
+[source, Java]
+----
+CommittedObjectCounter counter = new CommittedObjectCounter();
+
+ServerRuntime runtime = ...
+DataDomain domain = runtime.getDataDomain();
+
+// register filter
+// this will also add it as a listener (since 3.2)
+domain.addFilter(counter);
+----
+
+
+
+
+
+
+
+
+

Reply via email to