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


/**
	An application that defines the "Mandatory Attribute and Total Generalisation Equivalence" template transformation.
	This transformation should be applied on a schema of the "er" model.
	It creates a generalization hierarchy with a list of subentities. The created subentities are based
	on the values of a mandatory attribute in an existing entity. The mandatory attribute is removed
	from the general entity.
	
	The arguments for this transformation are:
	1. initial schema ID
	2. existing general entity ID
	3. existing mandatory attribute ID 
	4. new generalization name 
	5. argument sequence ID (list of new entity names)
	6. new total constraint ID (returned value) 
	7. new generalization ID (returned value) 
	8. argument sequence ID (list of new entity IDs) (returned value) 
	9. final schema ID (returned value)
*/
public class MandatoryAttribute {
  private static String modelName="erOld";
  private static String entityConstructName="entityOld";
  private static String attributeConstructName="attributeOld";
  private static String relationshipConstructName="relationshipOld";
  private static String generalizationConstructName="generalisationOld";

	private static String templateName = "Mandatory Attribute and Total Generalisation Equivalence";
	private static String templateInForEach = "AddEntity";
	private static String forEachTemplate = "foreach in Mandatory Attribute and Total Generalisation Equivalence";


	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 erGeneralization = er.getConstruct(generalizationConstructName);

		// define transformation to execute in foreach block
		defineSubTemplate(erEntity);


		// define foreach transformation
		TemplateArgumentSequence transformationArgs = new TemplateArgumentSequence();
		transformationArgs.createArgument(1, 1); 
		transformationArgs.createArgument(2, 2);
	
		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 transformation ///////////////////////////
		
		// initialise foreach statement's args
		TemplateArgumentSequence foreachArgs = new TemplateArgumentSequence();
		foreachArgs.createArgument(CompositeTransformation.ARG_SCHEMA_IN_FOREACH, 1);
		
		//singleton argument is the schema	
		TemplateArgumentSequence singletonArgs = new TemplateArgumentSequence();
		singletonArgs.createArgument(1, foreachArgs, CompositeTransformation.ARG_SCHEMA_IN_FOREACH);

