Return-Path: X-Original-To: apmail-cayenne-commits-archive@www.apache.org Delivered-To: apmail-cayenne-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E67D0DC74 for ; Wed, 7 Nov 2012 12:37:15 +0000 (UTC) Received: (qmail 53115 invoked by uid 500); 7 Nov 2012 12:37:15 -0000 Delivered-To: apmail-cayenne-commits-archive@cayenne.apache.org Received: (qmail 53075 invoked by uid 500); 7 Nov 2012 12:37:15 -0000 Mailing-List: contact commits-help@cayenne.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cayenne.apache.org Delivered-To: mailing list commits@cayenne.apache.org Received: (qmail 53028 invoked by uid 99); 7 Nov 2012 12:37:15 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 07 Nov 2012 12:37:15 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 07 Nov 2012 12:37:10 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 96B2F238896F for ; Wed, 7 Nov 2012 12:36:50 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1406588 [1/3] - in /cayenne/site/cms/trunk/content/v31/cayenne-guide: ./ css/ images/ Date: Wed, 07 Nov 2012 12:36:49 -0000 To: commits@cayenne.apache.org From: aadamchik@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20121107123650.96B2F238896F@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: aadamchik Date: Wed Nov 7 12:36:48 2012 New Revision: 1406588 URL: http://svn.apache.org/viewvc?rev=1406588&view=rev Log: Cayenne guide 3.1 Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/ cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part1.html cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part2.html cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part3.html cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-mapping-structure.html cayenne/site/cms/trunk/content/v31/cayenne-guide/cayennemodeler-application.html cayenne/site/cms/trunk/content/v31/cayenne-guide/client-configuration-properties.html cayenne/site/cms/trunk/content/v31/cayenne-guide/css/ cayenne/site/cms/trunk/content/v31/cayenne-guide/css/cayenne-doc.css cayenne/site/cms/trunk/content/v31/cayenne-guide/current-limitations.html cayenne/site/cms/trunk/content/v31/cayenne-guide/customizing-cayenne-runtime.html cayenne/site/cms/trunk/content/v31/cayenne-guide/expressions-bnf.html cayenne/site/cms/trunk/content/v31/cayenne-guide/expressions.html cayenne/site/cms/trunk/content/v31/cayenne-guide/images/ cayenne/site/cms/trunk/content/v31/cayenne-guide/images/.gitignore cayenne/site/cms/trunk/content/v31/cayenne-guide/implementing-rop-client.html cayenne/site/cms/trunk/content/v31/cayenne-guide/implementing-rop-server.html cayenne/site/cms/trunk/content/v31/cayenne-guide/including-cayenne-in-project.html cayenne/site/cms/trunk/content/v31/cayenne-guide/index.html cayenne/site/cms/trunk/content/v31/cayenne-guide/introduction-to-rop.html cayenne/site/cms/trunk/content/v31/cayenne-guide/lifecycle-events.html cayenne/site/cms/trunk/content/v31/cayenne-guide/orderings.html cayenne/site/cms/trunk/content/v31/cayenne-guide/performance-tuning.html cayenne/site/cms/trunk/content/v31/cayenne-guide/persistent-objects-objectcontext.html cayenne/site/cms/trunk/content/v31/cayenne-guide/queries.html cayenne/site/cms/trunk/content/v31/cayenne-guide/rop-deployment.html cayenne/site/cms/trunk/content/v31/cayenne-guide/rop-setup.html cayenne/site/cms/trunk/content/v31/cayenne-guide/server-configuration-properties.html cayenne/site/cms/trunk/content/v31/cayenne-guide/setup.html cayenne/site/cms/trunk/content/v31/cayenne-guide/starting-cayenne.html Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part1.html URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part1.html?rev=1406588&view=auto ============================================================================== --- cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part1.html (added) +++ cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part1.html Wed Nov 7 12:36:48 2012 @@ -0,0 +1,3 @@ + + + Part I. Object Relational Mapping with Cayenne \ No newline at end of file Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part2.html URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part2.html?rev=1406588&view=auto ============================================================================== --- cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part2.html (added) +++ cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part2.html Wed Nov 7 12:36:48 2012 @@ -0,0 +1,3 @@ + + + Part II. Cayenne Framework \ No newline at end of file Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part3.html URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part3.html?rev=1406588&view=auto ============================================================================== --- cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part3.html (added) +++ cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-guide-part3.html Wed Nov 7 12:36:48 2012 @@ -0,0 +1,3 @@ + + + Part III. Cayenne Framework - Remote Object Persistence \ No newline at end of file Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-mapping-structure.html URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-mapping-structure.html?rev=1406588&view=auto ============================================================================== --- cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-mapping-structure.html (added) +++ cayenne/site/cms/trunk/content/v31/cayenne-guide/cayenne-mapping-structure.html Wed Nov 7 12:36:48 2012 @@ -0,0 +1,3 @@ + + + Chapter 2. Cayenne Mapping Structure

