[464714] Added a new visitor to create the call graph
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/etl/MtcBroker.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/etl/MtcBroker.java
index ba29eb6..40e1e1a 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/etl/MtcBroker.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/etl/MtcBroker.java
@@ -51,6 +51,7 @@
 import org.eclipse.qvtd.pivot.qvtimperative.utilities.GraphMLBuilder;
 import org.eclipse.qvtd.pivot.schedule.Schedule;
 import org.eclipse.qvtd.pivot.schedule.SchedulePackage;
+import org.eclipse.qvtd.pivot.schedule.utilities.ScheduleToCallGraph;
 import org.eclipse.qvtd.pivot.schedule.utilities.ScheduleToDependencyGraphVisitor;
 
 // TODO: Auto-generated Javadoc
@@ -66,7 +67,7 @@
 	private static final String CONFIG_MODEL_NAME = "config";
 	
 	/** The Constant CONFIG_MM. */
-	private static final String CONFIG_MM = "platform:/resource/org.eclipse.qvtd.compiler/model/QVTcConfig.ecore";
+//	private static final String CONFIG_MM = "platform:/resource/org.eclipse.qvtd.compiler/model/QVTcConfig.ecore";
 	
 	/** The Constant CONFIG_URI. */
 	private static final String CONFIG_URI = QVTcConfigPackage.eNS_URI;
@@ -189,6 +190,8 @@
 	protected PivotModel oclStdLibModel;
 	
 	private URI dependencyGraphUri;
+	
+	private URI callGraphUri;
 
 	/** The r metamodel. */
 	@SuppressWarnings("unused")
@@ -230,6 +233,8 @@
 	
 	/** The i model. */
 	protected PivotModel iModel;
