
import uk.ac.ic.doc.automed.*;
import uk.ac.ic.doc.automed.reps.*;


/**
	An application that defines the "Attribute generalization" template transformation.
	This transformation should be applied on a schema of the "er" model.
	It creates a new attribute for each sub-entity in a generalization hierarcy and
	deletes an attribute from the general entity in the hierarchy. 
 
	The arguments for this transformation are:
	1. initial schema ID
	2. existing attribute ID
	3. sub-entity IDs 
	4. new attribute names
	5. new attribute IDs (returned value) 
	6. final schema ID (returned value)
*/
public class AttributeGeneralization {
  private static String modelName="er";
  private static String entityConstructName="erEntity";
  private static String attributeConstructName="erAttribute";
  private static String relationshipConstructName="erRelationship";
  private static String generalizationConstructName="erGeneralization";

	private static String templateName = "Attribute generalization";
	private static String templateInForEach = "AddAttribute";
	private static String forEachTemplate = "foreach in Attribute generalization";

	public static void defineTemplate()
		throws TemplateTransformationRepositoryException, RepositoryAccessException, TemplateTransformationSyntaxRepositoryException, AutoRepException, AutoMedException
	{
		try{
			CompositeTransformation.removeCompositeTransformation(templateInForEach);
		}
		catch(TemplateTransformationRepositoryException exc){
			System.out.println("new transformation "+templateInForEach);
		}

		try{
			CompositeTransformation.removeCompositeTransformation(forEachTemplate);
		}
		catch(TemplateTransformationRepositoryException exc){
			System.out.println("new transformation "+forEachTemplate);
		}

		try{
			CompositeTransformation.removeCompositeTransformation(templateName);
		}
		catch(TemplateTransformationRepositoryException exc){
			System.out.println("new transformation "+templateName);
		}

		Model er = Model.getModel(modelName);
//		Construct erEntity = er.getConstruct(entityConstructName);
		Construct erAttribute = er.getConstruct(attributeConstructName);


		///////// transformation to be execute inside the foreach statement /////////

		//create attribute
		TemplateArgumentSequence newAttributeArgs = new TemplateArgumentSequence();
		newAttributeArgs.createArgument(CompositeTransformation.ARG_CID_IN_NEWOBJECT, String.valueOf(erAttribute.getCID()));
		newAttributeArgs.createArgument(CompositeTransformation.ARG_VALUE_IN_NEWOBJECT, 3);
		newAttributeArgs.createArgument(CompositeTransformation.ARG_ISTEMP_IN_NEWOBJECT, "0");
		TemplateArgumentSequence newAttributeSchemeArgs = new TemplateArgumentSequence();
		newAttributeSchemeArgs.createArgument(1, 2); 
		newAttributeSchemeArgs.createArgument(2, newAttributeArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newAttributeArgs.createArgument(CompositeTransformation.ARG_SCHEME_IN_NEWOBJECT, String.valueOf(newAttributeSchemeArgs.getSequenceId()));

		//add attribute
		TemplateArgumentSequence addNewAttributeArgs = new TemplateArgumentSequence();
		addNewAttributeArgs.createArgument(CompositeTransformation.ARG_ACTION_IN_PRIMITIVE, "add");
		addNewAttributeArgs.createArgument(CompositeTransformation.ARG_FROMOBJ_IN_PRIMITIVE, "-1");
		addNewAttributeArgs.createArgument(CompositeTransformation.ARG_TOOBJ_IN_PRIMITIVE, newAttributeArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		addNewAttributeArgs.createArgument(CompositeTransformation.ARG_FROMSCHEMA_IN_PRIMITIVE, 1); 
		addNewAttributeArgs.createArgument(CompositeTransformation.ARG_TOSCHEMA_IN_PRIMITIVE, newAttributeArgs, CompositeTransformation.ARG_SID_IN_NEWOBJECT);
		addNewAttributeArgs.createArgument(CompositeTransformation.ARG_FUNCTION_IN_PRIMITIVE, "");
		addNewAttributeArgs.createArgument(CompositeTransformation.ARG_CONSTRAINTS_IN_PRIMITIVE, "");

		//define returned values
		TemplateArgumentSequence returnedArgs = new TemplateArgumentSequence();
		returnedArgs.createArgument(4, newAttributeArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		returnedArgs.createArgument(5, addNewAttributeArgs, CompositeTransformation.ARG_TOSCHEMA_IN_PRIMITIVE);
		//define transformation 
		CompositeTransformation addAttribute = new CompositeTransformation(templateInForEach, "extend schema with attribute", false);
		addAttribute.createArgumentDefinition(1, "schema", "SID", "initial schema ID", false);
		addAttribute.createArgumentDefinition(2, "object", "OBID", "existing entity ID", false);
		addAttribute.createArgumentDefinition(3, "object", "value", "new attribute name", false);
		addAttribute.createArgumentDefinition(4, "object", "OBID", "new attribute ID", true);
		addAttribute.createArgumentDefinition(5, "schema", "SID", "final schema ID", true);

		addAttribute.createReturnedArgumentsDefinition(returnedArgs);
		
		addAttribute.createStatementExecution(1, Statement.getStatement(CompositeTransformation.NEW_OBJECT_STATEMENT), newAttributeArgs);
		addAttribute.createStatementExecution(2, Statement.getStatement(CompositeTransformation.PRIMITIVE_TRANSFORMATION_STATEMENT), addNewAttributeArgs);



		////// define foreach template transformation //////////////

		TemplateArgumentSequence transformationArgs = new TemplateArgumentSequence();
		transformationArgs.createArgument(1, 1); 
		transformationArgs.createArgument(2, 2);
		transformationArgs.createArgument(3, 3);
	
		TemplateArgumentSequence invokeArgs = new TemplateArgumentSequence();
		invokeArgs.createArgument(CompositeTransformation.ARG_TRANSFORMATION_IN_INVOCATION, String.valueOf(CompositeTransformation.getCompositeTransformation(templateInForEach).getTransId())); 
		invokeArgs.createArgument(CompositeTransformation.ARG_ARGUMENTS_IN_INVOCATION, String.valueOf(transformationArgs.getSequenceId()));

		CompositeTransformation foreachBlock = new CompositeTransformation(forEachTemplate, null, false); 
		foreachBlock.createStatementExecution(1, Statement.getStatement(CompositeTransformation.INVOCATION_STATEMENT), invokeArgs);



		///////////// main template ///////////////////
	
		// initialise foreach statement's args
		TemplateArgumentSequence foreachArgs = new TemplateArgumentSequence();
		foreachArgs.createArgument(CompositeTransformation.ARG_SCHEMA_IN_FOREACH, 1);
	
		TemplateArgumentSequence singletonArgs = new TemplateArgumentSequence();
		singletonArgs.createArgument(1, foreachArgs, CompositeTransformation.ARG_SCHEMA_IN_FOREACH);

		TemplateArgumentSequence sequenceArgs = new TemplateArgumentSequence();
		sequenceArgs.createArgument(2, 3);	
		sequenceArgs.createArgument(3, 4);	
		
		foreachArgs.createArgument(CompositeTransformation.ARG_ARGSEQUENCES_IN_FOREACH, String.valueOf(sequenceArgs.getSequenceId()));
		foreachArgs.createArgument(CompositeTransformation.ARG_ARGSINGLETONS_IN_FOREACH, String.valueOf(singletonArgs.getSequenceId()));
		foreachArgs.createArgument(CompositeTransformation.ARG_TRANS_IN_FOREACH, String.valueOf(foreachBlock.getTransId()));

		//initialise delete attribute args
		TemplateArgumentSequence deleteAttributeArgs = new TemplateArgumentSequence();
		deleteAttributeArgs.createArgument(CompositeTransformation.ARG_ACTION_IN_PRIMITIVE, "del");
		deleteAttributeArgs.createArgument(CompositeTransformation.ARG_FROMOBJ_IN_PRIMITIVE, 2);
		deleteAttributeArgs.createArgument(CompositeTransformation.ARG_TOOBJ_IN_PRIMITIVE, "-1");
		deleteAttributeArgs.createArgument(CompositeTransformation.ARG_FROMSCHEMA_IN_PRIMITIVE, foreachArgs, CompositeTransformation.ARG_SCHEMA_IN_FOREACH);
		deleteAttributeArgs.createArgument(CompositeTransformation.ARG_FUNCTION_IN_PRIMITIVE, "");
		deleteAttributeArgs.createArgument(CompositeTransformation.ARG_CONSTRAINTS_IN_PRIMITIVE, "");

		//define main template's returned values
		TemplateArgumentSequence globalReturnedArgs = new TemplateArgumentSequence();
		globalReturnedArgs.createArgument(5, foreachArgs, CompositeTransformation.ARG_RETURNED_ARGS_START_IN_FOREACH);
		globalReturnedArgs.createArgument(6, foreachArgs, CompositeTransformation.ARG_RETURNED_ARGS_START_IN_FOREACH+1);
	
		//define main template
		CompositeTransformation trans = new CompositeTransformation(
				templateName, 
				"Transformation removes attribute and adds it to the subentities", 
				true);
		trans.createArgumentDefinition(1, "schema", "SID", "initial schema", false);
		trans.createArgumentDefinition(2, "object", "OBID", "existing general attribute ID", false);
		trans.createArgumentDefinition(3, "arguments", "arg_id", "sub-entities IDs", false);
		trans.createArgumentDefinition(4, "argument", "arg_id", "new attribute names", false);
		trans.createArgumentDefinition(5, "argument", "arg_id", "new attribute IDs", true);
		trans.createArgumentDefinition(6, "schema", "SID", "final schema ID", true);
	
		trans.createReturnedArgumentsDefinition(globalReturnedArgs);
		
		trans.createStatementExecution(1, Statement.getStatement(CompositeTransformation.FOREACH_STATEMENT), foreachArgs);	
		trans.createStatementExecution(2, Statement.getStatement(CompositeTransformation.PRIMITIVE_TRANSFORMATION_STATEMENT), deleteAttributeArgs);	
	}

	public static void main(String[] args){
		try{
			System.out.println("Re-creating template transformation Attribute generalization...");
			defineTemplate();
		}
		catch(Exception e){
			e.printStackTrace();
		}	

	}
}	
