/**
* Copyright (c) 2013, Andre Steingress
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1.) Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
* 2.) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
* 3.) Neither the name of Andre Steingress nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.gcontracts.util;
import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.stmt.AssertStatement;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.syntax.Token;
import org.codehaus.groovy.syntax.Types;
import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* <p>Internal utility class for extracting a boolean expression from the given expression or statement.</p>
*
* @see ClosureExpression
* @see BooleanExpression
*
* @author ast
*/
public class ExpressionUtils {
/**
* Returns all {@link BooleanExpression} instances found in the given {@link ClosureExpression}.
*/
public static List<BooleanExpression> getBooleanExpression(ClosureExpression closureExpression) {
if (closureExpression == null) return null;
final BlockStatement closureBlockStatement = (BlockStatement) closureExpression.getCode();
return getBooleanExpressions(closureBlockStatement);
}
/**
* Returns all {@link BooleanExpression} instances found in the given {@link BlockStatement}.
*/
private static List<BooleanExpression> getBooleanExpressions(BlockStatement closureBlockStatement) {
final List<Statement> statementList = closureBlockStatement.getStatements();
List<BooleanExpression> booleanExpressions = new ArrayList<BooleanExpression>();
for (Statement stmt : statementList) {
BooleanExpression tmp = null;
if (stmt instanceof ExpressionStatement && ((ExpressionStatement) stmt).getExpression() instanceof BooleanExpression) {
tmp = (BooleanExpression) ((ExpressionStatement) stmt).getExpression();
tmp.setNodeMetaData("statementLabel", stmt.getStatementLabel());
} else if (stmt instanceof ExpressionStatement) {
Expression expression = ((ExpressionStatement) stmt).getExpression();
tmp = new BooleanExpression(expression);
tmp.setSourcePosition(expression);
tmp.setNodeMetaData("statementLabel", stmt.getStatementLabel());
}
booleanExpressions.add(tmp);
}
return booleanExpressions;
}
/**
* Returns all {@link BooleanExpression} instances found in the given {@link BlockStatement}.
*/
public static List<BooleanExpression> getBooleanExpressionsFromAssertionStatements(BlockStatement blockStatement) {
AssertStatementCollector collector = new AssertStatementCollector();
collector.visitBlockStatement(blockStatement);
List<AssertStatement> assertStatements = collector.assertStatements;
if (assertStatements.isEmpty()) return Collections.emptyList();
List<BooleanExpression> booleanExpressions = new ArrayList<BooleanExpression>();
for (AssertStatement assertStatement : assertStatements) {
booleanExpressions.add(assertStatement.getBooleanExpression());
}
return booleanExpressions;
}
public static BooleanExpression getBooleanExpression(List<BooleanExpression> booleanExpressions) {
if (booleanExpressions == null || booleanExpressions.isEmpty()) return new BooleanExpression(ConstantExpression.TRUE);
BooleanExpression result = null;
for (BooleanExpression booleanExpression : booleanExpressions) {
if (result == null) {
result = booleanExpression;
} else {
result = new BooleanExpression(new BinaryExpression(result, Token.newSymbol(Types.LOGICAL_AND, -1, -1), booleanExpression));
}
}
return result;
}
static class AssertStatementCollector extends ClassCodeVisitorSupport implements Opcodes {
public List<AssertStatement> assertStatements = new ArrayList<AssertStatement>();
@Override
public void visitAssertStatement(AssertStatement statement) {
assertStatements.add(statement);
}
@Override
protected SourceUnit getSourceUnit() {
return null;
}
}
}