net.bpfurtado.tas.model.persistence.XMLAdventureReader.java Source code

Java tutorial

Introduction

Here is the source code for net.bpfurtado.tas.model.persistence.XMLAdventureReader.java

Source

/**                                                                           
 * Created by Bruno Patini Furtado [http://bpfurtado.livejournal.com]         
 * Created on 03/10/2005 17:36:44                                                          
 *                                                                            
 * This file is part of the Text Adventures Suite.                            
 *                                                                            
 * Text Adventures Suite is free software: you can redistribute it and/or modify          
 * it under the terms of the GNU General Public License as published by       
 * the Free Software Foundation, either version 3 of the License, or          
 * (at your option) any later version.                                        
 *                                                                            
 * Text Adventures Suite is distributed in the hope that it will be useful,               
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              
 * GNU General Public License for more details.                               
 *                                                                            
 * You should have received a copy of the GNU General Public License          
 * along with Text Adventures Suite.  If not, see <http://www.gnu.org/licenses/>.         
 *                                                                            
 * Project page: http://code.google.com/p/text-adventures-suite/              
 */

package net.bpfurtado.tas.model.persistence;

import java.io.File;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

import net.bpfurtado.tas.model.Adventure;
import net.bpfurtado.tas.model.IPath;
import net.bpfurtado.tas.model.Scene;
import net.bpfurtado.tas.model.SceneType;
import net.bpfurtado.tas.model.Skill;
import net.bpfurtado.tas.model.combat.Combat;
import net.bpfurtado.tas.model.combat.CombatType;
import net.bpfurtado.tas.model.combat.Fighter;

import org.apache.commons.validator.GenericValidator;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

/**
 * @author Bruno Patini Furtado
 */
public class XMLAdventureReader {
    @SuppressWarnings("unused")
    private static Logger logger = Logger.getLogger(XMLAdventureReader.class);

    private Adventure adventure;
    private Document xmlDocument;

    public XMLAdventureReader() {
        adventure = new Adventure();
    }

    public Adventure read(String adventureFileName) {
        readXMLDocument(adventureFileName);
        init();
        return adventure;
    }

    public Adventure read(File adventureFile) {
        createXMLDocument(adventureFile);
        init();
        return adventure;
    }

    private void init() {
        adventure.setName(((Node) xmlDocument.selectNodes("/adventure/name").iterator().next()).getText());
        // adventure.setId(((Node) xmlDocument.selectNodes("/adventure/id").iterator().next()).getText());

        Node assertionsNode = xmlDocument.selectSingleNode("/adventure/assertions");
        // to be compatible with old project files
        if (assertionsNode != null) {
            adventure.setAssertions(assertionsNode.getText());
        }
        readScenes();
    }

    private void readXMLDocument(String adventureFileName) {
        File adventureFile = new File(adventureFileName);
        if (!adventureFile.exists()) {
            throw new AdventureReaderException("The file [" + adventureFileName + "] does not exist");
        }
        createXMLDocument(adventureFile);
    }

    private void createXMLDocument(File file) {
        SAXReader xmlReader = new SAXReader();
        try {
            xmlDocument = xmlReader.read(file);
        } catch (DocumentException e) {
            throw new AdventureReaderException("Error reading XML document", e);
        }
    }

    @SuppressWarnings("unchecked")
    private void readScenes() {
        Node startNode = xmlDocument.selectSingleNode("//scene[@id='0']");
        Scene start = adventure.getStart();
        loadSceneAttributes(startNode, start.getId());

        Collection<Scene> allScenes = new LinkedList<Scene>();

        List<Node> scenesNodes = new LinkedList(xmlDocument.selectNodes("//scene"));
        for (Node node : scenesNodes) {
            allScenes.add(loadSceneAttributes(node, Integer.parseInt(node.valueOf("@id"))));
        }

        findAllTos(start, allScenes);

        // For the ones not visited, because can't be reached from the start scene.
        for (Scene s : allScenes) {
            findAllTos(s, null);
        }
    }

