Newer
Older
AlgebraicDataflowArchitectureModel / AlgebraicDataflowArchitectureModel / src / tests / UpdateCodeGenerationTest.java
package tests;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

import models.algebra.Constant;
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.UnificationFailed;
import models.algebra.ValueUndefined;
import models.algebra.Variable;
import models.dataConstraintModel.ChannelMember;
import models.dataConstraintModel.ChannelSelector;
import models.dataConstraintModel.DataConstraintModel;
import models.dataConstraintModel.GroupSelector;
import models.dataConstraintModel.IdentifierTemplate;
import models.dataConstraintModel.StateTransition;
import models.dataFlowModel.DataFlowModel;
import models.dataFlowModel.DataflowChannelGenerator;
import models.dataFlowModel.DataflowChannelGenerator.IResourceStateAccessor;
import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork;

public class UpdateCodeGenerationTest {
	
	public static void main(String[] args) {
		// Pre-defined symbols
		Symbol floor = new Symbol("floor", 1, Symbol.Type.PREFIX, "(int)Math.floor", Symbol.Type.PREFIX);
		Symbol sum = new Symbol("sum", 1, Symbol.Type.PREFIX, "stream().mapToInt(x->x).sum", Symbol.Type.METHOD);
		
		// resources
		IdentifierTemplate payment = new IdentifierTemplate("payment", DataConstraintModel.typeInt, 0);	// an identifier template to specify the payment resource
		IdentifierTemplate loyalty = new IdentifierTemplate("loyalty", DataConstraintModel.typeInt, 0);	// an identifier template to specify the loyalty resource
		IdentifierTemplate history = new IdentifierTemplate("history", DataConstraintModel.typeList, 0);// an identifier template to specify the payment history resource
		IdentifierTemplate total = new IdentifierTemplate("total", DataConstraintModel.typeInt, 0);		// an identifier template to specify the total payment resource
		
		// fields in the Java program
		final Field fPayment = new Field("payment", DataConstraintModel.typeInt);
		final Field fLoyalty = new Field("loyalty", DataConstraintModel.typeInt);
		final Field fHistory = new Field("history", DataConstraintModel.typeList);
		final Field fTotal = new Field("total", DataConstraintModel.typeInt);
		// parameters in the Java program
		final Parameter pPayment = new Parameter("payment", DataConstraintModel.typeInt);
		final Parameter pLoyalty = new Parameter("loyalty", DataConstraintModel.typeInt);
		final Parameter pHistory = new Parameter("history", DataConstraintModel.typeList);
		final Parameter pTotal = new Parameter("total", DataConstraintModel.typeInt);
		IResourceStateAccessor pushAccessor = new IResourceStateAccessor() {
			@Override
			public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) {
				if (target.equals(from)) {
					if (target.equals(payment)) return fPayment;
					if (target.equals(loyalty)) return fLoyalty;
					if (target.equals(history)) return fHistory;
					if (target.equals(total)) return fTotal;
				}
				return null;
			}
			@Override
			public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) {
				if (target.equals(payment)) return pPayment;
				if (target.equals(loyalty)) return pLoyalty;
				if (target.equals(history)) return pHistory;
				if (target.equals(total)) return pTotal;
				return null;
			}				
		};
		
		// methods in the Java program
		final Symbol paymentGetter = new Symbol("getPayment", 1, Symbol.Type.METHOD);
		final Symbol loyltyGetter = new Symbol("getLoyalty", 1, Symbol.Type.METHOD);
		final Symbol historyGetter = new Symbol("getHistory", 1, Symbol.Type.METHOD);
		final Symbol totalGetter = new Symbol("getTotal", 1, Symbol.Type.METHOD);
		IResourceStateAccessor pullAccessor = new IResourceStateAccessor() {
			@Override
			public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) {
				if (target.equals(from)) {
					if (target.equals(payment)) return fPayment;
					if (target.equals(loyalty)) return fLoyalty;
					if (target.equals(history)) return fHistory;
					if (target.equals(total)) return fTotal;
				}
				return null;
			}
			@Override
			public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) {
				if (target.equals(payment)) {
					Term getter = new Term(paymentGetter);
					getter.addChild(fPayment);
					return getter;
				}
				if (target.equals(loyalty)) {
					Term getter = new Term(loyltyGetter);
					getter.addChild(fLoyalty);
					return getter;
				}
				if (target.equals(history)) {
					Term getter = new Term(historyGetter);
					getter.addChild(fHistory);
					return getter;
				}
				if (target.equals(total)) {
					Term getter = new Term(totalGetter);
					getter.addChild(fTotal);
					return getter;
				}
				return null;
			}				
		};
		
		// === c1 ===
		//
		// payment(p1, update1(y)) == y
		// loyalty(l, update1(y)) == floor(y * 0.05)
		//
		DataflowChannelGenerator c1 = new DataflowChannelGenerator("c1");
		ChannelMember c1_payment = new ChannelMember(payment);
		ChannelMember c1_loyalty = new ChannelMember(loyalty);
		c1.addChannelMemberAsInput(c1_payment);
		c1.addChannelMemberAsOutput(c1_loyalty);
		
		Variable p1 = new Variable("p1");
		Variable y = new Variable("y");
		Variable l = new Variable("l");
		Constant c_0_05 = new Constant("0.05");
		Symbol update1 = new Symbol("update1", 1);
		Term c1_message = new Term(update1);		// update1(y)
		c1_message.addChild(y);
		Term rawLoyality = new Term(DataConstraintModel.mul);			// y*0.05
		rawLoyality.addChild(y);
		rawLoyality.addChild(c_0_05);
		Term nextLoyality = new Term(floor);		// floor(y*0.05)
		nextLoyality.addChild(rawLoyality);
		
		StateTransition c1_payment_transition = new StateTransition();
		c1_payment_transition.setCurStateExpression(p1);
		c1_payment_transition.setMessageExpression(c1_message);
		c1_payment_transition.setNextStateExpression(y);
		c1_payment.setStateTransition(c1_payment_transition);
		
		StateTransition c1_loyalty_transition = new StateTransition();
		c1_loyalty_transition.setCurStateExpression(l);
		c1_loyalty_transition.setMessageExpression(c1_message);
		c1_loyalty_transition.setNextStateExpression(nextLoyality);
		c1_loyalty.setStateTransition(c1_loyalty_transition);
		
		System.out.println(c1);
		
		try {
			System.out.println("-----");			
			System.out.println(c1.deriveUpdateExpressionOf(c1_loyalty).toImplementation());
			
			System.out.println("-- PUSH --");
			Expression loyaltyPushUpdate = c1.deriveUpdateExpressionOf(c1_loyalty, pushAccessor);
			Parameter param = null;
			for (Parameter p: loyaltyPushUpdate.getSubTerms(Parameter.class).values()) {
				if (p.equals(pPayment) || p.equals(pLoyalty) || p.equals(pHistory) || p.equals(pTotal)) {
					param = p;
					break;
				}
			}
			System.out.println("void update(" + param.getType().getImplementationTypeName() + " " + param.toImplementation() + ") {");
			System.out.println("\t" + fLoyalty + " = " + loyaltyPushUpdate.toImplementation() + ";");
			System.out.println("}");
			
			System.out.println("-- PULL --");
			System.out.println(loyalty.getResourceStateType().getImplementationTypeName() + " " + loyltyGetter.toImplementation() + "() {");
			System.out.println("\t return " + c1.deriveUpdateExpressionOf(c1_loyalty, pullAccessor).toImplementation() + ";");
			System.out.println("}");
		} catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage
				| UnificationFailed | ValueUndefined e) {
			e.printStackTrace();
		}
		
		System.out.println("==========");
		
		// === c2 ===
		//
		// payment(p1, update2(z)) == z
		// history(h, update2(z)) == cons(z, h)
		//
		DataflowChannelGenerator c2 = new DataflowChannelGenerator("c2");
		ChannelMember c2_payment = new ChannelMember(payment);
		ChannelMember c2_history = new ChannelMember(history);
		c2.addChannelMemberAsInput(c2_payment);
		c2.addChannelMemberAsOutput(c2_history);
		
		Variable z = new Variable("z");
		Variable h = new Variable("h");
		Symbol update2 = new Symbol("update2", 1);
		Term c2_message = new Term(update2);		// update2(z)
		c2_message.addChild(z);
		Term nextHistory = new Term(DataFlowModel.cons);	// cons(z, h)
		nextHistory.addChild(z);
		nextHistory.addChild(h);
		
		StateTransition c2_payment_transition = new StateTransition();
		c2_payment_transition.setCurStateExpression(p1);
		c2_payment_transition.setMessageExpression(c2_message);
		c2_payment_transition.setNextStateExpression(z);
		c2_payment.setStateTransition(c2_payment_transition);
		
		StateTransition c2_history_transition = new StateTransition();
		c2_history_transition.setCurStateExpression(h);
		c2_history_transition.setMessageExpression(c2_message);
		c2_history_transition.setNextStateExpression(nextHistory);
		c2_history.setStateTransition(c2_history_transition);
		
		System.out.println(c2);		
		
		try {
			System.out.println("-----");
			System.out.println(c2.deriveUpdateExpressionOf(c2_history).toImplementation());
			
			System.out.println("-- PUSH --");
			Expression historyPushUpdate = c2.deriveUpdateExpressionOf(c2_history, pushAccessor);
			Parameter param = null;
			for (Parameter p: historyPushUpdate.getSubTerms(Parameter.class).values()) {
				if (p.equals(pPayment) || p.equals(pLoyalty) || p.equals(pHistory) || p.equals(pTotal)) {
					param = p;
					break;
				}
			}
			System.out.println("void update(" + param.getType().getImplementationTypeName() + " " + param.toImplementation() + ") {");
			System.out.println("\t" + fHistory + " = " + historyPushUpdate.toImplementation() + ";");
			System.out.println("}");
			
			System.out.println("-- PULL --");
			System.out.println(history.getResourceStateType().getImplementationTypeName() + " " + historyGetter.toImplementation() + "() {");
			System.out.println("\t return " + c2.deriveUpdateExpressionOf(c2_history, pullAccessor).toImplementation() + ";");
			System.out.println("}");
		} catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage
				| UnificationFailed | ValueUndefined e) {
			e.printStackTrace();
		}
		
		System.out.println("==========");
		
		// === c3 ===
		//
		// history(h, update3(u)) = u
		// total(t, update3(u)) = sum(u)
		//
		DataflowChannelGenerator c3 = new DataflowChannelGenerator("c3");
		ChannelMember c3_history = new ChannelMember(history);
		ChannelMember c3_total = new ChannelMember(total);
		c3.addChannelMemberAsInput(c3_history);
		c3.addChannelMemberAsOutput(c3_total);
		
		Variable u = new Variable("u");
		Variable t = new Variable("t");
		Symbol update3 = new Symbol("update3", 1);
		Term c3_message = new Term(update3);		// update3(u)
		c3_message.addChild(u);
		Expression nextHistory2 = u;
		Term nextTotal = new Term(sum);
		nextTotal.addChild(u);
		
		StateTransition c3_history_transition = new StateTransition();
		c3_history_transition.setCurStateExpression(h);
		c3_history_transition.setMessageExpression(c3_message);
		c3_history_transition.setNextStateExpression(nextHistory2);
		c3_history.setStateTransition(c3_history_transition);

		StateTransition c3_total_transition = new StateTransition();
		c3_total_transition.setCurStateExpression(t);
		c3_total_transition.setMessageExpression(c3_message);
		c3_total_transition.setNextStateExpression(nextTotal);
		c3_total.setStateTransition(c3_total_transition);
		
		System.out.println(c3);

		try {
			System.out.println("-----");
			System.out.println(c3.deriveUpdateExpressionOf(c3_total).toImplementation());
			
			System.out.println("-- PUSH --");
			Expression totalPushUpdate = c3.deriveUpdateExpressionOf(c3_total, pushAccessor);
			Parameter param = null;
			for (Parameter p: totalPushUpdate.getSubTerms(Parameter.class).values()) {
				if (p.equals(pPayment) || p.equals(pLoyalty) || p.equals(pHistory) || p.equals(pTotal)) {
					param = p;
					break;
				}
			}
			System.out.println("void update(" + param.getType().getImplementationTypeName() + " " + param.toImplementation() + ") {");
			System.out.println("\t" + fTotal + " = " + totalPushUpdate.toImplementation() + ";");
			System.out.println("}");
			
			System.out.println("-- PULL --");
			System.out.println(total.getResourceStateType().getImplementationTypeName() + " " + totalGetter.toImplementation() + "() {");
			System.out.println("\t return " + c3.deriveUpdateExpressionOf(c3_total, pullAccessor).toImplementation() + ";");
			System.out.println("}");
		} catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage
				| UnificationFailed | ValueUndefined e) {
			e.printStackTrace();
		}
		
		System.out.println("==========");
	}

}