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


/**
	An application that defines the "Mandatory Field and Total Generalisation Equivalence" template transformation.
	This transformation should be applied on a schema of the "sql92" model.
	It creates a list of tables, and a field, PK, FK for each table. The created tables are based
	on the values of a mandatory field in an existing table, and are specialised elements of this table.
	
	The arguments for this transformation are:
	1. initial schema ID
	2. existing table ID
	3. existing field ID (primary key of the table in the 2nd argument)
	4. existing field ID (mandatory field of the table in the 2nd argument)
	5. argument sequence ID (list of new table names)
	6. argument sequence ID (list of new field names)
	7. argument sequence ID (list of new PK names)
	8. argument sequence ID (list of new FK names)
	9. argument sequence ID (list of new tables IDs) (returned value) 
	10. argument sequence ID (list of new field IDs) (returned value) 
	11. argument sequence ID (list of new PK IDs) (returned value) 
	12. argument sequence ID (list of new FK IDs) (returned value) 
	13. final schema ID (returned value)
*/
public class MandatoryField
{
  private static String modelName="sql92";
  private static String tableConstructName="table";
  private static String fieldConstructName="field";
  private static String primaryKeyConstructName="primary_key";
  private static String foreignKeyConstructName="foreign_key";

	private static String templateName = "Mandatory Field and Total Generalisation Equivalence";
	private static String templateInForEach = "AddRelationFieldPKFK";
	private static String forEachTemplate = "foreach in Mandatory Field 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 rel = Model.getModel(modelName);
		Construct table = rel.getConstruct(tableConstructName);
		Construct field = rel.getConstruct(fieldConstructName);
		Construct pk = rel.getConstruct(primaryKeyConstructName);
		Construct fk = rel.getConstruct(foreignKeyConstructName);

