Parser refactor complete
This commit is contained in:
parent
9564a205dc
commit
d0d2db70a4
41 changed files with 656 additions and 534 deletions
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
package com.github.dtschust.zork;
|
package com.github.dtschust.zork;
|
||||||
|
|
||||||
import com.github.dtschust.zork.parser.ZorkReader;
|
import com.github.dtschust.zork.parser.ParserIOC;
|
||||||
import com.github.dtschust.zork.repl.ActionDispatcher;
|
import com.github.dtschust.zork.repl.ActionDispatcher;
|
||||||
import com.github.dtschust.zork.types.ZorkContainer;
|
import com.github.dtschust.zork.types.ZorkContainer;
|
||||||
import com.github.dtschust.zork.types.ZorkObject;
|
import com.github.dtschust.zork.types.ZorkObject;
|
||||||
|
@ -13,16 +13,15 @@ import com.github.dtschust.zork.types.ZorkObject;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
import static com.github.dtschust.zork.Zork.Type.*;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.*;
|
||||||
|
|
||||||
/* And away we go*/
|
/* And away we go*/
|
||||||
public class Zork {
|
public class Zork {
|
||||||
ZorkGame game;
|
ZorkGame game;
|
||||||
Scanner source = new Scanner(System.in);
|
Scanner source = new Scanner(System.in);
|
||||||
|
|
||||||
public Zork(String filename) {
|
public Zork(final String filename) {
|
||||||
|
game = ParserIOC.xmlParser().parse(filename);
|
||||||
game = new ZorkReader(filename).build();
|
|
||||||
|
|
||||||
game.changeRoom("Entrance");
|
game.changeRoom("Entrance");
|
||||||
/* Print out the first entrance description, starting the game!*/
|
/* Print out the first entrance description, starting the game!*/
|
||||||
|
@ -147,8 +146,4 @@ public class Zork {
|
||||||
}
|
}
|
||||||
return skip;
|
return skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public enum Type {ROOM, ITEM, CONTAINER, CREATURE}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ package com.github.dtschust.zork;
|
||||||
import com.github.dtschust.zork.types.ZorkContainer;
|
import com.github.dtschust.zork.types.ZorkContainer;
|
||||||
import com.github.dtschust.zork.types.ZorkRoom;
|
import com.github.dtschust.zork.types.ZorkRoom;
|
||||||
|
|
||||||
import static com.github.dtschust.zork.Zork.Type.CONTAINER;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.CONTAINER;
|
||||||
import static com.github.dtschust.zork.Zork.Type.ROOM;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.ROOM;
|
||||||
|
|
||||||
|
|
||||||
/* Has conditions*/
|
/* Has conditions*/
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.github.dtschust.zork;
|
package com.github.dtschust.zork;
|
||||||
|
|
||||||
import com.github.dtschust.zork.Zork.Type;
|
|
||||||
import com.github.dtschust.zork.types.*;
|
import com.github.dtschust.zork.types.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -14,7 +13,7 @@ public class ZorkGame {
|
||||||
private final ZorkMap<ZorkItem> items = new ZorkMap<>();
|
private final ZorkMap<ZorkItem> items = new ZorkMap<>();
|
||||||
private final ZorkMap<ZorkContainer> containers = new ZorkMap<>();
|
private final ZorkMap<ZorkContainer> containers = new ZorkMap<>();
|
||||||
private final ZorkMap<ZorkCreature> creatures = new ZorkMap<>();
|
private final ZorkMap<ZorkCreature> creatures = new ZorkMap<>();
|
||||||
private final HashMap<String, Type> objectLookup = new HashMap<>();
|
private final HashMap<String, ZorkGameStatusType> objectLookup = new HashMap<>();
|
||||||
private boolean running = false;
|
private boolean running = false;
|
||||||
private String currentRoom;
|
private String currentRoom;
|
||||||
|
|
||||||
|
@ -39,11 +38,11 @@ public class ZorkGame {
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getTypeFromLookup(String object) {
|
public ZorkGameStatusType getTypeFromLookup(String object) {
|
||||||
return objectLookup.get(object);
|
return objectLookup.get(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addObjectThroughLookup(Type type, ZorkObject object) {
|
public void addObjectThroughLookup(ZorkGameStatusType type, ZorkObject object) {
|
||||||
putInMapGivenType(type, object);
|
putInMapGivenType(type, object);
|
||||||
objectLookup.put(object.getName(), type);
|
objectLookup.put(object.getName(), type);
|
||||||
}
|
}
|
||||||
|
@ -52,20 +51,20 @@ public class ZorkGame {
|
||||||
return values(cast, objectLookup.get(name));
|
return values(cast, objectLookup.get(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends ZorkObject> ZorkMap<T> values(Class<T> cast, Type type) {
|
public <T extends ZorkObject> ZorkMap<T> values(Class<T> cast, ZorkGameStatusType type) {
|
||||||
return (ZorkMap<T>) getMapFromType(type);
|
return (ZorkMap<T>) getMapFromType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ZorkObject get(Type type, String key) {
|
public ZorkObject get(ZorkGameStatusType type, String key) {
|
||||||
return getMapFromType(type).get(key);
|
return getMapFromType(type).get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void put(Type type, ZorkObject object) {
|
public void put(ZorkGameStatusType type, ZorkObject object) {
|
||||||
putInMapGivenType(type, object);
|
putInMapGivenType(type, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private ZorkMap<? extends ZorkObject> getMapFromType(Type type) {
|
private ZorkMap<? extends ZorkObject> getMapFromType(ZorkGameStatusType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ROOM:
|
case ROOM:
|
||||||
return rooms;
|
return rooms;
|
||||||
|
@ -80,7 +79,7 @@ public class ZorkGame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putInMapGivenType(Type type, ZorkObject object) {
|
private void putInMapGivenType(ZorkGameStatusType type, ZorkObject object) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ROOM:
|
case ROOM:
|
||||||
rooms.put((ZorkRoom) object);
|
rooms.put((ZorkRoom) object);
|
||||||
|
|
|
@ -1,70 +0,0 @@
|
||||||
package com.github.dtschust.zork.parser;
|
|
||||||
|
|
||||||
import org.w3c.dom.CharacterData;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
import org.w3c.dom.NodeList;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public final class DOMUtils {
|
|
||||||
private DOMUtils() {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a DOM element with one and only one child of text node type, returns the text as a string. If there is no
|
|
||||||
* such node, '?' is returned
|
|
||||||
* Get a string from an element (XML parsing stuff)
|
|
||||||
*
|
|
||||||
* @param e the element
|
|
||||||
* @return the text as string, or '?'
|
|
||||||
*/
|
|
||||||
public static String getInnerText(final Element e) {
|
|
||||||
final Node child = e.getFirstChild();
|
|
||||||
return child instanceof CharacterData ? ((CharacterData) child).getData() : "?";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getInnerTextByTagName(final Element element, final String elementName) {
|
|
||||||
return getInnerTextByTagName(element, elementName, Optional.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getInnerTextByTagName(final Element element,
|
|
||||||
final String name,
|
|
||||||
final String defaultValue) {
|
|
||||||
return getInnerTextByTagName(element, name, Optional.of(defaultValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getInnerTextByTagName(final Element element,
|
|
||||||
final String elementName,
|
|
||||||
final Optional<String> defaultValue) {
|
|
||||||
final NodeList field = element.getElementsByTagName(elementName);
|
|
||||||
|
|
||||||
if (field.getLength() == 0) {
|
|
||||||
return defaultValue.orElseThrow(() ->
|
|
||||||
new IllegalArgumentException(elementName + " element count in container is not 1"));
|
|
||||||
}
|
|
||||||
|
|
||||||
final Node first = field.item(0);
|
|
||||||
if (!(first instanceof Element)) {
|
|
||||||
// the contract of getElementsByTagName states that it returns a list of Element objects
|
|
||||||
throw new IllegalStateException("unreachable");
|
|
||||||
}
|
|
||||||
|
|
||||||
return getInnerText((Element) first);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Element> childrenElements(final Element parent) {
|
|
||||||
final List<Element> elements = new ArrayList<>();
|
|
||||||
final NodeList children = parent.getChildNodes();
|
|
||||||
for (int i = 0; i < children.getLength(); i++) {
|
|
||||||
final Node item = children.item(i);
|
|
||||||
if (item instanceof Element) {
|
|
||||||
elements.add((Element) item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return elements;
|
|
||||||
}
|
|
||||||
}
|
|
28
src/main/java/com/github/dtschust/zork/parser/ParserIOC.java
Normal file
28
src/main/java/com/github/dtschust/zork/parser/ParserIOC.java
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package com.github.dtschust.zork.parser;
|
||||||
|
|
||||||
|
import com.github.dtschust.zork.ZorkCondition;
|
||||||
|
import com.github.dtschust.zork.parser.strategies.*;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inversion of control for Zork parse strategies
|
||||||
|
*/
|
||||||
|
public final class ParserIOC {
|
||||||
|
private static final PropertyParseStrategy<ZorkCondition> condition = new ZorkConditionParseStrategy();
|
||||||
|
private static final TriggerPropertyParseStrategy trigger = new ZorkTriggerParseStrategy(condition);
|
||||||
|
private static final PropertyParseStrategy<ZorkContainer> container = new ZorkContainerParseStrategy(trigger);
|
||||||
|
private static final PropertyParseStrategy<ZorkItem> item = new ZorkItemParseStrategy(trigger);
|
||||||
|
private static final PropertyParseStrategy<ZorkRoom> room = new ZorkRoomParseStrategy(trigger);
|
||||||
|
private static final PropertyParseStrategy<ZorkCreature> creature = new ZorkCreatureParseStrategy(condition, trigger);
|
||||||
|
private static final ZorkParser xmlParser = new ZorkXMLParser(creature, container, item, room);
|
||||||
|
|
||||||
|
private ParserIOC() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ZorkParser xmlParser() {
|
||||||
|
return xmlParser;
|
||||||
|
}
|
||||||
|
}
|
91
src/main/java/com/github/dtschust/zork/parser/Property.java
Normal file
91
src/main/java/com/github/dtschust/zork/parser/Property.java
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
package com.github.dtschust.zork.parser;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property is an encoding-agnostic representation of a 3-tuple made of:
|
||||||
|
* - A property name (string);
|
||||||
|
* - A property value (string);
|
||||||
|
* - An (optional) list of sub-properties.
|
||||||
|
*/
|
||||||
|
public interface Property {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the property name
|
||||||
|
*
|
||||||
|
* @return the property name
|
||||||
|
*/
|
||||||
|
String name();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the property value
|
||||||
|
*
|
||||||
|
* @return the property value
|
||||||
|
*/
|
||||||
|
String value();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all sub-properties
|
||||||
|
*
|
||||||
|
* @return a list af all sub-properties
|
||||||
|
*/
|
||||||
|
List<? extends Property> subProperties();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of the sub-properties matching the given name
|
||||||
|
*
|
||||||
|
* @param name the name of the sub-properties
|
||||||
|
* @return a list of sub-properties
|
||||||
|
*/
|
||||||
|
List<? extends Property> subPropertiesByName(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a sub-property name and an optional default value, returns:
|
||||||
|
* - The sub-property value for the first sub-property with the given name, or;
|
||||||
|
* - If no such sub-properties are found and if the default value is given, the default value, or;
|
||||||
|
* - nothing, throwing an exception, if no default value is given
|
||||||
|
*
|
||||||
|
* @param elementName the sub-property name
|
||||||
|
* @param defaultValue the default value or Optional.empty()
|
||||||
|
* @return the sub-property value
|
||||||
|
* @throws IllegalStateException when the default value is not given and no sub-property is found
|
||||||
|
*/
|
||||||
|
String subPropertyValue(String elementName, Optional<String> defaultValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether at least one sub-property with the given name is found
|
||||||
|
*
|
||||||
|
* @param name the sub-property name
|
||||||
|
* @return whether at least one sub-property with the given name is found
|
||||||
|
*/
|
||||||
|
boolean hasSubProperty(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overload of {@link #subPropertyValue(String, Optional)} with empty default value
|
||||||
|
*/
|
||||||
|
default String subPropertyValue(String name) {
|
||||||
|
return subPropertyValue(name, Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overload of {@link #subPropertyValue(String, Optional)} with the given default value
|
||||||
|
* boxed as an {@link Optional}
|
||||||
|
*/
|
||||||
|
default String subPropertyValue(String name, String defaultValue) {
|
||||||
|
return subPropertyValue(name, Optional.of(defaultValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of property values for the sub-properties matching the given name
|
||||||
|
*
|
||||||
|
* @param propertyName the name of the sub-properties
|
||||||
|
* @return a list of sub-property values
|
||||||
|
*/
|
||||||
|
default List<String> subPropertyValues(final String propertyName) {
|
||||||
|
return subPropertiesByName(propertyName).stream()
|
||||||
|
.map(Property::value)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.github.dtschust.zork.parser;
|
||||||
|
|
||||||
|
public interface PropertyParseStrategy<T> {
|
||||||
|
T parse(final Property source);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.github.dtschust.zork.parser;
|
||||||
|
|
||||||
|
import com.github.dtschust.zork.ZorkTrigger;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public interface TriggerPropertyParseStrategy {
|
||||||
|
ZorkTrigger parseTrigger(final Property source, final Property parent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Partial function application for the parseTrigger method able to define the parent element first
|
||||||
|
*
|
||||||
|
* @param parent the parent element
|
||||||
|
* @return a lambda mapping a source, a child element of `parent`, to ZorkTrigger objects
|
||||||
|
*/
|
||||||
|
default Function<Property, ZorkTrigger> parse(final Property parent) {
|
||||||
|
return (source) -> this.parseTrigger(source, parent);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.github.dtschust.zork.parser;
|
||||||
|
|
||||||
|
import com.github.dtschust.zork.ZorkGame;
|
||||||
|
import com.github.dtschust.zork.types.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.*;
|
||||||
|
|
||||||
|
public abstract class ZorkParser {
|
||||||
|
private final Map<ZorkGameStatusType, PropertyParseStrategy<? extends ZorkObject>> strategies;
|
||||||
|
|
||||||
|
public ZorkParser(final PropertyParseStrategy<ZorkCreature> creatureStrategy,
|
||||||
|
final PropertyParseStrategy<ZorkContainer> containerStrategy,
|
||||||
|
final PropertyParseStrategy<ZorkItem> itemStrategy,
|
||||||
|
final PropertyParseStrategy<ZorkRoom> roomStrategy) {
|
||||||
|
this.strategies = Map.ofEntries(
|
||||||
|
Map.entry(CREATURE, creatureStrategy),
|
||||||
|
Map.entry(CONTAINER, containerStrategy),
|
||||||
|
Map.entry(ITEM, itemStrategy),
|
||||||
|
Map.entry(ROOM, roomStrategy)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Property getRootProperty(final String filename);
|
||||||
|
|
||||||
|
public ZorkGame parse(final String filename) {
|
||||||
|
ZorkGame data = new ZorkGame();
|
||||||
|
|
||||||
|
final Property rootElement = getRootProperty(filename);
|
||||||
|
|
||||||
|
// Every single first generation child is a room, container, creature, or item. So load them in
|
||||||
|
for (final Property element : rootElement.subProperties()) {
|
||||||
|
final String name = element.name();
|
||||||
|
final ZorkGameStatusType t = ZorkGameStatusType.fromPropertyName(name)
|
||||||
|
.orElseThrow(() -> new IllegalStateException("Unexpected value: " + name));
|
||||||
|
final ZorkObject built = strategies.get(t).parse(element);
|
||||||
|
data.addObjectThroughLookup(t, built);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,103 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.github.dtschust.zork.parser;
|
||||||
|
|
||||||
|
import com.github.dtschust.zork.parser.dom.DOMElement;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class ZorkXMLParser extends ZorkParser {
|
||||||
|
public ZorkXMLParser(final PropertyParseStrategy<ZorkCreature> creatureStrategy,
|
||||||
|
final PropertyParseStrategy<ZorkContainer> containerStrategy,
|
||||||
|
final PropertyParseStrategy<ZorkItem> itemStrategy,
|
||||||
|
final PropertyParseStrategy<ZorkRoom> roomStrategy) {
|
||||||
|
super(creatureStrategy, containerStrategy, itemStrategy, roomStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Property getRootProperty(String filename) {
|
||||||
|
File file = new File(filename);
|
||||||
|
if (!file.canRead()) {
|
||||||
|
System.out.println("Error opening file. Exiting...");
|
||||||
|
throw new NonReadableChannelException();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Open the xml file
|
||||||
|
final 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);
|
||||||
|
|
||||||
|
final Element rootElement = builder.newDocumentBuilder().parse(file).getDocumentElement();
|
||||||
|
return DOMElement.of(rootElement);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
System.out.println("Invalid XML file, exiting");
|
||||||
|
e.printStackTrace();
|
||||||
|
System.exit(-1);
|
||||||
|
return null; // never reached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,23 +0,0 @@
|
||||||
package com.github.dtschust.zork.parser.builders;
|
|
||||||
|
|
||||||
import com.github.dtschust.zork.ZorkCondition;
|
|
||||||
import com.github.dtschust.zork.ZorkTrigger;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inversion of control for Zork parse strategies
|
|
||||||
*/
|
|
||||||
public final class Parsers {
|
|
||||||
private static final ZorkParseStrategy<ZorkCondition> condition = new ZorkConditionParseStrategy();
|
|
||||||
private static final ZorkParseStrategy<ZorkTrigger> trigger = new ZorkTriggerListParseStrategy(condition);
|
|
||||||
public static final ZorkParseStrategy<ZorkContainer> container = new ZorkContainerParseStrategy(trigger);
|
|
||||||
public static final ZorkParseStrategy<ZorkItem> item = new ZorkItemParseStrategy(trigger);
|
|
||||||
public static final ZorkParseStrategy<ZorkRoom> room = new ZorkRoomParseStrategy(trigger);
|
|
||||||
public static final ZorkParseStrategy<ZorkCreature> creature = new ZorkCreatureParseStrategy(condition, trigger);
|
|
||||||
|
|
||||||
private Parsers() {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package com.github.dtschust.zork.parser.builders;
|
|
||||||
|
|
||||||
import com.github.dtschust.zork.ZorkCondition;
|
|
||||||
import com.github.dtschust.zork.ZorkConditionHas;
|
|
||||||
import com.github.dtschust.zork.ZorkConditionStatus;
|
|
||||||
import com.github.dtschust.zork.parser.DOMUtils;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
|
|
||||||
public class ZorkConditionParseStrategy implements ZorkParseStrategy<ZorkCondition> {
|
|
||||||
@Override
|
|
||||||
public ZorkCondition parse(final Element conditionElement) {
|
|
||||||
if (conditionElement.getElementsByTagName("has").getLength() > 0) {
|
|
||||||
return new ZorkConditionHas(
|
|
||||||
DOMUtils.getInnerTextByTagName(conditionElement, "has"),
|
|
||||||
DOMUtils.getInnerTextByTagName(conditionElement, "object"),
|
|
||||||
DOMUtils.getInnerTextByTagName(conditionElement, "owner")
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return new ZorkConditionStatus(
|
|
||||||
DOMUtils.getInnerTextByTagName(conditionElement, "status"),
|
|
||||||
DOMUtils.getInnerTextByTagName(conditionElement, "object")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package com.github.dtschust.zork.parser.builders;
|
|
||||||
|
|
||||||
import com.github.dtschust.zork.ZorkTrigger;
|
|
||||||
import com.github.dtschust.zork.parser.DOMUtils;
|
|
||||||
import com.github.dtschust.zork.parser.dom.Elements;
|
|
||||||
import com.github.dtschust.zork.types.ZorkContainer;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ZorkContainerParseStrategy implements ZorkParseStrategy<ZorkContainer> {
|
|
||||||
private final ZorkParseStrategy<ZorkTrigger> triggerStrategy;
|
|
||||||
|
|
||||||
public ZorkContainerParseStrategy(ZorkParseStrategy<ZorkTrigger> triggerStrategy) {
|
|
||||||
this.triggerStrategy = triggerStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ZorkContainer parse(final Element element) {
|
|
||||||
final String name = DOMUtils.getInnerTextByTagName(element, "name", "");
|
|
||||||
|
|
||||||
final String description = DOMUtils.getInnerTextByTagName(element, "description", "");
|
|
||||||
|
|
||||||
final List<ZorkTrigger> triggers = Elements.byTagName(element, "trigger").stream()
|
|
||||||
.map(triggerStrategy::parse)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
final String status = DOMUtils.getInnerTextByTagName(element, "status", "");
|
|
||||||
|
|
||||||
final List<String> accepts = Elements.innerTextByTagName(element, "accept");
|
|
||||||
|
|
||||||
final List<String> items = Elements.innerTextByTagName(element, "item");
|
|
||||||
|
|
||||||
return new ZorkContainer(name, description, status, items, accepts, triggers);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
package com.github.dtschust.zork.parser.builders;
|
|
||||||
|
|
||||||
import com.github.dtschust.zork.ZorkCondition;
|
|
||||||
import com.github.dtschust.zork.ZorkTrigger;
|
|
||||||
import com.github.dtschust.zork.parser.DOMUtils;
|
|
||||||
import com.github.dtschust.zork.parser.dom.Elements;
|
|
||||||
import com.github.dtschust.zork.types.ZorkCreature;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ZorkCreatureParseStrategy implements ZorkParseStrategy<ZorkCreature> {
|
|
||||||
|
|
||||||
private final ZorkParseStrategy<ZorkCondition> conditionStrategy;
|
|
||||||
private final ZorkParseStrategy<ZorkTrigger> triggerStrategy;
|
|
||||||
|
|
||||||
public ZorkCreatureParseStrategy(final ZorkParseStrategy<ZorkCondition> conditionStrategy,
|
|
||||||
final ZorkParseStrategy<ZorkTrigger> triggerStrategy) {
|
|
||||||
this.conditionStrategy = conditionStrategy;
|
|
||||||
this.triggerStrategy = triggerStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ZorkCreature parse(final Element source) {
|
|
||||||
// Get all possible creature attributes
|
|
||||||
final List<ZorkCondition> conditions = Elements.byTagName(source, "attack").stream()
|
|
||||||
.flatMap(e -> Elements.byTagName(e, "condition").stream())
|
|
||||||
.map(conditionStrategy::parse)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
final List<String> prints = Elements.byTagName(source, "attack").stream()
|
|
||||||
.flatMap(e -> Elements.innerTextByTagName(e, "print").stream())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
final List<String> actions = Elements.byTagName(source, "attack").stream()
|
|
||||||
.flatMap(e -> Elements.innerTextByTagName(e, "action").stream())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
final List<String> vulnerabilities = Elements.innerTextByTagName(source, "vulnerability");
|
|
||||||
|
|
||||||
final List<ZorkTrigger> triggers = Elements.byTagName(source, "trigger").stream()
|
|
||||||
.map(triggerStrategy::parse)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
final String name = DOMUtils.getInnerTextByTagName(source, "name", "");
|
|
||||||
final String description = DOMUtils.getInnerTextByTagName(source, "description", "");
|
|
||||||
final String status = DOMUtils.getInnerTextByTagName(source, "status", "");
|
|
||||||
|
|
||||||
return new ZorkCreature(name, description, status, triggers, vulnerabilities, conditions, prints, actions);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
package com.github.dtschust.zork.parser.builders;
|
|
||||||
|
|
||||||
import com.github.dtschust.zork.ZorkTrigger;
|
|
||||||
import com.github.dtschust.zork.parser.DOMUtils;
|
|
||||||
import com.github.dtschust.zork.parser.dom.Elements;
|
|
||||||
import com.github.dtschust.zork.types.ZorkItem;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ZorkItemParseStrategy implements ZorkParseStrategy<ZorkItem> {
|
|
||||||
|
|
||||||
private final ZorkParseStrategy<ZorkTrigger> triggerStrategy;
|
|
||||||
|
|
||||||
public ZorkItemParseStrategy(final ZorkParseStrategy<ZorkTrigger> triggerStrategy) {
|
|
||||||
this.triggerStrategy = triggerStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ZorkItem parse(final Element source) {
|
|
||||||
final List<String> prints = Elements.byTagName(source, "turnon").stream()
|
|
||||||
.flatMap(e -> Elements.innerTextByTagName(e, "print").stream())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
final List<String> actions = Elements.byTagName(source, "turnon").stream()
|
|
||||||
.flatMap(e -> Elements.innerTextByTagName(e, "action").stream())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
final List<ZorkTrigger> triggers = Elements.byTagName(source, "trigger").stream()
|
|
||||||
.map(triggerStrategy::parse)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
/* Get all possible item attributes*/
|
|
||||||
return new ZorkItem(
|
|
||||||
DOMUtils.getInnerTextByTagName(source, "name", ""),
|
|
||||||
DOMUtils.getInnerTextByTagName(source, "description", ""),
|
|
||||||
DOMUtils.getInnerTextByTagName(source, "status", ""),
|
|
||||||
DOMUtils.getInnerTextByTagName(source, "writing", ""),
|
|
||||||
triggers,
|
|
||||||
prints,
|
|
||||||
actions
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package com.github.dtschust.zork.parser.builders;
|
|
||||||
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
|
|
||||||
public interface ZorkParseStrategy<T> {
|
|
||||||
T parse(Element source);
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package com.github.dtschust.zork.parser.builders;
|
|
||||||
|
|
||||||
import com.github.dtschust.zork.ZorkTrigger;
|
|
||||||
import com.github.dtschust.zork.parser.DOMUtils;
|
|
||||||
import com.github.dtschust.zork.parser.dom.Elements;
|
|
||||||
import com.github.dtschust.zork.types.ZorkDirection;
|
|
||||||
import com.github.dtschust.zork.types.ZorkRoom;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ZorkRoomParseStrategy implements ZorkParseStrategy<ZorkRoom> {
|
|
||||||
|
|
||||||
private final ZorkParseStrategy<ZorkTrigger> triggerStrategy;
|
|
||||||
|
|
||||||
public ZorkRoomParseStrategy(final ZorkParseStrategy<ZorkTrigger> triggerStrategy) {
|
|
||||||
this.triggerStrategy = triggerStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ZorkRoom parse(final Element source) {
|
|
||||||
// Get all possible Room attributes
|
|
||||||
final String name = DOMUtils.getInnerTextByTagName(source, "name", "");
|
|
||||||
final String description = DOMUtils.getInnerTextByTagName(source, "description", "");
|
|
||||||
final String type = DOMUtils.getInnerTextByTagName(source, "type", "regular");
|
|
||||||
|
|
||||||
final List<ZorkTrigger> triggers = Elements.byTagName(source, "trigger").stream()
|
|
||||||
.map(triggerStrategy::parse)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
final String status = DOMUtils.getInnerTextByTagName(source, "status", "");
|
|
||||||
|
|
||||||
final List<String> items = Elements.innerTextByTagName(source, "item");
|
|
||||||
final List<String> creatures = Elements.innerTextByTagName(source, "creature");
|
|
||||||
final List<String> containers = Elements.innerTextByTagName(source, "container");
|
|
||||||
|
|
||||||
final Map<ZorkDirection, String> borders = Elements.byTagName(source, "border").stream()
|
|
||||||
.collect(Collectors.toMap(
|
|
||||||
e -> ZorkDirection.fromLong(DOMUtils.getInnerTextByTagName(e, "direction")),
|
|
||||||
e -> DOMUtils.getInnerTextByTagName(e, "name")
|
|
||||||
));
|
|
||||||
|
|
||||||
return new ZorkRoom(name, description, type, status, triggers, borders, containers, items, creatures);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
package com.github.dtschust.zork.parser.builders;
|
|
||||||
|
|
||||||
import com.github.dtschust.zork.ZorkCommand;
|
|
||||||
import com.github.dtschust.zork.ZorkCondition;
|
|
||||||
import com.github.dtschust.zork.ZorkTrigger;
|
|
||||||
import com.github.dtschust.zork.parser.DOMUtils;
|
|
||||||
import com.github.dtschust.zork.parser.dom.Elements;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ZorkTriggerListParseStrategy implements ZorkParseStrategy<ZorkTrigger> {
|
|
||||||
|
|
||||||
private final ZorkParseStrategy<ZorkCondition> conditionStrategy;
|
|
||||||
|
|
||||||
public ZorkTriggerListParseStrategy(final ZorkParseStrategy<ZorkCondition> conditionStrategy) {
|
|
||||||
this.conditionStrategy = conditionStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ZorkTrigger parse(final Element trigger) {
|
|
||||||
final String type = DOMUtils.getInnerTextByTagName((Element) trigger.getParentNode(), "type", "single");
|
|
||||||
|
|
||||||
final List<ZorkCommand> commands = Elements.byTagName(trigger, "command").stream()
|
|
||||||
.map(DOMUtils::getInnerText)
|
|
||||||
.map(ZorkCommand::new)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
final List<ZorkCondition> conditions = Elements.byTagName(trigger, "condition").stream()
|
|
||||||
.map(conditionStrategy::parse)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
final List<String> prints = Elements.innerTextByTagName(trigger, "print");
|
|
||||||
final List<String> actions = Elements.innerTextByTagName(trigger, "action");
|
|
||||||
|
|
||||||
return new ZorkTrigger(type, conditions, commands, prints, actions);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.github.dtschust.zork.parser.dom;
|
||||||
|
|
||||||
|
import com.github.dtschust.zork.parser.Property;
|
||||||
|
import org.w3c.dom.CharacterData;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class DOMElement implements Property {
|
||||||
|
private final Element backing;
|
||||||
|
|
||||||
|
public DOMElement(final Element backing) {
|
||||||
|
this.backing = backing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DOMElement of(final Element backing) {
|
||||||
|
return new DOMElement(backing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a DOM element with one and only one child of text node type, returns the text as a string. If there is no
|
||||||
|
* such node, '?' is returned
|
||||||
|
* Get a string from an element (XML parsing stuff)
|
||||||
|
*
|
||||||
|
* @return the text as string, or '?'
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String value() {
|
||||||
|
final Node child = backing.getFirstChild();
|
||||||
|
return child instanceof CharacterData ? ((CharacterData) child).getData() : "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends Property> subPropertiesByName(final String name) {
|
||||||
|
return DOMElementList.byTagName(backing, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String subPropertyValue(final String elementName,
|
||||||
|
final Optional<String> defaultValue) {
|
||||||
|
final NodeList field = backing.getElementsByTagName(elementName);
|
||||||
|
|
||||||
|
if (field.getLength() == 0) {
|
||||||
|
return defaultValue.orElseThrow(() ->
|
||||||
|
new IllegalArgumentException(elementName + " element count in container is not 1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
final Node first = field.item(0);
|
||||||
|
if (!(first instanceof Element)) {
|
||||||
|
// the contract of getElementsByTagName states that it returns a list of Element objects
|
||||||
|
throw new IllegalStateException("unreachable");
|
||||||
|
}
|
||||||
|
|
||||||
|
return DOMElement.of((Element) first).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return backing.getTagName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSubProperty(final String name) {
|
||||||
|
return backing.getElementsByTagName(name).getLength() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Property> subProperties() {
|
||||||
|
final List<Property> elements = new ArrayList<>();
|
||||||
|
final NodeList children = backing.getChildNodes();
|
||||||
|
for (int i = 0; i < children.getLength(); i++) {
|
||||||
|
final Node item = children.item(i);
|
||||||
|
if (item instanceof Element) {
|
||||||
|
elements.add(DOMElement.of((Element) item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.github.dtschust.zork.parser.dom;
|
||||||
|
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import java.util.AbstractList;
|
||||||
|
import java.util.RandomAccess;
|
||||||
|
|
||||||
|
public class DOMElementList extends AbstractList<DOMElement> implements RandomAccess {
|
||||||
|
private final NodeList list;
|
||||||
|
|
||||||
|
private DOMElementList(final NodeList l) {
|
||||||
|
list = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DOMElementList byTagName(final Element parent, final String name) {
|
||||||
|
return new DOMElementList(parent.getElementsByTagName(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DOMElement get(int index) {
|
||||||
|
final Node e = list.item(index);
|
||||||
|
if (!(e instanceof Element)) {
|
||||||
|
// the contract of getElementsByTagName states that it returns a list of Element objects
|
||||||
|
throw new IllegalStateException("unreachable");
|
||||||
|
}
|
||||||
|
return DOMElement.of((Element) e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return list.getLength();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
package com.github.dtschust.zork.parser.dom;
|
|
||||||
|
|
||||||
import com.github.dtschust.zork.parser.DOMUtils;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
import org.w3c.dom.NodeList;
|
|
||||||
|
|
||||||
import java.util.AbstractList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.RandomAccess;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class Elements extends AbstractList<Element> implements RandomAccess {
|
|
||||||
private final NodeList list;
|
|
||||||
|
|
||||||
private Elements(final NodeList l) {
|
|
||||||
list = l;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Elements byTagName(final Element parent, final String name) {
|
|
||||||
return new Elements(parent.getElementsByTagName(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> innerTextByTagName(final Element parent, final String name) {
|
|
||||||
return Elements.byTagName(parent, name).stream()
|
|
||||||
.map(DOMUtils::getInnerText)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Element get(int index) {
|
|
||||||
final Node e = list.item(index);
|
|
||||||
if (!(e instanceof Element)) {
|
|
||||||
// the contract of getElementsByTagName states that it returns a list of Element objects
|
|
||||||
throw new IllegalStateException("unreachable");
|
|
||||||
}
|
|
||||||
return (Element) e;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return list.getLength();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.github.dtschust.zork.parser.strategies;
|
||||||
|
|
||||||
|
import com.github.dtschust.zork.ZorkCondition;
|
||||||
|
import com.github.dtschust.zork.ZorkConditionHas;
|
||||||
|
import com.github.dtschust.zork.ZorkConditionStatus;
|
||||||
|
import com.github.dtschust.zork.parser.Property;
|
||||||
|
import com.github.dtschust.zork.parser.PropertyParseStrategy;
|
||||||
|
|
||||||
|
public class ZorkConditionParseStrategy implements PropertyParseStrategy<ZorkCondition> {
|
||||||
|
@Override
|
||||||
|
public ZorkCondition parse(final Property source) {
|
||||||
|
if (source.hasSubProperty("has")) {
|
||||||
|
return new ZorkConditionHas(
|
||||||
|
source.subPropertyValue("has"),
|
||||||
|
source.subPropertyValue("object"),
|
||||||
|
source.subPropertyValue("owner")
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return new ZorkConditionStatus(
|
||||||
|
source.subPropertyValue("status"),
|
||||||
|
source.subPropertyValue("object")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.github.dtschust.zork.parser.strategies;
|
||||||
|
|
||||||
|
import com.github.dtschust.zork.ZorkTrigger;
|
||||||
|
import com.github.dtschust.zork.parser.Property;
|
||||||
|
import com.github.dtschust.zork.parser.PropertyParseStrategy;
|
||||||
|
import com.github.dtschust.zork.parser.TriggerPropertyParseStrategy;
|
||||||
|
import com.github.dtschust.zork.types.ZorkContainer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ZorkContainerParseStrategy implements PropertyParseStrategy<ZorkContainer> {
|
||||||
|
private final TriggerPropertyParseStrategy triggerStrategy;
|
||||||
|
|
||||||
|
public ZorkContainerParseStrategy(TriggerPropertyParseStrategy triggerStrategy) {
|
||||||
|
this.triggerStrategy = triggerStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZorkContainer parse(final Property element) {
|
||||||
|
|
||||||
|
final String name = element.subPropertyValue("name", "");
|
||||||
|
|
||||||
|
final String description = element.subPropertyValue("description", "");
|
||||||
|
|
||||||
|
final List<ZorkTrigger> triggers = element.subPropertiesByName("trigger").stream()
|
||||||
|
.map(triggerStrategy.parse(element))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final String status = element.subPropertyValue("status", "");
|
||||||
|
|
||||||
|
final List<String> accepts = element.subPropertyValues("accept");
|
||||||
|
|
||||||
|
final List<String> items = element.subPropertyValues("item");
|
||||||
|
|
||||||
|
return new ZorkContainer(name, description, status, items, accepts, triggers);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.github.dtschust.zork.parser.strategies;
|
||||||
|
|
||||||
|
import com.github.dtschust.zork.ZorkCondition;
|
||||||
|
import com.github.dtschust.zork.ZorkTrigger;
|
||||||
|
import com.github.dtschust.zork.parser.Property;
|
||||||
|
import com.github.dtschust.zork.parser.PropertyParseStrategy;
|
||||||
|
import com.github.dtschust.zork.parser.TriggerPropertyParseStrategy;
|
||||||
|
import com.github.dtschust.zork.types.ZorkCreature;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ZorkCreatureParseStrategy implements PropertyParseStrategy<ZorkCreature> {
|
||||||
|
|
||||||
|
private final PropertyParseStrategy<ZorkCondition> conditionStrategy;
|
||||||
|
private final TriggerPropertyParseStrategy triggerStrategy;
|
||||||
|
|
||||||
|
public ZorkCreatureParseStrategy(final PropertyParseStrategy<ZorkCondition> conditionStrategy,
|
||||||
|
final TriggerPropertyParseStrategy triggerStrategy) {
|
||||||
|
this.conditionStrategy = conditionStrategy;
|
||||||
|
this.triggerStrategy = triggerStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZorkCreature parse(final Property source) {
|
||||||
|
// Get all possible creature attributes
|
||||||
|
final List<ZorkCondition> conditions = source.subPropertiesByName("attack").stream()
|
||||||
|
.flatMap(e -> e.subPropertiesByName("condition").stream())
|
||||||
|
.map(conditionStrategy::parse)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final List<String> prints = source.subPropertiesByName("attack").stream()
|
||||||
|
.flatMap(e -> e.subPropertyValues("print").stream())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final List<String> actions = source.subPropertiesByName("attack").stream()
|
||||||
|
.flatMap(e -> e.subPropertyValues("action").stream())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final List<String> vulnerabilities = source.subPropertyValues("vulnerability");
|
||||||
|
|
||||||
|
final List<ZorkTrigger> triggers = source.subPropertiesByName("trigger").stream()
|
||||||
|
.map(triggerStrategy.parse(source))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final String name = source.subPropertyValue("name", "");
|
||||||
|
|
||||||
|
final String description = source.subPropertyValue("description", "");
|
||||||
|
|
||||||
|
final String status = source.subPropertyValue("status", "");
|
||||||
|
|
||||||
|
return new ZorkCreature(name, description, status, triggers, vulnerabilities, conditions, prints, actions);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.github.dtschust.zork.parser.strategies;
|
||||||
|
|
||||||
|
import com.github.dtschust.zork.ZorkTrigger;
|
||||||
|
import com.github.dtschust.zork.parser.Property;
|
||||||
|
import com.github.dtschust.zork.parser.PropertyParseStrategy;
|
||||||
|
import com.github.dtschust.zork.parser.TriggerPropertyParseStrategy;
|
||||||
|
import com.github.dtschust.zork.types.ZorkItem;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ZorkItemParseStrategy implements PropertyParseStrategy<ZorkItem> {
|
||||||
|
|
||||||
|
private final TriggerPropertyParseStrategy triggerStrategy;
|
||||||
|
|
||||||
|
public ZorkItemParseStrategy(final TriggerPropertyParseStrategy triggerStrategy) {
|
||||||
|
this.triggerStrategy = triggerStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZorkItem parse(final Property source) {
|
||||||
|
final List<String> prints = source.subPropertiesByName("turnon").stream()
|
||||||
|
.flatMap(e -> e.subPropertyValues("print").stream())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final List<String> actions = source.subPropertiesByName("turnon").stream()
|
||||||
|
.flatMap(e -> e.subPropertyValues("action").stream())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final List<ZorkTrigger> triggers = source.subPropertiesByName("trigger").stream()
|
||||||
|
.map(triggerStrategy.parse(source))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
/* Get all possible item attributes*/
|
||||||
|
|
||||||
|
return new ZorkItem(
|
||||||
|
source.subPropertyValue("name", ""),
|
||||||
|
source.subPropertyValue("description", ""),
|
||||||
|
source.subPropertyValue("status", ""),
|
||||||
|
source.subPropertyValue("writing", ""),
|
||||||
|
triggers,
|
||||||
|
prints,
|
||||||
|
actions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.github.dtschust.zork.parser.strategies;
|
||||||
|
|
||||||
|
import com.github.dtschust.zork.ZorkTrigger;
|
||||||
|
import com.github.dtschust.zork.parser.Property;
|
||||||
|
import com.github.dtschust.zork.parser.PropertyParseStrategy;
|
||||||
|
import com.github.dtschust.zork.parser.TriggerPropertyParseStrategy;
|
||||||
|
import com.github.dtschust.zork.types.ZorkDirection;
|
||||||
|
import com.github.dtschust.zork.types.ZorkRoom;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ZorkRoomParseStrategy implements PropertyParseStrategy<ZorkRoom> {
|
||||||
|
|
||||||
|
private final TriggerPropertyParseStrategy triggerStrategy;
|
||||||
|
|
||||||
|
public ZorkRoomParseStrategy(final TriggerPropertyParseStrategy triggerStrategy) {
|
||||||
|
this.triggerStrategy = triggerStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZorkRoom parse(final Property source) {
|
||||||
|
// Get all possible Room attributes
|
||||||
|
|
||||||
|
final String name = source.subPropertyValue("name", "");
|
||||||
|
|
||||||
|
final String description = source.subPropertyValue("description", "");
|
||||||
|
|
||||||
|
final String type = source.subPropertyValue("type", "regular");
|
||||||
|
|
||||||
|
final List<ZorkTrigger> triggers = source.subPropertiesByName("trigger").stream()
|
||||||
|
.map(triggerStrategy.parse(source))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final String status = source.subPropertyValue("status", "");
|
||||||
|
|
||||||
|
final List<String> items = source.subPropertyValues("item");
|
||||||
|
final List<String> creatures = source.subPropertyValues("creature");
|
||||||
|
final List<String> containers = source.subPropertyValues("container");
|
||||||
|
|
||||||
|
final Map<ZorkDirection, String> borders = source.subPropertiesByName("border").stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
e -> ZorkDirection.fromLong(e.subPropertyValue("direction")),
|
||||||
|
e -> e.subPropertyValue("name")
|
||||||
|
));
|
||||||
|
|
||||||
|
return new ZorkRoom(name, description, type, status, triggers, borders, containers, items, creatures);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.github.dtschust.zork.parser.strategies;
|
||||||
|
|
||||||
|
import com.github.dtschust.zork.ZorkCommand;
|
||||||
|
import com.github.dtschust.zork.ZorkCondition;
|
||||||
|
import com.github.dtschust.zork.ZorkTrigger;
|
||||||
|
import com.github.dtschust.zork.parser.Property;
|
||||||
|
import com.github.dtschust.zork.parser.PropertyParseStrategy;
|
||||||
|
import com.github.dtschust.zork.parser.TriggerPropertyParseStrategy;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ZorkTriggerParseStrategy implements TriggerPropertyParseStrategy {
|
||||||
|
|
||||||
|
private final PropertyParseStrategy<ZorkCondition> conditionStrategy;
|
||||||
|
|
||||||
|
public ZorkTriggerParseStrategy(final PropertyParseStrategy<ZorkCondition> conditionStrategy) {
|
||||||
|
this.conditionStrategy = conditionStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ZorkTrigger parseTrigger(final Property source, final Property parent) {
|
||||||
|
final String type = parent.subPropertyValue("type", "single");
|
||||||
|
|
||||||
|
final List<ZorkCommand> commands = source.subPropertiesByName("command").stream()
|
||||||
|
.map(Property::value)
|
||||||
|
.map(ZorkCommand::new)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final List<ZorkCondition> conditions = source.subPropertiesByName("condition").stream()
|
||||||
|
.map(conditionStrategy::parse)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final List<String> prints = source.subPropertyValues("print");
|
||||||
|
final List<String> actions = source.subPropertyValues("action");
|
||||||
|
|
||||||
|
return new ZorkTrigger(type, conditions, commands, prints, actions);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
package com.github.dtschust.zork.repl.actions;
|
package com.github.dtschust.zork.repl.actions;
|
||||||
|
|
||||||
import com.github.dtschust.zork.Zork.Type;
|
|
||||||
import com.github.dtschust.zork.ZorkGame;
|
import com.github.dtschust.zork.ZorkGame;
|
||||||
import com.github.dtschust.zork.repl.Action;
|
import com.github.dtschust.zork.repl.Action;
|
||||||
import com.github.dtschust.zork.types.HasSetOfCollectable;
|
import com.github.dtschust.zork.types.HasSetOfCollectable;
|
||||||
|
import com.github.dtschust.zork.types.ZorkGameStatusType;
|
||||||
import com.github.dtschust.zork.types.ZorkObject;
|
import com.github.dtschust.zork.types.ZorkObject;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -29,8 +29,8 @@ public class AddAction implements Action {
|
||||||
final String destination = arguments.get(3);
|
final String destination = arguments.get(3);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Type destType = game.getTypeFromLookup(destination);
|
ZorkGameStatusType destType = game.getTypeFromLookup(destination);
|
||||||
Type objType = game.getTypeFromLookup(object);
|
ZorkGameStatusType objType = game.getTypeFromLookup(object);
|
||||||
ZorkObject tempObject = game.get(destType, destination);
|
ZorkObject tempObject = game.get(destType, destination);
|
||||||
((HasSetOfCollectable) tempObject).getSetFromType(objType).add(object);
|
((HasSetOfCollectable) tempObject).getSetFromType(objType).add(object);
|
||||||
game.put(destType, tempObject);
|
game.put(destType, tempObject);
|
||||||
|
|
|
@ -6,7 +6,7 @@ import com.github.dtschust.zork.types.ZorkCreature;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.github.dtschust.zork.Zork.Type.CREATURE;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.CREATURE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt an attack, do you feel lucky?
|
* Attempt an attack, do you feel lucky?
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
package com.github.dtschust.zork.repl.actions;
|
package com.github.dtschust.zork.repl.actions;
|
||||||
|
|
||||||
import com.github.dtschust.zork.Zork.Type;
|
|
||||||
import com.github.dtschust.zork.ZorkGame;
|
import com.github.dtschust.zork.ZorkGame;
|
||||||
import com.github.dtschust.zork.repl.Action;
|
import com.github.dtschust.zork.repl.Action;
|
||||||
import com.github.dtschust.zork.types.HasSetOfCollectable;
|
import com.github.dtschust.zork.types.HasSetOfCollectable;
|
||||||
|
import com.github.dtschust.zork.types.ZorkGameStatusType;
|
||||||
import com.github.dtschust.zork.types.ZorkObject;
|
import com.github.dtschust.zork.types.ZorkObject;
|
||||||
import com.github.dtschust.zork.types.ZorkRoom;
|
import com.github.dtschust.zork.types.ZorkRoom;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static com.github.dtschust.zork.Zork.Type.*;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete: figure out what object it is and delete it accordingly. Rooms are especially tricky
|
* Delete: figure out what object it is and delete it accordingly. Rooms are especially tricky
|
||||||
*/
|
*/
|
||||||
public class DeleteAction implements Action {
|
public class DeleteAction implements Action {
|
||||||
private static void deleteElementFromSpace(ZorkGame game, Type space, Type element, String object) {
|
private static void deleteElementFromSpace(ZorkGame game, ZorkGameStatusType space, ZorkGameStatusType element, String object) {
|
||||||
for (ZorkObject tempObject : game.values(ZorkObject.class, space)) {
|
for (ZorkObject tempObject : game.values(ZorkObject.class, space)) {
|
||||||
Set<String> set = ((HasSetOfCollectable) tempObject).getSetFromType(element);
|
Set<String> set = ((HasSetOfCollectable) tempObject).getSetFromType(element);
|
||||||
if (set.contains(object)) {
|
if (set.contains(object)) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import com.github.dtschust.zork.types.ZorkRoom;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.github.dtschust.zork.Zork.Type.ROOM;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.ROOM;
|
||||||
|
|
||||||
public class DropItemAction implements Action {
|
public class DropItemAction implements Action {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,7 +6,7 @@ import com.github.dtschust.zork.types.ZorkContainer;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.github.dtschust.zork.Zork.Type.CONTAINER;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.CONTAINER;
|
||||||
|
|
||||||
public class OpenAction implements Action {
|
public class OpenAction implements Action {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,7 +6,7 @@ import com.github.dtschust.zork.types.ZorkContainer;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.github.dtschust.zork.Zork.Type.CONTAINER;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.CONTAINER;
|
||||||
|
|
||||||
public class PutAction implements Action {
|
public class PutAction implements Action {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,7 +6,7 @@ import com.github.dtschust.zork.types.ZorkItem;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.github.dtschust.zork.Zork.Type.ITEM;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.ITEM;
|
||||||
|
|
||||||
public class ReadAction implements Action {
|
public class ReadAction implements Action {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,8 +7,8 @@ import com.github.dtschust.zork.types.ZorkRoom;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.github.dtschust.zork.Zork.Type.CONTAINER;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.CONTAINER;
|
||||||
import static com.github.dtschust.zork.Zork.Type.ROOM;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.ROOM;
|
||||||
|
|
||||||
public class TakeAction implements Action {
|
public class TakeAction implements Action {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,7 +6,7 @@ import com.github.dtschust.zork.types.ZorkItem;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.github.dtschust.zork.Zork.Type.ITEM;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.ITEM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn on an item
|
* Turn on an item
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
package com.github.dtschust.zork.types;
|
package com.github.dtschust.zork.types;
|
||||||
|
|
||||||
import com.github.dtschust.zork.Zork;
|
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public interface HasSetOfCollectable {
|
public interface HasSetOfCollectable {
|
||||||
|
|
||||||
default Set<String> getSetFromType(Zork.Type type) {
|
default Set<String> getSetFromType(ZorkGameStatusType type) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package com.github.dtschust.zork.types;
|
package com.github.dtschust.zork.types;
|
||||||
|
|
||||||
import com.github.dtschust.zork.Zork;
|
|
||||||
import com.github.dtschust.zork.ZorkTrigger;
|
import com.github.dtschust.zork.ZorkTrigger;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static com.github.dtschust.zork.Zork.Type.ITEM;
|
import static com.github.dtschust.zork.types.ZorkGameStatusType.ITEM;
|
||||||
|
|
||||||
/* Container*/
|
/* Container*/
|
||||||
public class ZorkContainer extends ZorkObject implements HasSetOfCollectable {
|
public class ZorkContainer extends ZorkObject implements HasSetOfCollectable {
|
||||||
|
@ -59,7 +58,7 @@ public class ZorkContainer extends ZorkObject implements HasSetOfCollectable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getSetFromType(Zork.Type type) {
|
public Set<String> getSetFromType(ZorkGameStatusType type) {
|
||||||
if (type.equals(ITEM))
|
if (type.equals(ITEM))
|
||||||
return items;
|
return items;
|
||||||
throw new IllegalStateException("Unexpected value: " + type);
|
throw new IllegalStateException("Unexpected value: " + type);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.github.dtschust.zork.types;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public enum ZorkGameStatusType {
|
||||||
|
ROOM("room"),
|
||||||
|
ITEM("item"),
|
||||||
|
CONTAINER("container"),
|
||||||
|
CREATURE("creature");
|
||||||
|
|
||||||
|
private final String propertyName;
|
||||||
|
|
||||||
|
ZorkGameStatusType(final String propertyName) {
|
||||||
|
this.propertyName = propertyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<ZorkGameStatusType> fromPropertyName(final String propertyName) {
|
||||||
|
return EnumSet.allOf(ZorkGameStatusType.class).stream().filter(e -> e.propertyName.equals(propertyName)).findFirst();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package com.github.dtschust.zork.types;
|
package com.github.dtschust.zork.types;
|
||||||
|
|
||||||
|
|
||||||
import com.github.dtschust.zork.Zork;
|
|
||||||
import com.github.dtschust.zork.ZorkTrigger;
|
import com.github.dtschust.zork.ZorkTrigger;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -32,7 +31,7 @@ public class ZorkRoom extends ZorkObject implements HasSetOfCollectable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getSetFromType(Zork.Type type) {
|
public Set<String> getSetFromType(ZorkGameStatusType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CONTAINER:
|
case CONTAINER:
|
||||||
return getContainer();
|
return getContainer();
|
||||||
|
|
Reference in a new issue