/*******************************************************************************
* Copyright (c) 2009 University of Edinburgh.
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the BSD Licence, which accompanies this feature
* and can be downloaded from http://groups.inf.ed.ac.uk/pepa/update/licence.txt
******************************************************************************/
package uk.ac.ed.inf.biopepa.core.compiler;
import java.util.ArrayList;
import java.util.List;
import uk.ac.ed.inf.biopepa.core.BioPEPAException;
import uk.ac.ed.inf.biopepa.core.dom.Component;
import uk.ac.ed.inf.biopepa.core.dom.Cooperation;
import uk.ac.ed.inf.biopepa.core.dom.Expression;
import uk.ac.ed.inf.biopepa.core.dom.LocatedName;
import uk.ac.ed.inf.biopepa.core.dom.Name;
import uk.ac.ed.inf.biopepa.core.dom.PropertyLiteral.Kind;
;
/**
* @author ajduguid
*
*/
public class CompositionalVisitor extends DefaultCompilerVisitor {
protected SystemEquationNode result = null;
private boolean locationsRequired = false;
public CompositionalVisitor(ModelCompiler compiler) {
super(compiler);
locationsRequired = compiler.getNumberOfDefinedCompartments() > 0;
}
public SystemEquationNode getData() {
return result;
}
/*
* (non-Javadoc)
*
* @see
* uk.ac.ed.inf.biopepa.core.dom.ASTVisitor#visit(uk.ac.ed.inf.biopepa.core
* .dom.Name)
*/
@Override
public boolean visit(Name name) throws BioPEPAException {
SystemEquationData data = compiler.checkAndGetComposition(name.getIdentifier());
if (data == null) {
ProblemKind pKind = ProblemKind.VARIABLE_USED_BUT_NOT_DEFINED;
pKind.setMessage("Variable: " + name.getIdentifier() +
" used but not defined");
compiler.problemRequestor.accept(pKind, name);
throw new CompilerException();
}
this.result = data.getSystemEquationNode();
return true;
}
/*
* (non-Javadoc)
*
* @see
* uk.ac.ed.inf.biopepa.core.dom.ASTVisitor#visit(uk.ac.ed.inf.biopepa.core
* .dom.Component)
*/
@Override
public boolean visit(Component component) throws BioPEPAException {
Expression level = component.getLevel();
ExpressionEvaluatorVisitor v = new ExpressionEvaluatorVisitor(compiler);
level.accept(v);
CompiledExpression compiledExpression = v.getExpressionNode();
ComponentNode nodeInfo = new ComponentNode(compiledExpression);
Name name = component.getName();
String identifier;
if (name instanceof LocatedName) {
identifier = ((LocatedName) name).getName();
List<Name> names = ((LocatedName) name).getLocations().names();
if (names.size() > 1) {
compiler.problemRequestor.accept(ProblemKind.INVALID_NUMBER_OF_LOCATIONS, component);
throw new CompilerException();
}
CompartmentData cd = compiler.checkAndGetCompartmentData(names.get(0).getIdentifier());
if (cd == null) {
compiler.problemRequestor.accept(ProblemKind.LOCATION_USED_BUT_NOT_DEFINED, component);
throw new CompilerException();
}
nodeInfo.setCompartment(cd);
} else {
if (locationsRequired) {
compiler.problemRequestor.accept(ProblemInfo.Severity.ERROR,
name.getIdentifier() + " does specify a location.",
component);
// throw new CompilerException();
}
identifier = component.getName().getIdentifier();
}
if (compiler.checkAndGetComponentData(identifier) == null) {
compiler.problemRequestor.accept(ProblemKind.SPECIES_NOT_DECLARED,
component);
throw new CompilerException();
}
nodeInfo.setComponent(identifier);
if (!(compiledExpression instanceof CompiledNumber)) { // evaluates
// to a
// non-integer
compiler.problemRequestor.accept(ProblemKind.DYNAMIC_VALUE, level);
throw new CompilerException();
}
CompiledNumber enn = (CompiledNumber) compiledExpression;
if (!enn.evaluatesToLong()) {
compiler.problemRequestor.accept(ProblemKind.NON_INTEGER_VALUE, level);
throw new CompilerException();
}
long count = enn.longValue();
if (count < 0) {
compiler.problemRequestor.accept(ProblemKind.INITIAL_COUNT_LT_ZERO, level);
throw new CompilerException();
}
SpeciesData data = compiler.checkAndGetSpeciesData(identifier);
if (data != null) {
if (data.getMaximumConcentration() < count) {
compiler.problemRequestor.accept(ProblemKind.INITIAL_COUNT_GT_MAX, level);
throw new CompilerException();
}
if (data.isSetProperty(Kind.MIN) && data.getMinimalConcentration() > count) {
compiler.problemRequestor.accept(ProblemKind.INITIAL_COUNT_LT_MIN, level);
throw new CompilerException();
}
}
nodeInfo.setCount(count);
result = nodeInfo;
return true;
}
/*
* (non-Javadoc)
*
* @see
* uk.ac.ed.inf.biopepa.core.dom.ASTVisitor#visit(uk.ac.ed.inf.biopepa.core
* .dom.Cooperation)
*/
@Override
public boolean visit(Cooperation cooperation) throws BioPEPAException {
CooperationNode result = new CooperationNode();
CompositionalVisitor lhsVisitor = new CompositionalVisitor(this.compiler);
cooperation.getLeftHandSide().accept(lhsVisitor);
CompositionalVisitor rhsVisitor = new CompositionalVisitor(compiler);
cooperation.getRightHandSide().accept(rhsVisitor);
result.setLeft(lhsVisitor.getData());
result.setRight(rhsVisitor.getData());
ArrayList<String> actions = new ArrayList<String>();
// Added to cover wildcard. All expressions are compiled before sets are
// generated.
List<Name> tActions = cooperation.getActionSet().names();
if (tActions.size() == 1 && tActions.get(0).getIdentifier().equals(Cooperation.WILDCARD))
actions.add(Cooperation.WILDCARD);
else {
String actionName;
for (Name name : tActions) {
actionName = name.getIdentifier();
if (compiler.checkAndGetFunctionalRate(actionName) == null) {
compiler.problemRequestor.accept(ProblemKind.FUNCTIONAL_RATE_USED_BUT_NOT_DECLARED, name);
throw new CompilerException();
}
if (actions.contains(actionName)) {
// This is just a warning
compiler.problemRequestor.accept(ProblemKind.DUPLICATE_ACTION_FOUND, name);
}
// TODO See semantics of returned boolean
actions.add(actionName);
}
}
result.setActions(actions.toArray(new String[actions.size()]));
this.result = result;
return true;
}
}