		//sequence is the sub-entity names
		TemplateArgumentSequence sequenceArgs = new TemplateArgumentSequence();
		sequenceArgs.createArgument(2, 5);
		
		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()));
	

		// new object: total
		TemplateArgumentSequence newTotalArgs = new TemplateArgumentSequence();
		newTotalArgs.createArgument(CompositeTransformation.ARG_CID_IN_NEWOBJECT, "0");//no construct???
		newTotalArgs.createArgument(CompositeTransformation.ARG_VALUE_IN_NEWOBJECT, "total");
		newTotalArgs.createArgument(CompositeTransformation.ARG_ISTEMP_IN_NEWOBJECT, "0");
		TemplateArgumentSequence newTotalSchemeArgs = new TemplateArgumentSequence();
		newTotalSchemeArgs.createArgument(1, newTotalArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newTotalArgs.createArgument(CompositeTransformation.ARG_SCHEME_IN_NEWOBJECT, String.valueOf(newTotalSchemeArgs.getSequenceId()));


		// new object: generalization
		TemplateArgumentSequence newGeneralizationArgs = new TemplateArgumentSequence();
		//the generalization's scheme must be the same as the total's
		newGeneralizationArgs.createArgument(CompositeTransformation.ARG_SID_IN_NEWOBJECT, newTotalArgs, CompositeTransformation.ARG_SID_IN_NEWOBJECT);
		newGeneralizationArgs.createArgument(CompositeTransformation.ARG_CID_IN_NEWOBJECT, String.valueOf(erGeneralization.getCID()));
		newGeneralizationArgs.createArgument(CompositeTransformation.ARG_VALUE_IN_NEWOBJECT, 4); 
		newGeneralizationArgs.createArgument(CompositeTransformation.ARG_ISTEMP_IN_NEWOBJECT, "0");
		TemplateArgumentSequence newGeneralizationSchemeArgs = new TemplateArgumentSequence();
		newGeneralizationSchemeArgs.createArgument(1, newGeneralizationArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newGeneralizationSchemeArgs.createArgument(2, newTotalArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newGeneralizationSchemeArgs.createArgument(3, 2);
		// the rest of the scheme is in a sequence of arguments
		// the generalization's scheme will be extended next
		newGeneralizationArgs.createArgument(CompositeTransformation.ARG_SCHEME_IN_NEWOBJECT, String.valueOf(newGeneralizationSchemeArgs.getSequenceId()));


		// extend scheme
		TemplateArgumentSequence extendSchemeArgs = new TemplateArgumentSequence();
		extendSchemeArgs.createArgument(1, foreachArgs, CompositeTransformation.ARG_RETURNED_ARGS_START_IN_FOREACH);
		extendSchemeArgs.createArgument(2, newGeneralizationArgs, CompositeTransformation.ARG_SCHEME_IN_NEWOBJECT);
		extendSchemeArgs.createArgument(3, "4"); //hardcoded???


		// add generalization
		TemplateArgumentSequence addNewGeneralizationArgs = new TemplateArgumentSequence();
		addNewGeneralizationArgs.createArgument(CompositeTransformation.ARG_ACTION_IN_PRIMITIVE, "add");
		addNewGeneralizationArgs.createArgument(CompositeTransformation.ARG_FROMOBJ_IN_PRIMITIVE, "-1");
		addNewGeneralizationArgs.createArgument(CompositeTransformation.ARG_TOOBJ_IN_PRIMITIVE, newGeneralizationArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		addNewGeneralizationArgs.createArgument(CompositeTransformation.ARG_FROMSCHEMA_IN_PRIMITIVE, foreachArgs, CompositeTransformation.ARG_SCHEMA_IN_FOREACH); 
		addNewGeneralizationArgs.createArgument(CompositeTransformation.ARG_TOSCHEMA_IN_PRIMITIVE, newGeneralizationArgs, CompositeTransformation.ARG_SID_IN_NEWOBJECT);
		addNewGeneralizationArgs.createArgument(CompositeTransformation.ARG_FUNCTION_IN_PRIMITIVE, "");
		addNewGeneralizationArgs.createArgument(CompositeTransformation.ARG_CONSTRAINTS_IN_PRIMITIVE, "");


		// delete attribute
		TemplateArgumentSequence deleteAttributeArgs = new TemplateArgumentSequence();
		deleteAttributeArgs.createArgument(CompositeTransformation.ARG_ACTION_IN_PRIMITIVE, "del");
		deleteAttributeArgs.createArgument(CompositeTransformation.ARG_FROMOBJ_IN_PRIMITIVE, 3); 
		deleteAttributeArgs.createArgument(CompositeTransformation.ARG_TOOBJ_IN_PRIMITIVE, "-1");
		deleteAttributeArgs.createArgument(CompositeTransformation.ARG_FROMSCHEMA_IN_PRIMITIVE, newGeneralizationArgs, CompositeTransformation.ARG_SID_IN_NEWOBJECT);
		deleteAttributeArgs.createArgument(CompositeTransformation.ARG_FUNCTION_IN_PRIMITIVE, "");
		deleteAttributeArgs.createArgument(CompositeTransformation.ARG_CONSTRAINTS_IN_PRIMITIVE, "");


		// template's returned values
		TemplateArgumentSequence globalReturnedArgs = new TemplateArgumentSequence();
		globalReturnedArgs.createArgument(6, newTotalArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		globalReturnedArgs.createArgument(7, newGeneralizationArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		globalReturnedArgs.createArgument(8, foreachArgs, CompositeTransformation.ARG_RETURNED_ARGS_START_IN_FOREACH);
		globalReturnedArgs.createArgument(9, deleteAttributeArgs, CompositeTransformation.ARG_TOSCHEMA_IN_PRIMITIVE);


		//define transformation
		CompositeTransformation trans = new CompositeTransformation(
				templateName, 
				"Transformation removes mandatory attribute and adds the corresponding subentities", 
				true);
		trans.createArgumentDefinition(1, "schema", "SID", "initial schema ID", false);
		trans.createArgumentDefinition(2, "object", "OBID", "existing general entity ID", false);
		trans.createArgumentDefinition(3, "object", "OBID", "existing mandatory attribute ID", false);
		trans.createArgumentDefinition(4, "object", "value", "new generalization name", false);
		trans.createArgumentDefinition(5, "arguments", "arg_id", "new sub-entity names", false);
		trans.createArgumentDefinition(6, "object", "OBID", "new total ID", true);
		trans.createArgumentDefinition(7, "object", "OBID", "new generalization ID", true);
		trans.createArgumentDefinition(8, "arguments", "arg_id", "new sub-entity IDs", true);
		trans.createArgumentDefinition(9, "schema", "SID", "final schema ID", true);


		trans.createReturnedArgumentsDefinition(globalReturnedArgs);

	
		trans.createStatementExecution(1, Statement.getStatement(CompositeTransformation.FOREACH_STATEMENT), foreachArgs);	
		trans.createStatementExecution(2, Statement.getStatement(CompositeTransformation.NEW_OBJECT_STATEMENT), newTotalArgs);	
		trans.createStatementExecution(3, Statement.getStatement(CompositeTransformation.NEW_OBJECT_STATEMENT), newGeneralizationArgs);	
		trans.createStatementExecution(4, Statement.getStatement(CompositeTransformation.EXTGENSCHEME_STATEMENT), extendSchemeArgs);	
		trans.createStatementExecution(5, Statement.getStatement(CompositeTransformation.PRIMITIVE_TRANSFORMATION_STATEMENT), addNewGeneralizationArgs);	
		trans.createStatementExecution(6, Statement.getStatement(CompositeTransformation.PRIMITIVE_TRANSFORMATION_STATEMENT), deleteAttributeArgs);	
	}


	// template adds a new entity to schema
	// template args: (initial schema ID, new entity name, &new entity ID, &final schema ID)
	private static void defineSubTemplate(Construct erEntity)
		throws TemplateTransformationRepositoryException, RepositoryAccessException, TemplateTransformationSyntaxRepositoryException, AutoRepException, AutoMedException
	{
		TemplateArgumentSequence newEntityArgs = new TemplateArgumentSequence();
		newEntityArgs.createArgument(CompositeTransformation.ARG_CID_IN_NEWOBJECT, String.valueOf(erEntity.getCID()));
		newEntityArgs.createArgument(CompositeTransformation.ARG_VALUE_IN_NEWOBJECT, 2);
		newEntityArgs.createArgument(CompositeTransformation.ARG_ISTEMP_IN_NEWOBJECT, "0");
		TemplateArgumentSequence newEntityScheme = new TemplateArgumentSequence();
		newEntityScheme.createArgument(1, newEntityArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newEntityArgs.createArgument(CompositeTransformation.ARG_SCHEME_IN_NEWOBJECT, String.valueOf(newEntityScheme.getSequenceId()));


		TemplateArgumentSequence addNewEntityArgs = new TemplateArgumentSequence();
		addNewEntityArgs.createArgument(CompositeTransformation.ARG_ACTION_IN_PRIMITIVE, "add");
		addNewEntityArgs.createArgument(CompositeTransformation.ARG_FROMOBJ_IN_PRIMITIVE, "-1");
		addNewEntityArgs.createArgument(CompositeTransformation.ARG_TOOBJ_IN_PRIMITIVE, newEntityArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		addNewEntityArgs.createArgument(CompositeTransformation.ARG_FROMSCHEMA_IN_PRIMITIVE, 1); 
		addNewEntityArgs.createArgument(CompositeTransformation.ARG_TOSCHEMA_IN_PRIMITIVE, newEntityArgs, CompositeTransformation.ARG_SID_IN_NEWOBJECT);
		addNewEntityArgs.createArgument(CompositeTransformation.ARG_FUNCTION_IN_PRIMITIVE, "");
		addNewEntityArgs.createArgument(CompositeTransformation.ARG_CONSTRAINTS_IN_PRIMITIVE, "");

	
		TemplateArgumentSequence returnedArgs = new TemplateArgumentSequence();
		returnedArgs.createArgument(3, newEntityArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		returnedArgs.createArgument(4, addNewEntityArgs, CompositeTransformation.ARG_TOSCHEMA_IN_PRIMITIVE);


		CompositeTransformation addEntity = new CompositeTransformation(templateInForEach, "extend schema with entity", false);
		addEntity.createArgumentDefinition(1, "schema", "SID", "initial schema ID", false);
		addEntity.createArgumentDefinition(2, "object", "value", "new entity name", false);
		addEntity.createArgumentDefinition(3, "object", "OBID", "new entity ID", true);
		addEntity.createArgumentDefinition(4, "schema", "SID", "final schema ID", true);


		addEntity.createReturnedArgumentsDefinition(returnedArgs);

		
		addEntity.createStatementExecution(1, Statement.getStatement(CompositeTransformation.NEW_OBJECT_STATEMENT), newEntityArgs);
		addEntity.createStatementExecution(2, Statement.getStatement(CompositeTransformation.PRIMITIVE_TRANSFORMATION_STATEMENT), addNewEntityArgs);
	}
	
	public static void main(String[] args)
	{
		try{
			System.out.println("creating template transformation Mandatory Attribute and Total Generalisation Equivalence...");
			defineTemplate();
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
}