    private Scene loadSceneAttributes(Node n, int id) {
        Scene s = null;
        if (id == 0) {
            s = adventure.getStart();
        } else {
            s = adventure.createScene(id, Boolean.valueOf(n.valueOf("@isEnd")));
        }
        s.setImageId(n.valueOf("@imageId"));
        if (s.getImageId() != null && s.getImageId().trim().length() == 0) {
            s.setImageId(null);
        }

        s.setName(n.valueOf("@name"));
        s.setTags(n.valueOf("@tags"));
        s.setText(n.selectSingleNode("./text").getText());

        try {
            s.setCode(n.selectSingleNode("./code").getText());
            if (s.getCode() == null) {
                s.setCode("");
            }
        } catch (NullPointerException npe) {
            logger.warn("No code node");
        }

        loadCombat(n, s);
        loadSkillTest(n, s);

        return s;
    }

    private void loadSkillTest(Node n, Scene s) {
        Node cn = n.selectSingleNode("skill-test");
        if (cn == null) {
            return;
        }
        String name = cn.valueOf("@name");
        s.setType(SceneType.skillTest);
        s.setSkillToTest(new Skill(name));
    }

    private void loadCombat(Node n, Scene s) {
        Node cn = n.selectSingleNode("combat");
        if (cn == null) {
            return;
        }

        Combat c = new Combat();
        String type = cn.valueOf("@type");
        c.setType(CombatType.fromPersistentRepr(type));

        List<Node> enemyNodes = cn.selectNodes("./enemy");
        for (Node en : enemyNodes) {
            Fighter fighter = new Fighter(en.valueOf("@name"), Integer.valueOf(en.valueOf("@skill")),
                    Integer.valueOf(en.valueOf("@stamina")));
            fighter.setDamage(Integer.valueOf(en.valueOf("@damage")));
            c.add(fighter);
        }

        s.setType(SceneType.combat);
        s.setCombat(c);
    }

    /**
     * @param scene
     * @param scenesNotScannedYet
     *            Just to keep the scenes not yet visited.
     */
    @SuppressWarnings("unchecked")
    private void findAllTos(Scene scene, Collection<Scene> scenesNotScannedYet) {
        if (scenesNotScannedYet != null) {
            scenesNotScannedYet.remove(scene);
        }

        Node sceneNode = xmlDocument.selectSingleNode("//scene[@id='" + scene.getId() + "']");
        List<Node> pathNodes = sceneNode.selectNodes("./path");
        int i = 0;
        logger.debug("Scene=" + scene + ", pathNodes.sz=" + pathNodes.size());
        for (Node pathNode : pathNodes) {
            logger.debug(i);
            IPath p = scene.createPath(pathNode.getText());
            String orderStr = pathNode.valueOf("@order");
            if (orderStr == null || orderStr.length() == 0) {
                p.setOrder(i++);
            }
            String idToStr = pathNode.valueOf("@toScene");
            if (!GenericValidator.isBlankOrNull(idToStr)) {
                Scene to = adventure.getScene(Integer.parseInt(idToStr));
                boolean hadScenesFrom = !to.getScenesFrom().isEmpty();
                p.setTo(to);

                logger.debug(p);

                if (!hadScenesFrom) {
                    logger.debug("BEFORE RECURSION: to=" + to);
                    logger.debug("BEFORE RECURSION: all=" + scenesNotScannedYet);
                    if (scenesNotScannedYet.contains(to)) {
                        findAllTos(to, scenesNotScannedYet);
                    }
                }
            } else {
                logger.debug(p);
            }
        }
    }

    @SuppressWarnings("unused")
    private String format(String text) {
        StringTokenizer stk = new StringTokenizer(text, "\n");
        StringBuilder buffer = new StringBuilder();
        while (stk.hasMoreTokens()) {
            String line = stk.nextToken().trim();
            buffer.append(line);
            buffer.append("\n");
        }
        return buffer.toString();
    }

    public static void main(String[] args) throws Exception {
        new XMLAdventureReader().read("conf/adventure.xml");
    }
}