Chapter 2. Cayenne Mapping Structure

Cayenne Project

DataMap

DataNode

DbEntity

ObjEntity

Mapping ObjAttributes to Custom Classes

Embeddable

Procedure

Query

Listeners and Callbacks

\ No newline at end of file Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/cayennemodeler-application.html URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/cayennemodeler-application.html?rev=1406588&view=auto ============================================================================== --- cayenne/site/cms/trunk/content/v31/cayenne-guide/cayennemodeler-application.html (added) +++ cayenne/site/cms/trunk/content/v31/cayenne-guide/cayennemodeler-application.html Wed Nov 7 12:36:48 2012 @@ -0,0 +1,13 @@ + + + Chapter 3. CayenneModeler Application

Chapter 3. CayenneModeler Application

Working with Mapping Projects

Reverse Engineering Database

Generating Database Schema

Migrations

Generating Java Classes

Modeling Inheritance

Modeling Generic Persistent Classes

Normally each ObjEntity is map ped to a specific Java class (such as Artist or + Painting) that explicitly declare all entity properties as pairs of getters and setters. + However Cayenne allows to map a completly generic class to any number of entities. The + only expectation is that a generic class implements + org.apache.cayenne.DataObject. So an ideal candidate for a + generic class is CayenneDataObject, or some custom subclass of CayenneDataObject.

If you don't enter anything for Java Class of an ObjEntity, Cayenne assumes generic + mapping and uses the following implicit rules to determine a class of a generic object. + If DataMap "Custom Superclass" is set, runtime uses this class to instantiate new + objects. If not, org.apache.cayenne.CayenneDataObject is used.

Class generation procedures (either done in the Modeler or with Ant or Maven) would + skip entities that are mapped to CayenneDataObject explicitly or have no class + mapping.

Modeling Primary Key Generation Strategy

\ No newline at end of file Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/client-configuration-properties.html URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/client-configuration-properties.html?rev=1406588&view=auto ============================================================================== --- cayenne/site/cms/trunk/content/v31/cayenne-guide/client-configuration-properties.html (added) +++ cayenne/site/cms/trunk/content/v31/cayenne-guide/client-configuration-properties.html Wed Nov 7 12:36:48 2012 @@ -0,0 +1,47 @@ + + + Appendix B. Service Collections

Appendix B. Service Collections

Note that the collection keys below are + defined as constants in org.apache.cayenne.configuration.Constants + interface.

+

