001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 011 * 012 * $Id$ 013 */ 014 015package org.nuxeo.ecm.core.api.tree; 016 017import java.text.Collator; 018 019import org.apache.commons.logging.Log; 020import org.apache.commons.logging.LogFactory; 021import org.nuxeo.ecm.core.api.DocumentModel; 022import org.nuxeo.ecm.core.api.PropertyException; 023 024/** 025 * Default implementation for document tree sorter. 026 * <p> 027 * Filters on sort property, case insensitively. 028 * 029 * @author Anahide Tchertchian 030 */ 031public class DefaultDocumentTreeSorter implements DocumentTreeSorter { 032 033 private static final long serialVersionUID = 1L; 034 035 private static final Log log = LogFactory.getLog(DefaultDocumentTreeSorter.class); 036 037 static final Collator collator = Collator.getInstance(); 038 039 static { 040 collator.setStrength(Collator.PRIMARY); // case+accent independent 041 } 042 043 protected String sortPropertyPath; 044 045 @Override 046 public String getSortPropertyPath() { 047 return sortPropertyPath; 048 } 049 050 @Override 051 public void setSortPropertyPath(String sortPropertyPath) { 052 this.sortPropertyPath = sortPropertyPath; 053 } 054 055 @Override 056 public int compare(DocumentModel doc1, DocumentModel doc2) { 057 if (sortPropertyPath == null) { 058 log.error("Cannot sort: no sort property path set"); 059 return 0; 060 } 061 062 if (doc1 == null && doc2 == null) { 063 return 0; 064 } else if (doc1 == null) { 065 return -1; 066 } else if (doc2 == null) { 067 return 1; 068 } 069 070 Object v1; 071 try { 072 v1 = doc1.getPropertyValue(sortPropertyPath); 073 } catch (PropertyException e) { 074 v1 = null; 075 } 076 Object v2; 077 try { 078 v2 = doc2.getPropertyValue(sortPropertyPath); 079 } catch (PropertyException e) { 080 v2 = null; 081 } 082 boolean useHash = false; 083 if (v1 == null && v2 == null) { 084 useHash = true; 085 } else if (v1 == null) { 086 return -1; 087 } else if (v2 == null) { 088 return 1; 089 } 090 091 final int cmp; 092 if (v1 instanceof Long && v2 instanceof Long) { 093 cmp = ((Long) v1).compareTo((Long) v2); 094 } else if (v1 instanceof Integer && v2 instanceof Integer) { 095 cmp = ((Integer) v1).compareTo((Integer) v2); 096 } else if (!useHash) { // avoid NPE 097 cmp = collator.compare(v1.toString(), v2.toString()); 098 } else { 099 cmp = 0; 100 } 101 102 if (cmp == 0) { 103 useHash = true; 104 } 105 if (useHash) { 106 // everything being equal, provide consistent ordering 107 if (doc1.hashCode() == doc2.hashCode()) { 108 return 0; 109 } else if (doc1.hashCode() < doc2.hashCode()) { 110 return -1; 111 } else { 112 return 1; 113 } 114 } 115 return cmp; 116 } 117 118}