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 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 (Element element : DOMUtils.childrenElements(rootElement)) { switch (element.getTagName()) { /* 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: " + element.getTagName()); } } } catch (Exception e) { // e.printStackTrace(); System.out.println("Invalid XML file, exiting"); System.exit(-1); } return data; } }