/* * Copyright 2014 (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.cdom.content.factset; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import pcgen.base.util.Indirect; import pcgen.base.util.ObjectContainer; import pcgen.cdom.base.CDOMObject; import pcgen.rules.context.AbstractReferenceContext; import pcgen.rules.context.LoadContext; /** * A FactSetGroup is an ObjectContainer that contains objects of a specific type * (e.g. Skill) that contain a specific value in a given FACTSET * * @param <T> * The Type of object contained in this FactSetGroup * @param <F> * The Type of the FactSet being checked in this FactSetGroup */ public class FactSetGroup<T extends CDOMObject, F> implements ObjectContainer<T> { /** * Contains the underlying FactSetInfo for this FactSetGroup (identifying * the "rules of the road") */ private final FactSetInfo<T, F> def; /** * The Indirect containing the fact to be matched */ private final Indirect<F> toMatch; /** * The ObjectContainer containing all of the objects of the type of object * where this FactSetGroup (and thus the FactInfo) are usable */ private final ObjectContainer<T> allObjects; /** * The cached answers for this FactSetGroup. * * Note that this cache can exist because these items are facts, and thus * semantically can't change. There is also the assumption that the global * list of objects cannot change. */ private List<T> cache; /** * Constructs a new FactSetGroup from the given context, FactSetInfo and * value. * * @param context * The LoadContext used to resolve references * @param fsi * The FactSetInfo indicating the underlying characteristics of * the Fact that this FactSetGroup will check * @param value * The String representation of the value that this FactSetGroup * will be looking for */ public FactSetGroup(LoadContext context, FactSetInfo<T, F> fsi, String value) { if (fsi.getUsableLocation().equals(CDOMObject.class)) { throw new IllegalArgumentException("FactSetGroup cannot be global"); } def = fsi; AbstractReferenceContext refContext = context.getReferenceContext(); allObjects = refContext.getCDOMAllReference(def.getUsableLocation()); toMatch = def.getFormatManager().convertIndirect(value); if (toMatch == null) { throw new IllegalArgumentException("Failed to convert " + value + " as a " + def.getFormatManager().getManagedClass().getSimpleName()); } } /** * @see pcgen.base.util.ObjectContainer#getContainedObjects() */ @Override public Collection<T> getContainedObjects() { if (cache == null) { List<T> setupCache = new ArrayList<>(); for (T obj : allObjects.getContainedObjects()) { if (contains(obj)) { setupCache.add(obj); } } cache = setupCache; } return Collections.unmodifiableCollection(cache); } /** * @see pcgen.base.util.ObjectContainer#getLSTformat(boolean) */ @Override public String getLSTformat(boolean useAny) { return def.getFactSetName() + "=" + def.getFormatManager().unconvert(toMatch.get()); } /** * @see pcgen.base.util.ObjectContainer#contains(java.lang.Object) */ @Override public boolean contains(T obj) { List<Indirect<F>> factset = obj.getSetFor(def.getFactSetKey()); if (factset != null) { F tgt = toMatch.get(); for (Indirect<F> indirect : factset) { if (indirect.get().equals(tgt)) { return true; } } } return false; } /** * @see pcgen.base.util.ObjectContainer#getReferenceClass() */ @Override public Class<T> getReferenceClass() { return allObjects.getReferenceClass(); } }