
nl.rrd.wool.model.command.WoolIfCommand Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of wool-core Show documentation
Show all versions of wool-core Show documentation
WOOL is a simple, powerful dialogue framework for creating virtual agent conversations.
The newest version!
/*
* Copyright 2019 Roessingh Research and Development.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package nl.rrd.wool.model.command;
import nl.rrd.wool.exception.LineNumberParseException;
import nl.rrd.wool.expressions.EvaluationException;
import nl.rrd.wool.expressions.Expression;
import nl.rrd.wool.expressions.Value;
import nl.rrd.wool.expressions.types.AssignExpression;
import nl.rrd.wool.model.WoolNodeBody;
import nl.rrd.wool.model.WoolReply;
import nl.rrd.wool.model.nodepointer.WoolNodePointer;
import nl.rrd.wool.parser.WoolBodyParser;
import nl.rrd.wool.parser.WoolBodyToken;
import nl.rrd.wool.parser.WoolNodeState;
import nl.rrd.wool.utils.CurrentIterator;
import java.util.*;
/**
* This class models the <<if ...>> command in Wool. It can be part
* of a {@link WoolNodeBody WoolNodeBody} (not inside a reply).
*
* @author Dennis Hofs (RRD)
*/
public class WoolIfCommand extends WoolExpressionCommand {
private List ifClauses = new ArrayList<>();
private WoolNodeBody elseClause = null;
public WoolIfCommand() {
}
public WoolIfCommand(WoolIfCommand other) {
for (Clause ifClause : other.ifClauses) {
this.ifClauses.add(new Clause(ifClause));
}
if (other.elseClause != null)
this.elseClause = new WoolNodeBody(other.elseClause);
}
/**
* Returns the if clauses. They should be processed from first to last.
* There should be at least one clause. That is the "if" clause. Any
* subsequent clauses are "elseif" clauses.
*
* @return the if clauses
*/
public List getIfClauses() {
return ifClauses;
}
/**
* Sets the if clauses. They should be processed from first to last. There
* should be at least one clause. That is the "if" clause. Any subsequent
* clauses are "elseif" clauses.
*
* @param ifClauses the if clauses
*/
public void setIfClauses(List ifClauses) {
this.ifClauses = ifClauses;
}
/**
* Adds an if clause. The clauses should be processed from first to last.
* There should be at least one clause.That is the "if" clause. Any
* subsequent clauses are "elseif" clauses.
*
* @param ifClause the if clause
*/
public void addIfClause(Clause ifClause) {
ifClauses.add(ifClause);
}
/**
* Returns the else clause. If there is no else clause, then this method
* returns null (default).
*
* @return the else clause or null
*/
public WoolNodeBody getElseClause() {
return elseClause;
}
/**
* Sets the else clause. If there is no else clause, this can be set to
* null (default).
*
* @param elseClause the else clause or null
*/
public void setElseClause(WoolNodeBody elseClause) {
this.elseClause = elseClause;
}
@Override
public WoolReply findReplyById(int replyId) {
for (Clause clause : ifClauses) {
WoolReply reply = clause.statement.findReplyById(replyId);
if (reply != null)
return reply;
}
if (elseClause != null)
return elseClause.findReplyById(replyId);
else
return null;
}
@Override
public void getReadVariableNames(Set varNames) {
for (Clause clause : ifClauses) {
varNames.addAll(clause.expression.getVariableNames());
clause.statement.getReadVariableNames(varNames);
}
if (elseClause != null)
elseClause.getReadVariableNames(varNames);
}
@Override
public void getWriteVariableNames(Set varNames) {
for (Clause clause : ifClauses) {
clause.statement.getWriteVariableNames(varNames);
}
if (elseClause != null)
elseClause.getWriteVariableNames(varNames);
}
@Override
public void getNodePointers(Set pointers) {
for (Clause clause : ifClauses) {
clause.statement.getNodePointers(pointers);
}
if (elseClause != null)
elseClause.getNodePointers(pointers);
}
@Override
public void executeBodyCommand(Map variables,
WoolNodeBody processedBody) throws EvaluationException {
for (Clause clause : ifClauses) {
Value clauseEval = clause.expression.evaluate(variables);
if (clauseEval.asBoolean()) {
clause.statement.execute(variables, false, processedBody);
return;
}
}
if (elseClause != null)
elseClause.execute(variables, false, processedBody);
}
@Override
public String toString() {
String newline = System.getProperty("line.separator");
Clause clause = ifClauses.get(0);
StringBuilder result = new StringBuilder(
"<>" + newline);
result.append(clause.statement + newline);
for (int i = 1; i < ifClauses.size(); i++) {
clause = ifClauses.get(i);
result.append("<>" + newline);
result.append(clause.statement + newline);
}
if (elseClause != null) {
result.append("<>" + newline);
result.append(elseClause + newline);
}
result.append("<>");
return result.toString();
}
public static WoolIfCommand parse(WoolBodyToken cmdStartToken,
CurrentIterator tokens, WoolNodeState nodeState)
throws LineNumberParseException {
WoolIfCommand command = new WoolIfCommand();
ReadContentResult content = readCommandContent(cmdStartToken, tokens);
ParseContentResult parsedIf = parseCommandContentExpression(
cmdStartToken, content, "if");
checkNoAssignment(cmdStartToken, parsedIf.name, parsedIf.expression);
while (true) {
WoolBodyParser bodyParser = new WoolBodyParser(nodeState);
WoolBodyParser.ParseUntilIfClauseResult bodyParse =
bodyParser.parseUntilIfClause(tokens, Arrays.asList(
"action", "if", "set"));
if (bodyParse.ifClauseStartToken == null) {
throw new LineNumberParseException(
"Command \"if\" not terminated",
cmdStartToken.getLineNum(), cmdStartToken.getColNum());
}
if (parsedIf.name.equals("if") || parsedIf.name.equals("elseif")) {
command.addIfClause(new Clause(parsedIf.expression,
bodyParse.body));
} else {
command.setElseClause(bodyParse.body);
}
WoolBodyToken clauseStartToken = bodyParse.ifClauseStartToken;
String clauseName = bodyParse.ifClauseName;
content = readCommandContent(clauseStartToken, tokens);
switch (clauseName) {
case "elseif":
if (command.elseClause != null) {
throw new LineNumberParseException(
"Found \"elseif\" after \"else\"",
clauseStartToken.getLineNum(),
clauseStartToken.getColNum());
}
parsedIf = parseCommandContentExpression(clauseStartToken,
content, clauseName);
checkNoAssignment(clauseStartToken, parsedIf.name,
parsedIf.expression);
break;
case "else":
if (command.elseClause != null) {
throw new LineNumberParseException(
"Found more than one \"else\"",
clauseStartToken.getLineNum(),
clauseStartToken.getColNum());
}
parsedIf = parseCommandContentName(clauseStartToken, content,
clauseName);
break;
case "endif":
parseCommandContentName(clauseStartToken, content, clauseName);
return command;
}
}
}
private static void checkNoAssignment(WoolBodyToken cmdStartToken,
String name, Expression expression)
throws LineNumberParseException {
List list = new ArrayList<>();
list.add(expression);
list.addAll(expression.getDescendants());
for (Expression expr : list) {
if (expr instanceof AssignExpression) {
throw new LineNumberParseException(String.format(
"Found assignment expression in \"%s\" command", name),
cmdStartToken.getLineNum(), cmdStartToken.getColNum());
}
}
}
@Override
public WoolIfCommand clone() {
return new WoolIfCommand(this);
}
/**
* This class models a clause of an if statement. That is the "if" clause
* or an "elseif" clause.
*/
public static class Clause {
private Expression expression;
private WoolNodeBody statement;
/**
* Constructs a new if clause.
*
* @param expression the if expression that should be evaluated as a
* boolean
* @param statement the statement that should be output if the
* expression evaluates to true
*/
public Clause(Expression expression, WoolNodeBody statement) {
this.expression = expression;
this.statement = statement;
}
public Clause(Clause other) {
this.expression = other.expression;
this.statement = new WoolNodeBody(other.statement);
}
/**
* Returns the if expression that should be evaluated as a boolean.
*
* @return the if expression
*/
public Expression getExpression() {
return expression;
}
/**
* Sets the if expression that should be evaluated as a boolean.
*
* @param expression the if expression
*/
public void setExpression(Expression expression) {
this.expression = expression;
}
/**
* Returns the statement that should be output if the expression
* evaluates to true.
*
* @return the statement
*/
public WoolNodeBody getStatement() {
return statement;
}
/**
* Sets the statement that should be output if the expression evaluates
* to true.
*
* @param statement the statement
*/
public void setStatement(WoolNodeBody statement) {
this.statement = statement;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy