001 package com.basilv.examples.dom4j;
002
003 import java.io.File;
004
005 import org.dom4j.*;
006 import org.dom4j.io.SAXReader;
007
008 public class MazeXmlConverter
009 {
010 private static final String MAZE_ELEMENT = "maze";
011 private static final String HEIGHT_ATTRIBUTE = "height";
012 private static final String WIDTH_ATTRIBUTE = "width";
013 private static final String WALL_ELEMENT = "wall";
014 private static final String START_X_ATTRIBUTE = "startX";
015 private static final String START_Y_ATTRIBUTE = "startY";
016 private static final String END_X_ATTRIBUTE = "endX";
017 private static final String END_Y_ATTRIBUTE = "endY";
018
019 public String toXml(Maze maze) {
020 Document document = DocumentHelper.createDocument();
021 Element root = document.addElement(MAZE_ELEMENT)
022 .addAttribute(WIDTH_ATTRIBUTE, Integer.toString(maze.getSize().width))
023 .addAttribute(HEIGHT_ATTRIBUTE, Integer.toString(maze.getSize().height))
024 .addText(nullToEmpty(maze.getDescription()));
025
026 for (Wall wall : maze.getWalls()) {
027 root.addElement(WALL_ELEMENT)
028 .addAttribute(START_X_ATTRIBUTE, Integer.toString(wall.getStart().x))
029 .addAttribute(START_Y_ATTRIBUTE, Integer.toString(wall.getStart().y))
030 .addAttribute(END_X_ATTRIBUTE, Integer.toString(wall.getEnd().x))
031 .addAttribute(END_Y_ATTRIBUTE, Integer.toString(wall.getEnd().y));
032 }
033
034 return document.asXML();
035 }
036
037 private String nullToEmpty(String text) {
038 if (text == null) {
039 return "";
040 } else {
041 return text;
042 }
043 }
044
045 public Maze fromXml(File xmlFile) {
046 SAXReader reader = new SAXReader();
047 try {
048 Document document = reader.read(xmlFile);
049 return fromXml(document);
050 } catch (DocumentException e) {
051 throw new RuntimeException("Error reading file [" + xmlFile.getAbsolutePath() + "].", e);
052 }
053 }
054
055 // For testing.
056 public Maze fromXml(String xml) {
057 try {
058 Document document = DocumentHelper.parseText(xml);
059 return fromXml(document);
060 } catch (DocumentException e) {
061 throw new RuntimeException("Error parsing xml string.", e);
062 }
063 }
064
065 private Maze fromXml(Document document) {
066 Element root = document.getRootElement();
067
068 int width = getElementIntAttribute(root, WIDTH_ATTRIBUTE);
069 int height = getElementIntAttribute(root, HEIGHT_ATTRIBUTE);
070
071 Maze maze = new Maze(width, height);
072 maze.setDescription(root.getText());
073
074 for (Object elementObj : root.elements(WALL_ELEMENT)) {
075 Element element = (Element) elementObj;
076
077 int startX = getElementIntAttribute(element, START_X_ATTRIBUTE);
078 int startY = getElementIntAttribute(element, START_Y_ATTRIBUTE);
079 int endX = getElementIntAttribute(element, END_X_ATTRIBUTE);
080 int endY = getElementIntAttribute(element, END_Y_ATTRIBUTE);
081
082 maze.addWall(startX, startY, endX, endY);
083 }
084
085 return maze;
086 }
087
088 private int getElementIntAttribute(Element element, String attributeName) {
089 Attribute attribute = getNonNullAttributeForElement(element, attributeName);
090 return Integer.parseInt(attribute.getValue());
091 }
092
093 private Attribute getNonNullAttributeForElement(Element element, String attributeName) {
094 Attribute attribute = element.attribute(attributeName);
095 if (attribute == null) {
096 throw new RuntimeException("Element [" + element.getName() + "] missing attribute named [" + attributeName + "].");
097 }
098 return attribute;
099 }
100
101 }