You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by am...@apache.org on 2007/11/08 09:52:03 UTC

svn commit: r593075 - in /cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne: query/Ordering.java reflect/PropertyUtils.java reflect/UnresolvablePathException.java

Author: amaniatis
Date: Thu Nov  8 00:52:01 2007
New Revision: 593075

URL: http://svn.apache.org/viewvc?rev=593075&view=rev
Log:
CAY-916 Ordering is now able to ignore paths which are not fully resolvable. These are sorted just like other NULLs. Initial code contributed by Marcin Skladaniec who is already covered under the ish group CLA lodged with Apache for this work.

Also, another switch allows the user to specify whether nulls are sorted to the top or bottom.

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/UnresolvablePathException.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/Ordering.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/Ordering.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/Ordering.java?rev=593075&r1=593074&r2=593075&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/Ordering.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/query/Ordering.java Thu Nov  8 00:52:01 2007
@@ -26,12 +26,13 @@
 import java.util.Comparator;
 import java.util.List;
 
-import org.apache.commons.collections.ComparatorUtils;
 import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionException;
 import org.apache.cayenne.util.ConversionUtil;
 import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
+import org.apache.commons.collections.ComparatorUtils;
 
 /**
  * Defines object sorting criteria, used either for in-memory sorting of object lists or
@@ -58,11 +59,13 @@
     protected transient Expression sortSpec;
     protected boolean ascending;
     protected boolean caseInsensitive;
+    protected boolean pathExceptionSuppressed = false;
+    protected boolean nullSortedFirst = true;
 
     /**
      * Orders a given list of objects, using a List of Orderings applied according the
      * default iteration order of the Orderings list. I.e. each Ordering with lower index
-     * is more significant than any other Ordering with higer index. List being ordered is
+     * is more significant than any other Ordering with higher index. List being ordered is
      * modified in place.
      */
     public static void orderList(List objects, List orderings) {
@@ -103,7 +106,47 @@
             this.sortSpec = null;
         }
     }
-
+     
+    /**
+     * Sets sort order for whether nulls are at the top or bottom of the resulting list. Default is true.
+     * 
+     * @param nullSortedFirst true sorts nulls to the top of the list, false sorts nulls to the bottom
+     */
+    public void setNullSortedFirst(boolean nullSortedFirst) {
+        this.nullSortedFirst = nullSortedFirst;
+    }
+    
+    /** 
+     * Get sort order for nulls.
+     * 
+     *  @return true if nulls are sorted to the top of the list, false if sorted to the bottom
+     */
+    public boolean isNullSortedFirst() {
+        return nullSortedFirst;
+    }
+    
+    /**
+     * Sets whether a path with a null in the middle is ignored. For example, a sort from <code>painting</code>
+     * on <code>artist.name</code> would by default throw an exception if the artist was null.
+     * If set to true, then this is treated just like a null value.
+     * Default is false.
+     * 
+     * @param pathExceptionSuppressed true to suppress exceptions and sort as null
+     */
+    public void setPathExceptionSupressed(boolean pathExceptionSuppressed) {
+        this.pathExceptionSuppressed = pathExceptionSuppressed;
+    }
+    
+    /** 
+     * Is a path with a null in the middle is ignored.
+     * 
+     * @return true is exception is suppressed and sorted as null
+     */
+    public boolean isPathExceptionSuppressed() {
+        return pathExceptionSuppressed;
+    }
+    
+    
     /**
      * Returns sortSpec string representation.
      * 
@@ -173,15 +216,36 @@
      */
     public int compare(Object o1, Object o2) {
         Expression exp = getSortSpec();
-        Object value1 = exp.evaluate(o1);
-        Object value2 = exp.evaluate(o2);
-
-        // nulls first policy... maybe make this configurable as some DB do
-        if (value1 == null) {
-            return (value2 == null) ? 0 : -1;
-        }
-        else if (value2 == null) {
-            return 1;
+		Object value1 = null;
+		Object value2 = null;
+		try {
+        	value1 = exp.evaluate(o1);
+		} catch (ExpressionException e) {
+			if (pathExceptionSuppressed && e.getCause() instanceof org.apache.cayenne.reflect.UnresolvablePathException) {
+				//do nothing, we expect this 
+			} else {
+				//rethrow
+				throw e;
+			}
+		}
+		
+		try {
+        	value2 = exp.evaluate(o2);
+		} catch (ExpressionException e) {
+			if (pathExceptionSuppressed && e.getCause() instanceof org.apache.cayenne.reflect.UnresolvablePathException) {
+				//do nothing, we expect this 
+			} else {
+				//rethrow
+				throw e;
+			}
+		}
+
+		if (value1 == null && value2 == null) {
+		    return 0;
+		} else if (value1 == null) {
+		    return nullSortedFirst? -1:1;
+		} else if (value2 == null) {
+            return nullSortedFirst? 1:-1;
         }
 
         if (this.caseInsensitive) {

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java?rev=593075&r1=593074&r2=593075&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java Thu Nov  8 00:52:01 2007
@@ -72,8 +72,8 @@
 
                 if (value == null) {
                     // null value in the middle....
-                    throw new CayenneRuntimeException(
-                            "Null value in the middle of the path");
+                    throw new UnresolvablePathException(
+                            "Null value in the middle of the path, failed on " + nestedPropertyName + " from " + object);
                 }
 
                 value = getSimpleProperty(value, pathSegment);

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/UnresolvablePathException.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/UnresolvablePathException.java?rev=593075&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/UnresolvablePathException.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/UnresolvablePathException.java Thu Nov  8 00:52:01 2007
@@ -0,0 +1,59 @@
+/*****************************************************************
+ *   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.reflect;
+
+import org.apache.cayenne.CayenneRuntimeException;
+
+/**
+ * A runtime exception thrown when <code>PropertyUtils.getProperty()</code> finds that
+ * there is a null value in middle of the resolved path.
+ * 
+ * @author Marcin Skladaniec
+ */
+public class UnresolvablePathException extends CayenneRuntimeException {
+
+    /**
+     * Creates new NullInPathException without detail message.
+     */
+    public UnresolvablePathException() {
+        super();
+    }
+
+    /**
+     * Constructs a NullInPathException with the specified detail message.
+     * 
+     * @param msg the detail message.
+     */
+    public UnresolvablePathException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a NullInPathException that wraps a <code>Throwable</code> thrown
+     * elsewhere.
+     */
+    public UnresolvablePathException(Throwable th) {
+        super(th);
+    }
+
+    public UnresolvablePathException(String msg, Throwable th) {
+        super(msg, th);
+    }
+}