You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by an...@apache.org on 2010/03/09 15:16:09 UTC

svn commit: r920884 [1/4] - in /cayenne/sandbox/cayenne-gwt/src: main/java/org/apache/cayenne/gwt/ main/java/org/apache/cayenne/gwt/client/ main/java/org/apache/cayenne/gwt/server/ main/java/org/apache/cayenne/query/ main/resources/org/apache/cayenne/ ...

Author: andrey
Date: Tue Mar  9 14:16:07 2010
New Revision: 920884

URL: http://svn.apache.org/viewvc?rev=920884&view=rev
Log:
full selectQuery&expression API support, GWTDataContext concept, modules separation

Added:
    cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/
    cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/
    cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/CayenneService.java
    cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/CayenneServiceAsync.java
    cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/GWTDataContext.java
    cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/server/
    cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/server/CayenneServiceImpl.java
    cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/query/
    cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/query/AbstractQuery_CustomFieldSerializer.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/Core.gwt.xml
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/java/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/java/util/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/java/util/StringTokenizer.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/org/apache/cayenne/util/ConversionUtil.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/org/apache/cayenne/util/Util.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/gwt/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/gwt/User.gwt.xml
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/Query.gwt.xml
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/DataRow.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/Expression.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/ExpressionException.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/ExpressionFactory.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/ExpressionParameter.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/TraversalHandler.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTAdd.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTAnd.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTBetween.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTDbPath.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTDivide.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTEqual.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTFalse.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTGreater.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTGreaterOrEqual.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTIn.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTLess.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTLessOrEqual.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTLike.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTLikeIgnoreCase.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTList.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTMultiply.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTNamedParameter.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTNegate.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTNot.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTNotBetween.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTNotEqual.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTNotIn.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTNotLike.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTNotLikeIgnoreCase.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTObjPath.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTOr.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTPath.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTScalar.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTSubtract.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ASTTrue.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/AggregateConditionNode.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ConditionNode.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/ExpressionParserTreeConstants.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/IgnoreCaseNode.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/Node.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/PatternMatchNode.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/parser/SimpleNode.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/AbstractQuery.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/AbstractQuery_CustomFieldSerializer.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/BaseQueryMetadata.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/Ordering.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/ParameterizedQuery.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/PrefetchTreeNode.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/QualifiedQuery.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/Query.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/QueryCacheStrategy.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/QueryMetadata.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SelectQuery.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SelectQueryMetadata.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SortOrder.java
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/commons/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/commons/collections/
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/commons/collections/Transformer.java
    cayenne/sandbox/cayenne-gwt/src/test/java/org/apache/cayenne/gwt/test/client/GwtTestQuery.java
Modified:
    cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/Cayenne.gwt.xml
    cayenne/sandbox/cayenne-gwt/src/test/java/org/apache/cayenne/gwt/test/client/CayenneGWTTest.java
    cayenne/sandbox/cayenne-gwt/src/test/java/org/apache/cayenne/gwt/test/client/TestService.java
    cayenne/sandbox/cayenne-gwt/src/test/java/org/apache/cayenne/gwt/test/client/TestServiceAsync.java
    cayenne/sandbox/cayenne-gwt/src/test/java/org/apache/cayenne/gwt/test/server/TestServiceImpl.java
    cayenne/sandbox/cayenne-gwt/src/test/resources/org/apache/cayenne/gwt/test/CayenneTest.gwt.xml

Added: cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/CayenneService.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/CayenneService.java?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/CayenneService.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/CayenneService.java Tue Mar  9 14:16:07 2010
@@ -0,0 +1,39 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+package org.apache.cayenne.gwt.client;
+
+import java.util.List;
+
+import org.apache.cayenne.query.Query;
+
+import com.google.gwt.user.client.rpc.RemoteService;
+import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
+
+/**
+ * Service for sending Cayenne data objects and queries between GWT client and server.
+ * This service is not intended for direct use. Instead, use {@link GWTDataContext} class
+ */
+@RemoteServiceRelativePath("service/cayenneService")
+public interface CayenneService extends RemoteService {
+	/**
+     * Executes a selecting query, returning a list of persistent objects or data rows.
+     */
+    @SuppressWarnings("unchecked")
+    public List performQuery(Query query);
+}

Added: cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/CayenneServiceAsync.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/CayenneServiceAsync.java?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/CayenneServiceAsync.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/CayenneServiceAsync.java Tue Mar  9 14:16:07 2010
@@ -0,0 +1,39 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+package org.apache.cayenne.gwt.client;
+
+import java.util.List;
+
+import org.apache.cayenne.query.Query;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+/**
+ * Service for asynchronous performing Cayenne queries and other operations.
+ * This service is not intended for direct use. Instead, use {@link GWTDataContext} class
+ */
+public interface CayenneServiceAsync {
+
+	/**
+     * Executes a selecting query, returning a list of persistent objects or data rows.
+     */
+    @SuppressWarnings("unchecked")
+	<T> void performQuery(Query query, AsyncCallback<List<T>> callback);
+
+}

