/**
* eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the
* <e-UCM> research group.
*
* Copyright 2005-2010 <e-UCM> research group.
*
* You can access a list of all the contributors to eAdventure at:
* http://e-adventure.e-ucm.es/contributors
*
* <e-UCM> is a research group of the Department of Software Engineering
* and Artificial Intelligence at the Complutense University of Madrid
* (School of Computer Science).
*
* C Profesor Jose Garcia Santesmases sn,
* 28040 Madrid (Madrid), Spain.
*
* For more info please visit: <http://e-adventure.e-ucm.es> or
* <http://www.e-ucm.es>
*
* ****************************************************************************
*
* This file is part of eAdventure, version 2.0
*
* eAdventure is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* eAdventure 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with eAdventure. If not, see <http://www.gnu.org/licenses/>.
*/
package es.eucm.ead.reader.model;
import es.eucm.ead.reader.DOMTags;
import es.eucm.ead.reader.ObjectsFactory;
import es.eucm.ead.reader.model.readers.ListReader;
import es.eucm.ead.reader.model.readers.MapReader;
import es.eucm.ead.reader.model.readers.ObjectReader;
import es.eucm.ead.reader.model.readers.ParamReader;
import es.eucm.ead.reader.model.translators.StringTranslator;
import es.eucm.ead.tools.reflection.ReflectionProvider;
import es.eucm.ead.tools.xml.XMLNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class ReaderVisitor {
private static final Logger logger = LoggerFactory
.getLogger(ReaderVisitor.class);
private ObjectsFactory objectsFactory;
private ParamReader paramReader;
private ListReader listReader;
private MapReader mapReader;
private ObjectReader objectReader;
private List<VisitorStep> stepsQueue;
private List<FinalStep> finalStepsQueue;
private List<StringTranslator> clazzTranslators;
private List<StringTranslator> fieldsTranslators;
private List<StringTranslator> paramsTranslators;
public ReaderVisitor(ReflectionProvider reflectionProvider) {
stepsQueue = new ArrayList<VisitorStep>();
finalStepsQueue = new ArrayList<FinalStep>();
clazzTranslators = new ArrayList<StringTranslator>();
fieldsTranslators = new ArrayList<StringTranslator>();
paramsTranslators = new ArrayList<StringTranslator>();
objectsFactory = new ObjectsFactory(reflectionProvider, this);
paramReader = new ParamReader(objectsFactory, this);
listReader = new ListReader(objectsFactory, this);
mapReader = new MapReader(objectsFactory, this);
objectReader = new ObjectReader(objectsFactory, this);
}
public void addFinalStep(FinalStep step) {
this.finalStepsQueue.add(step);
}
public void addClazzTranslator(StringTranslator t) {
this.clazzTranslators.add(t);
}
public void addFieldsTranslator(StringTranslator t) {
this.fieldsTranslators.add(t);
}
public void addParamsTranslator(StringTranslator t) {
this.paramsTranslators.add(t);
}
/**
* Adds an element to load to the stack
*
* @param node
* @param listener
*/
public void loadElement(XMLNode node, VisitorListener listener) {
stepsQueue.add(new VisitorStep(node, listener));
}
/**
* Takes a step in the reading process. Returns true if there is anything
* else to read
*
* @return
*/
public boolean step() {
if (stepsQueue.isEmpty()) {
return true;
}
VisitorStep step = stepsQueue.remove(0);
XMLNode node = step.getNode();
VisitorListener listener = step.getListener();
if (node == null) {
// First look for null in the node
// <p/> or <e/> or <a/> symbolizes null element
logger.warn("null element read; ignoring");
} else if (!node.hasChildNodes()
&& node.getAttributesLength() == 0
&& ("".equals(node.getNodeText()) || node.getNodeText() == null)) {
if (node.getNodeName().equals("p")) {
listener.loaded(node, null, true);
} else {
listener.loaded(node, listReader.EMPTY_LIST, false);
}
} else {
Object result = null;
if (objectsFactory.containsIdentified(node
.getAttributeValue(DOMTags.ID_AT))) {
result = objectsFactory.getObjectById(node
.getAttributeValue(DOMTags.ID_AT));
} else if (node.getNodeName().equals(DOMTags.PARAM_TAG)) {
result = paramReader.read(node);
} else if (node.getNodeName().equals(DOMTags.LIST_TAG)) {
result = listReader.read(node);
} else if (node.getNodeName().equals(DOMTags.ELEMENT_TAG)) {
result = objectReader.read(node);
} else if (node.getNodeName().equals(DOMTags.MAP_TAG)) {
result = mapReader.read(node);
} else {
logger.warn(" could not read node {} with name {}", node, node
.getNodeName());
}
listener.loaded(node, result, false);
}
boolean done = stepsQueue.isEmpty();
if (done) {
logger.debug("Executing {} final steps", finalStepsQueue.size());
for (FinalStep f : finalStepsQueue) {
f.execute();
}
}
return done;
}
public List<VisitorStep> getRefForId(String id) {
ArrayList<VisitorStep> list = new ArrayList<VisitorStep>();
for (VisitorStep s : stepsQueue) {
XMLNode n = s.getNode();
if (n.getNodeName().equals("e") && n.getAttributesLength() < 2) {
String i = n.getNodeText();
if (i.equals(id)) {
list.add(s);
}
}
}
return list;
}
public List<VisitorStep> getNodeWithId(String id) {
ArrayList<VisitorStep> list = new ArrayList<VisitorStep>();
for (VisitorStep s : stepsQueue) {
XMLNode n = s.getNode();
if (id.equals(n.getAttributeValue("i"))) {
list.add(s);
}
}
return list;
}
public void finish() {
while (!step())
;
}
public static interface VisitorListener {
/**
* Returns if the object was correctly processed
*
* @param node
* @param object
* @param isNullInOrigin Says if the object is null because data.xml says so, not
* because it is not still loaded
* @return
*/
boolean loaded(XMLNode node, Object object, boolean isNullInOrigin);
}
public static class VisitorStep {
private XMLNode node;
private VisitorListener listener;
public VisitorStep(XMLNode node, VisitorListener listener) {
this.node = node;
this.listener = listener;
}
public XMLNode getNode() {
return node;
}
public VisitorListener getListener() {
return listener;
}
}
private String translate(String string, List<StringTranslator> translators) {
for (StringTranslator t : translators) {
String translation = t.translate(string);
if (translation != null) {
return translation;
}
}
return string;
}
public String translateClass(String clazz) {
return translate(clazz, clazzTranslators);
}
public String translateField(String field) {
return translate(field, fieldsTranslators);
}
public String translateParam(String param) {
return translate(param, paramsTranslators);
}
public void clear() {
objectsFactory.clear();
stepsQueue.clear();
}
public static interface FinalStep {
void execute();
}
}