/**
* 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.engine.game.interfaces;
import es.eucm.ead.engine.operators.OperatorFactory;
import es.eucm.ead.model.elements.extra.EAdList;
import es.eucm.ead.model.elements.operations.Operation;
import es.eucm.ead.model.params.text.EAdString;
import es.eucm.ead.tools.StringHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TextProcessor {
private static final Logger logger = LoggerFactory
.getLogger(TextProcessor.class);
private static final char BEGIN_VAR_CHAR = '[';
private static final char END_VAR_CHAR = ']';
private static final char BEGIN_CONDITION_CHAR = '(';
private static final char END_CONDITION_CHAR = ')';
private OperatorFactory operatorFactory;
private StringHandler stringHandler;
public TextProcessor(OperatorFactory operatorFactory,
StringHandler stringHandler) {
this.operatorFactory = operatorFactory;
this.stringHandler = stringHandler;
}
/**
* <p>
* Substitutes the variables in a text for its values.
* </p>
* <p>
* The text format for the correct substitution should be:
* </p>
* <ul>
* <li><b>[op_index]:</b> The index of the operation whose result will be
* used to substitute the reference {@code 0 <= op_index < fields.size()}
* <li><b>{[condition]? true text : false text } </b> A conditional text,
* depending of the operation whose index is {@code condition} value.</p>
*
* @param text the text to be processed by the value map
* @return the processed text
*/
public String processTextVars(String text, EAdList<Operation> operations) {
text = processConditionalExpressions(text, operations);
return processVars(text, operations);
}
private String processVars(String text, EAdList<Operation> operations) {
boolean done = false;
while (!done) {
int i = text.indexOf(BEGIN_VAR_CHAR);
if (i != -1) {
int separatorIndex = text.indexOf(END_VAR_CHAR, i + 1);
if (separatorIndex != -1) {
String varName = text.substring(i + 1, separatorIndex);
int index = 0;
try {
index = Integer.parseInt(varName);
} catch (NumberFormatException e) {
logger.warn("{} is not a valid var index", varName);
}
Object o = operatorFactory.operate(operations.get(index));
if (o == null) {
o = "";
}
String value = o instanceof EAdString ? stringHandler
.getString((EAdString) o) : o.toString();
text = text.substring(0, i) + value
+ text.substring(separatorIndex + 1);
}
} else {
done = true;
}
}
return text;
}
private String processConditionalExpressions(String text,
EAdList<Operation> fields) {
String newText = "";
if (text != null) {
int i = 0;
boolean finished = false;
while (!finished && i < text.length()) {
int beginCondition = text.indexOf(BEGIN_CONDITION_CHAR, i);
int endCondition = text.indexOf(END_CONDITION_CHAR,
beginCondition);
if (beginCondition != -1 && endCondition != -1
&& endCondition > beginCondition) {
String condition = text.substring(beginCondition + 1,
endCondition);
String result = evaluateExpression(condition, fields);
newText += text.substring(i, beginCondition) + result;
i = endCondition + 1;
} else {
newText += text.substring(i);
finished = true;
}
}
}
return newText;
}
/**
* Evaluates conditional expressions (#boolean_var? value_1 : value_2 )
*
* @param expression the expression to evaluate
* @param operations a list of operations. In the expression, [i] will be substituted by the result of operations[i]
* @return the expression evaluated
*/
private String evaluateExpression(String expression,
EAdList<Operation> operations) {
if (expression.contains("?") && expression.contains(":")) {
int questionMark = expression.indexOf('?');
int points = expression.indexOf(':');
String condition = expression.substring(0, questionMark);
String trueValue = expression.substring(questionMark + 1, points);
String falseValue = expression.substring(points + 1, expression
.length());
int beginVar = condition.indexOf(BEGIN_VAR_CHAR);
int endVar = condition.indexOf(END_VAR_CHAR);
if (beginVar != -1 && endVar != -1 && endVar > beginVar) {
int indexCondition;
String varName = "";
try {
varName = expression.substring(beginVar + 1, endVar);
indexCondition = Integer.parseInt(varName);
} catch (NumberFormatException e) {
logger.warn(varName + " is not a valid index in "
+ expression);
return BEGIN_CONDITION_CHAR + expression
+ END_CONDITION_CHAR;
}
Object o = operatorFactory.operate(operations
.get(indexCondition));
if (o != null && o instanceof Boolean) {
Boolean b = (Boolean) o;
if (b)
return trueValue;
else
return falseValue;
} else if (o != null && o instanceof Number) {
Number n = (Number) o;
if (n.floatValue() != 0)
return trueValue;
else
return falseValue;
}
return falseValue;
}
}
return BEGIN_CONDITION_CHAR + expression + END_CONDITION_CHAR;
}
}