package algorithm;
import java.util.ArrayList;
import java.util.HashSet;
import models.*;
import models.algebra.Expression;
import models.algebra.Field;
import models.algebra.InvalidMessage;
import models.algebra.Parameter;
import models.algebra.ParameterizedIdentifierIsFutureWork;
import models.algebra.Symbol;
import models.algebra.Term;
import models.algebra.Type;
import models.algebra.UnificationFailed;
import models.algebra.ValueUndefined;
import models.dataConstraintModel.ChannelMember;
import models.dataConstraintModel.DataConstraintModel;
import models.dataConstraintModel.IdentifierTemplate;
import models.dataFlowModel.*;
import models.dataFlowModel.DataflowChannelGenerator.IResourceStateAccessor;
public class CodeGenerator {
static public ArrayList<String> doGenerate(ResourceDependencyGraph graph) {
ArrayList<String> codes = new ArrayList<>();
ArrayList<ResourceNode> resources = StoreResourceCheck(graph);
IResourceStateAccessor pushAccessor = new IResourceStateAccessor() {
@Override
public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) {
if (target.equals(from)) {
return new Field(target.getResourceName(),
target.getResourceStateType() != null ? target.getResourceStateType()
: DataConstraintModel.typeInt);
}
return null;
}
@Override
public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) {
return new Parameter(target.getResourceName(),
target.getResourceStateType() != null ? target.getResourceStateType()
: DataConstraintModel.typeInt);
}
};
IResourceStateAccessor pullAccessor = new IResourceStateAccessor() {
@Override
public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) {
if (target.equals(from)) {
return new Field(target.getResourceName(),
target.getResourceStateType() != null ? target.getResourceStateType()
: DataConstraintModel.typeInt);
}
return null;
}
@Override
public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) {
Term getter = new Term(new Symbol("get" + target.getResourceName(), 1, Symbol.Type.METHOD));
getter.addChild(new Field(target.getResourceName(), target.getResourceStateType()));
return getter;
}
};
codes.add("public class Main {");
for (ResourceNode n : resources) {
ResourceNode resource = (ResourceNode) n;
String str = "\t" + "private "
+ resource.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase()
+ resource.getIdentifierTemplate().getResourceName().substring(1) + " "
+ resource.getIdentifierTemplate().getResourceName() + " = new "
+ resource.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase()
+ resource.getIdentifierTemplate().getResourceName().substring(1) + "(";
str += ");";
codes.add(str);
}
codes.add("}");
codes.add("");
for (Node n : graph.getNodes()) {
ResourceNode resource = (ResourceNode) n;
String tmp;
codes.add("public class " + resource.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase()
+ resource.getIdentifierTemplate().getResourceName().substring(1) + " {");
if (((StoreAttribute) resource.getAttribute()).isStored()) {
for (Edge e : resource.getInEdges()) {
ResourceDependency re = (ResourceDependency) e;
for (ChannelMember cm : re.getChannelGenerator().getChannelMembers()) {
try {
Expression exp = re.getChannelGenerator().deriveUpdateExpressionOf(cm, pushAccessor);
if (exp != null) {
Parameter param = exp.getSubTerms(Parameter.class).values().iterator().next();
codes.add("\t" + "void update(" + param.getType().getImplementastionTypeName() + " "
+ param.toImplementation() + "){");
tmp = "\t\t" + exp.toImplementation();
codes.add(tmp);
codes.add("\t" + "}");
}
} catch (ParameterizedIdentifierIsFutureWork e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ResolvingMultipleDefinitionIsFutureWork e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InvalidMessage e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (UnificationFailed e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ValueUndefined e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
for (Edge e : resource.getOutEdges()) {
ResourceDependency re = (ResourceDependency) e;
for (ChannelMember cm : re.getChannelGenerator().getChannelMembers()) {
try {
Expression exp = re.getChannelGenerator().deriveUpdateExpressionOf(cm, pushAccessor);
if (exp != null) {
Parameter param = exp.getSubTerms(Parameter.class).values().iterator().next();
codes.add("\t" + "void update(" + param.getType().getImplementastionTypeName() + " "
+ param.toImplementation() + "){");
tmp = "\t\t" + exp.toImplementation();
codes.add(tmp);
codes.add("\t" + "}");
}
} catch (ParameterizedIdentifierIsFutureWork e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ResolvingMultipleDefinitionIsFutureWork e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InvalidMessage e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (UnificationFailed e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ValueUndefined e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
} else {
for (Edge e : resource.getInEdges()) {
ResourceDependency re = (ResourceDependency) e;
for (ChannelMember cm : re.getChannelGenerator().getChannelMembers()) {
try {
Expression exp = re.getChannelGenerator().deriveUpdateExpressionOf(cm, pullAccessor);
if (exp != null) {
tmp = "\t" + "return " + exp.toImplementation();
codes.add(tmp);
}
} catch (ParameterizedIdentifierIsFutureWork e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ResolvingMultipleDefinitionIsFutureWork e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InvalidMessage e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (UnificationFailed e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ValueUndefined e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
for (Edge e : resource.getOutEdges()) {
ResourceDependency re = (ResourceDependency) e;
for (ChannelMember cm : re.getChannelGenerator().getChannelMembers()) {
try {
Expression exp = re.getChannelGenerator().deriveUpdateExpressionOf(cm, pullAccessor);
if (exp != null) {
tmp = "\t" + "return " + exp.toImplementation();
tmp = "\t" + exp.toImplementation();
codes.add(tmp);
}
} catch (ParameterizedIdentifierIsFutureWork e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ResolvingMultipleDefinitionIsFutureWork e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InvalidMessage e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (UnificationFailed e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ValueUndefined e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
codes.add("}");
codes.add("");
}
return codes;
}
static private ArrayList<ResourceNode> StoreResourceCheck(ResourceDependencyGraph graph) {
ArrayList<ResourceNode> resources = new ArrayList<>();
for (Node n : graph.getNodes()) {
ResourceNode rn = (ResourceNode) n;
boolean flag = true;
for (Edge e : rn.getOutEdges()) {
ResourceDependency re = (ResourceDependency) e;
if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) {
flag = false;
}
}
for (Edge e : rn.getInEdges()) {
ResourceDependency re = (ResourceDependency) e;
if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) {
flag = false;
}
}
if (flag)
resources.add(rn);
}
return resources;
}
static private ArrayList<ResourceNode> trackNode(ResourceNode rn) {
ArrayList<ResourceNode> resources = new ArrayList<>();
for (Edge e : rn.getOutEdges()) {
ResourceDependency re = (ResourceDependency) e;
if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) {
return trackNode((ResourceNode) re.getDestination());
}
}
for (Edge e : rn.getInEdges()) {
ResourceDependency re = (ResourceDependency) e;
if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) {
return trackNode((ResourceNode) re.getSource());
}
}
return resources;
}
}