/*
* Mission.java
*
* Copyright (c) 2011 Jay Lawson <jaylawson39 at yahoo.com>. All rights reserved.
*
* This file is part of MekHQ.
*
* MekHQ is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MekHQ 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MekHQ. If not, see <http://www.gnu.org/licenses/>.
*/
package mekhq.campaign.mission;
import java.io.PrintWriter;
import java.io.Serializable;
import java.text.ParseException;
import java.util.ArrayList;
import mekhq.MekHQ;
import mekhq.MekHqXmlSerializable;
import mekhq.MekHqXmlUtil;
import mekhq.Version;
import mekhq.campaign.Campaign;
import mekhq.campaign.universe.Planet;
import mekhq.campaign.universe.Planets;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Missions are primarily holder objects for a set of scenarios.
*
* The really cool stuff will happen when we subclass this into Contract
*
* @author Jay Lawson <jaylawson39 at yahoo.com>
*/
public class Mission implements Serializable, MekHqXmlSerializable {
/**
*
*/
private static final long serialVersionUID = -5692134027829715149L;
public static final int S_ACTIVE = 0;
public static final int S_SUCCESS = 1;
public static final int S_FAILED = 2;
public static final int S_BREACH = 3;
public static final int S_NUM = 4;
private String name;
protected String planetName;
private int status;
private String desc;
private String type;
private ArrayList<Scenario> scenarios;
private int id = -1;
public Mission() {
this(null);
}
public Mission(String n) {
this.name = n;
this.planetName = "Unknown Planet";
this.desc = "";
this.type = "";
this.status = S_ACTIVE;
scenarios = new ArrayList<Scenario>();
}
public static String getStatusName(int s) {
switch(s) {
case S_ACTIVE:
return "Active";
case S_SUCCESS:
return "Success";
case S_FAILED:
return "Failed";
case S_BREACH:
return "Contract Breach";
default:
return "?";
}
}
public String getName() {
return name;
}
public void setName(String n) {
this.name = n;
}
public String getType() {
return type;
}
public void setType(String t) {
this.type = t;
}
public String getPlanetName() {
return planetName;
}
public void setPlanetName(String n) {
this.planetName = n;
}
public Planet getPlanet() {
return Planets.getInstance().getPlanetById(planetName);
}
public String getDescription() {
return desc;
}
public void setDesc(String d) {
this.desc = d;
}
public int getStatus() {
return status;
}
public void setStatus(int s) {
this.status = s;
}
public String getStatusName() {
return getStatusName(getStatus());
}
public ArrayList<Scenario> getScenarios() {
return scenarios;
}
/**
* Don't use this method directly as it will not
* add an id to the added scenario. Use Campaign#AddScenario instead
* @param s
*/
public void addScenario(Scenario s) {
s.setMissionId(getId());
scenarios.add(s);
}
public int getId() {
return id;
}
public void setId(int i) {
this.id = i;
}
public boolean isActive() {
return status ==S_ACTIVE;
}
public void removeScenario(int id) {
int idx = 0;
boolean found = false;
for(Scenario s : getScenarios()) {
if(s.getId() == id) {
found = true;
break;
}
idx++;
}
if(found) {
scenarios.remove(idx);
}
}
public void clearScenarios() {
scenarios.clear();
}
public boolean hasPendingScenarios() {
for(Scenario s : scenarios) {
if(s.isCurrent()) {
return true;
}
}
return false;
}
public void writeToXml(PrintWriter pw1, int indent) {
writeToXmlBegin(pw1, indent);
writeToXmlEnd(pw1, indent);
}
protected void writeToXmlBegin(PrintWriter pw1, int indent) {
pw1.println(MekHqXmlUtil.indentStr(indent) + "<mission id=\""
+id
+"\" type=\""
+this.getClass().getName()
+"\">");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<name>"
+MekHqXmlUtil.escape(name)
+"</name>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<type>"
+MekHqXmlUtil.escape(type)
+"</type>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<planetName>"
+MekHqXmlUtil.escape(planetName)
+"</planetName>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<status>"
+status
+"</status>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<desc>"
+MekHqXmlUtil.escape(desc)
+"</desc>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<id>"
+id
+"</id>");
pw1.println(MekHqXmlUtil.indentStr(indent+1) + "<scenarios>");
for(Scenario s : scenarios) {
s.writeToXml(pw1, indent+2);
}
pw1.println(MekHqXmlUtil.indentStr(indent+1) + "</scenarios>");
}
protected void writeToXmlEnd(PrintWriter pw1, int indent) {
pw1.println(MekHqXmlUtil.indentStr(indent) + "</mission>");
}
public void loadFieldsFromXmlNode(Node wn) throws ParseException {
//do nothing
}
public static Mission generateInstanceFromXML(Node wn, Campaign c, Version version) {
Mission retVal = null;
NamedNodeMap attrs = wn.getAttributes();
Node classNameNode = attrs.getNamedItem("type");
String className = classNameNode.getTextContent();
try {
// Instantiate the correct child class, and call its parsing function.
retVal = (Mission) Class.forName(className).newInstance();
retVal.loadFieldsFromXmlNode(wn);
// Okay, now load mission-specific fields!
NodeList nl = wn.getChildNodes();
for (int x=0; x<nl.getLength(); x++) {
Node wn2 = nl.item(x);
if (wn2.getNodeName().equalsIgnoreCase("name")) {
retVal.name = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("planetName")) {
retVal.planetName = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("status")) {
retVal.status = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("id")) {
retVal.id = Integer.parseInt(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("desc")) {
retVal.setDesc(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("type")) {
retVal.setType(wn2.getTextContent());
} else if (wn2.getNodeName().equalsIgnoreCase("scenarios")) {
NodeList nl2 = wn2.getChildNodes();
for (int y=0; y<nl2.getLength(); y++) {
Node wn3 = nl2.item(y);
// If it's not an element node, we ignore it.
if (wn3.getNodeType() != Node.ELEMENT_NODE)
continue;
if (!wn3.getNodeName().equalsIgnoreCase("scenario")) {
// Error condition of sorts!
// Errr, what should we do here?
MekHQ.logMessage("Unknown node type not loaded in Scenario nodes: "+wn3.getNodeName());
continue;
}
Scenario s = Scenario.generateInstanceFromXML(wn3, c, version);
retVal.addScenario(s);
}
}
}
} catch (Exception ex) {
// Errrr, apparently either the class name was invalid...
// Or the listed name doesn't exist.
// Doh!
MekHQ.logError(ex);
}
return retVal;
}
}