View Javadoc
1   package org.argeo.eclipse.ui.jcr.lists;
2   
3   import java.math.BigDecimal;
4   import java.util.Calendar;
5   
6   import javax.jcr.Node;
7   import javax.jcr.PropertyType;
8   import javax.jcr.RepositoryException;
9   import javax.jcr.Value;
10  import javax.jcr.ValueFormatException;
11  
12  import org.argeo.eclipse.ui.EclipseUiException;
13  import org.eclipse.jface.viewers.Viewer;
14  import org.eclipse.jface.viewers.ViewerComparator;
15  
16  /**
17   * Base comparator to enable ordering on Table or Tree viewer that display Jcr
18   * Nodes.
19   * 
20   * Note that the following snippet must be added before setting the comparator
21   * to the corresponding control: <code>
22   * // IMPORTANT: initialize comparator before setting it
23   * JcrColumnDefinition firstCol = colDefs.get(0);
24   * comparator.setColumn(firstCol.getPropertyType(),
25   * firstCol.getPropertyName());
26   * viewer.setComparator(comparator); </code>
27   */
28  public class NodeViewerComparator extends ViewerComparator {
29  	private static final long serialVersionUID = -7782916140737279027L;
30  
31  	protected String propertyName;
32  
33  	protected int propertyType;
34  	public static final int ASCENDING = 0, DESCENDING = 1;
35  	protected int direction = DESCENDING;
36  
37  	public NodeViewerComparator() {
38  	}
39  
40  	/**
41  	 * e1 and e2 must both be Jcr nodes.
42  	 * 
43  	 * @param viewer
44  	 * @param e1
45  	 * @param e2
46  	 * @return
47  	 */
48  	@Override
49  	public int compare(Viewer viewer, Object e1, Object e2) {
50  		int rc = 0;
51  		long lc = 0;
52  
53  		try {
54  			Node n1 = (Node) e1;
55  			Node n2 = (Node) e2;
56  
57  			Value v1 = null;
58  			Value v2 = null;
59  			if (n1.hasProperty(propertyName))
60  				v1 = n1.getProperty(propertyName).getValue();
61  			if (n2.hasProperty(propertyName))
62  				v2 = n2.getProperty(propertyName).getValue();
63  
64  			if (v2 == null && v1 == null)
65  				return 0;
66  			else if (v2 == null)
67  				return -1;
68  			else if (v1 == null)
69  				return 1;
70  
71  			switch (propertyType) {
72  			case PropertyType.STRING:
73  				rc = v1.getString().compareTo(v2.getString());
74  				break;
75  			case PropertyType.BOOLEAN:
76  				boolean b1 = v1.getBoolean();
77  				boolean b2 = v2.getBoolean();
78  				if (b1 == b2)
79  					rc = 0;
80  				else
81  					// we assume true is greater than false
82  					rc = b1 ? 1 : -1;
83  				break;
84  			case PropertyType.DATE:
85  				Calendar c1 = v1.getDate();
86  				Calendar c2 = v2.getDate();
87  				if (c1 == null || c2 == null)
88  					// log.trace("undefined date");
89  					;
90  				lc = c1.getTimeInMillis() - c2.getTimeInMillis();
91  				if (lc < Integer.MIN_VALUE)
92  					rc = -1;
93  				else if (lc > Integer.MAX_VALUE)
94  					rc = 1;
95  				else
96  					rc = (int) lc;
97  				break;
98  			case PropertyType.LONG:
99  				long l1;
100 				long l2;
101 				// TODO Sometimes an empty string is set instead of a long
102 				try {
103 					l1 = v1.getLong();
104 				} catch (ValueFormatException ve) {
105 					l1 = 0;
106 				}
107 				try {
108 					l2 = v2.getLong();
109 				} catch (ValueFormatException ve) {
110 					l2 = 0;
111 				}
112 
113 				lc = l1 - l2;
114 				if (lc < Integer.MIN_VALUE)
115 					rc = -1;
116 				else if (lc > Integer.MAX_VALUE)
117 					rc = 1;
118 				else
119 					rc = (int) lc;
120 				break;
121 			case PropertyType.DECIMAL:
122 				BigDecimal bd1 = v1.getDecimal();
123 				BigDecimal bd2 = v2.getDecimal();
124 				rc = bd1.compareTo(bd2);
125 				break;
126 			case PropertyType.DOUBLE:
127 				Double d1 = v1.getDouble();
128 				Double d2 = v2.getDouble();
129 				rc = d1.compareTo(d2);
130 				break;
131 			default:
132 				throw new EclipseUiException(
133 						"Unimplemented comparaison for PropertyType "
134 								+ propertyType);
135 			}
136 			// If descending order, flip the direction
137 			if (direction == DESCENDING) {
138 				rc = -rc;
139 			}
140 
141 		} catch (RepositoryException re) {
142 			throw new EclipseUiException("Unexpected error "
143 					+ "while comparing nodes", re);
144 		}
145 		return rc;
146 	}
147 
148 	/**
149 	 * @param propertyType
150 	 *            Corresponding JCR type
151 	 * @param propertyName
152 	 *            name of the property to use.
153 	 */
154 	public void setColumn(int propertyType, String propertyName) {
155 		if (this.propertyName != null && this.propertyName.equals(propertyName)) {
156 			// Same column as last sort; toggle the direction
157 			direction = 1 - direction;
158 		} else {
159 			// New column; do an ascending sort
160 			this.propertyType = propertyType;
161 			this.propertyName = propertyName;
162 			direction = ASCENDING;
163 		}
164 	}
165 
166 	// Getters and setters
167 	protected String getPropertyName() {
168 		return propertyName;
169 	}
170 
171 	protected void setPropertyName(String propertyName) {
172 		this.propertyName = propertyName;
173 	}
174 
175 	protected int getPropertyType() {
176 		return propertyType;
177 	}
178 
179 	protected void setPropertyType(int propertyType) {
180 		this.propertyType = propertyType;
181 	}
182 
183 	protected int getDirection() {
184 		return direction;
185 	}
186 
187 	protected void setDirection(int direction) {
188 		this.direction = direction;
189 	}
190 }