+
+	
 		
 	
 	/**
@@ -260,6 +265,7 @@
 		this.baseUri = baseURI;
 		this.debugUri = baseURI.appendSegment("debug");
 		String dgPath = this.debugUri.appendSegment(qvtcSource).trimFileExtension() + "Dependencies";
+		String cgPath = this.debugUri.appendSegment(qvtcSource).trimFileExtension() + "Calls";
 		System.out.println("Executing the QVTc to QVTi MTC for " + qvtcSource);
 		this.baseUri = baseURI;
 		URI qvtcURI = baseURI.appendSegment(qvtcSource);
@@ -272,6 +278,7 @@
 		this.configUri = URI.createURI(modelsBaseUri.toString() + "Config").appendFileExtension("xmi").toString();
 		this.scheduleUri = URI.createURI(modelsBaseUri.toString() + "Schedule").appendFileExtension("xmi").toString();
 		this.dependencyGraphUri = URI.createURI(dgPath).appendFileExtension("graphml");
+		this.callGraphUri = URI.createURI(cgPath).appendFileExtension("graphml");
 		
 		candidateMetamodelContainmentTrees = new HashMap<String, List<PivotModel>>();
 		registerMetamodels(environmentFactory);
@@ -373,7 +380,8 @@
 	
 	protected void qvtsToGraphML(PivotModel sModel) throws QvtMtcExecutionException {
 		
-		GraphBuilder builder = new GraphMLBuilder();
+		GraphBuilder depBuilder = new GraphMLBuilder();
+		GraphBuilder callBuilder = new GraphMLBuilder();
 		
 		Schedule s = null;
         try {
@@ -382,23 +390,38 @@
 			throw new QvtMtcExecutionException(e.getMessage(),e.getCause());
 		} finally {
 			if (s != null) {
-				ScheduleToDependencyGraphVisitor visitor = new ScheduleToDependencyGraphVisitor(builder, this.darkTheme);
+				ScheduleToDependencyGraphVisitor depVisitor = new ScheduleToDependencyGraphVisitor(depBuilder, this.darkTheme);
+				ScheduleToCallGraph callVisitor = new ScheduleToCallGraph(callBuilder, this.darkTheme);
 				// GEt the source/middle/target info from the configuration
 				for (EObject eContent : configModel.getResource().getContents()) {
 					if (eContent instanceof Configuration) {
 						Configuration c = (Configuration) eContent;
-						visitor.setInputDirection(c.getInputDirection().getName());
-						visitor.setMiddleDirection("middle"); // Always middle? Should the configuration have this value?
+						depVisitor.setInputDirection(c.getInputDirection().getName());
+						depVisitor.setMiddleDirection("middle"); // Always middle? Should the configuration have this value?
 						for (Direction od : c.getOutputDirection())  {
-							visitor.getOutputDirection().add(od.getName());
+							depVisitor.getOutputDirection().add(od.getName());
 						}
 					}
 				}
-				s.accept(visitor);
+				s.accept(depVisitor);
 				// Save/print the builder
 				try (Writer writer = new BufferedWriter(new OutputStreamWriter(
 						URIConverter.INSTANCE.createOutputStream(this.dependencyGraphUri), "utf-8"))) {
-				   writer.write(builder.toString());
+				   writer.write(depBuilder.toString());
+				} catch (UnsupportedEncodingException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				} catch (FileNotFoundException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				} catch (IOException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+				s.accept(callVisitor);
+				try (Writer writer = new BufferedWriter(new OutputStreamWriter(
+						URIConverter.INSTANCE.createOutputStream(this.callGraphUri), "utf-8"))) {
+				   writer.write(callBuilder.toString());
 				} catch (UnsupportedEncodingException e) {
 					// TODO Auto-generated catch block
 					e.printStackTrace();
@@ -411,6 +434,7 @@
 				}
 			}
 		}
+        System.out.println("Graphs created.");
 	}
 
 	public void executeQvtcToQvtu() throws QvtMtcExecutionException {
diff --git a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/utilities/GraphBuilder.java b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/utilities/GraphBuilder.java
index 6bcb0e6..9a210f2 100644
--- a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/utilities/GraphBuilder.java
+++ b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/utilities/GraphBuilder.java
@@ -15,6 +15,9 @@
 public interface GraphBuilder {
 	void appendEdge(@NonNull String sourceId, @NonNull String targetId, @NonNull String lineColor,
 			@NonNull String lineType, @NonNull String sourceArrowType, @NonNull String targetArrowType);
+	void appendEdge(@NonNull String sourceId, @NonNull String targetId, @NonNull String lineColor,
+			@NonNull String lineType, @NonNull String sourceArrowType, @NonNull String targetArrowType,
+			@NonNull String label);
 	void appendNode(@NonNull String id, @NonNull String shapeName,
 			@NonNull String fillColor, String label, @NonNull String labelColor);
 	void close();
diff --git a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/utilities/GraphMLBuilder.java b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/utilities/GraphMLBuilder.java
index 8a274a4..a87c1cc 100644
--- a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/utilities/GraphMLBuilder.java
+++ b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/utilities/GraphMLBuilder.java
@@ -200,6 +200,27 @@
 		s.popTag();
 	}
 	
+	@Override
+	public void appendEdge(@NonNull String sourceId, @NonNull String targetId,
+			@NonNull String lineColor, @NonNull String lineType,
+			@NonNull String sourceArrowType, @NonNull String targetArrowType,
+			@NonNull String label) {
+		s.pushTag("edge");
+		s.appendElement("id", "e" + edgeCount++);
+		s.appendElement("source", "n" + sourceId);
+		s.appendElement("target", "n" + targetId);
+		s.pushTag("data");
+			s.appendElement("key", "d9");
+			s.pushTag("y:PolyLineEdge");
+				appendLineStyle(new LineStyle(lineColor, LineType.valueOf(lineType)));
+				appendArrows(sourceArrowType, targetArrowType);
+				appendEdgeLabel(label, lineColor);
+			s.popTag();
+		s.popTag();
+	s.popTag();
+	}
+
+	
 	public void appendFill(@NonNull String fillColor) {
 		s.pushTag("y:Fill");
 			s.appendElement("color", fillColor);
@@ -217,7 +238,13 @@
 		s.popTag();
 	}
 	
-	protected void appendLabel(String label, String labelColor) {
+	protected void appendEdgeLabel(String label, String labelColor) {
+		s.pushTag("y:EdgeLabel");
+			s.appendElement("textColor", labelColor);
+		s.appendValueAndPopTag(label);
+	}
+	
+	protected void appendNodeLabel(String label, String labelColor) {
 		s.pushTag("y:NodeLabel");
 			s.appendElement("textColor", labelColor);
 		s.appendValueAndPopTag(label);
@@ -245,7 +272,7 @@
 					appendGeometry(g);
 					appendFill(fillColor);
 					appendBorder(new BorderStyle(labelColor, LineType.line));
-					appendLabel(label, labelColor);
+					appendNodeLabel(label, labelColor);
 					appendShape(shapeName);
 				s.popTag();
 			s.popTag();
@@ -305,4 +332,5 @@
 	}
 
 
+
 }
diff --git a/plugins/org.eclipse.qvtd.pivot.schedule/src/org/eclipse/qvtd/pivot/schedule/utilities/ScheduleToCallGraph.java b/plugins/org.eclipse.qvtd.pivot.schedule/src/org/eclipse/qvtd/pivot/schedule/utilities/ScheduleToCallGraph.java
new file mode 100644
index 0000000..940313c
--- /dev/null
+++ b/plugins/org.eclipse.qvtd.pivot.schedule/src/org/eclipse/qvtd/pivot/schedule/utilities/ScheduleToCallGraph.java
@@ -0,0 +1,196 @@
+package org.eclipse.qvtd.pivot.schedule.utilities;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.ocl.pivot.NamedElement;
+import org.eclipse.qvtd.pivot.qvtimperative.utilities.GraphBuilder;
+import org.eclipse.qvtd.pivot.qvtimperative.utilities.GraphMLBuilder.ArrowType;
+import org.eclipse.qvtd.pivot.qvtimperative.utilities.GraphMLBuilder.LineType;
+import org.eclipse.qvtd.pivot.qvtimperative.utilities.GraphMLBuilder.ShapeType;
+import org.eclipse.qvtd.pivot.schedule.AbstractAction;
+import org.eclipse.qvtd.pivot.schedule.MappingAction;
+import org.eclipse.qvtd.pivot.schedule.ParameterDerivation;
+import org.eclipse.qvtd.pivot.schedule.Schedule;
+import org.eclipse.qvtd.pivot.schedule.ScheduleElement;
+import org.eclipse.qvtd.pivot.schedule.util.AbstractExtendingScheduleVisitor;
+
+public class ScheduleToCallGraph extends AbstractExtendingScheduleVisitor<String, GraphBuilder> {
+	
+	private final List<String> SOL_BASE = Arrays.asList("#fdf6e3", "#eee8d5", "#93a1a1", "#839496", "#657b83", "#586e75", "#073642", "#002b36");
+	@NonNull private final int SOL_BACKROUND = 0;
+	@NonNull private final int SOL_BACKROUND_HL = 1;
+	@NonNull private final int SOL_SECONDARY = 2;
+	@NonNull private final int SOL_NONE = 3;
+	@NonNull private final int SOL_PRIMARY = 4;
+	@NonNull private final int SOL_OPTIONAL = 5;
+	
+	@NonNull private final String SOL_YELLOW = "#b58900";
+	@NonNull private final String SOL_ORANGE = "#cb4b16";
+	@NonNull private final String SOL_RED = "#dc322f";
+	@NonNull private final String SOL_MAGENTA = "#d33682";
+	@NonNull private final String SOL_VIOLET = "#6c71c4";
+	@NonNull private final String SOL_BLUE = "#268bd2";
+	@NonNull private final String SOL_CYAN = "#2aa198";
+	@NonNull private final String SOL_GREEN = "#859900";
+	
+	@NonNull private final String NODE_FILL_COLOR;
+	
+	@NonNull private final String MAPPING_ACTION_COLOR = SOL_ORANGE;
+	@NonNull private final String MAPPING_ACTION_SHAPE = ShapeType.hexagon.name();
+	@NonNull private final String LOOP_SHAPE = ShapeType.rectangle.name();
+	
+	@NonNull private final String SUPER_EDGE_COLOR;
+	@NonNull private final String PRODUCTION_EDGE_COLOR;
+	@NonNull private final String REQUISITE_EDGE_COLOR = SOL_GREEN;
+	@NonNull private final String REQUISITE_MULTIPLE_EDGE_COLOR = SOL_RED;
+	@NonNull private final String DEPENDENCY_ARROW_END = ArrowType.standard.name();
+	@NonNull private final String DEPENDENCY_LOOP_ARROW_END = ArrowType.transparent_circle.name();
+	@NonNull private final String SUPER_ARROW_END = ArrowType.delta.name();
+	
+	
+	private Map<MutiNamedElementKeyImpl, Integer> nodeOrder = new HashMap<MutiNamedElementKeyImpl, Integer>();
+	//private Map<CoreDomain, String> domainColor = new HashMap<CoreDomain, String>();
+	private List<String> outputDirection;
+	private boolean onlyClassDatums;
+//	private int loopNodeId;
+	
+	public ScheduleToCallGraph(GraphBuilder context) {
+		this(context, false);
+	}
+	
+	public ScheduleToCallGraph(GraphBuilder context, boolean darkTheme) {
+		super(context);
+		if (darkTheme) {
+			Collections.reverse(SOL_BASE);
+		}
+		NODE_FILL_COLOR = SOL_BASE.get(SOL_BACKROUND_HL);
+		SUPER_EDGE_COLOR = SOL_BASE.get(SOL_SECONDARY);
+		PRODUCTION_EDGE_COLOR = SOL_BASE.get(SOL_PRIMARY);
+	}
+
+	protected @NonNull String getMappingLabel(@NonNull MappingAction object) {
+		String id = object.getMapping().getName() + "\n" + "(" + object.getOrder() + ")"; 
+		return id;
+	}
+
+	/**
+	 * @param eo
+	 * @return
+	 */
+	private Integer getNodeOrder(@NonNull NamedElement... elements) {
+		MutiNamedElementKeyImpl key = new MutiNamedElementKeyImpl(elements);
+		Integer order;
+		if (nodeOrder.containsKey(key)) {
+			order = nodeOrder.get(key);
+		} else {
+			order = nodeOrder.size()+1;
+			nodeOrder.put(key, order);
+		}
+		return order;
+	}
+
+	public List<String> getOutputDirection() {
+		if (this.outputDirection == null)
+			this.outputDirection = new ArrayList<String>();
+		return this.outputDirection;
+	}
+	
+//	private String getPropertyId(PropertyDatum object) {
+//		String id = //object.getDomain().getName() + "\n" +
+//				object.getClassDatum().getType().getName() + "\n." + object.getProperty().getName();
+//		return id;
+//	}
+	
+//	private boolean nodeExists(@NonNull NamedElement... elements) {
+//		MutiNamedElementKeyImpl key = new MutiNamedElementKeyImpl(elements);
+//		return nodeOrder.containsKey(key);
+//	}
+	
+	@Override
+	@Nullable
+	public String visiting(ScheduleElement visitable) {
+		throw new IllegalArgumentException("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
+	}
+
+	@Override
+	public @Nullable String visitMappingAction(MappingAction object) {
+		
+		String mappingLabel;
+		String order;
+		if (object.getMapping() != null) {
+			mappingLabel = getMappingLabel(object);
+			order = getNodeOrder(object.getMapping()).toString();
+		}
+		else {
+			mappingLabel = "root";
+			order  = "0";
+		}
+		context.appendNode(order, MAPPING_ACTION_SHAPE, NODE_FILL_COLOR, mappingLabel, MAPPING_ACTION_COLOR);
+//		String lineType = LineType.line.name();
+		int childCount = 0;
+		for (AbstractAction mc : object.getChildren()) {
+			@SuppressWarnings("unused")
+			boolean allLoop = false;
+			StringBuilder loopVars = new StringBuilder();
+			String sep = "";
+			for (ParameterDerivation pd : mc.getParameterDerivations()) {
+				// Add nodes for loops
+				if (pd.getPrimaryParameter() == null) {
+					allLoop = true;
+					loopVars.append(pd.getSecondaryParameter().getDataParameter().getVariable().getName());
+					break;
+				} else {
+					//String pdOrder = String.valueOf(loopNodeId++);
+					//context.appendNode(pdOrder, LOOP_SHAPE, NODE_FILL_COLOR, mappingLabel, MAPPING_ACTION_COLOR);
+					loopVars.append(sep);
+					loopVars.append(pd.getSecondaryParameter().getDataParameter().getVariable().getName());
+				    sep = ",";
+				}
+			}
+			String targetId = null;
+			targetId = getNodeOrder(((MappingAction) mc).getMapping()).toString();
+			assert targetId != null;
+			context.appendEdge(order,
+					targetId,
+					PRODUCTION_EDGE_COLOR,
+					LineType.line.name(),
+					ArrowType.none.name(),
+					DEPENDENCY_ARROW_END,
+					loopVars.toString() + "(" + String.valueOf(childCount++) + ")");
+		}
+		return null;
+	}
+
+	@Override
+	public @Nullable String visitSchedule(Schedule object) {
+		
+		context.open();
+		// First the datums so the nodes exist
+//		loopNodeId = object.getActions().size()+1;
+		for (AbstractAction aa : object.getActions()) {
+			if (aa instanceof MappingAction) {
+				MappingAction ma = (MappingAction) aa;
+				//if (ma.getMapping() != null)
+					visitMappingAction(ma);
+			}
+		}
+		context.close();
+		return null;
+	}
+
+	public boolean isOnlyClassDatums() {
+		return onlyClassDatums;
+	}
+
+	public void setOnlyClassDatums(boolean onlyClassDatums) {
+		this.onlyClassDatums = onlyClassDatums;
+	}
+
+}
diff --git a/tests/org.eclipse.qvtd.build.etl.tests/src/org/eclipse/qvtd/build/etl/tests/QVTdMtcTests.java b/tests/org.eclipse.qvtd.build.etl.tests/src/org/eclipse/qvtd/build/etl/tests/QVTdMtcTests.java
index b04155b..692ab4d 100644
--- a/tests/org.eclipse.qvtd.build.etl.tests/src/org/eclipse/qvtd/build/etl/tests/QVTdMtcTests.java
+++ b/tests/org.eclipse.qvtd.build.etl.tests/src/org/eclipse/qvtd/build/etl/tests/QVTdMtcTests.java
@@ -119,7 +119,7 @@
     	MyQVT myQVT = createQVT();
     	
     	URI testBaseURI = TESTS_BASE_URI.appendSegment("UmlToRdbms");;
-    	URI samplesBaseUri = testBaseURI.appendSegment("samples");
+//    	URI samplesBaseUri = testBaseURI.appendSegment("samples");
     	MtcBroker mtc = new MtcBroker(testBaseURI, "UmlToRdbms.qvtcas", myQVT.getEnvironmentFactory(), TestsXMLUtil.defaultSavingOptions);
     	mtc.setCreateGraphml(true);
     	mtc.execute();