Added: cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/GWTDataContext.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/GWTDataContext.java?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/GWTDataContext.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/client/GWTDataContext.java Tue Mar  9 14:16:07 2010
@@ -0,0 +1,65 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+package org.apache.cayenne.gwt.client;
+
+import java.util.List;
+
+import org.apache.cayenne.query.Query;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+/**
+ * Main user frontend for performing Cayenne operations
+ */
+public class GWTDataContext {
+	private static GWTDataContext instance;
+	
+	/**
+	 * Internal implementation of RPC communication
+	 */
+	private CayenneServiceAsync service;
+	
+	/**
+	 * Returns shared GWTDataContext instance
+	 */
+	public static GWTDataContext getInstance() {
+		if (instance == null) {
+			instance = new GWTDataContext();
+		}
+		return instance;
+	}
+	
+	/**
+	 * Returns internal implementation of RPC communication
+	 */
+	private CayenneServiceAsync getService() {
+		if (service == null) {
+			service = GWT.create(CayenneService.class);
+		}
+		return service;
+	}
+	
+	/**
+     * Executes a selecting query, returning a list of persistent objects or data rows
+     */
+	public <T> void performQuery(Query query, AsyncCallback<List<T>> callback) {
+		getService().performQuery(query, callback);
+	}
+}

Added: cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/server/CayenneServiceImpl.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/server/CayenneServiceImpl.java?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/server/CayenneServiceImpl.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/gwt/server/CayenneServiceImpl.java Tue Mar  9 14:16:07 2010
@@ -0,0 +1,58 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+package org.apache.cayenne.gwt.server;
+
+import java.util.List;
+
+import org.apache.cayenne.BaseContext;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.access.DataContext;
+import org.apache.cayenne.conf.WebApplicationContextFilter;
+import org.apache.cayenne.gwt.client.CayenneService;
+import org.apache.cayenne.query.Query;
+
+import com.google.gwt.user.server.rpc.RemoteServiceServlet;
+
+/**
+ * Implementation of RPC Cayenne operations
+ */
+public class CayenneServiceImpl extends RemoteServiceServlet implements CayenneService {
+	/**
+	 * Returns object context for performing server Cayenne operations.
+	 * By default, it returns context bound to current thread, so {@link WebApplicationContextFilter}
+	 * is required for it to work correctly.
+	 * Override this method to get custom behavior.
+	 */
+	protected ObjectContext getObjectContext() {
+		try {
+			return BaseContext.getThreadObjectContext();
+		}
+		catch (IllegalStateException ex) {
+			ObjectContext context = DataContext.createDataContext();
+			BaseContext.bindThreadObjectContext(context);
+			return context;
+		}
+	}
+
+	@Override
+	public List performQuery(Query query) {
+		ObjectContext context = getObjectContext();
+		return context.performQuery(query);
+	}
+}

Added: cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/query/AbstractQuery_CustomFieldSerializer.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/query/AbstractQuery_CustomFieldSerializer.java?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/query/AbstractQuery_CustomFieldSerializer.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/java/org/apache/cayenne/query/AbstractQuery_CustomFieldSerializer.java Tue Mar  9 14:16:07 2010
@@ -0,0 +1,38 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+package org.apache.cayenne.query;
+
+import com.google.gwt.user.client.rpc.SerializationException;
+import com.google.gwt.user.client.rpc.SerializationStreamReader;
+import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+
+public class AbstractQuery_CustomFieldSerializer {
+	public static void serialize(SerializationStreamWriter streamWriter, AbstractQuery instance)
+			throws SerializationException {
+
+		streamWriter.writeString(instance.getName());
+		streamWriter.writeObject(instance.getRoot());
+	}
+
+	public static void deserialize(SerializationStreamReader streamReader, AbstractQuery instance)
+			throws SerializationException {
+		instance.setName(streamReader.readString());
+		instance.setRoot(streamReader.readObject());
+	}
+}

Modified: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/Cayenne.gwt.xml
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/Cayenne.gwt.xml?rev=920884&r1=920883&r2=920884&view=diff
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/Cayenne.gwt.xml (original)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/Cayenne.gwt.xml Tue Mar  9 14:16:07 2010
@@ -1,3 +1,5 @@
 <module>
-   <super-source path="emul"/>
+   <inherits name="org.apache.cayenne.Core"/>
+   <inherits name="org.apache.cayenne.query.Query"/>
+   <inherits name="org.apache.cayenne.gwt.User"/>
 </module>
