package models.visualModel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import models.algebra.Expression;
import models.algebra.Symbol;
import models.algebra.Term;
import models.algebra.Variable;
import models.dataConstraintModel.ChannelMember;
import models.dataConstraintModel.DataConstraintModel;
import models.dataConstraintModel.ResourcePath;
import models.dataConstraintModel.StateTransition;
import models.dataFlowModel.DataTransferChannel;
public class FormulaChannel extends DataTransferChannel {
private Symbol defaultOperator = null;
private String formula = null;
private Expression formulaRhs = null;
public FormulaChannel(String channelName, Symbol defaultOperator) {
super(channelName);
this.defaultOperator = defaultOperator;
}
public void addChannelMemberAsInput(ChannelMember channelMember) {
// StateTransition st = new StateTransition();
// st.setCurStateExpression(new Variable(channelMember.getIdentifierTemplate().getResourceName() + "1"));
// st.setNextStateExpression(new Variable(channelMember.getIdentifierTemplate().getResourceName() + "2"));
// channelMember.setStateTransition(st);
super.addChannelMemberAsInput(channelMember);
if (formula != null && getInputChannelMembers().size() > 1) {
formula += " " + defaultOperator + " " + channelMember.getResource().getLeafResourceName();
if (formulaRhs != null) {
if (formulaRhs instanceof Variable) {
Term newTerm = new Term(defaultOperator);
newTerm.addChild(formulaRhs);
newTerm.addChild(new Variable(channelMember.getResource().getLeafResourceName()), true);
formulaRhs = newTerm;
} else if (formulaRhs instanceof Term) {
Term newTerm = new Term(defaultOperator);
newTerm.addChild(formulaRhs);
newTerm.addChild(new Variable(channelMember.getResource().getLeafResourceName()));
formulaRhs = newTerm;
}
}
} else {
if (formula == null) formula = "";
formula += channelMember.getResource().getLeafResourceName();
formulaRhs = new Variable(channelMember.getResource().getLeafResourceName());
}
if (formulaRhs != null) {
setFormulaTerm(formulaRhs);
}
}
public void addChannelMemberAsOutput(ChannelMember channelMember) {
// StateTransition st = new StateTransition();
// st.setCurStateExpression(new Variable(channelMember.getIdentifierTemplate().getResourceName() + "1"));
// channelMember.setStateTransition(st);
super.addChannelMemberAsOutput(channelMember);
if (getOutputChannelMembers().size() == 1) {
if (formula == null) formula = "";
if (!formula.contains("=")) {
formula = channelMember.getResource().getLeafResourceName() + " = " + formula;
}
}
if (formulaRhs != null) {
setFormulaTerm(formulaRhs);
}
}
public Symbol getDefaultOperator() {
return defaultOperator;
}
public void setDefaultOperator(Symbol defaultOperator) {
this.defaultOperator = defaultOperator;
}
public void setFormulaTerm(Expression rhs) {
formulaRhs = rhs;
Collection<Variable> variables;
if (rhs instanceof Variable) {
variables = new ArrayList<>();
variables.add((Variable) rhs);
} else if (rhs instanceof Term) {
variables = ((Term) rhs).getVariables().values();
} else {
return;
}
Map<ResourcePath, Variable> curStates = new HashMap<>();
Map<ResourcePath, Variable> nextStates = new HashMap<>();
Map<Variable, Variable> resToNextVar = new HashMap<>();
for (ChannelMember cm: this.getInputChannelMembers()) {
ResourcePath id = cm.getResource();
String resName = id.getLeafResourceName();
Variable curVar = new Variable(resName + "1");
Variable nextVar = new Variable(resName + "2");
curStates.put(id, curVar);
nextStates.put(id, nextVar);
for (Variable var: variables) {
if (var.getName().equals(resName)) {
resToNextVar.put(var, nextVar);
break;
}
}
}
Symbol update = new Symbol("update");
update.setArity(resToNextVar.keySet().size());
for (ChannelMember cm: getInputChannelMembers()) {
ResourcePath id = cm.getResource();
StateTransition st = new StateTransition();
st.setCurStateExpression(curStates.get(id));
st.setNextStateExpression(nextStates.get(id));
Term message = new Term(update);
for (Variable var: resToNextVar.values()) {
message.addChild(var);
}
st.setMessageExpression(message);
cm.setStateTransition(st);
}
if (rhs instanceof Variable) {
rhs = resToNextVar.get((Variable) rhs);
} else if (rhs instanceof Term) {
formulaRhs = rhs;
for (Variable var: resToNextVar.keySet()) {
rhs = ((Term) rhs).substitute(var, resToNextVar.get(var));
}
}
for (ChannelMember cm: getOutputChannelMembers()) {
ResourcePath id = cm.getResource();
StateTransition st = new StateTransition();
String resName = id.getLeafResourceName();
Variable curVar = new Variable(resName + "1");
st.setCurStateExpression(curVar);
st.setNextStateExpression(rhs);
Term message = new Term(update);
for (Variable var: resToNextVar.values()) {
message.addChild(var);
}
st.setMessageExpression(message);
cm.setStateTransition(st);
}
}
public Expression getFormulaTerm() {
return formulaRhs;
}
public void setFormula(String formula) {
this.formula = formula;
}
public String getFormula() {
return formula;
}
}