001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010:
011: package org.mmbase.util;
012:
013: import java.util.*;
014: import org.mmbase.module.core.*;
015:
016: /**
017: * This class implements the Comparator interface for comparing MMObjectNodes.
018: * At forhand you specify in which fields a specified nodes should be compared,
019: * these fields may not have a null value.
020: *
021: * @application Tools
022: * @author Pierre van Rooden
023: * @version $Id: NodeComparator.java,v 1.6 2004/10/12 11:17:44 pierre Exp $
024: */
025: public class NodeComparator implements Comparator {
026:
027: public final static String UP = "UP";
028: public final static String DOWN = "DOWN";
029:
030: /**
031: * @todo Should be List, not Vector
032: */
033: private Vector fields;
034: /**
035: * @todo Should be List, not Vector
036: */
037: private Vector sortDirs;
038:
039: /**
040: * Simple constructor that uses the default sort order (UP).
041: * @param fields the fields on which the message nodes get compared.
042: */
043: public NodeComparator(Vector fields) {
044: this .fields = fields;
045: sortDirs = new Vector(fields.size());
046: }
047:
048: /**
049: * Constructor in which you spercify the sort order (UP or DOWN) per field.
050: * @param fields the fields on which the message nodes get compared.
051: * @param sortDirs the sort directions (UP or DOWN) for each field.
052: */
053: public NodeComparator(Vector fields, Vector sortDirs) {
054: this .fields = fields;
055: this .sortDirs = sortDirs;
056: for (int i = sortDirs.size(); i < fields.size(); i++) {
057: sortDirs.add(UP);
058: }
059: }
060:
061: /**
062: * The two message nodes will be compared using the compare function of
063: * the values of their fields.
064: * Only Comparable values can be used (String, Numbers, Date), as well as
065: * Boolean values.
066: * In other cases it's assumed that the values cannot be ordered.
067: * <br />
068: * Note: this class assumes that values in fields are of similar types
069: * (comparable to each other).
070: *
071: * @param o1 the first object to compare
072: * @param o2 the second object to compare
073: * @return 0 if both objects are equal, -1 if object 1 is 'less than'
074: * object 2, and +1 if object 1 is 'greater than' object 2.
075: */
076: public int compare(Object o1, Object o2) {
077: Object f1, f2;
078: int result = 0;
079: int fieldnr = 0;
080: String field;
081: while ((result == 0) && (fieldnr < fields.size())) {
082: field = (String) fields.elementAt(fieldnr);
083: f1 = ((MMObjectNode) o1).getValue(field);
084: f2 = ((MMObjectNode) o2).getValue(field);
085: if (f1 instanceof Comparable) {
086: try {
087: result = ((Comparable) f1).compareTo(f2);
088: } catch (ClassCastException e) {
089: // types do not compare -
090: // possibly the in-memory value type differs from the
091: // database value type (this can occur if you use setValue
092: // with a deviating type).
093: // Solving this coukld bring this compare to a crawl, so we
094: // don't. Just edit stuff the right way.
095: }
096: } else if (!f1.equals(f2)) {
097: if (f1 instanceof Boolean) {
098: result = ((Boolean) f1).booleanValue() ? 1 : -1;
099: }
100: }
101: fieldnr++;
102: }
103: if ((fieldnr > 0)
104: && (fieldnr <= sortDirs.size())
105: && ((String) sortDirs.elementAt(fieldnr - 1))
106: .equals(DOWN)) {
107: result = -result;
108: }
109: return result;
110: }
111:
112: /**
113: * Returns whether another object is equal to this comparator (that is,
114: * compare the same fields in the same order).
115: * @param obj the object to compare
116: * @return <code>true</code> if the objects are equal
117: * @throws ClassCastException
118: */
119: public boolean equals(Object obj) {
120: if (obj instanceof NodeComparator) {
121: return (obj.hashCode() == hashCode());
122: } else {
123: throw new ClassCastException();
124: }
125: }
126:
127: /**
128: * Returns the comparator's hash code.
129: */
130: public int hashCode() {
131: return fields.hashCode() ^ sortDirs.hashCode();
132: }
133: }
|