112 lines
4.4 KiB
Java
112 lines
4.4 KiB
Java
package com.github.dtschust.zork.parser;
|
|
|
|
import com.github.dtschust.zork.ZorkGame;
|
|
import com.github.dtschust.zork.parser.builders.Parsers;
|
|
import com.github.dtschust.zork.types.ZorkContainer;
|
|
import com.github.dtschust.zork.types.ZorkCreature;
|
|
import com.github.dtschust.zork.types.ZorkItem;
|
|
import com.github.dtschust.zork.types.ZorkRoom;
|
|
import org.w3c.dom.Element;
|
|
import org.w3c.dom.Node;
|
|
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
import java.io.File;
|
|
import java.nio.channels.NonReadableChannelException;
|
|
|
|
import static com.github.dtschust.zork.Zork.Type.*;
|
|
|
|
public class ZorkReader {
|
|
|
|
private final String filename;
|
|
|
|
public ZorkReader(String filename) {
|
|
this.filename = filename;
|
|
}
|
|
|
|
private static void addCreature(ZorkGame data, Element element) {
|
|
final ZorkCreature tempCreature = Parsers.creature.parse(element);
|
|
|
|
/* Put each creature in the creatures hashmap, the generic object hashmap, and the object lookup hashmap*/
|
|
data.addObjectThroughLookup(CREATURE, tempCreature);
|
|
}
|
|
|
|
private static void addContainer(ZorkGame data, Element element) {
|
|
final ZorkContainer tempCont = Parsers.container.parse(element);
|
|
|
|
/* Put each container in the containers hashmap, the generic object hashmap, and the objectlookup hashmap*/
|
|
data.addObjectThroughLookup(CONTAINER, tempCont);
|
|
}
|
|
|
|
private static void addItem(ZorkGame data, Element element) {
|
|
final ZorkItem tempItem = Parsers.item.parse(element);
|
|
|
|
/* Put each item in the items hashmap, the generic objects hashmap, and store its type in object lookup */
|
|
data.addObjectThroughLookup(ITEM, tempItem);
|
|
}
|
|
|
|
private static void addRoom(ZorkGame data, Element element) {
|
|
final ZorkRoom tempRoom = Parsers.room.parse(element);
|
|
|
|
/*Add this room to the rooms hashmap, put it in the generic objects hashmap, and store it's type in the objectlookup hashmap*/
|
|
data.addObjectThroughLookup(ROOM, tempRoom);
|
|
}
|
|
|
|
public ZorkGame build() {
|
|
ZorkGame data = new ZorkGame();
|
|
|
|
File file = new File(filename);
|
|
if (!file.canRead()) {
|
|
System.out.println("Error opening file. Exiting...");
|
|
throw new NonReadableChannelException();
|
|
}
|
|
|
|
try {
|
|
/* Open the xml file*/
|
|
DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance();
|
|
// Limit XML features to mitigate vulnerabilities
|
|
builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
|
builder.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
|
builder.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
|
|
|
Element rootElement = builder.newDocumentBuilder().parse(file).getDocumentElement();
|
|
|
|
/* Every single first generation child is a room, container, creature, or item. So load them in*/
|
|
for (Node node : DOMUtils.iterNodes(rootElement.getChildNodes())) {
|
|
Element element;
|
|
if (node instanceof Element) {
|
|
element = (Element) node;
|
|
String tagType = element.getTagName();
|
|
|
|
switch (tagType) {
|
|
/* If it's a room ... */
|
|
case "room":
|
|
addRoom(data, element);
|
|
break;
|
|
/* If it's an item... */
|
|
case "item":
|
|
addItem(data, element);
|
|
break;
|
|
/* If it's a container... */
|
|
case "container":
|
|
addContainer(data, element);
|
|
break;
|
|
/* And finally, if it's a creature...*/
|
|
case "creature":
|
|
addCreature(data, element);
|
|
break;
|
|
default:
|
|
throw new IllegalStateException("Unexpected value: " + tagType);
|
|
}
|
|
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
// e.printStackTrace();
|
|
System.out.println("Invalid XML file, exiting");
|
|
System.exit(-1);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
}
|