001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.factory;
017:
018: // J2SE dependencies
019: import java.util.Set;
020: import java.util.Map;
021: import java.util.Iterator;
022:
023: // Geotools dependencies
024: import org.geotools.resources.Utilities;
025:
026: /**
027: * Compares two factories for equality.
028: * Used internally for {@link AbstractFactory#equals} implementation only.
029: *
030: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/metadata/src/main/java/org/geotools/factory/FactoryComparator.java $
031: * @version $Id: FactoryComparator.java 22443 2006-10-27 20:47:22Z desruisseaux $
032: * @author Martin Desruisseaux
033: */
034: final class FactoryComparator {
035: /**
036: * A pair of factory already compared.
037: */
038: private final Factory f1, f2;
039:
040: /**
041: * Prepare a comparaison between the two specified factories.
042: */
043: FactoryComparator(final Factory f1, final Factory f2) {
044: this .f1 = f1;
045: this .f2 = f2;
046: }
047:
048: /**
049: * Returns {@code true} if {@code f1} and {@code f2} are equals.
050: *
051: * @param done An initially empty set. Used internally for preventing infinite recursivity.
052: */
053: boolean compare(final Set done) {
054: if (done.add(this )) {
055: final Map m1 = f1.getImplementationHints();
056: final Map m2 = f2.getImplementationHints();
057: if (m1.size() != m2.size()) {
058: return false;
059: }
060: for (final Iterator it = m1.entrySet().iterator(); it
061: .hasNext();) {
062: final Map.Entry entry = (Map.Entry) it.next();
063: final Object key = entry.getKey();
064: final Object v1 = entry.getValue();
065: final Object v2 = m2.get(key);
066: if (v1 == v2)
067: continue;
068: if (v1 instanceof Factory) {
069: if (v2 == null
070: || !v1.getClass().equals(v2.getClass())
071: || !new FactoryComparator((Factory) v1,
072: (Factory) v2).compare(done)) {
073: return false;
074: }
075: } else if (!Utilities.equals(v1, v2)) {
076: return false;
077: }
078: }
079: }
080: return true;
081: }
082:
083: /**
084: * For internal use only. This implementation assumes that {@code f1.equals(f2)}
085: * is symetric (i.e. equivalents to {@code f2.equals(f1)}).
086: */
087: public boolean equals(final Object object) {
088: if (object instanceof FactoryComparator) {
089: final FactoryComparator that = (FactoryComparator) object;
090: return (this .f1 == that.f1 && this .f2 == that.f2)
091: || (this .f1 == that.f2 && this .f2 == that.f1);
092: }
093: return false;
094: }
095:
096: /**
097: * For internal use only. Must be compatible with the symetry assumption made in
098: * {@link #equals(Object)}: use a commutative operation (addition here) and do not
099: * multiply a term by some factor like the usual 37.
100: */
101: public int hashCode() {
102: return System.identityHashCode(f1)
103: + System.identityHashCode(f2);
104: }
105: }
|