/*
* Copyright (c) Thomas Parker, 2013.
*
* 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 pcgen.gui2.facade;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import pcgen.base.lang.StringUtil;
import pcgen.base.util.HashMapToList;
import pcgen.cdom.base.CDOMObject;
import pcgen.cdom.base.CDOMReference;
import pcgen.cdom.base.Identified;
import pcgen.cdom.base.PrereqObject;
import pcgen.cdom.enumeration.CharID;
import pcgen.cdom.meta.CorePerspective;
import pcgen.cdom.meta.CorePerspectiveDB;
import pcgen.cdom.meta.CoreViewNodeBase;
import pcgen.cdom.meta.FacetView;
import pcgen.core.PlayerCharacter;
import pcgen.core.QualifiedObject;
import pcgen.facade.core.CoreViewNodeFacade;
import pcgen.core.prereq.PrerequisiteUtilities;
import pcgen.util.Logging;
public class CoreUtils
{
public static <T> List<CoreViewNodeFacade> buildCoreDebugList(PlayerCharacter pc,
CorePerspective pers)
{
CharID id = pc.getCharID();
List<CoreViewNodeFacade> coreViewList = new ArrayList<>();
Collection<Object> locations = CorePerspectiveDB.getLocations(pers);
HashMapToList<Object, FacetView<T>> sources =
new HashMapToList<>();
Map<FacetView<T>, CoreViewNodeBase> facetToNode =
new HashMap<>();
/*
* Create the nodes that are part of this perspective.
*/
for (Object location : locations)
{
//Create (w/ identifier)
FacetView<T> view = CorePerspectiveDB.getView(pers, location);
LocationCoreViewNode<T> node =
new LocationCoreViewNode<>(location);
facetToNode.put(view, node);
coreViewList.add(node);
//Store what facets listen to my content (for use later)
for (Object listener : view.getChildren())
{
Object lView = CorePerspectiveDB.getViewOfFacet(listener);
Object src = (lView == null) ? listener : lView;
sources.addToListFor(src, view);
}
Collection<Object> parents = CorePerspectiveDB.getVirtualParents(view);
if (parents != null)
{
for (Object parent : parents)
{
FacetView<T> parentView = CorePerspectiveDB.getViewOfFacet(parent);
if (parentView == null)
{
Logging.errorPrint("Expected " + parent
+ " to be a registered Facet in Perspective " + pers);
}
sources.addToListFor(view, parentView);
}
}
}
for (Object location : locations)
{
FacetView<T> view = CorePerspectiveDB.getView(pers, location);
CoreViewNodeBase node = facetToNode.get(view);
/*
* Check the source of each child to identify if:
*
* (a) The source is a Loadable that can thus be identified as such
*
* (b) The source is a known facet (and thus is identified as such)
*
* (c) the source is not something recognized
*/
for (T obj : view.getSet(id))
{
List<String> sourceDesc = new ArrayList<>();
for (Object src : view.getSources(id, obj))
{
if (src instanceof Identified)
{
sourceDesc.add(getLoadID(src));
}
else
{
FacetView<Object> srcView =
CorePerspectiveDB.getViewOfFacet(src);
if (srcView == null)
{
//Not a recognized view
sourceDesc.add("Orphaned ["
+ src.getClass().getSimpleName() + "]");
}
else if (facetToNode.get(srcView) == null)
{
//A View, but not part of this perspective
sourceDesc.add("Other Perspective ["
+ CorePerspectiveDB.getPerspectiveOfFacet(src)
+ ": " + srcView.getDescription() + "]");
}
}
}
//Insert the contents of the facet as children of this node
ObjectCoreViewNode<T> sourceNode =
new ObjectCoreViewNode<>(pc, obj, sourceDesc);
sourceNode.addGrantedByNode(node);
coreViewList.add(sourceNode);
}
}
/*
* For each location, put sources as children in the tree
*/
for (Object location : locations)
{
FacetView<T> view = CorePerspectiveDB.getView(pers, location);
CoreViewNodeBase node = facetToNode.get(view);
List<FacetView<T>> facetInputs = sources.getListFor(view);
if (facetInputs != null)
{
for (FacetView<T> facet : facetInputs)
{
facetToNode.get(facet).addGrantedByNode(node);
}
}
}
return coreViewList;
}
private static <T> String getLoadID(T obj)
{
if (obj instanceof Identified)
{
Identified l = (Identified) obj;
String name = l.getDisplayName();
String id = obj.getClass().getSimpleName() + ": " + name;
if (!l.getKeyName().equals(name))
{
id = id + " [" + l.getKeyName() + "]";
}
return id;
}
else if (obj instanceof QualifiedObject)
{
QualifiedObject<?> qo = (QualifiedObject<?>) obj;
return getLoadID(qo.getRawObject());
}
else if (obj instanceof CDOMReference)
{
CDOMReference<?> ref = (CDOMReference<?>) obj;
return ref.getReferenceClass().getSimpleName() + " Primitive: "
+ ref.getLSTformat(false);
}
else
{
return obj.getClass().getSimpleName() + ": " + obj.toString();
}
}
private static String getRequirementsInfo(PlayerCharacter pc, Object object)
{
if (object instanceof PrereqObject)
{
CDOMObject source = null;
if (object instanceof CDOMObject)
{
source = ((CDOMObject) object);
}
return PrerequisiteUtilities.preReqHTMLStringsForList(pc, source,
((PrereqObject) object).getPrerequisiteList(), true);
}
return "";
}
private static class LocationCoreViewNode<T> extends CoreViewNodeBase
{
private final Object object;
/**
* Create a new instance of CoreUtils.LocationCoreViewNode
*/
public LocationCoreViewNode(Object object)
{
this.object = object;
}
@Override
public String getNodeType()
{
return "Location";
}
@Override
public String getKey()
{
return object.toString();
}
@Override
public String getSource()
{
return "";
}
@Override
public String getRequirements()
{
return "";
}
@Override
public String toString()
{
return getLoadID(object);
}
}
private static class ObjectCoreViewNode<T> extends CoreViewNodeBase
{
private final T object;
private final List<String> sourceDesc;
private final PlayerCharacter pc;
/**
* Create a new instance of CoreUtils.LocationCoreViewNode
*/
public ObjectCoreViewNode(PlayerCharacter pc, T object, List<String> sourceDesc)
{
this.pc = pc;
this.object = object;
this.sourceDesc = sourceDesc;
}
@Override
public String getNodeType()
{
return "Source";
}
@Override
public String getKey()
{
if (object instanceof CDOMObject)
{
return ((CDOMObject) object).getKeyName();
}
return object.toString();
}
@Override
public String getSource()
{
return StringUtil.join(sourceDesc, ", ");
}
@Override
public String getRequirements()
{
return CoreUtils.getRequirementsInfo(pc, object);
}
@Override
public String toString()
{
return getLoadID(object);
}
}
}