You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ar...@apache.org on 2010/12/28 21:23:43 UTC

svn commit: r1053424 - in /myfaces/trinidad/trunk: trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/SortableModel.java trinidad-api/src/test/clirr/clirr-runner.txt trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/faces-config.xml

Author: arobinson74
Date: Tue Dec 28 20:23:43 2010
New Revision: 1053424

URL: http://svn.apache.org/viewvc?rev=1053424&view=rev
Log:
TRINIDAD-1965 - improve sortable model API to support case insensitive sorting

Modified:
    myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/SortableModel.java
    myfaces/trinidad/trunk/trinidad-api/src/test/clirr/clirr-runner.txt
    myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/faces-config.xml

Modified: myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/SortableModel.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/SortableModel.java?rev=1053424&r1=1053423&r2=1053424&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/SortableModel.java (original)
+++ myfaces/trinidad/trunk/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/SortableModel.java Tue Dec 28 20:23:43 2010
@@ -6,9 +6,9 @@
  *  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
@@ -23,8 +23,10 @@ import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 
 import javax.el.ELContext;
 import javax.el.ELResolver;
@@ -48,6 +50,60 @@ import org.apache.myfaces.trinidad.loggi
 public class SortableModel extends CollectionModel
 {
   /**
+   * This class provides an enumeration to work with the integer values of the
+   * {@link Collator} strength values.
+   */
+  public enum Strength
+  {
+    /** @see Collator#IDENTICAL */
+    IDENTICAL(Collator.IDENTICAL),
+    /** @see Collator#PRIMARY */
+    PRIMARY(Collator.PRIMARY),
+    /** @see Collator#SECONDARY */
+    SECONDARY(Collator.SECONDARY),
+    /** @see Collator#TERTIARY */
+    TERTIARY(Collator.TERTIARY);
+
+    private Strength(int strength)
+    {
+      _strength = strength;
+    }
+
+    public int getIntValue()
+    {
+      return _strength;
+    }
+
+    private final int _strength;
+  }
+
+  /**
+   * This class provides an enumeration to work with the integer values of the
+   * {@link Collator} decomposition values.
+   */
+  public enum Decomposition
+  {
+    /** @see Collator#PRIMARY */
+    NO_DECOMPOSITION(Collator.NO_DECOMPOSITION),
+    /** @see Collator#SECONDARY */
+    CANONICAL_DECOMPOSITION(Collator.CANONICAL_DECOMPOSITION),
+    /** @see Collator#TERTIARY */
+    FULL_DECOMPOSITION(Collator.FULL_DECOMPOSITION);
+
+    private Decomposition(int decomposition)
+    {
+      _decomposition = decomposition;
+    }
+
+    public int getIntValue()
+    {
+      return _decomposition;
+    }
+
+    private final int _decomposition;
+  }
+
+  /**
    * Create a new SortableModel from the given instance.
    * @param model This will be converted into a {@link DataModel}
    * @see #setWrappedData
@@ -204,7 +260,7 @@ public class SortableModel extends Colle
     //simple property -> resolve value directly
     if (!property.contains( "." ))
       return resolver.getValue(context, base, property );
-    
+
     int index = property.indexOf( '.' );
     Object newBase = resolver.getValue(context, base, property.substring( 0, index ) );
 
@@ -244,6 +300,97 @@ public class SortableModel extends Colle
     }
   }
 
+  /**
+   * Get the comparator associated with the given property.
+   *
+   * @param propertyName the property
+   * @return the comparator or null if one has not been set
+   */
+  public Comparator getComparator(
+    String propertyName)
+  {
+    return _propertyComparators == null ?
+      null :
+      _propertyComparators.get(propertyName);
+  }
+
+  /**
+   * Set a custom comparator to use to sort the given property name.
+   *
+   * @param propertyName the property with which to associate the comparator
+   * @param comparator the comparator to use, or null to remove one
+   */
+  public void setComparator(
+    String     propertyName,
+    Comparator comparator)
+  {
+    assert propertyName != null : "Property name may not be null";
+
+    if (comparator == null && _propertyComparators != null)
+    {
+      _propertyComparators.remove(propertyName);
+      if (_propertyComparators.isEmpty())
+      {
+        _propertyComparators = null;
+      }
+    }
+    else if (comparator != null)
+    {
+      if (_propertyComparators == null)
+      {
+        _propertyComparators = new HashMap<String, Comparator>();
+      }
+      _propertyComparators.put(propertyName, comparator);
+    }
+
+    if (_sortCriterion != null && propertyName.equals(_sortCriterion.getProperty()))
+    {
+      _sort(_sortCriterion.getProperty(), _sortCriterion.isAscending());
+    }
+  }
+
+  /**
+   * Convenience method to set a compatator for a property using a {@link Collator} setup with
+   * the given strength and decomposition values.
+   *
+   * @param propertyName the property
+   * @param collatorStrength the stregth to use or null to leave as the default for the
+   * default locale
+   * @param collatorDecomposition the decomposition to use or null to leave as the default for the
+   * default locale
+   * @see #setComparator(String, Comparator)
+   */
+  public void setCollator(
+    String        propertyName,
+    Strength      collatorStrength,
+    Decomposition collatorDecomposition)
+  {
+    Locale locale = null;
+
+    RequestContext reqCtx = RequestContext.getCurrentInstance();
+    if (reqCtx != null)
+    {
+      FacesContext facesContext = FacesContext.getCurrentInstance();
+      if (facesContext != null)
+      {
+        locale = _getLocale(reqCtx, facesContext);
+      }
+    }
+
+    Collator collator = locale == null ? Collator.getInstance() : Collator.getInstance(locale);
+    if (collatorDecomposition != null)
+    {
+      collator.setDecomposition(collatorDecomposition.getIntValue());
+    }
+
+    if (collatorStrength != null)
+    {
+      collator.setStrength(collatorStrength.getIntValue());
+    }
+
+    setComparator(propertyName, collator);
+  }
+
   @Override
   public String toString()
   {
@@ -355,7 +502,7 @@ public class SortableModel extends Colle
   }
 
 
-  
+
   private static final class IntList extends ArrayList<Integer>
   {
     public IntList(int size)
@@ -377,7 +524,11 @@ public class SortableModel extends Colle
 
   private final class Comp implements Comparator<Integer>
   {
-    public Comp(ELResolver resolver, ELContext context, Locale locale, String property)
+    public Comp(
+      ELResolver resolver,
+      ELContext  context,
+      Locale     locale,
+      String     property)
     {
       _resolver = resolver;
       _context  = context;
@@ -395,7 +546,9 @@ public class SortableModel extends Colle
     }
 
     @SuppressWarnings("unchecked")
-    public int compare(Integer o1, Integer o2)
+    public int compare(
+      Integer o1,
+      Integer o2)
     {
       int index1 = o1.intValue();
       int index2 = o2.intValue();
@@ -414,30 +567,40 @@ public class SortableModel extends Colle
       if (value2 == null)
         return 1;
 
-      // bug 4545164. Sometimes, isSortable returns true
-      // even if the underlying object is not a Comparable.
-      // This happens if the object at rowIndex zero is null.
-      // So test before we cast:
-      if (value1 instanceof Comparable)
+      Comparator comparator = getComparator(_prop);
+      if (comparator == null)
       {
-        if ((value1 instanceof String) && (value2 instanceof String)) 
+        // bug 4545164. Sometimes, isSortable returns true
+        // even if the underlying object is not a Comparable.
+        // This happens if the object at rowIndex zero is null.
+        // So test before we cast:
+        if (value1 instanceof Comparable)
         {
-          return compare((String) value1, (String) value2);
+          if ((value1 instanceof String) && (value2 instanceof String))
+          {
+            return _compare((String) value1, (String) value2);
+          }
+          else
+          {
+            return ((Comparable<Object>) value1).compareTo(value2);
+          }
         }
-        else 
+        else
         {
-          return ((Comparable<Object>) value1).compareTo(value2);
+          // if the object is not a Comparable, then
+          // the best we can do is string comparison:
+          return _compare(value1.toString(), value2.toString());
         }
       }
       else
       {
-        // if the object is not a Comparable, then
-        // the best we can do is string comparison:
-        return compare(value1.toString(), value2.toString());
+        return comparator.compare(value1, value2);
       }
     }
 
-    private int compare(String s1, String s2) 
+    private int _compare(
+      String s1,
+      String s2)
     {
       if (_collator != null)
       {
@@ -480,7 +643,7 @@ public class SortableModel extends Colle
     {
       _resolver = resolver;
     }
-    
+
     @Override
     public ELResolver getELResolver()
     {
@@ -502,7 +665,7 @@ public class SortableModel extends Colle
       // to an ELResolver, no VariableMapper is needed
       return null;
     }
-    
+
     private final ELResolver _resolver;
   }
 
@@ -522,7 +685,7 @@ public class SortableModel extends Colle
     if (context != null)
       return context.getELContext();
 
-    return new ELContextImpl(resolver); 
+    return new ELContextImpl(resolver);
   }
 
   static private ELResolver _getELResolver(FacesContext context)
@@ -537,10 +700,10 @@ public class SortableModel extends Colle
     ApplicationFactory factory = (ApplicationFactory)
       FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
     return factory.getApplication().getELResolver();
-    
+
   }
 
-  static private Locale _getLocale(RequestContext requestContext, FacesContext facesContext) 
+  static private Locale _getLocale(RequestContext requestContext, FacesContext facesContext)
   {
     if (requestContext != null)
       return requestContext.getFormattingLocale();
@@ -556,6 +719,8 @@ public class SortableModel extends Colle
   private DataModel _model = null;
   private Object _wrappedData = null;
 
+  private Map<String, Comparator> _propertyComparators;
+
   private IntList _sortedIndicesList = null, // from baseIndex to sortedIndex
     _baseIndicesList = null; // from sortedIndex to baseIndex
 

Modified: myfaces/trinidad/trunk/trinidad-api/src/test/clirr/clirr-runner.txt
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-api/src/test/clirr/clirr-runner.txt?rev=1053424&r1=1053423&r2=1053424&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-api/src/test/clirr/clirr-runner.txt (original)
+++ myfaces/trinidad/trunk/trinidad-api/src/test/clirr/clirr-runner.txt Tue Dec 28 20:23:43 2010
@@ -1317,6 +1317,11 @@ INFO: 4000: org.apache.myfaces.trinidad.
 INFO: 8000: org.apache.myfaces.trinidad.model.RowKeyPropertyModel: Class org.apache.myfaces.trinidad.model.RowKeyPropertyModel added
 INFO: 8000: org.apache.myfaces.trinidad.model.RowKeyPropertyTreeModel: Class org.apache.myfaces.trinidad.model.RowKeyPropertyTreeModel added
 INFO: 4000: org.apache.myfaces.trinidad.model.SortableModel: Added java.lang.Iterable to the set of implemented interfaces
+INFO: 7011: org.apache.myfaces.trinidad.model.SortableModel: Method 'public java.util.Comparator getComparator(java.lang.String)' has been added
+INFO: 7011: org.apache.myfaces.trinidad.model.SortableModel: Method 'public void setCollator(java.lang.String, org.apache.myfaces.trinidad.model.SortableModel$Strength, org.apache.myfaces.trinidad.model.SortableModel$Decomposition)' has been added
+INFO: 7011: org.apache.myfaces.trinidad.model.SortableModel: Method 'public void setComparator(java.lang.String, java.util.Comparator)' has been added
+INFO: 8000: org.apache.myfaces.trinidad.model.SortableModel$Decomposition: Class org.apache.myfaces.trinidad.model.SortableModel$Decomposition added
+INFO: 8000: org.apache.myfaces.trinidad.model.SortableModel$Strength: Class org.apache.myfaces.trinidad.model.SortableModel$Strength added
 INFO: 4000: org.apache.myfaces.trinidad.model.TreeModel: Added java.lang.Iterable to the set of implemented interfaces
 INFO: 4000: org.apache.myfaces.trinidad.model.ViewIdPropertyMenuModel: Added java.lang.Iterable to the set of implemented interfaces
 INFO: 4000: org.apache.myfaces.trinidad.model.XMLMenuModel: Added java.lang.Iterable to the set of implemented interfaces

Modified: myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/faces-config.xml
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/faces-config.xml?rev=1053424&r1=1053423&r2=1053424&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/faces-config.xml (original)
+++ myfaces/trinidad/trunk/trinidad-examples/trinidad-demo/src/main/webapp/WEB-INF/faces-config.xml Tue Dec 28 20:23:43 2010
@@ -150,7 +150,7 @@
        request
     </managed-bean-scope>
   </managed-bean>
-  
+
   <managed-bean>
     <managed-bean-name>dateRestrictionValidator</managed-bean-name>
     <managed-bean-class>
@@ -231,7 +231,7 @@
     <managed-bean-scope>
        session
     </managed-bean-scope>
-  </managed-bean>  
+  </managed-bean>
 
   <managed-bean>
     <managed-bean-name>messages</managed-bean-name>
@@ -932,6 +932,7 @@
         <value>table_selection.jspx</value>
         <value>table_dynamic.jspx</value>
         <value>table_nested.jspx</value>
+        <value>table_sorting.jspx</value>
         <value>tree.jspx</value>
         <value>treeTable.jspx</value>
         <value>treeTable_selection.jspx</value>
@@ -2561,6 +2562,12 @@
     </navigation-case>
 
     <navigation-case>
+      <from-outcome>guide.table_sorting</from-outcome>
+      <to-view-id>/components/table_sorting.jspx</to-view-id>
+      <redirect/>
+    </navigation-case>
+
+    <navigation-case>
       <from-outcome>guide.panelTip</from-outcome>
       <to-view-id>/components/panelTip.jspx</to-view-id>
       <redirect/>
@@ -2937,6 +2944,12 @@
   </managed-bean>
 
   <managed-bean>
+    <managed-bean-name>sortableTable</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.trinidaddemo.table.SortableModelBean</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
     <managed-bean-name>periodicTable</managed-bean-name>
     <managed-bean-class>
        org.apache.myfaces.trinidaddemo.table.TableBuilder