/* * Copyright 2009 (C) Tom Parker <thpr@users.sourceforge.net> * * 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; either version 2.1 of the License, or (at your option) * any later version. * * 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. * * 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., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package pcgen.rules.context; import java.net.URI; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.WeakHashMap; import pcgen.base.util.DoubleKeyMapToList; import pcgen.cdom.base.CDOMReference; import pcgen.cdom.base.Categorized; import pcgen.cdom.base.Category; import pcgen.cdom.base.Loadable; import pcgen.cdom.reference.ManufacturableFactory; import pcgen.cdom.reference.ReferenceManufacturer; import pcgen.cdom.reference.UnconstructedEvent; import pcgen.cdom.reference.UnconstructedListener; import pcgen.util.Logging; public class TrackingReferenceContext extends RuntimeReferenceContext implements UnconstructedListener { private final DoubleKeyMapToList<CDOMReference<?>, URI, String> track = new DoubleKeyMapToList<>(WeakHashMap.class, HashMap.class); private final Set<ReferenceManufacturer<?>> listening = new HashSet<>(); @Override public <T extends Categorized<T>> ReferenceManufacturer<T> getManufacturer( Class<T> cl, Category<T> cat) { ReferenceManufacturer<T> mfg = super.getManufacturer(cl, cat); if (mfg instanceof TrackingManufacturer) { return mfg; } if (!listening.contains(mfg)) { mfg.addUnconstructedListener(this); listening.add(mfg); } return new TrackingManufacturer<>(this, mfg); } @Override public <T extends Loadable> ReferenceManufacturer<T> getManufacturer( Class<T> cl) { ReferenceManufacturer<T> mfg = super.getManufacturer(cl); if (mfg instanceof TrackingManufacturer) { return mfg; } if (!listening.contains(mfg)) { mfg.addUnconstructedListener(this); listening.add(mfg); } return new TrackingManufacturer<>(this, mfg); } @Override public <T extends Loadable> ReferenceManufacturer<T> getManufacturer( ManufacturableFactory<T> factory) { ReferenceManufacturer<T> mfg = super.getManufacturer(factory); if (mfg instanceof TrackingManufacturer) { return mfg; } if (!listening.contains(mfg)) { mfg.addUnconstructedListener(this); listening.add(mfg); } return new TrackingManufacturer<>(this, mfg); } @Override public void unconstructedReferenceFound(UnconstructedEvent e) { CDOMReference<?> ref = e.getReference(); Set<URI> uris = track.getSecondaryKeySet(ref); if (uris == null) { // Shouldn't happen, but this is reporting, not critical, so be safe return; } for (URI uri : uris) { List<String> tokens = track.getListFor(ref, uri); Set<String> tokenNames = new TreeSet<>(); for (String tok : tokens) { if (tok != null) { tokenNames.add(tok); } } Logging.errorPrint(" Was used in " + uri + " in tokens: " + tokenNames); } } private String getSource() { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); String source = null; for (int i = 0; i < stackTrace.length; i++) { String className = stackTrace[i].getClassName(); if (className.startsWith("plugin.lsttokens")) { source = className; break; } } return source; } protected <T> void trackReference(CDOMReference<T> ref) { String src = getSource(); if (src == null) { src = "?"; } track.addToListFor(ref, getSourceURI(), src); } }