/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2002-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2009-2012, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.factory; import java.util.Set; import java.util.Map; import java.util.Objects; import java.awt.RenderingHints; /** * Compares two factories for equality. * Used internally for {@link Factory#equals} implementation only. * * @author Martin Desruisseaux (IRD) * @version 3.00 * * @since 2.1 * @module */ final class FactoryComparator { /** * A pair of factory already compared. */ private final Factory f1, f2; /** * Prepares a comparison between the two specified factories. */ FactoryComparator(final Factory f1, final Factory f2) { this.f1 = f1; this.f2 = f2; } /** * Returns {@code true} if {@code f1} and {@code f2} are equals. * * @param done An initially empty set. Used internally for preventing infinite recursivity. */ boolean compare(final Set<FactoryComparator> done) { if (done.add(this)) { final Map<RenderingHints.Key, ?> m1 = f1.getImplementationHints(); final Map<RenderingHints.Key, ?> m2 = f2.getImplementationHints(); if (m1.size() != m2.size()) { return false; } for (final Map.Entry<RenderingHints.Key, ?> entry : m1.entrySet()) { final Object key = entry.getKey(); final Object v1 = entry.getValue(); final Object v2 = m2.get(key); if (v1 == v2) continue; if (v1 instanceof Factory) { if (v2 == null || v1.getClass() != v2.getClass() || !new FactoryComparator((Factory) v1, (Factory) v2).compare(done)) { return false; } } else if (!Objects.equals(v1, v2)) { return false; } } } return true; } /** * For internal use only. This implementation assumes that {@code f1.equals(f2)} * is symmetric (i.e. equivalents to {@code f2.equals(f1)}). */ @Override public boolean equals(final Object object) { if (object instanceof FactoryComparator) { final FactoryComparator that = (FactoryComparator) object; return (this.f1 == that.f1 && this.f2 == that.f2) || (this.f1 == that.f2 && this.f2 == that.f1); } return false; } /** * For internal use only. Must be compatible with the symmetry assumption made in * {@link #equals(Object)}: use a commutative operation (addition here) and do not * multiply a term by some factor like the usual 31. */ @Override public int hashCode() { return System.identityHashCode(f1) + System.identityHashCode(f2); } }