import uk.ac.ic.doc.automed.*;
import uk.ac.ic.doc.automed.reps.*;
import java.io.*;
import java.sql.*;

public class OptimiseERTransformationPathway
{
   // evolve s1d with 3 transforamtions so contents of evolved
   // schema are the same as those in s1 except new schema has
   // <<male>> and s1 doesn't.
   public static Schema createEvolvedSchema()
      throws AutoMedException, SQLException, IOException
   {
      // the first integrated schema created from er_s1 is named er_s1d
      Schema s1d = Schema.getSchema("er_s1d");

      // We will go for double angle brackets to represent the chevrons in
      // this application
      SchemaTransformationRepository.setOpenSchemeBracket("<<");
      SchemaTransformationRepository.setCloseSchemeBracket(">>");

      // Build an upto date hashmap of scheme names, using the 
      // format "<<person>>", "<<person,name>>" etc. This is
      // used by the subsequent transformation steps
      s1d.updateSchemaObjectNameHashMap();

      Model er=Model.getModel("er");
      Construct ent=er.getConstruct("entity");
      Construct att=er.getConstruct("attribute");
      Construct rel=er.getConstruct("relationship");
      Construct gen=er.getConstruct("generalisation");

      // Check that we have the objects that we want to transform
      SchemaObject person=s1d.getSchemaObjectByName("<<person>>");
      SchemaObject genSex =
         s1d.getSchemaObjectByName("<<sex,total,person,male,female>>");
      SchemaObject female = s1d.getSchemaObjectByName("<<female>>");

      if (person==null || genSex==null || female==null) {
         System.out.println("Schema "+s1d.getName()+" does not contain "+
            "<<person>> and <<sex,total,person,male,female>> and <<female>>");
         return null;
      }

      Schema s1d1 = s1d.applyAddTransformation(att,
                     new Object[] {person, "sex", "notnull"},
                     "added person_sex att", null);

      Schema s1d2 = s1d1.applyDeleteTransformation(genSex,
                     "deleted gen sex", null);

      return s1d2.applyDeleteTransformation(female,
                     "deleted female", null);
   }

   public static void listTP(String s1, String s2)
    throws AutoRepException, SchemaTransformationRepositoryException,
         SQLException, DataSourceRepositoryException, IOException,
         ModelDefinitionsRepositoryException, BadSchemaException
   {
      TransformationPathway tp1 =
         TransformationPathway.findShortestPath(s1, s2);

      Transformation[] tp1Trans = tp1.getTransformations();

      System.out.println("original pathway:");

      for (int i=0; i<tp1Trans.length; i++)
      {
         Transformation t = tp1Trans[i];
         System.out.println((i+1) + ": " + t);
      }
   }

   public static void optimiseTP(String s1, String s2)
    throws AutoMedException, AutoRepException,
         SchemaTransformationRepositoryException,
         SQLException, DataSourceRepositoryException, IOException
   {
      TransformationPathway tp1 =
         TransformationPathway.findShortestPath(s1, s2);

      TransformationPathway optimisedTP =
         TransformationOptimiser.optimisePathway(tp1);

      Transformation[] optimisedTrans = optimisedTP.getTransformations();

      System.out.println("\n\noptimised pathway:");

      for (int i=0; i<optimisedTrans.length; i++)
      {
         Transformation t = optimisedTrans[i];
         System.out.println((i+1) + ": " + t);
      }
   }
   
   public static void main(String[] args)
   {
      try
      {
         // Run the next two lines only the first time this prog is run
         Schema s = createEvolvedSchema();
         String evolvedSchemaName = s.getName();

         // Next time should be uncommented after this prog has been
         // run once and the last two lines should be commented
         //String evolvedSchemaName = "er_s1g1";
         listTP("er_s1", evolvedSchemaName);
         optimiseTP("er_s1", evolvedSchemaName);
      }
      catch (SQLException se)
      { 
         se.printStackTrace();
      }
      catch (IOException ie)
      {
         ie.printStackTrace();
      }
      catch (AutoMedException ame)
      {
         ame.printStackTrace();
      }
      catch (Exception e)
      {
         e.printStackTrace();
      }
   }
}
