随笔-193  评论-715  文章-1  trackbacks-0
作者:张明星 时间:2006.04.07. MSN:fastzch@hotmail.com

extremeComponents是一个十分不错的WEB层显示表格的好东东,其功能十分强大,而且对个性化支持也很好,自己可以做很多的扩展。相关的资料要查看官方网站(http://www.extremecomponents.org)。

extremeComponents提供了诸多的接口,其中有一个接口就是为了实现排序而出现的,接口如下:
1 public interface SortRowsCallback {
2  public Collection sortRows(TableModel model, Collection rows) throws Exception;
3 } 

同时,在标签中需指明排序所用的接口,代码如下:
1 <ec:table  var="pres"  action="/showNews.do"  sortRowsCallback="demo.MySortCallback"  />
2 

经过我的一番研究,在排序时,extremeComponents使用的是org.apache.commons.beanutils.BeanComparator这个类作为实现的比较器,同时也使用了ReverseComparator,NullComparator等类,官方的实现可以参见org.extremecomponents.table.callback.ProcessRowsCallback文件(这个文件实现了三个接口,分别是RetrieveRowsCallback, FilterRowsCallback, SortRowsCallback,我们在这里只用实现SortRowsCallback就够了)。问题的关键就在于NullComparator这个类,如果你对JAVA基础很熟悉的话,你就会知道JAVA的排序时都会有一个Comparator,在这里就不多讲了,有兴趣的读者可以去看JDK的源码。

经过我的几次追踪,发现排序的最终实现交给了Arrays类的mergeSort方法,这个方法是一个静态的方法,有两个实现,这里用到的是一个带Comparator的实现,具体代码如下:
 1 private static void mergeSort(Object src[], Object dest[],
 2                                   int low, int high, int off, Comparator c) {
 3     int length = high - low;
 4 
 5     // Insertion sort on smallest arrays
 6     if (length < INSERTIONSORT_THRESHOLD) {
 7         for (int i=low; i<high; i++)
 8         for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
 9             swap(dest, j, j-1);
10         return;
11     }
12 
13         // Recursively sort halves of dest into src
14         int destLow  = low;
15         int destHigh = high;
16         low  += off;
17         high += off;
18         int mid = (low + high) >> 1;
19         mergeSort(dest, src, low, mid, -off, c);
20         mergeSort(dest, src, mid, high, -off, c);
21 
22         // If list is already sorted, just copy from src to dest.  This is an
23         // optimization that results in faster sorts for nearly ordered lists.
24         if (c.compare(src[mid-1], src[mid]) <= 0) {
25            System.arraycopy(src, low, dest, destLow, length);
26            return;
27         }
28 
29         // Merge sorted halves (now in src) into dest
30         for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
31             if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
32                 dest[i] = src[p++];
33             else
34                 dest[i] = src[q++];
35         }
36     }

仔细看看,不难发现,问题的关键就在于使用的Comparator 的compare方法。

由此,找到了解决问题的根本办法,实现自己的Comparator 类,我的实现如下:

 1 package demo;
 2 
 3 import org.apache.commons.collections.comparators.NullComparator;
 4 public class MyComparator extends NullComparator{
 5 
 6     public int compare(Object object, Object object1) {
 7         String s1=(String)object;
 8         String s2=(String)object1;
 9         
10         return s1.compareToIgnoreCase(s2);
11     }
12 }
13 
看看,是不是超级简单?答案是肯定的(你或许会说,弄了半天就这么简单呀)。

再来看看我对SortRowsCallback接口的实现,代码如下:
 1 package demo;
 2 
 3 import java.util.*;
 4 
 5 import org.apache.commons.beanutils.BeanComparator;
 6 import org.apache.commons.collections.comparators.ReverseComparator;
 7 import org.extremecomponents.table.bean.Column;
 8 import org.extremecomponents.table.core.TableConstants;
 9 import org.extremecomponents.table.core.TableModel;
10 import org.extremecomponents.table.callback.SortRowsCallback;
11 import org.extremecomponents.table.limit.Sort;
12 
13 public final class MySortCallback implements SortRowsCallback {
14 
15     public Collection sortRows(TableModel model, Collection rows)
16             throws Exception {
17         boolean sorted = model.getLimit().isSorted();
18 
19         if (!sorted) {
20             return rows;
21         }
22 
23         Sort sort = model.getLimit().getSort();
24         String sortProperty = sort.getProperty();
25         String sortOrder = sort.getSortOrder();
26         Column column = model.getColumnHandler().getColumnByAlias(sortProperty);
27         String property = column.getProperty();
28 
29         if (sortOrder.equals(TableConstants.SORT_ASC)) {
30             BeanComparator comparator = new BeanComparator(property,
31                     new MyComparator());
32             Collections.sort((List) rows, comparator);
33         } else if (sortOrder.equals(TableConstants.SORT_DESC)) {
34             BeanComparator reversedNaturalOrderBeanComparator = new BeanComparator(
35                     property, new ReverseComparator(new MyComparator()));
36             Collections.sort((List) rows, reversedNaturalOrderBeanComparator);
37         }
38 
39         return rows;
40     }
41 
42  }
好了,大功告成。