+ + + + + + + + + + + + + + + +
Table B.1. Service Collection Keys Present in ServerRuntime and/or ClientRuntime
cayenne.properties - Map<String,String> of properties used by built-in + Cayenne services. The keys in this map are the property names from the table + in Appendix A. Separate copies of this map exist on the server and ROP + client.
cayenne.server.adapter_detectors - List<DbAdapterDetector> that contains + objects that can discover the type of current database and install the + correct DbAdapter in runtime.
cayenne.server.domain_filters - List<DataChannelFilter> storing DataDomain + filters.
cayenne.server.project_locations - List<String> storing + locations of the one of more project configuration files.
cayenne.server.default_types - List<ExtendedType> storing + default adapter-agnostic ExtendedTypes. Default ExtendedTypes can be + overridden / extended by DB-specific DbAdapters as well as by user-provided + types configured in another colltecion (see + "cayenne.server.user_types").
cayenne.server.user_types - List<ExtendedType> storing a + user-provided ExtendedTypes. This collection will be merged into a full list + of ExtendedTypes and would override any ExtendedTypes defined in a default + list, or by a DbAdapter.
cayenne.server.type_factories - List<ExtendedTypeFactory> + storing default and user-provided ExtendedTypeFactories. ExtendedTypeFactory + allows to define ExtendedTypes dynamically for the whole group of Java + classes. E.g. Cayenne supplies a factory to map all Enums regardless of + their type.
cayenne.server.rop_event_bridge_properties - Map<String, + String> storing event bridge properties passed to the ROP client on + bootstrap. This means that the map is configured by server DI, and passed to + the client via the wire. The properties in this map are specific to + EventBridgeFactory implementation (e.g JMS or XMPP connection prameters). + One common property is "cayenne.server.rop_event_bridge_factory" that + defines the type of the factory.

+

\ No newline at end of file Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/css/cayenne-doc.css URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/css/cayenne-doc.css?rev=1406588&view=auto ============================================================================== (empty) Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/current-limitations.html URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/current-limitations.html?rev=1406588&view=auto ============================================================================== --- cayenne/site/cms/trunk/content/v31/cayenne-guide/current-limitations.html (added) +++ cayenne/site/cms/trunk/content/v31/cayenne-guide/current-limitations.html Wed Nov 7 12:36:48 2012 @@ -0,0 +1,3 @@ + + + Chapter 18. Current Limitations

Chapter 18. Current Limitations

\ No newline at end of file Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/customizing-cayenne-runtime.html URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/customizing-cayenne-runtime.html?rev=1406588&view=auto ============================================================================== --- cayenne/site/cms/trunk/content/v31/cayenne-guide/customizing-cayenne-runtime.html (added) +++ cayenne/site/cms/trunk/content/v31/cayenne-guide/customizing-cayenne-runtime.html Wed Nov 7 12:36:48 2012 @@ -0,0 +1,189 @@ + + + Chapter 12. Customizing Cayenne Runtime

Chapter 12. 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:

public interface Service1 {
+	public String getString();
+}
public interface Service2 {
+	public int getInt();
+}

A service implementation using instance variable + injection:

public class Service1Impl implements Service1 {
+	@Inject
+	private Service2 service2;
+	
+	public String getString() {
+		return service2.getInt() + "_Service1Impl";
+	}
+}

Same + thing, but using constructor + injection:

public class Service1Impl implements Service1 {
+
+	private Service2 service2;
+
+	public Service1Impl(@Inject Service2 service2) {
+		this.service2 = service2;
+	}
+
+	public String getString() {
+		return service2.getInt() + "_Service1Impl";
+	}
+}
+
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:

+

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:

Injector injector = DIBootstrap.createInjector(new Module1());

Now that we have created the container, we can obtain services from it and call + their + methods:

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: +

// 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:

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:

public class MyExtensionsModule implements Module {
+	public void configure(Binder binder) {
+		// customizations go here...
+	}	
+}
Module extensions = new MyExtensionsModule();
+ServerRuntime runtime = 
+	new ServerRuntime("com/example/cayenne-mydomain.xml", extensions);

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 -Dorg.apache.cayenne.sync_contexts=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:

public class MyDbAdapterDetector implements DbAdapterDetector {
+	public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
+		// check if we support this database and retun custom adapter
+		...
+	}
+}
// 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:

binder.bind(QueryCache.class).to(EhCacheQueryCache.class);

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.CommonsJdbcEventLogger that performs logging + via commons-logging library. Cayenne library includes another potentially useful + logger - org.apache.cayenne.log.FormattedCommonsJdbcEventLogger that + produces formatted multiline SQL output that can be easier to read.

DataSourceFactory

