
import java.sql.*;
import java.io.*;

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

/*..........................................
	extends RepsTest.java by defining more schemas and their contents
	and adding the TransformationPath.findAllPathsToSchema(String schemaName)
	method.
............................................*/

public class AutoMedRepsTest implements Constants
{
  public static void main(String[] args)
  {
    System.out.println("hahahahahaha!!!!!!");
    try
      {
	// clear the databases first
	System.out.println("Re initializing MDR..." );
	DataSourceRepository.doDropdbCommand(new String[]{
	  "", ModelDefinitionsRepository.getMDR_DataSourceName()
	});
	DataSourceRepository.doCreatedbCommand(new String[]{
	  "", ModelDefinitionsRepository.getMDR_DataSourceName()
	});
	// you should always do this after altering the MDR not throug the
	// reps API if you are going to then use the MDR through the reps API
	Model.reloadModels();

	System.out.println("Re initializing STR...");
	DataSourceRepository.doDropdbCommand(new String[]{
	  "", SchemaTransformationRepository.getSTR_DataSourceName()
	});
	DataSourceRepository.doCreatedbCommand(new String[]{
	  "", SchemaTransformationRepository.getSTR_DataSourceName()
	});
	// you should always do this after altering the STR not through the
	// reps API if you are going to then use the STR through the reps API
	Schema.clearSchemas();
	
	System.out.println("Creating Models...");
	// Create an ER model
	Model erModel = Model.createModel("er");
	
	// Create constructs for the ER model
	// Create erEntity, erAttribute, erRelationship, erGeneralization
	Construct erEntity =
	  erModel.createConstruct("erEntity", CONSTRUCT_CLASS_NODAL, true);
	Construct erAttribute =
	  erModel.createConstruct("erAttribute", CONSTRUCT_CLASS_LINK_NODAL, true);
	Construct erRelationship =
	  erModel.createConstruct("erRelationship", CONSTRUCT_CLASS_LINK, true);
	Construct erGeneralization =
	  erModel.createConstruct("erGeneralization", CONSTRUCT_CLASS_CONSTRAINT, true);

			// for each Construct created, create their constructScheme
	erEntity.createConstructScheme(SCHEME_TYPE_NAME, null,
				       true, SCHEME_HDM_TYPE_N1, 1, 1);

	erAttribute.createConstructScheme(SCHEME_TYPE_CONSTRUCT, erEntity,
					  true, SCHEME_HDM_TYPE_P1, 1, 1);
	erAttribute.createConstructScheme(SCHEME_TYPE_NAME, null,
					  true, SCHEME_HDM_TYPE_N1, 1, 1);

	erRelationship.createConstructScheme(SCHEME_TYPE_NAME, null,
					     true, SCHEME_HDM_TYPE_N1, 1, 1);
	erRelationship.createConstructScheme(SCHEME_TYPE_CONSTRUCT,
					     erEntity, true, SCHEME_HDM_TYPE_P1, 1, 1);
	erRelationship.createConstructScheme(SCHEME_TYPE_CONSTRUCT,
					     erEntity, true, SCHEME_HDM_TYPE_P2, 1, 1);
	erRelationship.createConstructScheme(SCHEME_TYPE_NAME, null,
					     true, SCHEME_HDM_TYPE_C, 1, 1);
	erRelationship.createConstructScheme(SCHEME_TYPE_NAME, null,
					     true, SCHEME_HDM_TYPE_C, 1, 1);

	erGeneralization.createConstructScheme(SCHEME_TYPE_NAME, null,
					       true, SCHEME_HDM_TYPE_C, 1, 1);
	erGeneralization.createConstructScheme(SCHEME_TYPE_NAME, null,
					       true, SCHEME_HDM_TYPE_C, 1, 1);
	erGeneralization.createConstructScheme(SCHEME_TYPE_CONSTRUCT,
					       erEntity, true, SCHEME_HDM_TYPE_C, 1, 1);
	erGeneralization.createConstructScheme(SCHEME_TYPE_CONSTRUCT,
					       erEntity, true, SCHEME_HDM_TYPE_C, 1, 1);
	erGeneralization.createConstructScheme(SCHEME_TYPE_CONSTRUCT,
					       erEntity, true, SCHEME_HDM_TYPE_C, 1, 0);
		
	System.out.println("Creating Schemas...");

			// creating schema s1
	System.out.println("Creating schema s1...");
	Schema s1 = Schema.createSchema("s1", false);
	// Just testing the createIntSchemaName method in Transformation
	//Schema s1 = Schema.createSchema("s1a", false);
	SchemaObject s1person = s1.createSchemaObject(erEntity, new Object[] {"person"});

	SchemaObject s1personId =
	  s1.createSchemaObject(erAttribute, new Object[] {s1person, "id"});
	SchemaObject s1personName =
	  s1.createSchemaObject(erAttribute, new Object[] {s1person, "name"});
	SchemaObject s1personSex =
	  s1.createSchemaObject(erAttribute, new Object[] {s1person, "sex"});
	SchemaObject s1dept =
	  s1.createSchemaObject(erEntity, new Object[] {"dept"});
	SchemaObject s1deptDname =
	  s1.createSchemaObject(erAttribute, new Object[] {s1dept, "dname"});
	SchemaObject s1worksin =
	  s1.createSchemaObject(erRelationship,
				new Object[] {"worksin", s1person, s1dept, "1:1", "1:N"});

	// creating schema s2
	System.out.println("Creating schema s2...");
	Schema s2 = Schema.createSchema("s2", false);
	//Schema s2 = Schema.createSchema("s2e", false);
	SchemaObject s2person =
	  s2.createSchemaObject(erEntity, new Object[] {"person"});
	SchemaObject s2personId =
	  s2.createSchemaObject(erAttribute, new Object[] {s2person, "id"});
	SchemaObject s2personName =
	  s2.createSchemaObject(erAttribute, new Object[] {s2person, "name"});
	SchemaObject s2personDname =
	  s2.createSchemaObject(erAttribute, new Object[] {s2person, "dname"});
	SchemaObject s2male =
	  s2.createSchemaObject(erEntity, new Object[] {"male"});
	SchemaObject s2female =
	  s2.createSchemaObject(erEntity, new Object[] {"female"});
	SchemaObject s2sex =
	  s2.createSchemaObject(erGeneralization,
				new Object[] {"sex", "total", s2person, s2male, s2female});

	// creating schema s3
	System.out.println("Creating schema s3...");
	Schema s3 = Schema.createSchema("s3", false);
	//Schema s3 = Schema.createSchema("s3z", false);
	SchemaObject s3person =
	  s3.createSchemaObject(erEntity, new Object[] {"person"});
	SchemaObject s3personId =
	  s3.createSchemaObject(erAttribute, new Object[] {s3person, "id"});

	SchemaObject s3male =
	  s3.createSchemaObject(erEntity, new Object[] {"male"});
	SchemaObject s3female =
	  s3.createSchemaObject(erEntity, new Object[] {"female"});
	SchemaObject s3sex =
	  s3.createSchemaObject(erGeneralization,
				new Object[] {"sex", "total", s3person, s3male, s3female});

	SchemaObject s3dept =
	  s3.createSchemaObject(erEntity, new Object[] {"dept"});
	SchemaObject s3deptDname =
	  s3.createSchemaObject(erAttribute, new Object[] {s3dept, "dname"});
	SchemaObject s3worksin =
	  s3.createSchemaObject(erRelationship,
				new Object[] {"worksin", s3person, s3dept, "1:1", "1:N"});

	SchemaObject s3degree =
	  s3.createSchemaObject(erEntity, new Object[] {"degree"});
	SchemaObject s3degreeCode =
	  s3.createSchemaObject(erAttribute, new Object[] {s3degree, "code"});
	SchemaObject s3degreeTitle =
	  s3.createSchemaObject(erAttribute, new Object[] {s3degree, "title"});
	SchemaObject s3runby =
	  s3.createSchemaObject(erRelationship,
				new Object[] {"runby", s3dept, s3degree, "1:N", "1:1"});


	// creating transformations
	System.out.println("Creating Transformations...");

	// transformations from s1 to s4
	System.out.println("Creating Transformations from s1 to s4...");

	Transformation t1a =
	  Transformation.createAddTransformation(s1, erEntity,
						 new Object[] {"male"}, "query", "constraint");
	// supply name of new schema
	//new Object[] {"male"}, "query", "constraint", "s1-1");
				/*....	
				Transformation.createTransformation(TRAN_ACTION_ADD,
					null, null, erEntity, new Object[] {"male"}, s1, "s1a",
					"query", "constraint");
				......*/

	Transformation t1b =
	  Transformation.createAddTransformation(t1a.getOtherSchema(s1),
						 erEntity,
						 new Object[] {"female"},
						 "query", "constraint");

	//new Object[] {"female"}, "query", "constraint", "s1-2");
				/*........
				  Transformation.createTransformation(TRAN_ACTION_ADD,
				  null, null, erEntity, new Object[] {"female"},
				  t1a.getToSchema(), "s1b", "query", "constraint");
				  ........*/	

			/*.......
			SchemaObject s1bPerson = null;
			SchemaObject s1bMale = null;
			SchemaObject s1bFemale = null;
			SchemaObject[] s1bObjects = t1b.getToSchema().getSchemaObjects();

			if (t1b.getToSchema() == null)
			{
				System.out.println("t1b.getToSchema() == null");
			}

			if (s1bObjects == null)
			{
				System.out.println("s1bObject == null");
				System.out.println("t1b.getToSchema().getSID(): " + t1b.getToSchema().getSID());
			}

			for (int i=0; i<s1bObjects.length; i++)
			{
				SchemaObject so = s1bObjects[i];
				if (so.getConstruct() == erEntity)
				{
					if (so.getValue().equals("person"))
					{
						s1bPerson = so;
					}
					if (so.getValue().equals("male"))
					{
						s1bMale = so;
					}
					if (so.getValue().equals("female"))
					{
						s1bFemale = so;
					}
				}
			}
			.........*/

	Transformation t1c =
	  Transformation.createAddTransformation(t1b.getOtherSchema(t1a.getOtherSchema(s1)),
						 erGeneralization,
						 new Object[] {"sex", "total",
							       s1person,
							       t1a.getSchemaObject(t1a.getOtherSchema(s1)),
							       t1b.getSchemaObject(t1b.getOtherSchema(t1a.getOtherSchema(s1))},
						 "query", "constraint");

	//"query", "constraint", "s1-3");
				/*.....
				  Transformation.createTransformation(TRAN_ACTION_ADD,
				  null, null, erGeneralization,
				  //new Object[] {"sex", "total", s1bPerson, s1bMale, s1bFemale},
				  new Object[] {"sex", "total", s1person, t1a.getToObject(), t1b.getToObject()},
				  t1b.getToSchema(), "s1c", "query", "constraint");
				  .....*/

			/*........
			SchemaObject s1cPersonSex = null;
			SchemaObject[] s1cObjects = t1c.getToSchema().getSchemaObjects();
			for (int i=0; i<s1cObjects.length; i++)
			{
				SchemaObject so = s1cObjects[i];
				if (so.getConstruct() == erAttribute)
				{
					if (so.getValue().equals("sex"))
					{
						s1cPersonSex = so;
						break;
					}
				}
			}
			...........*/

	Transformation t1d =
	  Transformation.createDeleteTransformation(t1c.getToSchema(), s1personSex,
						    "query", "constraint");
	//"query", "constraint", "s4");
				/*.......
				  Transformation.createTransformation(TRAN_ACTION_DELETE,
				  // don't need to specify fromObjectConstructType when
				  // deleting existing object
				  //erAttribute, s1cPersonSex, null, null,
				  //null, s1cPersonSex, null, null,
				  null, s1personSex, null, null,
				  t1c.getToSchema(), "s4", "query", "constraint");
				  .........*/



			// transformations from s2 to s4
	System.out.println("Creating Transformations from s2 to s4...");
	Transformation t2a =
	  Transformation.createAddTransformation(s2, erEntity, new Object[] {"dept"},
						 "query", "constraint");
	//"query", "constraint", "s2-1");
				/*.......
				  Transformation.createTransformation(TRAN_ACTION_ADD,
				  null, null, erEntity, new Object[] {"dept"}, s2, "s2a",
				  "query", "constraint");
				  ........*/

			/*............
			SchemaObject s2aDept = null;
			SchemaObject[] s2aObjects = t2a.getToSchema().getSchemaObjects();
			for (int i=0; i<s2aObjects.length; i++)
			{
				SchemaObject so = s2aObjects[i];
				if (so.getConstruct() == erEntity)
				{
					if (so.getValue().equals("dept"))
					{
						s2aDept = so;
						break;
					}
				}
			}
			...........*/

	Transformation t2b =
	  Transformation.createAddTransformation(t2a.getToSchema(), erAttribute,
						 new Object[] {t2a.getToObject(), "dname"}, "query", "constraint");
	//new Object[] {t2a.getToObject(), "dname"}, "query", "constraint", "s2-2");
				/*.......
				  Transformation.createTransformation(TRAN_ACTION_ADD,
				  null, null, erAttribute, new Object[] {t2a.getToObject(), "dname"},
				  t2a.getToSchema(), "s2b", "query", "constraint");
				  .....*/

			/*..........
			SchemaObject s2bPersonDname = null;
			SchemaObject[] s2bObjects = t2b.getToSchema().getSchemaObjects();
			for (int i=0; i<s2bObjects.length; i++)
			{
				SchemaObject so = s2bObjects[i];
				if (so.getConstruct() == erAttribute &&
						so.getValue().equals("dname"))
				{
					Scheme[] scheme = so.getSchemeObjects();
					if (scheme[0].getRefSchemaObject().getValue().equals("person"))
					{
						s2bPersonDname = so;
						break;
					}
				}
			}
			.............*/

	Transformation t2c =
	  Transformation.createDeleteTransformation(t2b.getToSchema(), s2personDname,
						    "query", "constraint");
	//"query", "constraint", "s2-3");
				/*.......	
				  Transformation.createTransformation(TRAN_ACTION_DELETE,
				  null, s2personDname, null, null,
				  t2b.getToSchema(), "s2c", "query", "constraint");
				  ........*/

			/*.........
			SchemaObject s2cPerson = null;
			SchemaObject s2cDept = null;

			SchemaObject[] s2cObjects = t2c.getToSchema().getSchemaObjects();
			for (int i=0; i<s2cObjects.length; i++)
			{
				SchemaObject so = s2cObjects[i];
				if (so.getConstruct() == erEntity)
				{
					if (so.getValue().equals("person"))
					{
						s2cPerson = so;
					}
					if (so.getValue().equals("dept"))
					{
						s2cDept = so;
					}
				}
			}
			.............*/

/*............. TODO: id-transformation - nt 20/08/01
			// id-transformation...
*/
	Transformation t2d =
	  Transformation.createAddTransformation(t2c.getToSchema(), erRelationship,
						 new Object[] {"worksin", s2person, 
							       t2a.getToObject(), "1:1", "1:N"},
						 "query", "constraint");

	Transformation[] trans1d_2d = 
	  Transformation.createIdentTransformations(t1d.getToSchema(), t2d.getToSchema(),
						    "query", "constraint");

			
	// transformations from s3 to s5
	System.out.println("Creating Transformations from s3 to s5...");
	Transformation t3a =
	  Transformation.createExtendTransformation(s3, erAttribute,
						    new Object[] {s3person, "name"}, "query", "constraint");
	//new Object[] {s3person, "name"}, "query", "constraint", "s5");
				/*.......
				  Transformation.createTransformation(TRAN_ACTION_EXTEND,
				  null, null, erAttribute, new Object[] {s3person, "name"},
				  s3, "s5", "query", "constraint");
				  ........*/


			// transformations from s4 to s5
			// s4 = t1d.getToSchema()		s5 = t3a.getToSchema()
	System.out.println("Creating Transformations from s4 to s5...");
	Transformation t4a =
	  Transformation.createExtendTransformation(t1d.getToSchema(), erEntity,
						    //new Object[] {"degree"}, "query", "constraint");
						    new Object[] {"degree"}, "query", "constraint", "s4-1");
				/*.....
				Transformation.createTransformation(TRAN_ACTION_EXTEND,
					null, null, erEntity, new Object[] {"degree"},
					t1d.getToSchema(), "s4a", "query", "constraint");
				.......*/

			/*........
			SchemaObject s4aDegree = null;
			SchemaObject[] s4aObjects = t4a.getToSchema().getSchemaObjects();

			for (int i=0; i<s4aObjects.length; i++)
			{
				SchemaObject so = s4aObjects[i];

				if (so.getConstruct() == erEntity &&
						so.getValue().equals("degree"))
				{
					s4aDegree = so;
					break;
				}
			}
			.........*/

	Transformation t4b =
	  Transformation.createExtendTransformation(t4a.getToSchema(), erAttribute,
						    new Object[] {t4a.getToObject(), "code"}, "query", "constraint");
	//new Object[] {t4a.getToObject(), "code"}, "query", "constraint", "s4-2");
				/*.......
				  Transformation.createTransformation(TRAN_ACTION_EXTEND,
				  //null, null, erAttribute, new Object[] {s4aDegree, "code"},
				  null, null, erAttribute, new Object[] {t4a.getToObject(), "code"},
				  t4a.getToSchema(), "s4b", "query", "constraint");
				  .........*/

			/*..........
			SchemaObject s4bDegree = null;
			SchemaObject[] s4bObjects = t4b.getToSchema().getSchemaObjects();
			for (int i=0; i<s4bObjects.length; i++)
			{
				SchemaObject so = s4bObjects[i];
				if (so.getConstruct() == erEntity &&
						so.getValue().equals("degree"))
				{
					s4bDegree = so;
					break;
				}
			}
			..............*/

	Transformation t4c =
	  Transformation.createExtendTransformation(t4b.getToSchema(), erAttribute,
						    new Object[] {t4a.getToObject(), "title"}, "query", "constraint");
	//new Object[] {t4a.getToObject(), "title"}, "query", "constraint", "s4-3");
				/*.......
				  Transformation.createTransformation(TRAN_ACTION_EXTEND,
				  //null, null, erAttribute, new Object[] {s4bDegree, "title"},
				  null, null, erAttribute, new Object[] {t4a.getToObject(), "title"},
				  t4b.getToSchema(), "s4c", "query", "constraint");
				  ..........*/

			/*...........
			SchemaObject s4cDept = null;
			SchemaObject s4cDegree = null;
			SchemaObject[] s4cObjects = t4c.getToSchema().getSchemaObjects();
			for (int i=0; i<s4cObjects.length; i++)
			{
				SchemaObject so = s4cObjects[i];
				if (so.getConstruct() == erEntity)
				{
					if (so.getValue().equals("dept"))
					{
						s4cDept = so;
					}
					if (so.getValue().equals("degree"))
					{
						s4cDegree = so;
					}
				}
			}
			..........*/

/*............. TODO: id-transformation - nt 20/08/01
			// id-transformation...
			Transformation t4d =
				Transformation.createTransformation(TRAN_ACTION_EXTEND,
					null, null, erRelationship,
					//new Object[] {"runby", s4cDept, s4cDegree, "1:N", "1:1"},
					// which dept should I take?  s1dept or s2dept (toObj of a t2 tran)?
					// will id-tran mappings map the Java objects as well so that I
					// can use either one?
					new Object[] {"runby", s4cDept, t4a.getToObject, "1:N", "1:1"},
					// s5 = t3a.getToSchema()
					t4c.getToSchema(), t3a.getToSchema(), "query", "constraint");
......................................*/

	Transformation t4d =
	  Transformation.createExtendTransformation(t4c.getToSchema(), erRelationship,
						    new Object[] {"runby", s1dept, t4a.getToObject(), "1:N", "1:1"},
						    // using t2a.getToObject() as the 2nd element for the Object[] won't
						    // work for id transformations creation
						    // s2's dept is the toObject of transformation t2a
						    //new Object[] {"runby", t2a.getToObject(), t4a.getToObject(), "1:N", "1:1"},
						    "query", "constraint");

	Transformation[] trans1d_4d = 
	  Transformation.createIdentTransformations(t3a.getToSchema(), t4d.getToSchema(),
						    "query", "constraint");

	System.out.println("all scheme names for " + s1.getName()
			   + "\n" + s1.getAllSchemeNamesString());
	System.out.println("all scheme names for " + s2.getName()
			   + "\n" + s2.getAllSchemeNamesString());
	System.out.println("all scheme names for " + s3.getName()
			   + "\n" + s3.getAllSchemeNamesString());
	System.out.println("all scheme names for " + t1d.getToSchema().getName()
			   + "\n" + t1d.getToSchema().getAllSchemeNamesString());
	System.out.println("all scheme names for " + t3a.getToSchema().getName()
			   + "\n" + t3a.getToSchema().getAllSchemeNamesString());
      }
    catch (Exception e)
      {
	System.out.println(e.toString());
	e.printStackTrace(System.out);
      }
  }
}
