0

Is it possible to globally configure the default comparators used for 'auto'? [closed]

asked 2013-02-01 15:42:15 +0800

RetoH gravatar image RetoH flag of Switzerland
44 5

I use a grid with

<column label="name" sort="auto(name)" />

But unfortunately the automatic sorting is case sensitive (see http://forum.zkoss.org/question/78175/zk-listbox-auto-sorting-by-pojo-without-using-any-comparator/).

As a workaround to the above problem I would like to push my own "default comparators". I did not find any hints here: http://books.zkoss.org/wiki/ZK%20Configuration%20Reference/zk.xml/The%20Library%20Properties (Library Properties).

delete flag offensive retag edit

The question has been closed for the following reason "the question is answered, right answer was accepted" by sjoshi
close date 2013-02-08 05:56:29

Comments

dude try this link i think its helpful

http://www.zkoss.org/zkdemo/listbox/sort_by_comparator?search=compara (ZK Comparator)

good luck

kazma ( 2013-02-04 19:35:34 +0800 )edit

3 Answers

Sort by » oldest newest most voted
0

answered 2013-02-05 10:18:28 +0800

RetoH gravatar image RetoH flag of Switzerland
44 5

Thanks to samchuang's hints I was able to roll my own workaround. Here my (hackish) solution.

Note that I plan to extend this for property "paths" (e.g. "bean.property1.property2"), but at the moment it only works for simple "one-level" properties. Also note that the current version cannot handle null-entities or null-properties.

I defined a language addon (as suggested by samchuang):

<language-addon>

<addon-name>MyColumn</addon-name>
  <language-name>xul/html</language-name>

  <component>
    <component-name>column</component-name>
    <extends>column</extends>
    <component-class>mypackage.MyColumn</component-class>
  </component>

</language-addon>

The implementation of MyColumn:

public class MyColumn extends Column
{
  @SuppressWarnings("unused")
  private static final Logger LOGGER = Logger.getLogger(IbrLimsColumn.class.getName());

  public MyColumn()
  {
  }

  @Override
  public void setSort(String type) throws ClassNotFoundException, InstantiationException, IllegalAccessException
  {
    if(type.startsWith("str"))
    {
      String propertyName = type.substring("str(".length(), type.length() - 1);

      setSortAscending(new StringPropertyComparator(propertyName, true));
      setSortDescending(new StringPropertyComparator(propertyName, false));
    }
    else
    {
      super.setSort(type);
    }
  }
}

The usage:

<grid model="@load(vm.employees)" sizedByContent="true">
  <columns sizable="true" menupopup="auto">
    <column label="Last name" sort="str(lastName)" />
    <column label="First name" sort="str(firstName)" />
  </columns>
  <template name="model">
    <row>
      <a href="/Employee.zul?id=${each.id}">${each.lastName}</a>
      <label value="${each.firstName}" />         
    </row>
  </template>
</grid>

And finally the heart of the implementation, the StringPropertyComparator:

public class StringPropertyComparator implements Comparator<Object>
{
  private final boolean       m_ascending;
  private final String        m_propertyPath;   
  private Method              m_getter     = null;
  private Comparator          m_comparator = null;

  public StringPropertyComparator(String propertyPath, boolean ascending)
  {
    m_propertyPath = propertyPath;
    m_ascending = ascending;
  }

  @Override
  public int compare(Object entity1, Object entity2)
  {
    try
    {
      return compare0(entity1, entity2);
    }
    catch(Throwable t)
    {
      throw new RuntimeException("unexpected", t);
    }
  }

  private int compare0(Object entity1, Object entity2) throws Exception
  {
    if(m_getter == null)
    {
      m_getter = ReflectionTools.getGetterMethod(entity1, m_propertyPath);
    }

    if(m_comparator == null)
    {
      // determine comparator based on property type

      Collator collator = Collator.getInstance(new Locale("en", "US"));
      // sort A, a, Ä, ä, Â, â, À, à (and other accents) at the same position in the list
      collator.setStrength(Collator.PRIMARY);

      m_comparator = collator;
    }

    Object value1 = m_getter.invoke(entity1);
    Object value2 = m_getter.invoke(entity2);

    if(m_ascending)
    {
      return m_comparator.compare(value1, value2);
    }
    else
    {
      return -m_comparator.compare(value1, value2);
    }
  }
}

And the ReflectionTools:

public class ReflectionTools
{
  public static Method getGetterMethod(Object bean, String propertyName)
  {
    Class<?> beanClass = bean.getClass();

    try
    {
      return beanClass.getMethod(getGetterName(propertyName));
    }
    catch(Throwable t)
    {
      // ignore
    }

    try
    {
      return beanClass.getMethod(getBooleanGetterName(propertyName));
    }
    catch(Throwable t)
    {
      // ignore
    }

    throw new IllegalArgumentException("not getter method found for '" + propertyName + "', bean: " + bean);
  }

  public static String getGetterName(String propertyName)
  {
    String getterName = "get" + capitalizeFirstLetter(propertyName);
    return getterName;
  }

  public static String getBooleanGetterName(String propertyName)
  {
    String getterName = "is" + capitalizeFirstLetter(propertyName);
    return getterName;
  }

  private static String capitalizeFirstLetter(String string)
  {
    String result = string.substring(0, 1).toUpperCase() + string.substring(1, string.length());
    return result;
  }
}
link publish delete flag offensive edit

Comments

Please close this question if your issue resolved

sjoshi ( 2013-02-05 10:23:09 +0800 )edit
1

answered 2013-02-04 01:33:08 +0800

samchuang gravatar image samchuang
4084 4

Hi, you can implement it easily by

  1. MyColumn extends from Column, override the getSortAscending() & getSortDescending(), if default comparator is null, try to read a Library Property and create comparator and set it to Column.
  2. define the MyColumn as a component in lang-addon.xml

    <component>
    <component-name>column</component-name>
    <extends>column</extends>
    <component-class>test.MyColumn</component-class>
    

    </component>

you can also refer to The language-addon

link publish delete flag offensive edit
0

answered 2013-02-01 16:39:31 +0800

sjoshi gravatar image sjoshi flag of India
3493 1 8
http://zkframeworkhint.bl...

Take a look Here you can write your own comparator this example will help you to overcome your issue.

link publish delete flag offensive edit

Comments

this is not really an option, as it would require me to write and configure a comparator for every single entity and page. i would like to change the default sort behaviour for all string properties in my application.

RetoH ( 2013-02-03 22:55:22 +0800 )edit

Question tools

Follow
1 follower

RSS

Stats

Asked: 2013-02-01 15:42:15 +0800

Seen: 34 times

Last updated: Feb 05 '13

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More