/* * Copyright (c) 2010-13 Tom Parker <thpr@users.sourceforge.net> * * This program 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; either version 2.1 of the License, or (at your option) * any later version. * * This program 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. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package compare; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Map; import java.util.Set; import pcgen.base.formula.inst.ScopeInstanceFactory; import pcgen.base.formula.inst.SimpleVariableStore; import pcgen.base.lang.StringUtil; import pcgen.base.solver.AggressiveSolverManager; import pcgen.base.test.InequalityTester; import pcgen.cdom.facet.model.ClassFacet; import pcgen.cdom.formula.MonitorableVariableStore; import pcgen.core.PlayerCharacter; import pcgen.core.SpellSupportForPCClass; public final class InequalityTesterInst implements InequalityTester { private static InequalityTester instance; private static final Map<Class<?>, InequalityTest> INEQ_MAP = new HashMap<>(); static { INEQ_MAP.put(Collection.class, new CollectionInequality()); INEQ_MAP.put(Map.class, new MapInequality()); INEQ_MAP.put(WeakReference.class, new WeakReferenceInequality()); INEQ_MAP.put(IdentityHashMap.class, new IdentityHashMapInequality()); INEQ_MAP.put(ClassFacet.ClassInfo.class, new ClassFacetInfoInequality()); INEQ_MAP.put(PlayerCharacter.class, new IgnoreInequality()); INEQ_MAP.put(SpellSupportForPCClass.class, new IgnoreInequality()); INEQ_MAP.put(ScopeInstanceFactory.class, new IgnoreInequality()); INEQ_MAP.put(AggressiveSolverManager.class, new IgnoreInequality()); //TODO SimpleVariableStore should not be ignored - but needs (hard?) custom comparator due to scopes... INEQ_MAP.put(SimpleVariableStore.class, new IgnoreInequality()); //TODO MonitorableVariableStore should not be ignored - but needs (hard?) custom comparator due to scopes... INEQ_MAP.put(MonitorableVariableStore.class, new IgnoreInequality()); } @Override public String testEquality(Object o1, Object o2, String location) { if (o1 == null) { if (o2 == null) { return null; } else { return "@" + location + ": o1 is null, o2 is a " + o2.getClass().getCanonicalName(); } } if (o2 == null) { return "@IT=" + location + "o1 is a " + o1.getClass().getCanonicalName() + ", o2 is null"; } Class<?> c1 = o1.getClass(); Class<?> c2 = o2.getClass(); Collection<String> reasons = new ArrayList<>(); if (c1.equals(c2)) { if (INEQ_MAP.containsKey(c1)) { return runTest(c1, o1, o2, location + "/" + c1); } else { if (o1.equals(o2)) { return null; } reasons.add("@IT=" + location + "/" + c1.getCanonicalName() + " objects not equal: " + o1 + " " + o2); } } else { reasons.add("@IT=" + location + "/" + c1 + " not same class as " + c2); } Set<Class<?>> ifs1 = getInterfaces(c1); Set<Class<?>> ifs2 = getInterfaces(c2); for (Class<?> if1 : ifs1) { for (Class<?> if2 : ifs2) { if (if1.equals(if2) && INEQ_MAP.containsKey(if1)) { String rt = runTest(if1, o1, o2, location + "/" + c1 + " as " + if1); if (rt == null) { return null; } else { reasons.add(rt); } } } } return reasons.isEmpty() ? null : StringUtil.join(reasons, "\n"); } private static Set<Class<?>> getInterfaces(Class<?> c1) { Set<Class<?>> if1 = new HashSet<>(Arrays.asList(c1.getInterfaces())); Class<?> sc = c1.getSuperclass(); if (sc != null) { if1.addAll(getInterfaces(sc)); } return if1; } @SuppressWarnings("unchecked") private <T> String runTest(Class<T> c1, Object o1, Object o2, String context) { return INEQ_MAP.get(c1).testInequality(o1, o2, this, context); } public static synchronized InequalityTester getInstance() { if (instance == null) { instance = new InequalityTesterInst(); } return instance; } }