PS:别忘了在标签中设置你自己定义的接口哟。
posted on 2006-04-07 21:34 Robin's Programming World 阅读(3384) 评论(6)  编辑  收藏 所属分类: Java

评论:
# re: extremeComponents排序实现不区分大小写 2006-04-08 13:29 | xplucky
写的非常棒,extremeComponents提供了很多的接口用于定制,至于排序extremeComponents给出了一个基础的参考实现,如果你需要定制自己的实现,你只要参考已有的视线,将其中的视线方法替换为你自己的就行了。这在extremeComponents的指南中已经提过。相关的中文文档可以参考extremeComponents网站的wiki,或我的blog
---- http://www.blogjava.net/lucky  回复  更多评论
  
# re: extremeComponents排序实现不区分大小写 2006-04-08 15:30 | Robin's Java World
@xplucky 过奖了,真的有点不敢当,其实排序也存在着一定的问题,好像只能对字符串进行排序。其它类型的我不知道行不?按我的程序实现好像是不行的,我也没测试过。不过方法就是这样,起个抛砖引玉的作用。
  回复  更多评论
  
# re: extremeComponents排序实现不区分大小写 2006-04-08 16:11 | xplucky
extremeComponents只是提供了一个基础的框架,或者定义了一个基础的结构,并给出了一些必要的也是比较基础的实现。它的强大之处就是给了使用者,很多机会来完成自己的定制工作,因为每个实际应用要求的实现可能有区别。当然,这时候有人可能会说,既然需要我自己去实现,那我又为什么还要去使用它呢,还不如我自己从头到尾完全按照自己的需要去做自己的不就行了?关于这个问题,我的看法是更好的复用性(reuse)。因为extremeComponents提供了最基础的结构,给定了一些基准,如果大家都能够参照这些基准根据自己的需求去定制一些东西,比如说:cell、filter,然后大家都能share出来,使整个的外围能够繁荣起来。那么对于大家来说,就有机会选择自己需要的实现,而不用再去完成一些别人已经完成的工作,这跟eclipse的插件类似。
以上只是我的一家之言。
  回复  更多评论
  
# re: extremeComponents排序实现不区分大小写 2006-04-10 20:39 | Robin's Java World
@xplucky
其实有时候很弄不懂一些人不喜欢这样的方式,反正我很喜欢开源的东东。  回复  更多评论
  
# re: extremeComponents排序实现不区分大小写 2006-04-11 09:25 | xplucky
@Robin's Java World
每个人都有自己的想法,这样才能百家争鸣,像在软件开发方法上就有: 模型驱动、测试驱动...... 每种都有它的支持者,志同道合坚持自己的理想吧。  回复  更多评论
  
# re: extremeComponents排序实现不区分大小写 2008-06-27 13:31 | coolshuiping
这个对嵌套属性不起作用啊,报错
源码:
<ec:table items="orderList" var="order" action="${pageContext.request.contextPath}/history/test"autoIncludeParameters="${(empty param.autoInc)?(true):(false)}" sortRowsCallback="com.zealyoung.gsm.web.viewdoc.MySortCallback">
<ec:exportXls fileName="orderList.xls" tooltip="导出 Excel"/>
<ec:row>
<ec:column property="id" width="5%" cell="rowCount" title="序号"/>
<ec:column property="district.name" width="5%" title="地区" alias="district" ></ec:column>
<ec:column property="number" width="12%" title="订单号" ><a href="#" onclick="window.parent.location='/order/showOrder/${order.id }'">${order.number }</a></ec:column>
<ec:column property="store.name" width="15%" alias="store" title="店铺名称" ><a href="#" onclick="winOpen('/store/particular/${order.store.id }','excelpreview_store_${order.store.id }')" >${order.store.name }</a> </ec:column>
<ec:column property="store.address" alias="store" title="店铺地址" />
<ec:column property="date.time" width="18%" alias="date" cell="date" title="时间" ></ec:column>
</ec:row>
</ec:table>


错误信息:
javax.servlet.jsp.JspException: TableTag Problem: javax.servlet.jsp.JspException:
TableTag.doAfterBody() Problem: java.lang.NullPointerException
at com.zealyoung.gsm.web.viewdoc.MySortCallback.sortRows(MySortCallback.java:29)
at org.extremecomponents.table.core.TableModelUtils.sortRows(TableModelUtils.java:66)
at org.extremecomponents.table.core.TableModelImpl.execute(TableModelImpl.java:233)
at org.extremecomponents.table.tag.TableTag.doAfterBody(TableTag.java:459)
at _jsp._web_22dinf._views._common._excelpreview__jsp._jspService(_excelpreview__jsp.java:197)
at com.caucho.jsp.JavaPage.service(JavaPage.java:61)
at com.caucho.jsp.Page.pageservice(Page.java:578)
...................  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: