/**
*
*/
package cz.cuni.mff.abacs.burglar.logics.storage;
import cz.cuni.mff.abacs.burglar.logics.DataMap;
import cz.cuni.mff.abacs.burglar.logics.ExecutingMap;
import cz.cuni.mff.abacs.burglar.logics.objects.Room;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Agent;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.BeliefBase;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Burglar;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Guard;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Item;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Key;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Treasure;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Uniform;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.*;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Static class, it's sole function is to loads a map from an XML file.
*
* @author abacs
*
*/
public class XMLLoader extends XMLBase {
// -------------------------------------------------------------------------
// constructors:
/**
* Private constructor to prevent object creation.
*/
private XMLLoader() { }
// -------------------------------------------------------------------------
// public functions:
/**
* Loads a map file.
*
* @param filename map name
* @return level representation
*/
public static ExecutingMap load(String filename) {
Document doc = XMLBase.parseXmlFile(filename);
return fillMap(doc);
}
/**
* Loads a map file.
*
* @param inputStream loads from an input stream
* @return level representation
*/
public static ExecutingMap load(InputStream inputStream) {
Document doc = XMLBase.parseXmlStream(inputStream);
return fillMap(doc);
}
/**
* Loads a map file.
*
* @param doc input source
* @return level representation
*/
public static ExecutingMap fillMap(Document doc) {
if(doc == null)
return null;
// get the root element
Element root = doc.getDocumentElement();
ExecutingMap ret =
new ExecutingMap(
XMLLoader.getHighestID(root) + 1,
XMLLoader.getRequiredTrapRoomCount(root)
);
ret.addRooms(XMLLoader.getRooms(root, ret));
ret.addPositions(XMLLoader.getPositions(root, ret));
ret.addAgents(XMLLoader.getAgents(root, ret));
ret.addItems(XMLLoader.getItems(root, ret));
ret.addLevelNotes(XMLLoader.getNotes(root));
ret.connectPositions();
return ret;
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// private implementation:
/**
* Returns the highest id used in the map.
* */
private static int getHighestID(Element root) {
int ret = 0;
// get any element:
NodeList nodes = root.getElementsByTagName("*");
if(nodes == null || nodes.getLength() == 0)
return ret;
// find the largest id:
for(int i = 0; i < nodes.getLength(); i++){
Element element = (Element)nodes.item(i);
int id = XMLBase.getIntAttrOrZero(element, STR_ID);
if(id > ret)
ret = id;
}
// return:
return ret;
}
private static int getRequiredTrapRoomCount(Element root) {
if(root.getNodeName().equals(STR_MAP)){
return XMLBase.getIntAttrOrZero(root, STR_TRAP_COUNT);
}
// get a node list of selected elements:
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if(
node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_MAP)
){
// get the element
Element pathElement = (Element)node;
return XMLBase.getIntAttrOrZero(pathElement, STR_TRAP_COUNT);
}
}
return 0;
}
// -------------------------------------------------------------------------
private static List<Position> getPositions(Element root, DataMap map) {
List<Position> ret = new ArrayList<Position>();
ret.addAll(XMLLoader.getCameras(root, map));
ret.addAll(XMLLoader.getContainers(root, map));
ret.addAll(XMLLoader.getDoors(root, map));
ret.addAll(XMLLoader.getFloors(root, map));
ret.addAll(XMLLoader.getPhones(root, map));
ret.addAll(XMLLoader.getSwitches(root, map));
ret.addAll(XMLLoader.getVenders(root, map));
return ret;
}
private static List<Agent> getAgents(Element root, DataMap map) {
List<Agent> ret = new ArrayList<Agent>();
ret.add(XMLLoader.getBurglar(root, map));
ret.addAll(XMLLoader.getGuards(root, map));
return ret;
}
private static List<Item> getItems(Element root, DataMap map) {
List<Item> ret = new ArrayList<Item>();
ret.addAll(XMLLoader.getTreasures(root, map));
ret.addAll(XMLLoader.getKeys(root, map));
return ret;
}
// -------------------------------------------------------------------------
// room:
/**
* Returns all rooms in the map.
*
* @param root
* @param nextFreeId
* @return list of all rooms
*/
private static List<Room> getRooms(Element root, DataMap map) {
List<Room> ret = new ArrayList<Room>();
// get a node list of selected elements:
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if(
node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_ROOM)
){
Room room = XMLLoader.getRoom((Element)node, map);
ret.add(room);
}
}
return ret;
}
/**
* Returns a single room in the map.
*
* @param room_element
* @param nextFreeId
* @return room
*/
private static Room getRoom(Element roomElement, DataMap map) {
// get the attributes:
int x = XMLBase.getIntAttrOrZero(roomElement, STR_X);
int y = XMLBase.getIntAttrOrZero(roomElement, STR_Y);
int width = XMLBase.getIntAttrOrZero(roomElement, STR_WIDTH);
int height = XMLBase.getIntAttrOrZero(roomElement, STR_HEIGHT);
boolean isLit = XMLBase.getBooleanAttrOrTrue(roomElement, STR_IS_LIT);
int id;
try{
id = Integer.parseInt(roomElement.getAttribute(STR_ID));
}catch(NumberFormatException e){
id = map.getNextID();
}
// create the Room object
Room room = new Room(id, x, y, height, width, map);
room.setIsLit(isLit);
return room;
}
// -------------------------------------------------------------------------
// cameras:
private static List<Position> getCameras(Element root, DataMap map) {
List<Position> ret = new ArrayList<Position>();
// get a node list of selected elements:
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if(
node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_CAMERA)
){
Position camera = XMLLoader.getCamera((Element)node, map);
ret.add(camera);
}
}
return ret;
}
private static Position getCamera(
Element cameraElement,
DataMap map
) {
// get the attributes:
int id = XMLBase.getIntAttrOrZero(cameraElement, STR_ID);
int x = XMLBase.getIntAttrOrZero(cameraElement, STR_X);
int y = XMLBase.getIntAttrOrZero(cameraElement, STR_Y);
boolean isActive =
XMLBase.getBooleanAttrOrFalse(cameraElement, STR_IS_ACTIVE);
Room room;
try{
int roomId =
Integer.parseInt(cameraElement.getAttribute(STR_ROOM));
room = map.getRoom(roomId);
}catch(NumberFormatException e){
room = null;
}
// create the object
return new Camera(id, x, y, room, isActive, map);
}
// -------------------------------------------------------------------------
// containers:
private static List<Position> getContainers(Element root, DataMap map) {
List<Position> ret = new ArrayList<Position>();
// get a node list of selected elements
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if(
node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_CONTAINER)
){
Position container =
XMLLoader.getContainer((Element)node, map);
ret.add(container);
}
}
return ret;
}
private static Position getContainer(
Element containerElement,
DataMap map
) {
// get the attributes:
int id = XMLBase.getIntAttrOrZero(containerElement, STR_ID);
int x = XMLBase.getIntAttrOrZero(containerElement, STR_X);
int y = XMLBase.getIntAttrOrZero(containerElement, STR_Y);
int roomId = XMLBase.getIntAttrOrZero(containerElement, STR_ROOM);
int keyId = XMLBase.getIntAttrOrZero(containerElement, STR_KEY);
boolean isLocked =
XMLBase.getBooleanAttrOrFalse(containerElement, STR_IS_LOCKED);
boolean isClosed =
XMLBase.getBooleanAttrOrTrue(containerElement, STR_IS_CLOSED);
// create the object
Room room = map.getRoom(roomId);
Container container;
if(keyId == 0) {
container = new Container(id, x, y, room, isClosed, map);
}else{
container = new Container(id, x, y, room, isClosed, isLocked, keyId, map);
}
// fill the inventory:
NodeList rawList = containerElement.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if(
node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_INVENTORY)
){
List<Item> items = XMLLoader.getItems((Element)node, map);
map.addItems(items);
container.addItems(items);
}
}
return container;
}
// -------------------------------------------------------------------------
// doors:
private static List<Position> getDoors(Element root, DataMap map) {
List<Position> ret = new ArrayList<Position>();
// get a node list of selected elements
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if(
node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_DOOR)
){
// get the element
Element doorElement = (Element)node;
Position door = XMLLoader.getDoor(doorElement, map);
// add it to list
ret.add(door);
}
}
return ret;
}
private static Position getDoor(Element doorElement, DataMap map) {
// get the attributes:
int id = XMLBase.getIntAttrOrZero(doorElement, STR_ID);
int x = XMLBase.getIntAttrOrZero(doorElement, STR_X);
int y = XMLBase.getIntAttrOrZero(doorElement, STR_Y);
int fromRoom = XMLBase.getIntAttrOrZero(doorElement, STR_FROM_ROOM);
int toRoom = XMLBase.getIntAttrOrZero(doorElement, STR_TO_ROOM);
int keyId = XMLBase.getIntAttrOrZero(doorElement, STR_KEY);
boolean isLocked =
XMLBase.getBooleanAttrOrFalse(doorElement, STR_IS_LOCKED);
boolean isClosed =
XMLBase.getBooleanAttrOrTrue(doorElement, STR_IS_CLOSED);
// create the object
Room from = map.getRoom(fromRoom);
Room to = map.getRoom(toRoom);
// if(keyId == 0){
// return new Door(id, x, y, from, to, isClosed, map);
// }else{
return new Door(id, x, y, from, to, isClosed, isLocked, keyId, map);
// }
}
// -------------------------------------------------------------------------
// floors:
/**
*
* It also sets onPath to true.
*
* @param root
* @param map
* @return
*/
private static List<Position> getFloors(Element root, DataMap map) {
List<Position> ret = new ArrayList<Position>();
// get a node list of selected elements
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_FLOOR)
){
// get the element
Element floorElement = (Element)node;
// create the object
Position floor = XMLLoader.getFloor(floorElement, map);
ret.add(floor);
}
}
return ret;
}
/**
*
* It also sets onPath to true.
*
* @param floorElement
* @param map
* @return
*/
private static Position getFloor(Element floorElement, DataMap map) {
// get the attributes:
int id = XMLBase.getIntAttrOrZero(floorElement, STR_ID);
int x = XMLBase.getIntAttrOrZero(floorElement, STR_X);
int y = XMLBase.getIntAttrOrZero(floorElement, STR_Y);
Room room;
try{
int roomId =
Integer.parseInt(floorElement.getAttribute(STR_ROOM));
room = map.getRoom(roomId);
}catch(NumberFormatException e){
room = null;
}
// create the object
return new Floor(id, x, y, room, map);
}
// -------------------------------------------------------------------------
// phones:
private static List<Position> getPhones(Element root, DataMap map) {
List<Position> ret = new ArrayList<Position>();
// get a node list of selected elements
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_PHONE)
){
// get the element
Element phoneElement = (Element)node;
// create the object
Position phone = XMLLoader.getPhone(phoneElement, map);
ret.add(phone);
}
}
return ret;
}
private static Position getPhone(Element phoneElement, DataMap map) {
// get the attributes:
int id = XMLBase.getIntAttrOrZero(phoneElement, STR_ID);
int x = XMLBase.getIntAttrOrZero(phoneElement, STR_X);
int y = XMLBase.getIntAttrOrZero(phoneElement, STR_Y);
Boolean isRinging =
XMLBase.getBooleanAttrOrFalse(phoneElement, STR_IS_RINGING);
Room room;
try{
int roomId = Integer.parseInt(phoneElement.getAttribute(STR_ROOM));
room = map.getRoom(roomId);
}catch(NumberFormatException e){
room = null;
}
// create the object
return new Phone(id, x, y, room, isRinging, map);
}
// -------------------------------------------------------------------------
// switches:
private static List<Position> getSwitches(Element root, DataMap map) {
List<Position> ret = new ArrayList<Position>();
// get a node list of selected elements
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_SWITCH)
){
// get the element
Element switchElement = (Element)node;
// create the object
Position position = XMLLoader.getSwitch(switchElement, map);
ret.add(position);
}
}
return ret;
}
private static Position getSwitch(Element switchElement, DataMap map) {
// get the attributes:
int id = XMLBase.getIntAttrOrZero(switchElement, STR_ID);
int x = XMLBase.getIntAttrOrZero(switchElement, STR_X);
int y = XMLBase.getIntAttrOrZero(switchElement, STR_Y);
int targetId = XMLBase.getIntAttrOrZero(switchElement, STR_TARGET);
Room room;
try{
int roomId = Integer.parseInt(switchElement.getAttribute(STR_ROOM));
room = map.getRoom(roomId);
}catch(NumberFormatException e){
room = null;
}
// create the object
return new Switch(id, x, y, room, targetId, map);
}
// -------------------------------------------------------------------------
// venders:
private static List<Position> getVenders(Element root, DataMap map) {
List<Position> ret = new ArrayList<Position>();
// get a node list of selected elements
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_VENDER)
){
// get the element
Element venderElement = (Element)node;
// create the object
Position vender = XMLLoader.getVender(venderElement, map);
ret.add(vender);
}
}
return ret;
}
private static Position getVender(Element venderElement, DataMap map) {
// get the attributes:
int id = XMLBase.getIntAttrOrZero(venderElement, STR_ID);
int x = XMLBase.getIntAttrOrZero(venderElement, STR_X);
int y = XMLBase.getIntAttrOrZero(venderElement, STR_Y);
boolean hasDropped =
XMLBase.getBooleanAttrOrFalse(venderElement, STR_HAS_DROPPED);
Room room;
try{
int roomId = Integer.parseInt(venderElement.getAttribute(STR_ROOM));
room = map.getRoom(roomId);
}catch(NumberFormatException e){
room = null;
}
// create the object
return new Vender(id, x, y, room, hasDropped, map);
}
// -------------------------------------------------------------------------
// burglar:
private static Agent getBurglar(Element root, DataMap map) {
// get a node list of selected elements
NodeList nodes = root.getElementsByTagName(STR_BURGLAR);
if(nodes == null || nodes.getLength() == 0)
return null;
// get the element
Element burglarElement = (Element)nodes.item(0);
// get the attributes:
int id =
XMLBase.getIntAttrOrZero(burglarElement, STR_ID);
int positionId =
XMLBase.getIntAttrOrZero(burglarElement, STR_POSITION);
int aimId = -1;
int collectId = -1;
NodeList rawList = burglarElement.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
// fill the goals:
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_GOAL)
){
aimId =
XMLBase.getIntAttrOrZero((Element)node, STR_AIM);
collectId =
XMLBase.getIntAttrOrZero((Element)node, STR_COLLECT);
}
}
Position position = map.getPosition(positionId);
Room aim = map.getRoom(aimId);
// create the object:
Burglar burglar = new Burglar(id, position, aim, collectId, map);
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
// fill the belief base object:
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_BELIEFBASE)
){
Element mind = (Element)node;
BeliefBase knowledge = burglar.getBeliefBase();
knowledge.seenFromNear(XMLLoader.getPositions(mind, map));
}
// fill the inventory:
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_INVENTORY)
){
Element inventory = (Element)node;
List<Item> items = XMLLoader.getItems(inventory, map);
map.addItems(items);
burglar.addItems(items);
}
}
return burglar;
}
// -------------------------------------------------------------------------
// guards:
private static List<Agent> getGuards(Element root, DataMap map) {
List<Agent> ret = new ArrayList<Agent>();
// get a node list of selected elements
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_GUARD)
){
// get the element
Element guardElement = (Element)node;
// create the object
Agent agent = XMLLoader.getGuard(guardElement, map);
ret.add(agent);
}
}
return ret;
}
private static Agent getGuard(Element guardElement, DataMap map) {
// get the attributes:
int id = XMLBase.getIntAttrOrZero(guardElement, STR_ID);
int positionId = XMLBase.getIntAttrOrZero(guardElement, STR_POSITION);
boolean isStunned = XMLBase.getBooleanAttrOrFalse(guardElement, STR_IS_STUNNED);
Position position = map.getPosition(positionId);
List<Integer> pathPositions = new LinkedList<Integer>();
NodeList rawList = guardElement.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_GOAL)
){
// get the element
Element goalElement = (Element)node;
List<Integer> routePositionIds =
XMLLoader.getRoomIds(goalElement, map);
pathPositions.addAll(routePositionIds);
}
}
// create the object
Guard guard = new Guard(id, position, pathPositions, map);
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
// fill the belief base object:
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_BELIEFBASE)
){
Element mind = (Element)node;
BeliefBase knowledge = guard.getBeliefBase();
knowledge.seenFromNear(XMLLoader.getPositions(mind, map));
}
// fill the inventory:
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_INVENTORY)
){
Element inventory = (Element)node;
List<Item> items = XMLLoader.getItems(inventory, map);
map.addItems(items);
guard.addItems(items);
}
}
// add the uniform:
Uniform clothes = new Uniform(map.getNextID(), map);
guard.addItem(clothes);
map.addItem(clothes);
if(isStunned)
guard.daze();
return guard;
}
// -------------------------------------------------------------------------
// treasures:
private static List<Item> getTreasures(Element root, DataMap map) {
List<Item> ret = new ArrayList<Item>();
// get a node list of selected elements
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_TREASURE)
){
// get the element
Element treasureElement = (Element)node;
// create the object
Item item = XMLLoader.getTreasure(treasureElement, map);
ret.add(item);
}
}
return ret;
}
private static Item getTreasure(Element treasureElement, DataMap map) {
// get the attributes:
int id = XMLBase.getIntAttrOrZero(treasureElement, STR_ID);
// create the object:
Item item = new Treasure(id, map);
return item;
}
// -------------------------------------------------------------------------
// keys:
private static List<Item> getKeys(Element root, DataMap map) {
List<Item> ret = new ArrayList<Item>();
// get a node list of selected elements
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_KEY)
){
// get the element
Element keyElement = (Element)node;
// create the object
Item key = XMLLoader.getKey(keyElement, map);
// add it to list
ret.add(key);
}
}
return ret;
}
private static Item getKey(Element keyElement, DataMap map) {
// get the attributes:
int id = XMLBase.getIntAttrOrZero(keyElement, STR_ID);
// create the object:
Item key = new Key(id, map);
return key;
}
// -------------------------------------------------------------------------
private static List<String> getNotes(Element root) {
List<String> ret = new ArrayList<String>();
// get a node list of selected elements
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if( node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_NOTES)
){
// get the element
Element notesElement = (Element)node;
NodeList subList = notesElement.getChildNodes();
for(int j = 0; j < subList.getLength(); j++){
Node subNode = subList.item(j);
if( subNode.getNodeType() == Node.ELEMENT_NODE &&
subNode.getNodeName().equals(STR_NOTE)
){
// get the element
Element noteElement = (Element)subNode;
// create the object
String note = noteElement.getTextContent();
ret.add(note);
}
}
}
}
return ret;
}
// -------------------------------------------------------------------------
private static List<Integer> getRoomIds(Element root, DataMap map) {
List<Integer> ret = new ArrayList<Integer>();
// get a node list of selected elements
NodeList rawList = root.getChildNodes();
for(int i = 0; i < rawList.getLength(); i++){
Node node = rawList.item(i);
if(
node.getNodeType() == Node.ELEMENT_NODE &&
node.getNodeName().equals(STR_ROOM)
){
// get the element
Element roomElement = (Element)node;
// create the object
Integer id = XMLLoader.getRoomId(roomElement, map);
// add it to list
ret.add(id);
}
}
return ret;
}
private static Integer getRoomId(Element roomElement, DataMap map) {
// get the attributes:
int id = XMLBase.getIntAttrOrZero(roomElement, STR_ID);
return id;
}
}