package forge.quest.data;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.mapper.MapperWrapper;
import forge.error.ErrorViewer;
import forge.properties.ForgeProps;
import forge.properties.NewConstants;
import forge.quest.data.item.QuestInventory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* <p>QuestDataIO class.</p>
*
* @author Forge
* @version $Id: $
*/
public class QuestDataIO {
/**
* <p>Constructor for QuestDataIO.</p>
*/
public QuestDataIO() {
}
/**
* <p>loadData.</p>
*
* @return a {@link forge.quest.data.QuestData} object.
*/
public static QuestData loadData() {
try {
//read file "questData"
QuestData data = null;
File xmlSaveFile = ForgeProps.getFile(NewConstants.QUEST.XMLDATA);
GZIPInputStream zin =
new GZIPInputStream(new FileInputStream(xmlSaveFile));
StringBuilder xml = new StringBuilder();
char[] buf = new char[1024];
InputStreamReader reader = new InputStreamReader(zin);
while (reader.ready()) {
int len = reader.read(buf);
xml.append(buf, 0, len);
}
IgnoringXStream xStream = new IgnoringXStream();
data = (QuestData) xStream.fromXML(xml.toString());
if (data.versionNumber != QuestData.CURRENT_VERSION_NUMBER) {
updateSaveFile(data, xml.toString());
}
zin.close();
return data;
} catch (Exception ex) {
ErrorViewer.showError(ex, "Error loading Quest Data");
throw new RuntimeException(ex);
}
}
/**
* <p>updateSaveFile.</p>
*
* @param newData a {@link forge.quest.data.QuestData} object.
* @param input a {@link java.lang.String} object.
*/
private static void updateSaveFile(
final QuestData newData, final String input) {
try {
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(input));
Document document = builder.parse(is);
switch (newData.versionNumber) {
//There should be a fall-through b/w the cases so that each
// version's changes get applied progressively
case 0:
// First beta release with new file format,
// inventory needs to be migrated
newData.inventory = new QuestInventory();
NodeList elements = document.getElementsByTagName("estatesLevel");
newData.getInventory().setItemLevel("Estates", Integer.parseInt(elements.item(0).getTextContent()));
elements = document.getElementsByTagName("luckyCoinLevel");
newData.getInventory().setItemLevel("Lucky Coin", Integer.parseInt(elements.item(0).getTextContent()));
elements = document.getElementsByTagName("sleightOfHandLevel");
newData.getInventory().setItemLevel("Sleight", Integer.parseInt(elements.item(0).getTextContent()));
elements = document.getElementsByTagName("gearLevel");
int gearLevel = Integer.parseInt(elements.item(0).getTextContent());
if (gearLevel >= 1) {
newData.inventory.setItemLevel("Map", 1);
}
if (gearLevel == 2) {
newData.inventory.setItemLevel("Zeppelin", 1);
}
break;
}
//mark the QD as the latest version
newData.versionNumber = QuestData.CURRENT_VERSION_NUMBER;
} catch (Exception e) {
forge.error.ErrorViewer.showError(e);
}
}
/**
* <p>saveData.</p>
*
* @param qd a {@link forge.quest.data.QuestData} object.
*/
public static void saveData(QuestData qd) {
try {
File f = ForgeProps.getFile(NewConstants.QUEST.XMLDATA);
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(f));
GZIPOutputStream zout = new GZIPOutputStream(bout);
XStream xStream = new XStream();
xStream.toXML(qd, zout);
zout.flush();
zout.close();
} catch (Exception ex) {
ErrorViewer.showError(ex, "Error saving Quest Data.");
throw new RuntimeException(ex);
}
}
/**
* Xstream subclass that ignores fields that are present in the save but not in the class.
*/
private static class IgnoringXStream extends XStream {
List<String> ignoredFields = new ArrayList<String>();
@Override
protected MapperWrapper wrapMapper(MapperWrapper next) {
return new MapperWrapper(next) {
@Override
public boolean shouldSerializeMember(
@SuppressWarnings("rawtypes") Class definedIn,
String fieldName) {
if (definedIn == Object.class) {
ignoredFields.add(fieldName);
return false;
}
return super.shouldSerializeMember(definedIn, fieldName);
}
};
}
}
}