package vooga.towerdefense.gameeditor.gameloader.xmlloaders;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Element;
import util.XMLTool;
import vooga.towerdefense.action.Action;
import vooga.towerdefense.factories.actionfactories.ActionFactory;
import vooga.towerdefense.gameelements.GameElement;
import vooga.towerdefense.model.GameMap;
import vooga.towerdefense.model.Player;
/**
* This class is responsible for loading Action objects
* from an XML file.
*
* @author Erick Gonzalez
*/
public class ActionXMLLoader {
private static final String PARAMETERS_TAG = "parameter";
private static final String WAVE_ACTION_FACTORIES_CLASSPATH =
"vooga.towerdefense.factories.waveactionfactories.";
private static final String ACTION_FACTORIES_CLASSPATH =
"vooga.towerdefense.factories.actionfactories.";
private static final String WAVE = "Wave";
private static final String FACTORY = "Factory";
private XMLTool myXMLTool;
/**
*
* @param xmlTool an XMLTool containing the xml document
*/
public ActionXMLLoader (XMLTool xmlTool) {
myXMLTool = xmlTool;
}
/**
* Given an XML element representing the <actions> tag, returns
* a List of Action objects under this tag. Because no
* GameElement parameter is specified, these actions do not
* act on a specific GameElement.
*
* @param actionsElement the xml element for the <actions> tag
* @param gameMap a game map
* @param player a player object
* @return a list of actions under the actionsElement
*/
public List<Action> loadActions (Element actionsElement, GameMap gameMap, Player player) {
return loadActions(null, actionsElement, gameMap, player);
}
/**
* Given an XML element representing the <actions> tag, returns a List of
* Action objects under this tag. Because a GameElement parameter is specified,
* these actions will act on this specified GameElement object.
*
* @param e a game element upon which the list of actions will act on
* @param actionsElement the XML element represening the <actions> tag
* @param gameMap a game map object
* @param player a player object
* @return a list of actions acting on the given GameElement
*/
public List<Action> loadActions (GameElement e, Element actionsElement, GameMap gameMap,
Player player) {
List<ActionFactory> actionFactories = loadActionFactories(actionsElement, gameMap, player);
List<Action> actions = new ArrayList<Action>();
for (ActionFactory af : actionFactories) {
actions.add(af.createAction(e));
}
return actions;
}
/**
* Given an XML element representing the <actions> tag, returns a List of
* ActionFactory objects under this tag.
*
* @param actionsElement the XML element representing the <actions> tag
* @param gameMap a game map object
* @param player a player object
* @return a list of ActionFactory objects acting on the given GameElement
*/
public List<ActionFactory> loadActionFactories (Element actionsElement, GameMap gameMap,
Player player) {
List<Element> subElements = myXMLTool.getChildrenList(actionsElement);
List<ActionFactory> actionFactories = new ArrayList<ActionFactory>();
for (Element e : subElements) {
actionFactories.add(loadActionFactory(e, gameMap, player));
}
return actionFactories;
}
@SuppressWarnings("rawtypes")
private ActionFactory loadActionFactory (Element actionElement, GameMap gameMap, Player player) {
String actionName = myXMLTool.getTagName(actionElement);
List<String> parameterStrings = new ArrayList<String>();
List<ActionFactory> subActionFactories = new ArrayList<ActionFactory>();
List<Element> subElements = myXMLTool.getChildrenList(actionElement);
for (Element subElement: subElements) {
String subElementName = myXMLTool.getTagName(subElement);
if (subElementName.equals(PARAMETERS_TAG)) {
parameterStrings.add(loadParameterString(subElement));
}
else {
subActionFactories.add(loadActionFactory(subElement, gameMap, player));
}
}
try {
String classPath = "";
if (actionName.contains(WAVE)) {
classPath = WAVE_ACTION_FACTORIES_CLASSPATH;
}
else {
classPath = ACTION_FACTORIES_CLASSPATH;
}
classPath += actionName + FACTORY;
Class actionFactoryClass = Class.forName(classPath);
Constructor[] constructors = actionFactoryClass.getDeclaredConstructors();
// ActionFactory objects have only one constructor
Constructor constructor = constructors[0];
ActionFactory af = (ActionFactory) constructor.newInstance(parameterStrings.toArray());
af.addFollowUpActionsFactories(subActionFactories);
af.initialize(gameMap, player);
return af;
}
catch (InstantiationException e) {
return null;
}
catch (IllegalAccessException e) {
return null;
}
catch (IllegalArgumentException e) {
return null;
}
catch (InvocationTargetException e) {
return null;
}
catch (ClassNotFoundException e) {
return null;
}
}
private String loadParameterString (Element parameterElement) {
return myXMLTool.getContent(parameterElement);
}
}