001: /*
002: * @(#) ObjectComparatorManager.java
003: *
004: * Copyright 2002 - 2003 JIDE Software. All rights reserved.
005: */
006: package com.jidesoft.comparator;
007:
008: import com.jidesoft.converter.CacheMap;
009: import com.jidesoft.converter.RegistrationListener;
010:
011: import java.text.Collator;
012: import java.util.Calendar;
013: import java.util.Comparator;
014:
015: /**
016: * A global object that can register comparator with a type and a ComparatorContext.
017: */
018: public class ObjectComparatorManager {
019:
020: private final static CacheMap<Comparator<?>, ComparatorContext> _cache = new CacheMap<Comparator<?>, ComparatorContext>(
021: new ComparatorContext(""));
022:
023: private final static Comparator<Object> _defaultComparator = new DefaultComparator();
024:
025: public static void registerComparator(Class<?> clazz,
026: Comparator comparator) {
027: registerComparator(clazz, comparator,
028: ComparatorContext.DEFAULT_CONTEXT);
029: }
030:
031: /**
032: * Registers a comparator with the type specified as class and a comparator context specified as context.
033: *
034: * @param clazz type.
035: * @param comparator the comparator to be registered.
036: * @param context the comparator context.
037: */
038: public static void registerComparator(Class<?> clazz,
039: Comparator comparator, ComparatorContext context) {
040: if (clazz == null) {
041: throw new IllegalArgumentException(
042: "Parameter clazz cannot be null");
043: }
044: if (context == null) {
045: context = ComparatorContext.DEFAULT_CONTEXT;
046: }
047: _cache.register(clazz, comparator, context);
048: }
049:
050: /**
051: * Unregisters comparator associated with clazz and context.
052: *
053: * @param clazz the data type.
054: */
055: public static void unregisterComparator(Class<?> clazz) {
056: _cache.unregister(clazz, ComparatorContext.DEFAULT_CONTEXT);
057: }
058:
059: /**
060: * Unregisters comparator associated with clazz and context.
061: *
062: * @param clazz the data type.
063: * @param context the comparator context.
064: */
065: public static void unregisterComparator(Class<?> clazz,
066: ComparatorContext context) {
067: if (context == null) {
068: context = ComparatorContext.DEFAULT_CONTEXT;
069: }
070: _cache.unregister(clazz, context);
071: }
072:
073: /**
074: * Unregisters all the comparators which registered before.
075: */
076: public static void unregisterAllComparators() {
077: _cache.clear();
078: }
079:
080: /**
081: * Gets the registered comparator associated with class and default context.
082: *
083: * @param clazz the data type.
084: * @return the registered comparator.
085: */
086: public static Comparator getComparator(Class<?> clazz) {
087: return getComparator(clazz, ComparatorContext.DEFAULT_CONTEXT);
088: }
089:
090: /**
091: * Gets the comparator.
092: *
093: * @param clazz the data type.
094: * @param context the comparator context.
095: * @return the comparator.
096: */
097: public static Comparator getComparator(Class<?> clazz,
098: ComparatorContext context) {
099: if (isAutoInit()) {
100: initDefaultComparator();
101: }
102:
103: if (context == null) {
104: context = ComparatorContext.DEFAULT_CONTEXT;
105: }
106: Comparator object = _cache.getRegisteredObject(clazz, context);
107: if (object != null) {
108: return object;
109: } else {
110: return _defaultComparator;
111: }
112: }
113:
114: /**
115: * Compares the two objects. It will look up in <code>ObjectComparatorManager</code>
116: * to find the comparator and compare.
117: *
118: * @param o1 the first object to be compared.
119: * @param o2 the second object to be compared.
120: * @return the compare result as defined in {@link Comparator#compare(Object,Object)}
121: */
122:
123: public static int compare(Object o1, Object o2) {
124: return compare(o1, o2, ComparatorContext.DEFAULT_CONTEXT);
125: }
126:
127: /**
128: * Compares the two objects. It will look up in <code>ObjectComparatorManager</code>
129: * to find the comparator and compare.
130: *
131: * @param o1 the first object to be compared.
132: * @param o2 the second object to be compared.
133: * @param context the comparator context
134: * @return the compare result as defined in {@link Comparator#compare(Object,Object)}
135: */
136:
137: public static int compare(Object o1, Object o2,
138: ComparatorContext context) {
139: if (o1 == null && o2 == null) {
140: return 0;
141: } else if (o1 == null) {
142: return -1;
143: } else if (o2 == null) {
144: return 1;
145: }
146:
147: // both not null
148:
149: Class<?> clazz;
150: Class<?> clazz1 = o1.getClass();
151: Class<?> clazz2 = o2.getClass();
152: if (clazz1 == clazz2) {
153: clazz = clazz1;
154: } else if (clazz1.isAssignableFrom(clazz2)) {
155: clazz = clazz1;
156: } else if (clazz2.isAssignableFrom(clazz1)) {
157: clazz = clazz2;
158: } else if (clazz1.isAssignableFrom(Comparable.class)
159: && clazz2.isAssignableFrom(Comparable.class)) {
160: clazz = Comparable.class;
161: } else {
162: clazz = Object.class;
163: }
164:
165: return compare(o1, o2, clazz, context);
166: }
167:
168: /**
169: * Compares the two objects. It will look up in <code>ObjectComparatorManager</code>
170: * to find the comparator and compare. This method needs a third parameter which is the data type.
171: * This is useful when you have two objects that have different data types but both extend
172: * the same super class. In this case, you may want the super class as the key to look up in
173: * <code>ObjectComparatorManager</code>.
174: *
175: * @param o1 the first object to be compared.
176: * @param o2 the second object to be compared.
177: * @param clazz the data type of the two objects. If your two objects have the same type, you may just use {@link #compare(Object,Object)} methods.
178: * @return the compare result as defined in {@link Comparator#compare(Object,Object)}
179: */
180: public static int compare(Object o1, Object o2, Class<?> clazz) {
181: return compare(o1, o2, clazz, ComparatorContext.DEFAULT_CONTEXT);
182: }
183:
184: /**
185: * Compares the two objects. It will look up in <code>ObjectComparatorManager</code>
186: * to find the comparator and compare. If it is not found, we will convert the object to
187: * string and compare the two strings.
188: *
189: * @param o1 the first object to be compared.
190: * @param o2 the second object to be compared.
191: * @param clazz the data type of the two objects. If your two objects have the same type, you may just use {@link #compare(Object,Object)} methods.
192: * @param context the comparator context
193: * @return the compare result as defined in {@link Comparator#compare(Object,Object)}
194: */
195: public static int compare(Object o1, Object o2, Class<?> clazz,
196: ComparatorContext context) {
197: Comparator comparator = getComparator(clazz, context);
198: if (comparator != null) {
199: return comparator.compare(o1, o2);
200: } else {
201: if (o1 == o2) {
202: return 0;
203: } else {
204: if (o1 == null) {
205: return -1;
206: } else if (o2 == null) {
207: return 1;
208: } else { // otherwise, compare as string
209: return o1.toString().compareTo(o2.toString());
210: }
211: }
212: }
213: }
214:
215: private static boolean _inited = false;
216: private static boolean _autoInit = true;
217:
218: /**
219: * Checks the value of autoInit.
220: *
221: * @return true or false.
222: * @see #setAutoInit(boolean)
223: */
224: public static boolean isAutoInit() {
225: return _autoInit;
226: }
227:
228: /**
229: * Sets autoInit to true or false. If autoInit is true, whenever someone tries to call methods like
230: * as toString or fromString, {@link #initDefaultComparator()} will be called if it has never be called.
231: * By default, autoInit is true.
232: * <p/>
233: * This might affect the behavior if users provide their own comparators and want to overwrite
234: * default comparators. In this case, instead of depending on autoInit to initialize default comparators,
235: * you should call {@link #initDefaultComparator()} first, then call registerComparator to add your own comparators.
236: *
237: * @param autoInit false if you want to disable autoInit which means you either don't
238: * want those default comparators registered or you will call {@link #initDefaultComparator()} yourself.
239: */
240: public static void setAutoInit(boolean autoInit) {
241: _autoInit = autoInit;
242: }
243:
244: /**
245: * Adds a listener to the list that's notified each time a change
246: * to the manager occurs.
247: *
248: * @param l the RegistrationListener
249: */
250: public static void addRegistrationListener(RegistrationListener l) {
251: _cache.addRegistrationListener(l);
252: }
253:
254: /**
255: * Removes a listener from the list that's notified each time a
256: * change to the manager occurs.
257: *
258: * @param l the RegistrationListener
259: */
260: public static void removeRegistrationListener(RegistrationListener l) {
261: _cache.removeRegistrationListener(l);
262: }
263:
264: /**
265: * Returns an array of all the registration listeners
266: * registered on this manager.
267: *
268: * @return all of this registration's <code>RegistrationListener</code>s
269: * or an empty array if no registration listeners are currently registered
270: * @see #addRegistrationListener
271: * @see #removeRegistrationListener
272: */
273: public static RegistrationListener[] getRegistrationListeners() {
274: return _cache.getRegistrationListeners();
275: }
276:
277: /**
278: * Gets the available ComparatorContexts registered with the class.
279: *
280: * @param clazz the class.
281: * @return the available ComparatorContext.
282: */
283: public static ComparatorContext[] getComparatorContexts(
284: Class<?> clazz) {
285: return _cache.getKeys(clazz, new ComparatorContext[0]);
286: }
287:
288: /**
289: * Initialize default comparator. Please make sure you call this method
290: * before you use any comparator related classes such as SortableTableModel.
291: */
292: public static void initDefaultComparator() {
293: if (_inited) {
294: return;
295: }
296:
297: registerComparator(Boolean.class, new BooleanComparator());
298: registerComparator(Calendar.class, new CalendarComparator());
299: NumberComparator numberComparator = new NumberComparator();
300: registerComparator(Number.class, numberComparator);
301: registerComparator(double.class, numberComparator);
302: registerComparator(float.class, numberComparator);
303: registerComparator(long.class, numberComparator);
304: registerComparator(int.class, numberComparator);
305: registerComparator(short.class, numberComparator);
306: registerComparator(Comparable.class,
307: new FastComparableComparator());
308: registerComparator(Object.class, new DefaultComparator());
309: registerComparator(String.class, Collator.getInstance());
310:
311: _inited = true;
312: }
313:
314: /**
315: * If {@link #initDefaultComparator()} is called once, calling it again will have no effect because an internal flag is set.
316: * This method will reset the internal flag so that you can call {@link #initDefaultComparator()} in case you unresgister all
317: * comparators using {@link #unregisterAllComparators()}.
318: */
319: public static void resetInit() {
320: _inited = false;
321: }
322:
323: // public static void main(String[] args) {
324: // ObjectComparatorManager.initDefaultComparator();
325: // Comparator comparator = ObjectComparatorManager.getComparator(Information.class);
326: // System.out.println(comparator.getClass().getName());
327: // }
328: //
329: // private static class Information implements Comparable {
330: // public int compareTo(Object o) {
331: // return 0;
332: // }
333: // }
334: }
|