		TemplateArgumentSequence newTableArgs = new TemplateArgumentSequence();
		newTableArgs.createArgument(CompositeTransformation.ARG_CID_IN_NEWOBJECT, String.valueOf(table.getCID()));
		newTableArgs.createArgument(CompositeTransformation.ARG_VALUE_IN_NEWOBJECT, 4);
		newTableArgs.createArgument(CompositeTransformation.ARG_ISTEMP_IN_NEWOBJECT, "0");
		TemplateArgumentSequence newTableScheme = new TemplateArgumentSequence();
		newTableScheme.createArgument(1, newTableArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newTableArgs.createArgument(CompositeTransformation.ARG_SCHEME_IN_NEWOBJECT, String.valueOf(newTableScheme.getSequenceId()));

		TemplateArgumentSequence addNewTableArgs = new TemplateArgumentSequence();
		addNewTableArgs.createArgument(CompositeTransformation.ARG_ACTION_IN_PRIMITIVE, "add");
		addNewTableArgs.createArgument(CompositeTransformation.ARG_FROMOBJ_IN_PRIMITIVE, "-1");
		addNewTableArgs.createArgument(CompositeTransformation.ARG_TOOBJ_IN_PRIMITIVE, newTableArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		addNewTableArgs.createArgument(CompositeTransformation.ARG_FROMSCHEMA_IN_PRIMITIVE, 1); 
		addNewTableArgs.createArgument(CompositeTransformation.ARG_TOSCHEMA_IN_PRIMITIVE, newTableArgs, CompositeTransformation.ARG_SID_IN_NEWOBJECT);
		addNewTableArgs.createArgument(CompositeTransformation.ARG_FUNCTION_IN_PRIMITIVE, "");
		addNewTableArgs.createArgument(CompositeTransformation.ARG_CONSTRAINTS_IN_PRIMITIVE, "");
		
		TemplateArgumentSequence newFieldArgs = new TemplateArgumentSequence();
		newFieldArgs.createArgument(CompositeTransformation.ARG_CID_IN_NEWOBJECT, String.valueOf(field.getCID()));
		newFieldArgs.createArgument(CompositeTransformation.ARG_VALUE_IN_NEWOBJECT, 5);
		newFieldArgs.createArgument(CompositeTransformation.ARG_ISTEMP_IN_NEWOBJECT, "0");
		TemplateArgumentSequence newFieldScheme = new TemplateArgumentSequence();
		newFieldScheme.createArgument(1, newTableArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newFieldScheme.createArgument(2, newFieldArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newFieldArgs.createArgument(CompositeTransformation.ARG_SCHEME_IN_NEWOBJECT, String.valueOf(newFieldScheme.getSequenceId())); 

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

		TemplateArgumentSequence newPrimaryKeyArgs = new TemplateArgumentSequence();
		newPrimaryKeyArgs.createArgument(CompositeTransformation.ARG_CID_IN_NEWOBJECT, String.valueOf(pk.getCID()));
		newPrimaryKeyArgs.createArgument(CompositeTransformation.ARG_VALUE_IN_NEWOBJECT, 6); 
		newPrimaryKeyArgs.createArgument(CompositeTransformation.ARG_ISTEMP_IN_NEWOBJECT, "0");
		TemplateArgumentSequence newPrimaryKeyScheme = new TemplateArgumentSequence();
		newPrimaryKeyScheme.createArgument(1, newPrimaryKeyArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newPrimaryKeyScheme.createArgument(2, newTableArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newPrimaryKeyScheme.createArgument(3, newFieldArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newPrimaryKeyArgs.createArgument(CompositeTransformation.ARG_SCHEME_IN_NEWOBJECT, String.valueOf(newPrimaryKeyScheme.getSequenceId())); 

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

		TemplateArgumentSequence newForeignKeyArgs = new TemplateArgumentSequence();
		newForeignKeyArgs.createArgument(CompositeTransformation.ARG_CID_IN_NEWOBJECT, String.valueOf(fk.getCID()));
		newForeignKeyArgs.createArgument(CompositeTransformation.ARG_VALUE_IN_NEWOBJECT, 7); 
		newForeignKeyArgs.createArgument(CompositeTransformation.ARG_ISTEMP_IN_NEWOBJECT, "0");
		TemplateArgumentSequence newForeignKeyScheme = new TemplateArgumentSequence();
		newForeignKeyScheme.createArgument(1, newForeignKeyArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newForeignKeyScheme.createArgument(2, newTableArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newForeignKeyScheme.createArgument(3, newFieldArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		newForeignKeyScheme.createArgument(4, 2); 
		newForeignKeyScheme.createArgument(5, 3); 
		newForeignKeyArgs.createArgument(CompositeTransformation.ARG_SCHEME_IN_NEWOBJECT, String.valueOf(newForeignKeyScheme.getSequenceId()));

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

		TemplateArgumentSequence returnedArgs = new TemplateArgumentSequence();
		returnedArgs.createArgument(8, newTableArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		returnedArgs.createArgument(9, newFieldArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		returnedArgs.createArgument(10, newPrimaryKeyArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		returnedArgs.createArgument(11, newForeignKeyArgs, CompositeTransformation.ARG_OBID_IN_NEWOBJECT);
		returnedArgs.createArgument(12, addNewForeignKeyArgs, CompositeTransformation.ARG_TOSCHEMA_IN_PRIMITIVE);

		CompositeTransformation addRelFieldFk = new CompositeTransformation(templateInForEach, "extend schema with table+field+pk+fk(isa relationship)", false); 
		addRelFieldFk.createArgumentDefinition(1, "schema", "SID", "initial schema", false);
		addRelFieldFk.createArgumentDefinition(2, "object", "OBID", "existing relation ID", false);
		addRelFieldFk.createArgumentDefinition(3, "object", "OBID", "existing field ID", false);
		addRelFieldFk.createArgumentDefinition(4, "object", "value", "new relation's name", false);
		addRelFieldFk.createArgumentDefinition(5, "object", "value", "new field's name", false);
		addRelFieldFk.createArgumentDefinition(6, "object", "value", "new primary key name", false);
		addRelFieldFk.createArgumentDefinition(7, "object", "value", "new foreign key name", false);
		addRelFieldFk.createArgumentDefinition(8, "object", "OBID", "new table ID", true);
		addRelFieldFk.createArgumentDefinition(9, "object", "OBID", "new field ID", true);
		addRelFieldFk.createArgumentDefinition(10, "object", "OBID", "new primary key ID", true);
		addRelFieldFk.createArgumentDefinition(11, "object", "OBID", "new foreign key ID", true);
		addRelFieldFk.createArgumentDefinition(12, "schema", "SID", "final schema ID", true);

		addRelFieldFk.createReturnedArgumentsDefinition(returnedArgs);

		addRelFieldFk.createStatementExecution(1, Statement.getStatement(CompositeTransformation.NEW_OBJECT_STATEMENT), newTableArgs);
		addRelFieldFk.createStatementExecution(2, Statement.getStatement(CompositeTransformation.PRIMITIVE_TRANSFORMATION_STATEMENT), addNewTableArgs);
		addRelFieldFk.createStatementExecution(3, Statement.getStatement(CompositeTransformation.NEW_OBJECT_STATEMENT), newFieldArgs);
		addRelFieldFk.createStatementExecution(4, Statement.getStatement(CompositeTransformation.PRIMITIVE_TRANSFORMATION_STATEMENT), addNewFieldArgs);
		addRelFieldFk.createStatementExecution(5, Statement.getStatement(CompositeTransformation.NEW_OBJECT_STATEMENT), newPrimaryKeyArgs);
		addRelFieldFk.createStatementExecution(6, Statement.getStatement(CompositeTransformation.PRIMITIVE_TRANSFORMATION_STATEMENT), addNewPrimaryKeyArgs);
		addRelFieldFk.createStatementExecution(7, Statement.getStatement(CompositeTransformation.NEW_OBJECT_STATEMENT), newForeignKeyArgs);
		addRelFieldFk.createStatementExecution(8, Statement.getStatement(CompositeTransformation.PRIMITIVE_TRANSFORMATION_STATEMENT), addNewForeignKeyArgs);


		TemplateArgumentSequence foreachArgs = new TemplateArgumentSequence();
		foreachArgs.createArgument(CompositeTransformation.ARG_SCHEMA_IN_FOREACH, 1);
		
		TemplateArgumentSequence transformationArgs = new TemplateArgumentSequence();
		transformationArgs.createArgument(1, 1); 
		transformationArgs.createArgument(2, 2);
		transformationArgs.createArgument(3, 3);
		transformationArgs.createArgument(4, 4);	
		transformationArgs.createArgument(5, 5);
		transformationArgs.createArgument(6, 6);
		transformationArgs.createArgument(7, 7);

		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);
	

		TemplateArgumentSequence sequenceArgs = new TemplateArgumentSequence();
		sequenceArgs.createArgument(4, 5);
		sequenceArgs.createArgument(5, 6);
		sequenceArgs.createArgument(6, 7);
		sequenceArgs.createArgument(7, 8); 

		TemplateArgumentSequence singletonArgs = new TemplateArgumentSequence();
		singletonArgs.createArgument(1, foreachArgs, CompositeTransformation.ARG_SCHEMA_IN_FOREACH);
		singletonArgs.createArgument(2, 2);
		singletonArgs.createArgument(3, 3);	

		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()));



		TemplateArgumentSequence deleteFieldArgs = new TemplateArgumentSequence();
		deleteFieldArgs.createArgument(CompositeTransformation.ARG_ACTION_IN_PRIMITIVE, "del");
		deleteFieldArgs.createArgument(CompositeTransformation.ARG_FROMOBJ_IN_PRIMITIVE, 4);
		deleteFieldArgs.createArgument(CompositeTransformation.ARG_TOOBJ_IN_PRIMITIVE, "-1");
		deleteFieldArgs.createArgument(CompositeTransformation.ARG_FROMSCHEMA_IN_PRIMITIVE, foreachArgs, CompositeTransformation.ARG_SCHEMA_IN_FOREACH);
		deleteFieldArgs.createArgument(CompositeTransformation.ARG_FUNCTION_IN_PRIMITIVE, "");
		deleteFieldArgs.createArgument(CompositeTransformation.ARG_CONSTRAINTS_IN_PRIMITIVE, "");

		TemplateArgumentSequence globalReturnedArgs = new TemplateArgumentSequence();
		globalReturnedArgs.createArgument(9, foreachArgs, CompositeTransformation.ARG_RETURNED_ARGS_START_IN_FOREACH);
		globalReturnedArgs.createArgument(10, foreachArgs, CompositeTransformation.ARG_RETURNED_ARGS_START_IN_FOREACH+1);
		globalReturnedArgs.createArgument(11, foreachArgs, CompositeTransformation.ARG_RETURNED_ARGS_START_IN_FOREACH+2);
		globalReturnedArgs.createArgument(12, foreachArgs, CompositeTransformation.ARG_RETURNED_ARGS_START_IN_FOREACH+3);
		globalReturnedArgs.createArgument(13, foreachArgs, CompositeTransformation.ARG_SCHEMA_IN_FOREACH);	

		
		CompositeTransformation trans = new CompositeTransformation(
				templateName, 
				"Transformation removes field from existing relation and adds the corresponding relations", 
				true);
		trans.createArgumentDefinition(1, "schema", "SID", "initial schema", false);
		trans.createArgumentDefinition(2, "object", "OBID", "existing table ID", false);
		trans.createArgumentDefinition(3, "object", "OBID", "existing primary key field ID", false);
		trans.createArgumentDefinition(4, "object", "OBID", "existing mandatory field ID", false);
		trans.createArgumentDefinition(5, "arguments", "arg_id", "new sub-table names", false);
		trans.createArgumentDefinition(6, "arguments", "arg_id", "new field names", false);
		trans.createArgumentDefinition(7, "arguments", "arg_id", "new primary key names", false);
		trans.createArgumentDefinition(8, "arguments", "arg_id", "new foreign key names", false);
		trans.createArgumentDefinition(9, "arguments", "arg_id", "new sub-table IDS", true);
		trans.createArgumentDefinition(10, "arguments", "arg_id", "new sub-field IDS", true);
		trans.createArgumentDefinition(11, "arguments", "arg_id", "new primary-key IDS", true);
		trans.createArgumentDefinition(12, "arguments", "arg_id", "new foreign-key IDS", true);
		trans.createArgumentDefinition(13, "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), deleteFieldArgs);
	}


	public static void main(String[] args)
	{
		try{
			System.out.println("Re-creating template transformation Mandatory Field and Total Generalisation Equivalence...");
			MandatoryField.defineTemplate();
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
}
