blob: f433ad6e041cce94aed8a42c0f0800334a950288 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005-2014 Obeo
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.query.legacy.gen.template.statements;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
import org.eclipse.sirius.query.legacy.gen.template.Template;
import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
import org.eclipse.sirius.query.legacy.gen.template.TemplateNodeElement;
import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
import org.eclipse.sirius.query.legacy.gen.template.eval.log.EvalFailure;
import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateExpression;
import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
import org.eclipse.sirius.query.legacy.tools.strings.Int2;
import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
/**
* This is a 'if' statement for the generation tool. It is a kind of statement
* that contains a conditional expression and two templates. If the conditional
* expression is validated then the first template is evaluated, else the second
* template is evaluated.
*
*
*/
public class TemplateIfStatement extends TemplateNodeElement {
/**
* The conditional expression.
*/
protected TemplateExpression condition;
/**
* Template that is evaluated if the conditional expression is validated.
*/
protected Template ifTemplate;
/**
* The expressions for all the "else if" conditions.
*/
protected TemplateExpression[] elseIfConditions;
/**
* The "else if" templates.
*/
protected Template[] elseIfTemplates;
/**
* Template that is evaluated if the conditional expression is not
* validated.
*/
protected Template elseTemplate;
/**
* Constructor.
*
* @param condition
* is the conditional expression
* @param ifTemplate
* is the template that is evaluated if the conditional
* expression is validated
* @param elseTemplate
* is the template that is evaluated if the conditional
* expression is not validated.
* @param script
* is the script
*/
public TemplateIfStatement(TemplateExpression condition, Template ifTemplate, Template elseTemplate, IScript script) {
this(condition, ifTemplate, new TemplateExpression[] {}, new Template[] {}, elseTemplate, script);
}
/**
* Constructor.
*
* @param condition
* is the conditional expression
* @param ifTemplate
* is the template that is evaluated if the conditional
* expression is validated
* @param elseIfConditions
* are "else if" conditions
* @param elseIfTemplates
* are "else if" templates
* @param elseTemplate
* is the template that is evaluated if the conditional
* expression is not validated.
* @param script
* is the script
*/
public TemplateIfStatement(TemplateExpression condition, Template ifTemplate, TemplateExpression[] elseIfConditions, Template[] elseIfTemplates, Template elseTemplate, IScript script) {
super(script);
this.condition = condition;
this.condition.setParent(this);
this.ifTemplate = ifTemplate;
this.ifTemplate.setParent(this);
this.elseIfConditions = elseIfConditions;
for (final TemplateExpression elseIfCondition : elseIfConditions) {
elseIfCondition.setParent(this);
}
this.elseIfTemplates = elseIfTemplates;
for (final Template elseIfTemplate : elseIfTemplates) {
elseIfTemplate.setParent(this);
}
this.elseTemplate = elseTemplate;
this.elseTemplate.setParent(this);
}
/**
* @return the conditional expression
*/
public TemplateExpression getCondition() {
return condition;
}
/**
* @return the elseIf conditions
*/
public TemplateExpression[] getElseIfConditions() {
return elseIfConditions;
}
/**
* @return the elseIf templates
*/
public Template[] getElseIfTemplates() {
return elseIfTemplates;
}
/**
* @return the else template
*/
public Template getElseTemplate() {
return elseTemplate;
}
/**
* @return the if template
*/
public Template getIfTemplate() {
return ifTemplate;
}
/**
* Returns the conditional expression for the given template.
*
* @return the conditional expression for the given template or null
*/
public String getConditionText(Template template) {
if (template == ifTemplate) {
return condition.toString();
} else if (template == elseTemplate) {
return "else"; //$NON-NLS-1$
} else {
for (int i = 0; i < elseIfTemplates.length && i < elseIfConditions.length; i++) {
if (template == elseIfTemplates[i]) {
return elseIfConditions[i].toString();
}
}
return ""; //$NON-NLS-1$
}
}
/* (non-Javadoc) */
@Override
public ENode evaluate(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
try {
final ENode result = evaluateSub(object, mode);
return result;
} catch (final ENodeException e) {
final ENode result = new ENode(ENode.EMPTY, object, this, mode.isSynchronize());
result.log().addError(new EvalFailure(e.getMessage()));
return result;
}
}
private ENode evaluateSub(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
final ENode node = new ENode(ENode.EMPTY, object, this, mode.isSynchronize());
boolean testOK = false;
ENode test = condition.evaluate(new ENode(object, condition, mode.isSynchronize()), script, mode);
if (mode.getMode() == LaunchManager.DEBUG_MODE) {
node.log().getAll(test.log(), false);
}
try {
testOK = test.getBoolean();
} catch (final ENodeCastException e) {
try {
final Object boolValue = test.getAdapterValue(boolean.class);
if (boolValue instanceof Boolean) {
testOK = ((Boolean) boolValue).booleanValue();
} else {
throw new ENodeException(AcceleoGenMessages.getString("ENodeError.BooleanRequired", new Object[] { test.getType(), }), condition.getPos(), script, object, true); //$NON-NLS-1$
}
} catch (final ENodeCastException ex) {
throw new ENodeException(ex.getMessage(), condition.getPos(), script, object, true);
}
}
if (testOK) {
node.append(ifTemplate.evaluate(object, mode));
} else {
for (int i = 0; !testOK && i < elseIfConditions.length; i++) {
final TemplateExpression elseIfCondition = elseIfConditions[i];
test = elseIfCondition.evaluate(new ENode(object, elseIfCondition, mode.isSynchronize()), script, mode);
if (mode.getMode() == LaunchManager.DEBUG_MODE) {
node.log().getAll(test.log(), false);
}
try {
testOK = test.getBoolean();
} catch (final ENodeCastException e) {
try {
final Object boolValue = test.getAdapterValue(boolean.class);
if (boolValue instanceof Boolean) {
testOK = ((Boolean) boolValue).booleanValue();
} else {
throw new ENodeException(AcceleoGenMessages.getString("ENodeError.BooleanRequired", new Object[] { test.getType(), }), elseIfCondition.getPos(), script, object, true); //$NON-NLS-1$
}
} catch (final ENodeCastException ex) {
throw new ENodeException(ex.getMessage(), elseIfCondition.getPos(), script, object, true);
}
}
if (testOK) {
node.append(elseIfTemplates[i].evaluate(object, mode));
}
}
if (!testOK) {
node.append(elseTemplate.evaluate(object, mode));
}
}
return node;
}
/* (non-Javadoc) */
@Override
public String toString() {
String optElse = elseTemplate.toString();
if (optElse.length() > 0) {
optElse = TemplateConstants.IF_ELSE + optElse;
}
final StringBuffer optElseIf = new StringBuffer(""); //$NON-NLS-1$
for (int i = 0; i < elseIfConditions.length; i++) {
optElseIf.append(TemplateConstants.IF_ELSE_IF);
optElseIf.append(elseIfConditions[i].toString());
optElseIf.append(TemplateConstants.IF_THEN);
optElseIf.append(elseIfTemplates[i].toString());
}
return TemplateConstants.IF_BEGIN + condition.toString() + TemplateConstants.IF_THEN + ifTemplate.toString() + optElseIf.toString() + optElse + TemplateConstants.IF_END;
}
/* (non-Javadoc) */
@Override
public String getOutlineText() {
return "if " + condition.toString(); //$NON-NLS-1$
}
/**
* It checks the syntax and creates a statement for the given part of the
* text. The part of the text to be parsed is delimited by the given limits.
*
* @param buffer
* is the textual representation of the templates
* @param limits
* delimits the part of the text to be parsed for this statement
* @param script
* is the generator's configuration
* @return the new statement
* @throws TemplateSyntaxException
*/
public static TemplateNodeElement fromString(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
TemplateExpression condition;
Template ifTemplate;
final List elseIfConditions = new ArrayList();
final List elseIfTemplates = new ArrayList();
Template elseTemplate;
// If -> Then
final Int2 iThen = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.IF_THEN, limits.b(), limits.e(), TemplateConstants.SPEC, TemplateConstants.INHIBS_EXPRESSION);
if (iThen.b() > -1) {
condition = TemplateExpression.fromString(buffer, new Int2(limits.b(), iThen.b()), script);
int iThenEnd;
// Else -> End
final Int2 iElse = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.IF_ELSE, iThen.e(), limits.e(), null, TemplateConstants.INHIBS_STATEMENT);
if (iElse.b() > -1) {
iThenEnd = iElse.b();
Int2 elsePos = new Int2(iElse.e(), limits.e());
elsePos = Template.formatTemplate(buffer, elsePos, 0);
elseTemplate = Template.read(buffer, elsePos, script);
} else {
iThenEnd = limits.e();
elseTemplate = new Template(script);
}
// ElseIf -> ElseIf|Else|End
final int iElseIfEndMax = iThenEnd;
Int2 iElseIf = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.IF_ELSE_IF, iThen.e(), iElseIfEndMax, null, TemplateConstants.INHIBS_STATEMENT);
if (iElseIf.b() > -1) {
iThenEnd = iElseIf.b();
while (iElseIf.b() > -1) {
// ElseIf test
TemplateExpression elseIfTest;
final Int2 iTestEnd = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.IF_THEN, iElseIf.e(), iElseIfEndMax, TemplateConstants.SPEC,
TemplateConstants.INHIBS_EXPRESSION);
if (iTestEnd.b() > -1) {
elseIfTest = TemplateExpression.fromString(buffer, new Int2(iElseIf.e(), iTestEnd.b()), script);
} else {
throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingCloseIf"), script, new Int2(iElseIf.e(), iElseIfEndMax)); //$NON-NLS-1$
}
iElseIf = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.IF_ELSE_IF, iTestEnd.e(), iElseIfEndMax, null, TemplateConstants.INHIBS_STATEMENT);
Int2 elseIfPos;
if (iElseIf.b() > -1) {
elseIfPos = new Int2(iTestEnd.e(), iElseIf.b());
} else {
elseIfPos = new Int2(iTestEnd.e(), iElseIfEndMax);
}
elseIfPos = Template.formatTemplate(buffer, elseIfPos, 0);
final Template elseIfTemplate = Template.read(buffer, elseIfPos, script);
elseIfConditions.add(elseIfTest);
elseIfTemplates.add(elseIfTemplate);
}
}
// Then -> ElseIf|Else|End
Int2 ifPos = new Int2(iThen.e(), iThenEnd);
ifPos = Template.formatTemplate(buffer, ifPos, 0);
ifTemplate = Template.read(buffer, ifPos, script);
} else {
condition = TemplateExpression.fromString(buffer, new Int2(limits.b(), limits.e()), script);
ifTemplate = new Template(script);
elseTemplate = new Template(script);
}
final TemplateIfStatement element = new TemplateIfStatement(condition, ifTemplate, (TemplateExpression[]) elseIfConditions.toArray(new TemplateExpression[elseIfConditions.size()]),
(Template[]) elseIfTemplates.toArray(new Template[elseIfTemplates.size()]), elseTemplate, script);
element.setPos(limits);
return element;
}
}