\ No newline at end of file

Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/Core.gwt.xml
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/Core.gwt.xml?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/Core.gwt.xml (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/Core.gwt.xml Tue Mar  9 14:16:07 2010
@@ -0,0 +1,3 @@
+<module>
+	<super-source path="emul"/>
+</module>
\ No newline at end of file

Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/java/util/StringTokenizer.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/java/util/StringTokenizer.java?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/java/util/StringTokenizer.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/java/util/StringTokenizer.java Tue Mar  9 14:16:07 2010
@@ -0,0 +1,208 @@
+/*
+ *  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.
+ */
+
+/*
+ * This file is based on code from the Apache Harmony Project.
+ * http://svn.apache.org/repos/asf/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/StringTokenizer.java
+ */
+
+package java.util;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+/**
+ * String tokenizer is used to break a string apart into tokens.
+ *
+ * If returnDelimiters is false, successive calls to nextToken() return maximal
+ * blocks of characters that do not contain a delimiter.
+ *
+ * If returnDelimiters is true, delimiters are considered to be tokens, and
+ * successive calls to nextToken() return either a one character delimiter, or a
+ * maximal block of text between delimiters.
+ */
+public class StringTokenizer implements Enumeration<Object> {
+
+    private String string;
+
+    private String delimiters;
+
+    private boolean returnDelimiters;
+
+    private int position;
+
+    /**
+     * Constructs a new StringTokenizer for string using whitespace as the
+     * delimiter, returnDelimiters is false.
+     *
+     * @param string
+     *            the string to be tokenized
+     */
+    public StringTokenizer(String string) {
+        this(string, " \t\n\r\f", false); //$NON-NLS-1$
+    }
+
+    /**
+     * Constructs a new StringTokenizer for string using the specified
+     * delimiters, returnDelimiters is false.
+     *
+     * @param string
+     *            the string to be tokenized
+     * @param delimiters
+     *            the delimiters to use
+     */
+    public StringTokenizer(String string, String delimiters) {
+        this(string, delimiters, false);
+    }
+
+    /**
+     * Constructs a new StringTokenizer for string using the specified
+     * delimiters and returning delimiters as tokens when specified.
+     *
+     * @param string
+     *            the string to be tokenized
+     * @param delimiters
+     *            the delimiters to use
+     * @param returnDelimiters
+     *            true to return each delimiter as a token
+     */
+    public StringTokenizer(String string, String delimiters,
+            boolean returnDelimiters) {
+        if (string != null) {
+            this.string = string;
+            this.delimiters = delimiters;
+            this.returnDelimiters = returnDelimiters;
+            this.position = 0;
+        } else
+            throw new NullPointerException();
+    }
+
+    /**
+     * Returns the number of unprocessed tokens remaining in the string.
+     *
+     * @return number of tokens that can be retreived before an exception will
+     *         result
+     */
+    public int countTokens() {
+        int count = 0;
+        boolean inToken = false;
+        for (int i = position, length = string.length(); i < length; i++) {
+            if (delimiters.indexOf(string.charAt(i), 0) >= 0) {
+                if (returnDelimiters)
+                    count++;
+                if (inToken) {
+                    count++;
+                    inToken = false;
+                }
+            } else {
+                inToken = true;
+            }
+        }
+        if (inToken)
+            count++;
+        return count;
+    }
+
+    /**
+     * Returns true if unprocessed tokens remain.
+     *
+     * @return true if unprocessed tokens remain
+     */
+    public boolean hasMoreElements() {
+        return hasMoreTokens();
+    }
+
+    /**
+     * Returns true if unprocessed tokens remain.
+     *
+     * @return true if unprocessed tokens remain
+     */
+    public boolean hasMoreTokens() {
+        int length = string.length();
+        if (position < length) {
+            if (returnDelimiters)
+                return true; // there is at least one character and even if
+            // it is a delimiter it is a token
+
+            // otherwise find a character which is not a delimiter
+            for (int i = position; i < length; i++)
+                if (delimiters.indexOf(string.charAt(i), 0) == -1)
+                    return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns the next token in the string as an Object.
+     *
+     * @return next token in the string as an Object
+     * @exception NoSuchElementException
+     *                if no tokens remain
+     */
+    public Object nextElement() {
+        return nextToken();
+    }
+
+    /**
+     * Returns the next token in the string as a String.
+     *
+     * @return next token in the string as a String
+     * @exception NoSuchElementException
+     *                if no tokens remain
+     */
+    public String nextToken() {
+        int i = position;
+        int length = string.length();
+
+        if (i < length) {
+            if (returnDelimiters) {
+                if (delimiters.indexOf(string.charAt(position), 0) >= 0)
+                    return String.valueOf(string.charAt(position++));
+                for (position++; position < length; position++)
+                    if (delimiters.indexOf(string.charAt(position), 0) >= 0)
+                        return string.substring(i, position);
+                return string.substring(i);
+            }
+
+            while (i < length && delimiters.indexOf(string.charAt(i), 0) >= 0)
+                i++;
+            position = i;
+            if (i < length) {
+                for (position++; position < length; position++)
+                    if (delimiters.indexOf(string.charAt(position), 0) >= 0)
+                        return string.substring(i, position);
+                return string.substring(i);
+            }
+        }
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Returns the next token in the string as a String. The delimiters used are
+     * changed to the specified delimiters.
+     *
+     * @param delims
+     *            the new delimiters to use
+     * @return next token in the string as a String
+     * @exception NoSuchElementException
+     *                if no tokens remain
+     */
+    public String nextToken(String delims) {
+        this.delimiters = delims;
+        return nextToken();
+    }
+}
\ No newline at end of file

Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/org/apache/cayenne/util/ConversionUtil.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/org/apache/cayenne/util/ConversionUtil.java?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/org/apache/cayenne/util/ConversionUtil.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/org/apache/cayenne/util/ConversionUtil.java Tue Mar  9 14:16:07 2010
@@ -0,0 +1,123 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+
+
+package org.apache.cayenne.util;
+
+
+/**
+ * A collection of static conversion utility methods.
+ * 
+ * @since 1.1
+ */
+public final class ConversionUtil {
+
+    public static int toInt(Object object, int defaultValue) {
+        if (object == null) {
+            return defaultValue;
+        }
+        else if (object instanceof Number) {
+            return ((Number) object).intValue();
+        }
+        else if (object instanceof String) {
+            try {
+                return Integer.parseInt((String) object);
+            }
+            catch (NumberFormatException ex) {
+                return defaultValue;
+            }
+        }
+
+        return defaultValue;
+    }
+
+    public static boolean toBoolean(Object object) {
+        if (object instanceof Boolean) {
+            return ((Boolean) object).booleanValue();
+        }
+
+        if (object instanceof Number) {
+            return ((Number) object).intValue() != 0;
+        }
+
+        return object != null;
+    }
+
+    /**
+     * Attempts to convert an object to Comparable instance.
+     */
+    public static Comparable toComparable(Object object) {
+        if (object == null) {
+            return null;
+        }
+        else if (object instanceof Comparable) {
+            return (Comparable) object;
+        }
+        else if (object instanceof StringBuffer) {
+            return object.toString();
+        }
+        else if (object instanceof char[]) {
+            return new String((char[]) object);
+        }
+        else {
+            throw new ClassCastException(
+                "Invalid Comparable class:" + object.getClass().getName());
+        }
+    }
+
+    /**
+     * Attempts to convert an object to Comparable instance.
+     */
+    public static String toString(Object object) {
+        if (object == null) {
+            return null;
+        }
+        else if (object instanceof String) {
+            return (String) object;
+        }
+        else if (object instanceof StringBuffer) {
+            return object.toString();
+        }
+        else if (object instanceof char[]) {
+            return new String((char[]) object);
+        }
+        else {
+            throw new ClassCastException(
+                "Invalid class for String conversion:" + object.getClass().getName());
+        }
+    }
+
+    /**
+     * Attempts to convert an object to an uppercase string.
+     */
+    public static Object toUpperCase(Object object) {
+        if ((object instanceof String) || (object instanceof StringBuffer)) {
+            return object.toString().toUpperCase();
+        }
+        else if (object instanceof char[]) {
+            return new String((char[]) object).toUpperCase();
+        }
+        else {
+            return object;
+        }
+    }
+
+    private ConversionUtil() {
+    }
+}

Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/org/apache/cayenne/util/Util.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/org/apache/cayenne/util/Util.java?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/org/apache/cayenne/util/Util.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/emul/org/apache/cayenne/util/Util.java Tue Mar  9 14:16:07 2010
@@ -0,0 +1,71 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+
+package org.apache.cayenne.util;
+
+
+/**
+ * Contains various unorganized static utility methods used across Cayenne.
+ * 
+ */
+public class Util {
+
+    /**
+     * Compares two objects similar to "Object.equals(Object)". Unlike Object.equals(..),
+     * this method doesn't throw an exception if any of the two objects is null.
+     */
+    public static boolean nullSafeEquals(Object o1, Object o2) {
+
+        if (o1 == null) {
+            return o2 == null;
+        }
+
+        return o1.equals(o2);
+    }
+
+    /**
+     * Compares two objects similar to "Comparable.compareTo(Object)". Unlike
+     * Comparable.compareTo(..), this method doesn't throw an exception if any of the two
+     * objects is null.
+     * 
+     * @since 1.1
+     */
+    public static <T> int nullSafeCompare(boolean nullsFirst, Comparable<T> o1, T o2) {
+        if (o1 == null && o2 == null) {
+            return 0;
+        }
+        else if (o1 == null) {
+            return nullsFirst ? -1 : 1;
+        }
+        else if (o2 == null) {
+            return nullsFirst ? 1 : -1;
+        }
+        else {
+            return o1.compareTo(o2);
+        }
+    }
+
+    /**
+     * Returns true, if the String is null or an empty string.
+     */
+    public static boolean isEmptyString(String string) {
+        return string == null || string.length() == 0;
+    }
+
+}

Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/gwt/User.gwt.xml
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/gwt/User.gwt.xml?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/gwt/User.gwt.xml (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/gwt/User.gwt.xml Tue Mar  9 14:16:07 2010
@@ -0,0 +1,2 @@
+<module>
+</module>
\ No newline at end of file

Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/Query.gwt.xml
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/Query.gwt.xml?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/Query.gwt.xml (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/Query.gwt.xml Tue Mar  9 14:16:07 2010
@@ -0,0 +1,3 @@
+<module>
+   <super-source path="emul"/>
+</module>
\ No newline at end of file

Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/DataRow.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/DataRow.java?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/DataRow.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/DataRow.java Tue Mar  9 14:16:07 2010
@@ -0,0 +1,132 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+
+package org.apache.cayenne;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cayenne.util.Util;
+
+/**
+ * DataRow a map that holds values retrieved from the database for a given query row.
+ * DataRows are used to cache raw database data and as a reference point for tracking
+ * DataObject changes.
+ * 
+ * @since 1.1
+ */
+public class DataRow extends HashMap<String, Object> {
+
+    // "volatile" is supposed to ensure consistency in read and increment operations;
+    // is this universally true?
+
+    // make sure the starting value is different from DataObject default version value
+    private static volatile long currentVersion = DataObject.DEFAULT_VERSION + 1;
+
+    protected long version = currentVersion++;
+    protected long replacesVersion = DataObject.DEFAULT_VERSION;
+
+    /**
+     * @since 3.0
+     */
+    protected String entityName;
+    
+    @SuppressWarnings("unused")
+    private DataRow() {};
+
+    public DataRow(Map<String, ?> map) {
+        super(map);
+    }
+
+    public DataRow(int initialCapacity) {
+        super(initialCapacity);
+    }
+
+    public long getVersion() {
+        return version;
+    }
+
+    public long getReplacesVersion() {
+        return replacesVersion;
+    }
+
+    /**
+     * Sets the version of DataRow replaced by this one in the store.
+     */
+    public void setReplacesVersion(long replacesVersion) {
+        this.replacesVersion = replacesVersion;
+    }
+
+    /**
+     * Builds a new DataRow, merging changes from <code>diff</code> parameter with data
+     * contained in this DataRow.
+     */
+    public DataRow applyDiff(DataRow diff) {
+        DataRow merged = new DataRow(this);
+
+        for (Map.Entry<String, Object> entry : diff.entrySet()) {
+            merged.put(entry.getKey(), entry.getValue());
+        }
+
+        return merged;
+    }
+
+    /**
+     * Creates a DataRow that contains only the keys that have values that differ between
+     * this object and <code>row</code> parameter. Diff values are taken from the
+     * <code>row</code> parameter. It is assumed that key sets are compatible in both rows
+     * (e.g. they represent snapshots for the same entity). Returns null if no differences
+     * are found.
+     */
+    public DataRow createDiff(DataRow row) {
+
+        // build a diff...
+        DataRow diff = null;
+
+        for (Map.Entry<String, Object> entry : entrySet()) {
+
+            String key = entry.getKey();
+            Object currentValue = entry.getValue();
+            Object rowValue = row.get(key);
+
+            if (!Util.nullSafeEquals(currentValue, rowValue)) {
+                if (diff == null) {
+                    diff = new DataRow(this.size());
+                }
+                diff.put(key, rowValue);
+            }
+        }
+
+        return diff;
+    }
+
+    /**
+     * @since 3.0
+     */
+    public String getEntityName() {
+        return entityName;
+    }
+
+    /**
+     * @since 3.0
+     */
+    public void setEntityName(String entityName) {
+        this.entityName = entityName;
+    }
+}

Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/Expression.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/Expression.java?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/Expression.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/Expression.java Tue Mar  9 14:16:07 2010
@@ -0,0 +1,506 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+
+package org.apache.cayenne.exp;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.exp.parser.ASTScalar;
+import org.apache.cayenne.util.ConversionUtil;
+import org.apache.cayenne.util.Util;
+import org.apache.commons.collections.Transformer;
+
+/**
+ * Superclass of Cayenne expressions that defines basic API for expressions use.
+ */
+public abstract class Expression implements Serializable {
+
+    /**
+     * A value that a Transformer might return to indicate that a node has to be pruned
+     * from the expression during the transformation.
+     * 
+     * @since 1.2
+     */
+    public final static Object PRUNED_NODE = new Object();
+
+    public static final int AND = 0;
+    public static final int OR = 1;
+    public static final int NOT = 2;
+    public static final int EQUAL_TO = 3;
+    public static final int NOT_EQUAL_TO = 4;
+    public static final int LESS_THAN = 5;
+    public static final int GREATER_THAN = 6;
+    public static final int LESS_THAN_EQUAL_TO = 7;
+    public static final int GREATER_THAN_EQUAL_TO = 8;
+    public static final int BETWEEN = 9;
+    public static final int IN = 10;
+    public static final int LIKE = 11;
+    public static final int LIKE_IGNORE_CASE = 12;
+    public static final int ADD = 16;
+    public static final int SUBTRACT = 17;
+    public static final int MULTIPLY = 18;
+    public static final int DIVIDE = 19;
+    public static final int NEGATIVE = 20;
+    public static final int TRUE = 21;
+    public static final int FALSE = 22;
+
+    /**
+     * Expression describes a path relative to an ObjEntity. OBJ_PATH expression is
+     * resolved relative to some root ObjEntity. Path expression components are separated
+     * by "." (dot). Path can point to either one of these:
+     * <ul>
+     * <li><i>An attribute of root ObjEntity.</i> For entity Gallery OBJ_PATH expression
+     * "galleryName" will point to ObjAttribute "galleryName"
+     * <li><i>Another ObjEntity related to root ObjEntity via a chain of relationships.</i>
+     * For entity Gallery OBJ_PATH expression "paintingArray.toArtist" will point to
+     * ObjEntity "Artist"
+     * <li><i>ObjAttribute of another ObjEntity related to root ObjEntity via a chain of
+     * relationships.</i> For entity Gallery OBJ_PATH expression
+     * "paintingArray.toArtist.artistName" will point to ObjAttribute "artistName"
+     * </ul>
+     */
+    public static final int OBJ_PATH = 26;
+
+    /**
+     * Expression describes a path relative to a DbEntity. DB_PATH expression is resolved
+     * relative to some root DbEntity. Path expression components are separated by "."
+     * (dot). Path can point to either one of these:
+     * <ul>
+     * <li><i>An attribute of root DbEntity.</i> For entity GALLERY, DB_PATH expression
+     * "GALLERY_NAME" will point to a DbAttribute "GALLERY_NAME". </li>
+     * <li><i>Another DbEntity related to root DbEntity via a chain of relationships.</i>
+     * For entity GALLERY DB_PATH expression "paintingArray.toArtist" will point to
+     * DbEntity "ARTIST". </li>
+     * <li><i>DbAttribute of another ObjEntity related to root DbEntity via a chain of
+     * relationships.</i> For entity GALLERY DB_PATH expression
+     * "paintingArray.toArtist.ARTIST_NAME" will point to DbAttribute "ARTIST_NAME". </li>
+     * </ul>
+     */
+    public static final int DB_PATH = 27;
+
+    /**
+     * Interpreted as a comma-separated list of literals.
+     */
+    public static final int LIST = 28;
+
+    public static final int NOT_BETWEEN = 35;
+    public static final int NOT_IN = 36;
+    public static final int NOT_LIKE = 37;
+    public static final int NOT_LIKE_IGNORE_CASE = 38;
+
+    protected int type;
+
+    /**
+     * Returns a map of path aliases for this expression. It returns a non-empty map only
+     * if this is a path expression and the aliases are known at the expression creation
+     * time. Otherwise an empty map is returned.
+     * 
+     * @since 3.0
+     */
+    public abstract Map<String, String> getPathAliases();
+
+    /**
+     * Returns String label for this expression. Used for debugging.
+     */
+    public String expName() {
+        switch (type) {
+            case AND:
+                return "AND";
+            case OR:
+                return "OR";
+            case NOT:
+                return "NOT";
+            case EQUAL_TO:
+                return "=";
+            case NOT_EQUAL_TO:
+                return "<>";
+            case LESS_THAN:
+                return "<";
+            case LESS_THAN_EQUAL_TO:
+                return "<=";
+            case GREATER_THAN:
+                return ">";
+            case GREATER_THAN_EQUAL_TO:
+                return ">=";
+            case BETWEEN:
+                return "BETWEEN";
+            case IN:
+                return "IN";
+            case LIKE:
+                return "LIKE";
+            case LIKE_IGNORE_CASE:
+                return "LIKE_IGNORE_CASE";
+            case OBJ_PATH:
+                return "OBJ_PATH";
+            case DB_PATH:
+                return "DB_PATH";
+            case LIST:
+                return "LIST";
+            case NOT_BETWEEN:
+                return "NOT BETWEEN";
+            case NOT_IN:
+                return "NOT IN";
+            case NOT_LIKE:
+                return "NOT LIKE";
+            case NOT_LIKE_IGNORE_CASE:
+                return "NOT LIKE IGNORE CASE";
+            default:
+                return "other";
+        }
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if (!(object instanceof Expression)) {
+            return false;
+        }
+
+        Expression e = (Expression) object;
+
+        if (e.getType() != getType() || e.getOperandCount() != getOperandCount()) {
+            return false;
+        }
+
+        // compare operands
+        int len = e.getOperandCount();
+        for (int i = 0; i < len; i++) {
+            if (!Util.nullSafeEquals(e.getOperand(i), getOperand(i))) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns a type of expression. Most common types are defined as public static fields
+     * of this interface.
+     */
+    public int getType() {
+        return type;
+    }
+
+    public void setType(int type) {
+        this.type = type;
+    }
+
+    /**
+     * A shortcut for <code>expWithParams(params, true)</code>.
+     */
+    public Expression expWithParameters(Map<String, ?> parameters) {
+        return expWithParameters(parameters, true);
+    }
+
+    /**
+     * Creates and returns a new Expression instance using this expression as a prototype.
+     * All ExpressionParam operands are substituted with the values in the
+     * <code>params</code> map.
+     * <p>
+     * <i>Null values in the <code>params</code> map should be explicitly created in the
+     * map for the corresponding key. </i>
+     * </p>
+     * 
+     * @param parameters a map of parameters, with each key being a string name of an
+     *            expression parameter, and value being the value that should be used in
+     *            the final expression.
+     * @param pruneMissing If <code>true</code>, subexpressions that rely on missing
+     *            parameters will be pruned from the resulting tree. If <code>false</code>,
+     *            any missing values will generate an exception.
+     * @return Expression resulting from the substitution of parameters with real values,
+     *         or null if the whole expression was pruned, due to the missing parameters.
+     */
+    public Expression expWithParameters(
+            final Map<String, ?> parameters,
+            final boolean pruneMissing) {
+
+        // create transformer for named parameters
+        Transformer transformer = new Transformer() {
+
+            public Object transform(Object object) {
+                if (!(object instanceof ExpressionParameter)) {
+                    return object;
+                }
+
+                String name = ((ExpressionParameter) object).getName();
+                if (!parameters.containsKey(name)) {
+                    if (pruneMissing) {
+                        return PRUNED_NODE;
+                    }
+                    else {
+                        throw new ExpressionException("Missing required parameter: $"
+                                + name);
+                    }
+                }
+                else {
+                    Object value = parameters.get(name);
+
+                    // wrap lists (for now); also support null parameters
+                    // TODO: andrus 8/14/2007 - shouldn't we also wrap non-null object
+                    // values in ASTScalars?
+                    return (value != null)
+                            ? ExpressionFactory.wrapPathOperand(value)
+                            : new ASTScalar(null);
+                }
+            }
+        };
+
+        return transform(transformer);
+    }
+
+    /**
+     * Creates a new expression that joins this object with another expression, using
+     * specified join type. It is very useful for incrementally building chained
+     * expressions, like long AND or OR statements.
+     */
+    public Expression joinExp(int type, Expression exp) {
+        Expression join = ExpressionFactory.expressionOfType(type);
+        join.setOperand(0, this);
+        join.setOperand(1, exp);
+        join.flattenTree();
+        return join;
+    }
+
+    /**
+     * Chains this expression with another expression using "and".
+     */
+    public Expression andExp(Expression exp) {
+        return joinExp(Expression.AND, exp);
+    }
+
+    /**
+     * Chains this expression with another expression using "or".
+     */
+    public Expression orExp(Expression exp) {
+        return joinExp(Expression.OR, exp);
+    }
+
+    /**
+     * Returns a logical NOT of current expression.
+     * 
+     * @since 1.0.6
+     */
+    public abstract Expression notExp();
+
+    /**
+     * Returns a count of operands of this expression. In real life there are unary (count ==
+     * 1), binary (count == 2) and ternary (count == 3) expressions.
+     */
+    public abstract int getOperandCount();
+
+    /**
+     * Returns a value of operand at <code>index</code>. Operand indexing starts at 0.
+     */
+    public abstract Object getOperand(int index);
+
+    /**
+     * Sets a value of operand at <code>index</code>. Operand indexing starts at 0.
+     */
+    public abstract void setOperand(int index, Object value);
+
+    /**
+     * Calculates expression value with object as a context for path expressions.
+     * 
+     * @since 1.1
+     */
+    public abstract Object evaluate(Object o);
+
+    /**
+     * Calculates expression boolean value with object as a context for path expressions.
+     * 
+     * @since 1.1
+     */
+    public boolean match(Object o) {
+        return ConversionUtil.toBoolean(evaluate(o));
+    }
+
+    /**
+     * Returns a list of objects that match the expression.
+     */
+    public <T> List<T> filterObjects(List<T> objects) {
+        if (objects == null || objects.size() == 0) {
+            return Collections.EMPTY_LIST;
+        }
+
+        return (List<T>) filter(objects, new LinkedList<T>());
+    }
+
+    /**
+     * Adds objects matching this expression from the source collection to the target
+     * collection.
+     * 
+     * @since 1.1
+     */
+    public <T> Collection<?> filter(Collection<T> source, Collection<T> target) {
+        for (T o : source) {
+            if (match(o)) {
+                target.add(o);
+            }
+        }
+
+        return target;
+    }
+
+    /**
+     * Clones this expression.
+     * 
+     * @since 1.1
+     */
+    public Expression deepCopy() {
+        return transform(null);
+    }
+
+    /**
+     * Creates a copy of this expression node, without copying children.
+     * 
+     * @since 1.1
+     */
+    public abstract Expression shallowCopy();
+
+    /**
+     * Returns true if this node should be pruned from expression tree in the event a
+     * child is removed.
+     * 
+     * @since 1.1
+     */
+    protected abstract boolean pruneNodeForPrunedChild(Object prunedChild);
+
+    /**
+     * Restructures expression to make sure that there are no children of the same type as
+     * this expression.
+     * 
+     * @since 1.1
+     */
+    protected abstract void flattenTree();
+
+    /**
+     * Traverses itself and child expressions, notifying visitor via callback methods as
+     * it goes. This is an Expression-specific implementation of the "Visitor" design
+     * pattern.
+     * 
+     * @since 1.1
+     */
+    public void traverse(TraversalHandler visitor) {
+        if (visitor == null) {
+            throw new NullPointerException("Null Visitor.");
+        }
+
+        traverse(null, visitor);
+    }
+
+    /**
+     * Traverses itself and child expressions, notifying visitor via callback methods as
+     * it goes.
+     * 
+     * @since 1.1
+     */
+    protected void traverse(Expression parentExp, TraversalHandler visitor) {
+
+        visitor.startNode(this, parentExp);
+
+        // recursively traverse each child
+        int count = getOperandCount();
+        for (int i = 0; i < count; i++) {
+            Object child = getOperand(i);
+
+            if (child instanceof Expression) {
+                Expression childExp = (Expression) child;
+                childExp.traverse(this, visitor);
+            }
+            else {
+                visitor.objectNode(child, this);
+            }
+
+            visitor.finishedChild(this, i, i < count - 1);
+        }
+
+        visitor.endNode(this, parentExp);
+    }
+
+    /**
+     * Creates a transformed copy of this expression, applying transformation provided by
+     * Transformer to all its nodes. Null transformer will result in an identical deep
+     * copy of this expression.
+     * <p>
+     * To force a node and its children to be pruned from the copy, Transformer should
+     * return Expression.PRUNED_NODE. Otherwise an expectation is that if a node is an
+     * Expression it must be transformed to null or another Expression. Any other object
+     * type would result in a ExpressionException.
+     * 
+     * @since 1.1
+     */
+    public Expression transform(Transformer transformer) {
+        Object transformed = transformExpression(transformer);
+
+        if (transformed == PRUNED_NODE || transformed == null) {
+            return null;
+        }
+        else if (transformed instanceof Expression) {
+            return (Expression) transformed;
+        }
+
+        throw new ExpressionException("Invalid transformed expression: " + transformed);
+    }
+
+    /**
+     * A recursive method called from "transform" to do the actual transformation.
+     * 
+     * @return null, Expression.PRUNED_NODE or transformed expression.
+     * @since 1.2
+     */
+    protected Object transformExpression(Transformer transformer) {
+        Expression copy = shallowCopy();
+        int count = getOperandCount();
+        for (int i = 0, j = 0; i < count; i++) {
+            Object operand = getOperand(i);
+            Object transformedChild;
+
+            if (operand instanceof Expression) {
+                transformedChild = ((Expression) operand)
+                        .transformExpression(transformer);
+            }
+            else if (transformer != null) {
+                transformedChild = transformer.transform(operand);
+            }
+            else {
+                transformedChild = operand;
+            }
+
+            // prune null children only if there is a transformer and it indicated so
+            boolean prune = transformer != null && transformedChild == PRUNED_NODE;
+
+            if (!prune) {
+                copy.setOperand(j, transformedChild);
+                j++;
+            }
+
+            if (prune && pruneNodeForPrunedChild(operand)) {
+                // bail out early...
+                return PRUNED_NODE;
+            }
+        }
+
+        // all the children are processed, only now transform this copy
+        return (transformer != null) ? (Expression) transformer.transform(copy) : copy;
+    }
+}

Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/ExpressionException.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/ExpressionException.java?rev=920884&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/ExpressionException.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/exp/ExpressionException.java Tue Mar  9 14:16:07 2010
@@ -0,0 +1,78 @@
+/*****************************************************************
+ *   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.
+ ****************************************************************/
+
+
+package org.apache.cayenne.exp;
+
+import org.apache.cayenne.CayenneRuntimeException;
+
+/** 
+ * RuntimeException subclass thrown in cases of errors during 
+ * expressions creation/parsing.
+ * 
+ */
+public class ExpressionException extends CayenneRuntimeException {
+    protected String expressionString;
+
+    /**
+     * Constructor for ExpressionException.
+     */
+    public ExpressionException() {
+        super();
+    }
+
+    /**
+     * Constructor for ExpressionException.
+     * @param msg
+     */
+    public ExpressionException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructor for ExpressionException.
+     * @param th
+     */
+    public ExpressionException(Throwable th) {
+        super(th);
+    }
+
+    /**
+     * Constructor for ExpressionException.
+     * @param msg
+     * @param th
+     */
+    public ExpressionException(String msg, Throwable th) {
+        super(msg, th);
+    }
+
+    /**
+     * Constructor for ExpressionException.
+     * 
+     * @since 1.1
+     */
+    public ExpressionException(String msg, String expressionString, Throwable th) {
+        super(msg, th);
+        this.expressionString = expressionString;
+    }
+
+    public String getExpressionString() {
+        return expressionString;
+    }
+}