/**
*
*/
package cz.cuni.mff.abacs.burglar.logics.storage;
import cz.cuni.mff.abacs.burglar.logics.DataMap;
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.Inventory;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Item;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.*;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Creates a DOM XML tree and then prints the XML.
*
* Static class.
*
* @author abacs
*
*/
public class XMLSaver extends XMLBase {
// -------------------------------------------------------------------------
// constructors:
/**
* Private constructor to prevent object creation.
*/
private XMLSaver() { }
// -------------------------------------------------------------------------
// public functions:
/**
* Saves the map object to a file.
*
* @param map map object to save.
* @param fileName name of the target file.
*/
public static void save(DataMap map, String fileName) {
XMLSaver.writeToFile(generateXML(map), fileName);
}
/**
* Saves the map object to a stream.
*
* @param map map object to save.
* @param outstream output stream as the target to write.
*/
public static void save(DataMap map, OutputStream outstream) {
XMLSaver.writeToStream(generateXML(map), outstream);
}
/**
* Saves the map object to a string.
*
* @param map map object to save.
*/
public static String generateXML(DataMap map) {
try {
// Creating an empty XML Document
// We need a Document
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.newDocument();
// Creating the XML tree
// create the root element and add it to the document
Element root = doc.createElement(STR_MAP);
doc.appendChild(root);
// create a comment and put it in the root element
Comment comment = doc.createComment("generated by burglar-game");
root.appendChild(comment);
// create child element, add an attribute, and add to root
for(Room room : map.getRooms())
root.appendChild(XMLSaver.generateRoomXML(room, doc));
for(Position position : map.getPositions())
root.appendChild(XMLSaver.generatePositionXML(position, doc));
for(Agent agent : map.getAgents())
root.appendChild(XMLSaver.generateAgentXML(agent, doc));
root.appendChild(XMLSaver.generateNotesXML(map.getLevelNotes(), doc));
// Output the XML
// set up a transformer
TransformerFactory transfac = TransformerFactory.newInstance();
Transformer trans = transfac.newTransformer();
trans.setOutputProperty(OutputKeys.INDENT, "yes");
// create string from XML tree
StringWriter sWriter = new StringWriter();
StreamResult result = new StreamResult(sWriter);
DOMSource source = new DOMSource(doc);
trans.transform(source, result);
return sWriter.toString();
}catch (Exception e){
System.err.println(e);
}
return "";
}
// -------------------------------------------------------------------------
/**
* Creates a room XML object.
*
* @param obj room object.
* @param doc document to write.
* @return The created XML element.
*/
private static Element generateRoomXML(Room obj, Document doc) {
Element child = doc.createElement(STR_ROOM);
int id = obj.getId();
child.setAttribute(STR_ID, String.valueOf(id));
int x = obj.getX();
child.setAttribute(STR_X, String.valueOf(x));
int y = obj.getY();
child.setAttribute(STR_Y, String.valueOf(y));
int width = obj.getWidth();
child.setAttribute(STR_WIDTH, String.valueOf(width));
int height = obj.getHeight();
child.setAttribute(STR_HEIGHT, String.valueOf(height));
boolean is_lit = obj.getIsLit();
child.setAttribute(STR_IS_LIT, String.valueOf(is_lit));
return child;
}
/**
* Creates a position XML object.
*
* @param obj position object.
* @param doc document to write.
* @return The created XML element.
*/
private static Element generatePositionXML(Position obj, Document doc) {
switch(obj.getType()){
case CAMERA:
return generateCameraXML((Camera)obj, doc);
case CONTAINER:
return generateContainerXML((Container)obj, doc);
case DOOR:
return generateDoorXML((Door)obj, doc);
case FLOOR:
return generateFloorXML((Floor)obj, doc);
case PHONE:
return generatePhoneXML((Phone)obj, doc);
case SWITCH:
return generateSwitchXML((Switch)obj, doc);
case VENDER:
return generateVenderXML((Vender)obj, doc);
default:
return doc.createElement("position");
}
}
/**
* Creates an agent XML object.
*
* @param obj agent object.
* @param doc document to write.
* @return The created XML element.
*/
private static Element generateAgentXML(Agent obj, Document doc) {
switch(obj.getType()){
case BURGLAR:
return generateBurglarXML((Burglar)obj, doc);
case GUARD:
return generateGuardXML((Guard)obj, doc);
default:
return null;
}
}
// -------------------------------------------------------------------------
private static Element generateCameraXML(Camera camera, Document doc) {
Element child = doc.createElement(STR_CAMERA);
int roomId = camera.getRoomId();
child.setAttribute(STR_ROOM, String.valueOf(roomId));
child.setAttribute(STR_IS_ACTIVE, String.valueOf(camera.isActive()));
setBasePositionAttributes(camera, child);
return child;
}
private static Element generateContainerXML(
Container container,
Document doc
) {
Element child = doc.createElement(STR_CONTAINER);
int roomId = container.getRoomId();
child.setAttribute(STR_ROOM, String.valueOf(roomId));
child.setAttribute(STR_IS_CLOSED, String.valueOf(container.isClosed()));
child.setAttribute(STR_IS_LOCKED, String.valueOf(container.isLocked()));
child.setAttribute(STR_KEY, String.valueOf(container.getKeyId()));
child.appendChild(addInventoryXML(container, doc));
setBasePositionAttributes(container, child);
return child;
}
private static Element generateDoorXML(Door door, Document doc) {
Element child = doc.createElement(STR_DOOR);
int[] roomIds = door.getRoomIds();
child.setAttribute(STR_FROM_ROOM, String.valueOf(roomIds[0]));
child.setAttribute(STR_TO_ROOM, String.valueOf(roomIds[1]));
child.setAttribute(STR_IS_CLOSED, String.valueOf(door.isClosed()));
child.setAttribute(STR_IS_LOCKED, String.valueOf(door.isLocked()));
child.setAttribute(STR_KEY, String.valueOf(door.getKeyId()));
setBasePositionAttributes(door, child);
return child;
}
private static Element generateFloorXML(Floor floor, Document doc) {
Element child = doc.createElement(STR_FLOOR);
int roomId = floor.getRoomId();
child.setAttribute(STR_ROOM, String.valueOf(roomId));
setBasePositionAttributes(floor, child);
return child;
}
private static Element generatePhoneXML(Phone phone, Document doc) {
Element child = doc.createElement(STR_PHONE);
int roomId = phone.getRoomId();
child.setAttribute(STR_ROOM, String.valueOf(roomId));
child.setAttribute(STR_IS_ACTIVE, String.valueOf(phone.isActive()));
setBasePositionAttributes(phone, child);
return child;
}
private static Element generateSwitchXML(Switch switchObj, Document doc) {
Element child = doc.createElement(STR_SWITCH);
int roomId = switchObj.getRoomId();
child.setAttribute(STR_ROOM, String.valueOf(roomId));
// TODO
setBasePositionAttributes(switchObj, child);
return child;
}
private static Element generateVenderXML(Vender vender, Document doc) {
Element child = doc.createElement(STR_VENDER);
int roomId = vender.getRoomId();
child.setAttribute(STR_ROOM, String.valueOf(roomId));
child.setAttribute(STR_HAS_DROPPED, String.valueOf(vender.hasDropped()));
setBasePositionAttributes(vender, child);
return child;
}
private static void setBasePositionAttributes(
Position position,
Element element
) {
int id = position.getId();
element.setAttribute(STR_ID, String.valueOf(id));
int x = position.getX();
element.setAttribute(STR_X, String.valueOf(x));
int y = position.getY();
element.setAttribute(STR_Y, String.valueOf(y));
}
private static Element generateBurglarXML(Burglar burglar, Document doc) {
Element child = doc.createElement(STR_BURGLAR);
child.setAttribute(STR_POSITION, String.valueOf(burglar.getPositionId()));
child.appendChild(addInventoryXML(burglar, doc));
child.appendChild(addBurglarGoalXML(burglar, doc));
child.appendChild(addBeliefBaseXML(burglar, doc));
setBaseAgentAttributes(burglar, child);
return child;
}
private static Element generateGuardXML(Guard guard, Document doc) {
Element child = doc.createElement(STR_GUARD);
child.setAttribute(STR_POSITION, String.valueOf(guard.getPositionId()));
child.setAttribute(STR_IS_STUNNED, String.valueOf(guard.isInState(Agent.State.STUNNED)));
child.appendChild(addInventoryXML(guard, doc));
child.appendChild(addGuardGoalXML(guard, doc));
child.appendChild(addBeliefBaseXML(guard, doc));
setBaseAgentAttributes(guard, child);
return child;
}
private static void setBaseAgentAttributes(
Agent agent,
Element element
) {
int id = agent.getId();
element.setAttribute(STR_ID, String.valueOf(id));
int positionId = agent.getPosition().getId();
element.setAttribute(STR_POSITION, String.valueOf(positionId));
}
private static Element addBurglarGoalXML(
Burglar burglar,
Document doc
) {
Element goal = doc.createElement(STR_GOAL);
goal.setAttribute(STR_AIM, String.valueOf(burglar.getAimId()));
goal.setAttribute(STR_COLLECT, String.valueOf(burglar.getItemIdToCollect()));
return goal;
}
private static Element addGuardGoalXML(
Guard guard,
Document doc
) {
Element goal = doc.createElement(STR_GOAL);
for(Integer roomId : guard.getAllGoalRooms()){
Element room = doc.createElement(STR_ROOM);
room.setAttribute(STR_ID, String.valueOf(roomId));
goal.appendChild(room);
}
return goal;
}
private static Element addInventoryXML(
Inventory inv,
Document doc
) {
Element inventory = doc.createElement(STR_INVENTORY);
for(Item item : inv.getItems())
inventory.appendChild(generateItemXML(item, doc));
return inventory;
}
private static Element generateItemXML(
Item item,
Document doc
) {
Element element;
switch(item.getType()){
case KEY:
element = doc.createElement(STR_KEY);
break;
case LADDER:
element = doc.createElement(STR_LADDER);
break;
case TREASURE:
element = doc.createElement(STR_TREASURE);
break;
default:
return null;
}
int id = item.getId();
element.setAttribute(STR_ID, String.valueOf(id));
return element;
}
private static Element addBeliefBaseXML(
Agent agent,
Document doc
) {
Element bBaseElement = doc.createElement(STR_BELIEFBASE);
BeliefBase bb = agent.getBeliefBase();
for(Position position : bb.getKnownPositions()){
Element posElement = generatePositionXML(position, doc);
bBaseElement.appendChild(posElement);
}
return bBaseElement;
}
private static Element generateNotesXML(List<String> notes, Document doc) {
Element notesElement = doc.createElement(STR_NOTES);
for(String note : notes){
Element noteElement = doc.createElement(STR_NOTE);
noteElement.setTextContent(note);
notesElement.appendChild(noteElement);
}
return notesElement;
}
}