DataChannelFilter

QueryCache

ExtendedTypes

\ No newline at end of file Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/expressions-bnf.html URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/expressions-bnf.html?rev=1406588&view=auto ============================================================================== --- cayenne/site/cms/trunk/content/v31/cayenne-guide/expressions-bnf.html (added) +++ cayenne/site/cms/trunk/content/v31/cayenne-guide/expressions-bnf.html Wed Nov 7 12:36:48 2012 @@ -0,0 +1,125 @@ + + + Appendix C. Expressions BNF

Appendix C. Expressions BNF

+

+TOKENS
+<DEFAULT> SKIP : {
+" "
+| "\t"
+| "\n"
+| "\r"
+}
+
+<DEFAULT> TOKEN : {
+<NULL: "null" | "NULL">
+| <TRUE: "true" | "TRUE">
+| <FALSE: "false" | "FALSE">
+}
+
+<DEFAULT> TOKEN : {
+<PROPERTY_PATH: <IDENTIFIER> ("." <IDENTIFIER>)*>
+}
+
+<DEFAULT> TOKEN : {
+<IDENTIFIER: <LETTER> (<LETTER> | <DIGIT>)* (["+"])?>
+| <#LETTER: ["_","a"-"z","A"-"Z"]>
+| <#DIGIT: ["0"-"9"]>
+}
+
+/** 
+ * Quoted Strings, whose object value is stored in the token manager's
+ * "literalValue" field. Both single and double qoutes are allowed 
+ */<DEFAULT> MORE : {
+"\'" : WithinSingleQuoteLiteral
+| "\"" : WithinDoubleQuoteLiteral
+}
+
+<WithinSingleQuoteLiteral> MORE : {
+<ESC: "\\" (["n","r","t","b","f","\\","\'","`","\""] | (["0"-"3"])? ["0"-"7"] (["0"-"7"])?)> : {
+| <~["\'","\\"]> : {
+}
+
+<WithinSingleQuoteLiteral> TOKEN : {
+<SINGLE_QUOTED_STRING: "\'"> : DEFAULT
+}
+
+<WithinDoubleQuoteLiteral> MORE : {
+<STRING_ESC: <ESC>> : {
+| <~["\"","\\"]> : {
+}
+
+<WithinDoubleQuoteLiteral> TOKEN : {
+<DOUBLE_QUOTED_STRING: "\""> : DEFAULT
+}
+
+/**
+ * Integer or real Numeric literal, whose object value is stored in the token manager's
+ * "literalValue" field.
+ */<DEFAULT> TOKEN : {
+<INT_LITERAL: ("0" (["0"-"7"])* | ["1"-"9"] (["0"-"9"])* | "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+) (["l","L","h","H"])?> : {
+| <FLOAT_LITERAL: <DEC_FLT> (<EXPONENT>)? (<FLT_SUFF>)? | <DEC_DIGITS> <EXPONENT> (<FLT_SUFF>)? | <DEC_DIGITS> <FLT_SUFF>> : {
+| <#DEC_FLT: (["0"-"9"])+ "." (["0"-"9"])* | "." (["0"-"9"])+>
+| <#DEC_DIGITS: (["0"-"9"])+>
+| <#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+>
+| <#FLT_SUFF: ["d","D","f","F","b","B"]>
+}
+
+NON-TERMINALS
+	expression	:=	orCondition <EOF>
+	orCondition	:=	andCondition ( "or" andCondition )*
+	andCondition	:=	notCondition ( "and" notCondition )*
+	notCondition	:=	( "not" | "!" ) simpleCondition
+		|	simpleCondition
+	simpleCondition	:=	<TRUE>
+		|	<FALSE>
+		|	scalarConditionExpression 
+             ( simpleNotCondition 
+               | ( "=" | "==" ) scalarExpression 
+               | ( "!=" | "<>" ) scalarExpression 
+               | "<=" scalarExpression 
+               | "<" scalarExpression | ">" scalarExpression 
+               | ">=" scalarExpression 
+               | "like" scalarExpression 
+               | "likeIgnoreCase" scalarExpression 
+               | "in" ( namedParameter | "(" scalarCommaList ")" ) 
+               | "between" scalarExpression "and" scalarExpression 
+             )?
+	simpleNotCondition	:=	( "not" | "!" ) 
+             ( "like" scalarExpression 
+               | "likeIgnoreCase" scalarExpression 
+               | "in" ( namedParameter | "(" scalarCommaList ")" ) 
+               | "between" scalarExpression "and" scalarExpression 
+             )
+	scalarCommaList	:=	( scalarConstExpression ( "," scalarConstExpression )* )
+	scalarConditionExpression	:=	scalarNumericExpression
+		|	<SINGLE_QUOTED_STRING> 
+		|	<DOUBLE_QUOTED_STRING> 
+		|	<NULL>
+	scalarExpression	:=	scalarConditionExpression
+		|	<TRUE> 
+		|	<FALSE> 
+	scalarConstExpression	:=	<SINGLE_QUOTED_STRING> 
+		|	<DOUBLE_QUOTED_STRING> 
+		|	namedParameter
+		|	<INT_LITERAL> 
+		|	<FLOAT_LITERAL> 
+		|	<TRUE> 
+		|	<FALSE> 
+	scalarNumericExpression	:=	multiplySubtractExp 
+             ( "+" multiplySubtractExp | "-" multiplySubtractExp )*
+	multiplySubtractExp	:=	numericTerm ( "*" numericTerm | "/" numericTerm )*
+	numericTerm	:=	( "+" )? numericPrimary
+		|	"-" numericPrimary
+	numericPrimary	:=	"(" orCondition ")"
+		|	pathExpression
+		|	namedParameter
+		|	<INT_LITERAL> 
+		|	<FLOAT_LITERAL> 
+	namedParameter	:=	"$" <PROPERTY_PATH> 
+	pathExpression	:=	( <PROPERTY_PATH>  
+                            | "obj:" <PROPERTY_PATH>  
+                            | "db:" <PROPERTY_PATH>  
+                            | "enum:" <PROPERTY_PATH>  )
+
+

+

\ No newline at end of file Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/expressions.html URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/expressions.html?rev=1406588&view=auto ============================================================================== --- cayenne/site/cms/trunk/content/v31/cayenne-guide/expressions.html (added) +++ cayenne/site/cms/trunk/content/v31/cayenne-guide/expressions.html Wed Nov 7 12:36:48 2012 @@ -0,0 +1,168 @@ + + + Chapter 7. Expressions

Chapter 7. Expressions

Expressions Overview

Cayenne provides a simple yet powerful object-based expression language. The most common + usese 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 + understanding the semantics. A Cayenne expression can be represented as a String, which + can be later converted to an expression object using Expression.fromString + static method. Here is an + example:

String expString = "name like 'A%' and price < 1000";
+Expression exp = Expression.fromString(expString);

This + particular expression may be used to match Paintings with names that start with "A" and + a price 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:

name = 'ABC'
+
+// double quotes are escaped inside Java Strings of course
+name = \"ABC\"

Case sensitivity. Expression operators are all case + sensitive and are usually lowercase. Complex words follow the java camel-case + style:

// valid
+name likeIgnoreCase 'A%'
+
+// invalid - will throw a parse exception
+name LIKEIGNORECASE 'A%'

Grouping with + parenthesis:

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:

// 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:

name like 'A%'

Named parameters. Expressions can have named parameters (names that + start with "$"). 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 some + examples:

Expression template = Expression.fromString("name = $name");
+...
+Map p1 = Collections.singletonMap("name", "Salvador Dali");
+Expression qualifier1 = template.expWithParameters(p1);
+...
+Map p2 = Collections.singletonMap("name", "Monet");
+Expression qualifier2 = template.expWithParameters(p2);

To + create a named parameterized expression with a LIKE clause, SQL wildcards must be part + of the values in the Map and not the expression string + itself:

Expression template = Expression.fromString("name like $name");
+...
+Map p1 = Collections.singletonMap("name", "Salvador%");
+Expression qualifier1 = template.expWithParameters(p1);

When + matching on a relationship, parameters can be Persistent objects or + ObjectIds:

Expression template = Expression.fromString("artist = $artist");
+...
+Artist dali = // asume we fetched this one already
+Map p1 = Collections.singletonMap("artist", dali);
+Expression qualifier1 = template.expWithParameters(p1);

Uninitialized + parameters will be automatically pruned from expressions, so a user can omit some + parameters when creating an expression from a parameterized + template:

Expression template = Expression.fromString("name like $name and dateOfBirth > $date");
+...
+Map p1 = Collections.singletonMap("name", "Salvador%");
+Expression qualifier1 = template.expWithParameters(p1);
+
+// qualifier1 is now equals to "name like 'Salvador%'", the 'dateOfBirth' 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 can be used directly with null + values. It is up to Cayenne to translate expressions with nulls to the valid SQL.

+

Note

A formal definition of all possible valid expressions in a form of JavaCC + grammar is provided in Appendix C

+

Creating Expressions with API

Creating expressions from Strings is a powerful and dynamic approach, however a safer + alternative is to use Java API. It provides some degree of compile-time checking of + expressions validity. The API is cenetred around ExpressionFactory class, and the + Expression class. ExpressionFactory contains a number of rather self-explanatory factory + methods. We won't be going over all of them in detail, but will rather show a few + general examples and some gotchas.

The following code recreates the expression from the previous chapter, but now using + expression + API:

// String expression: name like 'A%' and price < 1000
+Expression e1 = ExpressionFactory.likeExp(Painting.NAME_PROPERTY, "A%");
+Expression e2 = ExpressionFactory.lessExp(Painting.PRICE_PROPERTY, 1000);
+Expression finalExp = e1.andExp(e2); 

This + is more verbose than creating it from String, but it is also more resilient to the + entity properties renaming and precludes semantic errors in the expression String.

Note

The last line in the example above shows how to create a new expression by + "chaining" 2 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:

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.

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:

Expression e = ExpressionFactory.inExp(User.NAME_PROPERTY, "John", "Bob");
+User user = ...
+if(e.match(user)) {
+   ...
+}

Reading + property + value:

Expression e = Expression.fromString(User.NAME_PROPERTY);
+String name = e.evaluate(user);

Filtering a list of + objects:

Expression e = ExpressionFactory.inExp(User.NAME_PROPERTY, "John", "Bob");
+List<User> unfiltered = ...
+List<User> filtered = e.filterObjects(unfiltered);

+

Note

Current limitation of in-memory expressions is that no collections are + permitted in the property path.

+

\ No newline at end of file Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/images/.gitignore URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/images/.gitignore?rev=1406588&view=auto ============================================================================== (empty) Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/implementing-rop-client.html URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/implementing-rop-client.html?rev=1406588&view=auto ============================================================================== --- cayenne/site/cms/trunk/content/v31/cayenne-guide/implementing-rop-client.html (added) +++ cayenne/site/cms/trunk/content/v31/cayenne-guide/implementing-rop-client.html Wed Nov 7 12:36:48 2012 @@ -0,0 +1,3 @@ + + + Chapter 16. Implementing ROP Client

Chapter 16. Implementing ROP Client

\ No newline at end of file Added: cayenne/site/cms/trunk/content/v31/cayenne-guide/implementing-rop-server.html URL: http://svn.apache.org/viewvc/cayenne/site/cms/trunk/content/v31/cayenne-guide/implementing-rop-server.html?rev=1406588&view=auto ============================================================================== --- cayenne/site/cms/trunk/content/v31/cayenne-guide/implementing-rop-server.html (added) +++ cayenne/site/cms/trunk/content/v31/cayenne-guide/implementing-rop-server.html Wed Nov 7 12:36:48 2012 @@ -0,0 +1,3 @@ + + + Chapter 15. Implementing ROP Server

Chapter 15. Implementing ROP Server

\ No newline at end of file