package tests;

import static org.junit.Assert.*;

import org.junit.Test;

import models.*;
import models.algebra.Variable;
import models.dataConstraintModel.*;
import models.dataFlowModel.*;

public class DataTransferModelTest {

	@Test
	public void test() {
		// Construct a data-flow architecture model.
		DataTransferModel model = new DataTransferModel();
		
		ResourcePath customers = new ResourcePath("customers");						// "customers"
		ResourcePath customer = new ResourcePath(customers, new Variable("uid"));	// "customers.{uid}"
		ResourcePath customer_off = new ResourcePath(customer, "off");				// "customers.{uid}.off"
		ResourcePath customer_add = new ResourcePath(customer, "add");				// "customers.{uid}.add"
		ResourcePath companies = new ResourcePath("companies");						// "companies"
		ResourcePath company = new ResourcePath(companies, new Variable("cid"));	// "companies.{cid}"
		ResourcePath company_add = new ResourcePath(company, "add");				// "companies.{cid}.add"
		model.addResourcePath(customer_off);
		model.addResourcePath(customer_add);
		model.addResourcePath(company_add);
				
		// === cio_setCustomerOff(uid) ===
		//
		// out customers.{uid}.off(c, set(x)) = x
		//
		DataTransferChannel cio_setCustomerOff = new DataTransferChannel("CIO_SetCustomerOff", new Variable("uid"));	// set customer's office (an input channel)
		ChannelMember customer_off_1 = new ChannelMember(customer_off);
		cio_setCustomerOff.addChannelMemberAsOutput(customer_off_1);
		assertEquals(customer_off.getPathParams().get(0), cio_setCustomerOff.getSelectors().iterator().next().getExpression());
		
		// === cio_setCompanyAdd(cid) ===
		//
		// out companies.{cid}.add(a, set(y)) = y
		//
		DataTransferChannel cio_setCompanyAdd = new DataTransferChannel("CIO_SetCompanyAdd", new Variable("cid"));	// set companie's address (an input channel)
		ChannelMember company_add_1 = new ChannelMember(company_add);
		cio_setCompanyAdd.addChannelMemberAsOutput(company_add_1);		
		assertEquals(company_add.getPathParams().get(0), cio_setCompanyAdd.getSelectors().iterator().next().getExpression());
		
		// === c ===
		//		
		// in customers.{uid}.off( c, update(cid, a2)) = cid
		// in companies.{cid}.add( a, update(cid, a2)) = a2
		// out customers.{uid}.add(b, update(cid, a2)) = a2
		//
		DataTransferChannel c = new DataTransferChannel("c", new Variable("uid"));		// update customer's address
		ChannelMember customer_off_2 = new ChannelMember(customer_off);
		ChannelMember company_add_2 = new ChannelMember(company_add);
		ChannelMember customer_add_2 = new ChannelMember(customer_add);
		c.addChannelMemberAsInput(customer_off_2);
		c.addChannelMemberAsInput(company_add_2);
		c.addChannelMemberAsOutput(customer_add_2);
		assertEquals(customer_off.getPathParams().get(0), c.getSelectors().iterator().next().getExpression());
		assertEquals(customer_add.getPathParams().get(0), c.getSelectors().iterator().next().getExpression());
		assertEquals(company_add.getPathParams().get(0), new Variable("cid"));
		
		// Construct a data-flow architecture model.
		model.addInputChannel(cio_setCustomerOff);
		model.addInputChannel(cio_setCompanyAdd);
		model.addChannel(c);
		
		// Check the model.
		assertEquals(3, model.getResourcePaths().size());
		assertEquals(7, model.getResourceHierarchies().size());
		assertEquals(2, model.getInputChannels().size());
		assertEquals(1, model.getChannels().size());
		
		// Extract the resource dependency graph.
		DataFlowGraph resourceDependencyGraph = model.getDataFlowGraph();
		
		// Check the graph.
		assertEquals(7, resourceDependencyGraph.getResourceNodes().size());
		assertEquals(3, resourceDependencyGraph.getChannelNodes().size());
		assertEquals(5, resourceDependencyGraph.getEdges().size());
		for (Edge e: resourceDependencyGraph.getEdges()) {
			System.out.println(e.getSource() + "-(" + e + ")->" + e.getDestination());
		}
	}

}
