package caise05;

import java.sql.*;
import java.io.*;
import uk.ac.ic.doc.automed.*;
import uk.ac.ic.doc.automed.reps.*;
import java.util.ArrayList;
import uk.ac.ic.doc.automed.wrappers.SQLWrapperFactory;

/*
 * An application to demonstrate how to link schemas in YATTA model together 
 * via transformation pathways 
 */

// NOTE: The transformation here doesn't take patterns into consideration. 
//       We just want to test merging schemas in YATTA model. 

public class DefineTransformations {

  public static Schema transformS1ToSg(Schema s1) 
    throws NotFoundException, TypeMismatchException {
    Model yatta=Model.getModel("yatta");
    Construct rootnode=yatta.getConstruct("rootnode");
    Construct yattanode=yatta.getConstruct("yattanode");
    Construct sequence=yatta.getConstruct("sequence");

    // Retrieve the objects of the schema
    SchemaObject s1_root=s1.getSchemaObject("<<root>>");
    SchemaObject s1_ug=s1.getSchemaObject("<<root,ug>>");
    SchemaObject s1_name=s1.getSchemaObject("<<<<root,ug>>,name>>");
    SchemaObject s1_tutor=s1.getSchemaObject("<<<<root,ug>>,tutor>>");    
    SchemaObject s1_course=s1.getSchemaObject("<<<<root,ug>>,course>>");
    SchemaObject s1_code=s1.getSchemaObject("<<<<<<root,ug>>,course>>,code>>");
    SchemaObject s1_dept=s1.getSchemaObject("<<<<<<root,ug>>,course>>,dept>>");
    SchemaObject s1_lecturer=s1.getSchemaObject("<<<<<<root,ug>>,course>>,lecturer>>");
    SchemaObject s1_year=s1.getSchemaObject("<<<<<<root,ug>>,course>>,year>>");
    SchemaObject s1_grade=s1.getSchemaObject("<<<<<<root,ug>>,course>>,grade>>");
    SchemaObject s1_seq_name_tutor=s1.getSchemaObject("<<_,<<<<root,ug>>,name>>,<<<<root,ug>>,tutor>>>>");
    SchemaObject s1_seq_tutor_course=s1.getSchemaObject("<<_,<<<<root,ug>>,tutor>>,<<<<root,ug>>,course>>>>");
    SchemaObject s1_seq_code_dept=s1.getSchemaObject("<<_,<<<<<<root,ug>>,course>>,code>>,<<<<<<root,ug>>,course>>,dept>>>>");
    SchemaObject s1_seq_dept_lecturer=s1.getSchemaObject("<<_,<<<<<<root,ug>>,course>>,dept>>,<<<<<<root,ug>>,course>>,lecturer>>>>");
    SchemaObject s1_seq_lecturer_year=s1.getSchemaObject("<<_,<<<<<<root,ug>>,course>>,lecturer>>,<<<<<<root,ug>>,course>>,year>>>>");
    SchemaObject s1_seq_year_grade=s1.getSchemaObject("<<_,<<<<<<root,ug>>,course>>,year>>,<<<<<<root,ug>>,course>>,grade>>>>");


    //********************************************//
    // Start the transformation steps S1 -> Sg    //
    //********************************************//

    //Growing Phrase
    //--------------


    // EXTEND "student" node
    Transformation t1_1 = Transformation.createExtendTransformation(s1, yattanode, 
								 new Object[] {s1_root, "student","set","+"},
								 "[{r,s} | {r,u} <- <<root,ug>>; {u,n} <- <<<<root,ug>>,name>>; s <- [generateGID 's1' u [n] 'student']]",
								 null);
    Schema s1a=t1_1.getOtherSchema(s1);
    SchemaObject sg_student=t1_1.getSchemaObject(s1a);

    // EXTEND "name" node
    Transformation t1_2 = Transformation.createExtendTransformation(s1a, yattanode, 
								 new Object[] {sg_student, "name","string","k"},
								 "[{s,n} | {u,n} <- <<<<root,ug>>,name>>; s <- [generateGID 's1' u [n] 'student']]",
								 null);
    Schema s1b=t1_2.getOtherSchema(s1a);
    SchemaObject sg_name=t1_2.getSchemaObject(s1b);

    // EXTEND "level" node
    Transformation t1_3 = Transformation.createExtendTransformation(s1b, yattanode,
								 new Object[] {sg_student, "level","string",""},
								 "[{s,'ug'} | {u,n} <- <<<<root,ug>>,name>>; s <- [generateGID 's1' u [n] 'student']]",
								 null);
    Schema s1c=t1_3.getOtherSchema(s1b);
    SchemaObject sg_level=t1_3.getSchemaObject(s1c);


    // EXTEND "tutor" node
    Transformation t1_4 = Transformation.createExtendTransformation(s1c, yattanode, 
								 new Object[] {sg_student, "tutor","string","?"},
								 "[{s,t} | {u,n} <- <<<<root,ug>>,name>>; {u,t} <- <<<<root,ug>>,tutor>>; s <- [generateGID 's1' u [n] 'student']]",
								 null);
    Schema s1d=t1_4.getOtherSchema(s1c);
    SchemaObject sg_tutor=t1_4.getSchemaObject(s1d);

    // EXTEND "results" node
    Transformation t1_5 = Transformation.createExtendTransformation(s1d, yattanode, 
								 new Object[] {sg_student, "results","set","*"},
  								 "[{s,re} | {u,n} <- <<<<root,ug>>,name>>; {u,c} <- <<<<root,ug>>,course>>; {c,co} <- <<<<<<root,ug>>,course>>,code>>; s <- [generateGID 's1' u [n] 'student']; re <- [generateGID 's1' c [n,co] 'results']]", 
								 null);
    Schema s1e=t1_5.getOtherSchema(s1d);
    SchemaObject sg_results=t1_5.getSchemaObject(s1e);

    // EXTEND "code" node
    Transformation t1_6 = Transformation.createExtendTransformation(s1e, yattanode,
								 new Object[] {sg_results, "code","string","k"},
  								 "[{re,co} | {u,n} <- <<<<root,ug>>,name>>; {u,c} <- <<<<root,ug>>,course>>; {c,co} <- <<<<<<root,ug>>,course>>,code>>; re <- [generateGID 's1' c [n,co] 'results']]", 
								 null);
    Schema s1f=t1_6.getOtherSchema(s1e);
    SchemaObject sg_code=t1_6.getSchemaObject(s1f);


    // EXTEND "year" node
    Transformation t1_7 = Transformation.createExtendTransformation(s1f, yattanode, 
								 new Object[] {sg_results, "year","integer",""},
  								 "[{re,y} | {u,n} <- <<<<root,ug>>,name>>; {u,c} <- <<<<root,ug>>,course>>; {c,co} <- <<<<<<root,ug>>,course>>,code>>; {c,y} <- <<<<<<root,ug>>,course>>,year>>; re <- [generateGID 's1' c [n,co] 'results']]",
								 null);
    Schema s1g=t1_7.getOtherSchema(s1f);
    SchemaObject sg_year=t1_7.getSchemaObject(s1g);

     // EXTEND "grade" node
    Transformation t1_8 = Transformation.createExtendTransformation(s1g, yattanode, 
								 new Object[] {sg_results, "grade","string","?"},
  								 "[{re,g} | {u,n} <- <<<<root,ug>>,name>>; {u,c} <- <<<<root,ug>>,course>>; {c,co} <- <<<<<<root,ug>>,course>>,code>>; {c,g} <- <<<<<<root,ug>>,course>>,grade>>; re <- [generateGID 's1' c [n,co] 'results']]",
								 null);
    Schema s1h=t1_8.getOtherSchema(s1g);
    SchemaObject sg_grade=t1_8.getSchemaObject(s1h);

    // EXTEND "dept" node
    Transformation t1_9 = Transformation.createExtendTransformation(s1h, yattanode,
								 new Object[] {s1_root, "dept","set","+"},
								 "[{r,de} | {r,u} <- <<root,ug>>; {u,c} <- <<<<root,ug>>,course>>; {c,d} <- <<<<<<root,ug>>,course>>,dept>>; de <- [generateGID 's1' c [d] 'dept']]", 
								 null);
    Schema s1i=t1_9.getOtherSchema(s1h);
    SchemaObject sg_dept=t1_9.getSchemaObject(s1i);

    // EXTEND "dname" node
    Transformation t1_10 = Transformation.createExtendTransformation(s1i, yattanode,
								 new Object[] {sg_dept, "dname","string","k"},
								 "[{de,d} | {c,d} <- <<<<<<root,ug>>,course>>,dept>>; de <- [generateGID 's1' c [d] 'dept']]", 
								 null);
    Schema s1j=t1_10.getOtherSchema(s1i);
    SchemaObject sg_dname=t1_10.getSchemaObject(s1j);

    // EXTEND "building" node
    Transformation t1_11 = Transformation.createExtendTransformation(s1j, yattanode,
								     new Object[] {sg_dept, "building","string","?"},
								     null,
								     null);
    Schema s1k=t1_11.getOtherSchema(s1j);
    SchemaObject sg_building=t1_11.getSchemaObject(s1k);

    // EXTEND "course" node
    Transformation t1_12 = Transformation.createExtendTransformation(s1k, yattanode,
								 new Object[] {sg_dept, "course","set","+"},
								 "[{de,c1} | {r,u} <- <<root,ug>>; {u,c} <- <<<<root,ug>>,course>>; {c,co} <- <<<<<<root,ug>>,course>>,code>>; {c,d} <- <<<<<<root,ug>>,course>>,dept>>; de <- [generateGID 's1' c [d] 'dept']; c1 <- [generateGID 's1' c [co] 'course']]", 								  
								 null);
    Schema s1l=t1_12.getOtherSchema(s1k);
    SchemaObject sg_course=t1_12.getSchemaObject(s1l);

    // EXTEND "course.code" node
    Transformation t1_13 = Transformation.createExtendTransformation(s1l, yattanode,
								 new Object[] {sg_course, "code","string","k"},
								 "[{c1,co} | {c,co} <- <<<<<<root,ug>>,course>>,code>>; c1 <- [generateGID 's1' c [co] 'course']]", 								  
								 null);
    Schema s1m=t1_13.getOtherSchema(s1l);
    SchemaObject sg_course_code=t1_13.getSchemaObject(s1m);

    // EXTEND "lecturer" node
    Transformation t1_14 = Transformation.createExtendTransformation(s1m, yattanode,
								 new Object[] {sg_course, "lecturer","string","?"},
								 "[{c1,lt} | {c,co} <- <<<<<<root,ug>>,course>>,code>>; {c,lt} <- <<<<<<root,ug>>,course>>,lecturer>>; c1 <- [generateGID 's1' c [co] 'course']]",
								 // ++ [{c1,Void} | {c,co} <- <<<<<<root,ug>>,course>>,code>>; c1 <- [generateGID 's1' c [co] 'course']; not (member [{c} | {c,lt} <- <<<<<<root,ug>>,course>>,lecturer>>] c)]", 								  
								 null);
    Schema s1n=t1_14.getOtherSchema(s1m);
    SchemaObject sg_lecturer=t1_14.getSchemaObject(s1n);


    //Shrinking Phrase
    //-----------------

    // CONTRACT sequence: year-grade
    Transformation t1_15 = Transformation.createContractTransformation(s1n, s1_seq_year_grade,
								       null,
								       null);
    Schema s1o=t1_15.getOtherSchema(s1n);

    // CONTRACT sequence: lecturer-year
    Transformation t1_16 = Transformation.createContractTransformation(s1o, s1_seq_lecturer_year,
								       null,
								       null);
    Schema s1p=t1_16.getOtherSchema(s1o);

    // CONTRACT sequence: dept-lecturer
    Transformation t1_17 = Transformation.createContractTransformation(s1p, s1_seq_dept_lecturer,
								       null,
								       null);
    Schema s1q=t1_17.getOtherSchema(s1p);

    // CONTRACT sequence: code-dept
    Transformation t1_18 = Transformation.createContractTransformation(s1q, s1_seq_code_dept,
								       null,
								       null);
    Schema s1r=t1_18.getOtherSchema(s1q);

    // CONTRACT sequence: tutor-course
    Transformation t1_19 = Transformation.createContractTransformation(s1r, s1_seq_tutor_course,
								       null,
								       null);
    Schema s1s=t1_19.getOtherSchema(s1r);


    // CONTRACT sequence: name-tutor 
    Transformation t1_20 = Transformation.createContractTransformation(s1s, s1_seq_name_tutor,
								       null,
								       null);
    Schema s1t=t1_20.getOtherSchema(s1s);


    // CONTRACT "grade" node <<root.ug.course,grade>>
    Transformation t1_21 = Transformation.createContractTransformation(s1t, s1_grade, 
								       "[{c,g} | {s,n} <- <<<<root,student>>,name>>; {s,'ug'} <- <<<<root,student>>,level>>; {s,re} <- <<<<root,student>>,results>>; {re,co} <- <<<<<<root,student>>,results>>,code>>; {re,g} <- <<<<<<root,student>>,results>>,grade>>; c <- [generateSID 's1' [n,co] 'results']]", 
								       null);
    Schema s1u=t1_21.getOtherSchema(s1t);

    // CONTRACT "year" node <<root.ug.course,year>>
    Transformation t1_22 = Transformation.createContractTransformation(s1u, s1_year, 
								       "[{c,y} | {s,n} <- <<<<root,student>>,name>>; {s,'ug'} <- <<<<root,student>>,level>>; {s,re} <- <<<<root,student>>,results>>; {re,co} <- <<<<<<root,student>>,results>>,code>>; {re,y} <- <<<<<<root,student>>,results>>,year>>; c <- [generateSID 's1' [n,co] 'results']]",  
								       null);
    Schema s1v=t1_22.getOtherSchema(s1u);

    // CONTRACT "lecturer" node <<root.ug.course,lecturer>>
    Transformation t1_23 = Transformation.createContractTransformation(s1v, s1_lecturer, 
								       "[{c,l} | {s,n} <- <<<<root,student>>,name>>; {s,'ug'} <- <<<<root,student>>,level>>; {s,re} <- <<<<root,student>>,results>>; {re,co} <- <<<<<<root,student>>,results>>,code>>; {de,c} <- <<<<root,dept>>,course>>; {c,co} <- <<<<<<root,dept>>,course>>,code>>; {c,l} <- <<<<<<root,dept>>,course>>,lecturer>>;  c <- [generateSID 's1' [n,co] 'results']]",  
								       null);
    Schema s1w=t1_23.getOtherSchema(s1v);

    // CONTRACT "dept" node <<root.ug.course,dept>>
    Transformation t1_24 = Transformation.createContractTransformation(s1w, s1_dept, 
								       "[{c,d} | {s,n} <- <<<<root,student>>,name>>; {s,'ug'} <- <<<<root,student>>,level>>; {s,re} <- <<<<root,student>>,results>>; {re,co} <- <<<<<<root,student>>,result>>,code>>; {de,d} <- <<<<root,dept>>,dname>>; {de,c} <- <<<<root,dept>>,course>>; {c,co} <- <<<<<<root,dept>>,course>>,code>>; {c,l} <- <<<<<<root,dept>>,course>>,lecturer>>;  c <- [generateSID 's1' [n,co] 'results']]",  
								       null);
    Schema s1x=t1_24.getOtherSchema(s1w);

    // CONTRACT "code" node <<root.ug.course,code>>
    Transformation t1_25 = Transformation.createContractTransformation(s1x, s1_code, 
								       "[{c,co} | {s,n} <- <<<<root,student>>,name>>; {s,'ug'} <- <<<<root,student>>,level>>; {s,re} <- <<<<root,student>>,results>>; {re,co} <- <<<<<<root,student>>,result>>,code>>; c <- [generateSID 's1' [n,co] 'results']]", 
								       null);
    Schema s1y=t1_25.getOtherSchema(s1x);

    // CONTRACT "course" node <<root.ug,course>>
    Transformation t1_26 = Transformation.createContractTransformation(s1y, s1_course, 
								       "[{u,c} | {s,n} <- <<<<root,student>>,name>>; {s,'ug'} <- <<<<root,student>>,level>>; {s,re} <- <<<<root,student>>,results>>; {re,co} <- <<<<<<root,student>>,result>>,code>>; c <- [generateSID 's1' [n,co] 'results']; u <- [generateSID 's1' [n] 'student']]", 
								       null);
    Schema s1z=t1_26.getOtherSchema(s1y);

    // CONTRACT "tutor" node from ug
    Transformation t1_27 = Transformation.createContractTransformation(s1z, s1_tutor, 
								       "[{u,t} | {s,n}<- <<<<root,student>>,name>>; {s,'ug'} <- <<<<root,student>>,level>>; {s,t} <- <<<<root,student>>,tutor>>; u <- [generateSID 's1' [n] 'student']]",  
								       null);
    Schema s1aa=t1_27.getOtherSchema(s1z);

    // CONTRACT "name" node from ug
    Transformation t1_28 = Transformation.createContractTransformation(s1aa, s1_name, 
								       "[{u,n} | {s,n}<- <<<<root,student>>,name>>; {s,'ug'} <- <<<<root,student>>,level>>; u <- [generateSID 's1' [n] 'student']]",  
								       null);
    Schema s1ab=t1_28.getOtherSchema(s1aa);

    // CONTRACT "ug" node from root
    Transformation t1_29 = Transformation.createContractTransformation(s1ab, s1_ug, 
								       "[{r,u} | {r,s} <- <<root,student>>; {s,n}<- <<<<root,student>>,name>>; {s,'ug'} <- <<<<root,student>>,level>>; u <- [generateSID 's1' [n] 'student']]",  
								       null);
    Schema s1ac=t1_29.getOtherSchema(s1ab);


    // EXTEND sequence for Sg
    //------------------------
    // EXTEND sequence: name-level
    Transformation t1_30 = Transformation.createExtendTransformation(s1ac, sequence,
								  new Object[] {"",sg_name,sg_level},
								  null,
								  null);
    Schema s1ad=t1_30.getOtherSchema(s1ac);

    // EXTEND sequence: level-tutor
    Transformation t1_31 = Transformation.createExtendTransformation(s1ad, sequence,
								  new Object[] {"",sg_level,sg_tutor},
								  null,
								  null);
    Schema s1ae=t1_31.getOtherSchema(s1ad);

    // EXTEND sequence: tutor-results
    Transformation t1_32 = Transformation.createExtendTransformation(s1ae, sequence,
								  new Object[] {"",sg_tutor,sg_results},
								  null,
								  null);
    Schema s1af=t1_32.getOtherSchema(s1ae);


    // EXTEND sequence: code-year
    Transformation t1_33 = Transformation.createExtendTransformation(s1af, sequence,
								  new Object[] {"",sg_code,sg_year},
								  null,
								  null);
    Schema s1ag=t1_33.getOtherSchema(s1af);

    // EXTEND sequence: year-grade
    Transformation t1_34 = Transformation.createExtendTransformation(s1ag, sequence,
								  new Object[] {"",sg_year,sg_grade},
								  null,
								  null);
    Schema s1ah=t1_34.getOtherSchema(s1ag);

    // EXTEND sequence: student-dept
    Transformation t1_35 = Transformation.createExtendTransformation(s1ah, sequence,
								  new Object[] {"",sg_student,sg_dept},
								  null,
								  null);
    Schema s1ai=t1_35.getOtherSchema(s1ah);

    // EXTEND sequence: dname-building
    Transformation t1_36 = Transformation.createExtendTransformation(s1ai, sequence,
								  new Object[] {"",sg_dname,sg_building},
								  null,
								  null);
    Schema s1aj=t1_36.getOtherSchema(s1ai);

    // EXTEND sequence: building-course
    Transformation t1_37 = Transformation.createExtendTransformation(s1aj, sequence,
								  new Object[] {"",sg_building,sg_course},
								  null,
								  null);
    Schema s1ak=t1_37.getOtherSchema(s1aj);

    // EXTEND sequence: code-lecturer
    Transformation t1_38 = Transformation.createExtendTransformation(s1ak, sequence,
								  new Object[] {"",sg_course_code,sg_lecturer},
								  null,
								  null);
    Schema s1al=t1_38.getOtherSchema(s1ak);

    return(s1al);

  }

  public static Schema transformS2ToSg(Schema s2) 
    throws NotFoundException, TypeMismatchException {
    Model yatta=Model.getModel("yatta");
    Construct rootnode=yatta.getConstruct("rootnode");
    Construct yattanode=yatta.getConstruct("yattanode");
    Construct sequence=yatta.getConstruct("sequence");

    // Retrieve the objects of the schema
    SchemaObject s2_root=s2.getSchemaObject("<<root>>");
    SchemaObject s2_course=s2.getSchemaObject("<<root,course>>");
    SchemaObject s2_code=s2.getSchemaObject("<<<<root,course>>,code>>");
    SchemaObject s2_dept=s2.getSchemaObject("<<<<root,course>>,dept>>");
    SchemaObject s2_building=s2.getSchemaObject("<<<<root,course>>,building>>");
    SchemaObject s2_ug_pg=s2.getSchemaObject("<<<<root,course>>,ug_pg>>");
    SchemaObject s2_name=s2.getSchemaObject("<<<<<<root,course>>,ug_pg>>,name>>");
    SchemaObject s2_level=s2.getSchemaObject("<<<<<<root,course>>,ug_pg>>,level>>");
    SchemaObject s2_year=s2.getSchemaObject("<<<<<<root,course>>,ug_pg>>,year>>");
    SchemaObject s2_grade=s2.getSchemaObject("<<<<<<root,course>>,ug_pg>>,grade>>");
    SchemaObject s2_seq_code_dept=s2.getSchemaObject("<<_,<<<<root,course>>,code>>,<<<<root,course>>,dept>>>>");
    SchemaObject s2_seq_dept_building=s2.getSchemaObject("<<_,<<<<root,course>>,dept>>,<<<<root,course>>,building>>>>");
    SchemaObject s2_seq_building_ug_pg=s2.getSchemaObject("<<_,<<<<root,course>>,building>>,<<<<root,course>>,ug_pg>>>>");
    SchemaObject s2_seq_name_level=s2.getSchemaObject("<<_,<<<<<<root,course>>,ug_pg>>,name>>,<<<<<<root,course>>,ug_pg>>,level>>>>");
    SchemaObject s2_seq_level_year=s2.getSchemaObject("<<_,<<<<<<root,course>>,ug_pg>>,level>>,<<<<<<root,course>>,ug_pg>>,year>>>>");
    SchemaObject s2_seq_year_grade=s2.getSchemaObject("<<_,<<<<<<root,course>>,ug_pg>>,year>>,<<<<<<root,course>>,ug_pg>>,grade>>>>");



    //********************************************//
    // Start the transformation steps S2 -> Sg    //
    //********************************************//

    //  Growing Phrase
    //-----------------

    // Add "student" node
    Transformation t2_1 = Transformation.createAddTransformation(s2, yattanode, 
								 new Object[] {s2_root,"student","set","+"},
								 "[{rr,ss} | {rr,cc} <- <<root,course>>; {cc,pp} <- <<<<root,course>>,ug_pg>>; {pp,nn} <- <<<<<<root,course>>,ug_pg>>,name>>; ss <- [generateGID 's2' pp [nn] 'student']]",
								 null);
    Schema s2a=t2_1.getOtherSchema(s2);
    SchemaObject sg_student=t2_1.getSchemaObject(s2a);

    // Add "name" node
    Transformation t2_2 = Transformation.createAddTransformation(s2a, yattanode, 
								 new Object[] {sg_student,"name","string","k"},
								 "[{ss,nn} | {cc,pp} <- <<<<root,course>>,ug_pg>>; {pp,nn} <- <<<<<<root,course>>,ug_pg>>,name>>; ss <- [generateGID 's2' pp [nn] 'student']]",
								 null);
    Schema s2b=t2_2.getOtherSchema(s2a);
    SchemaObject sg_name=t2_2.getSchemaObject(s2b);
    

    // Add "level" node
    Transformation t2_3 = Transformation.createAddTransformation(s2b, yattanode, 
								 new Object[] {sg_student,"level","string",""},
								 "[{ss,ll} | {cc,pp} <- <<<<root,course>>,ug_pg>>; {pp,nn} <- <<<<<<root,course>>,ug_pg>>,name>>; {pp,ll} <- <<<<<<root,course>>,ug_pg>>,level>>; ss <- [generateGID 's2' pp [nn] 'student']]",
								 null);
    Schema s2c=t2_3.getOtherSchema(s2b);
    SchemaObject sg_level=t2_3.getSchemaObject(s2c);

    // Extend "tutor" node 
    Transformation t2_4 = Transformation.createExtendTransformation(s2c, yattanode,
								 new Object[] {sg_student,"tutor","string","?"},
								 null, null);
    Schema s2d=t2_4.getOtherSchema(s2c);
    SchemaObject sg_tutor=t2_4.getSchemaObject(s2d);    

    // Add "results" node
    Transformation t2_5 = Transformation.createAddTransformation(s2d, yattanode, 
								 new Object[] {sg_student,"results","set","*"},
								 "[{ss,rre} | {cc,pp} <- <<<<root,course>>,ug_pg>>; {pp,nn} <- <<<<<<root,course>>,ug_pg>>,name>>; {cc,cco} <- <<<<root,course>>,code>>; ss <- [generateGID 's2' pp [nn] 'student']; rre <- [generateGID 's2' pp [nn,cco] 'results']]",   
								 null);
    Schema s2e=t2_5.getOtherSchema(s2d);
    SchemaObject sg_results=t2_5.getSchemaObject(s2e);

    // Add "code" node
    Transformation t2_6 = Transformation.createAddTransformation(s2e, yattanode,
								  new Object[] {sg_results,"code","string","k"},
								  "[{rre,co} | {cc,pp} <- <<<<root,course>>,ug_pg>>; {pp,nn} <- <<<<<<root,course>>,ug_pg>>,name>>; {cc,cco} <- <<<<root,course>>,code>>; rre <- [generateGID 's2' pp [nn,cco] 'results']]",
								  null);
    Schema s2f=t2_6.getOtherSchema(s2e);
    SchemaObject sg_results_code=t2_6.getSchemaObject(s2f);

    // Add "year" node
    Transformation t2_7 = Transformation.createAddTransformation(s2f, yattanode, 
								 new Object[] {sg_results,"year","integer",""},
								 "[{rre,yy} | {cc,pp} <- <<<<root,course>>,ug_pg>>; {pp,nn} <- <<<<<<root,course>>,ug_pg>>,name>>; {cc,cco} <- <<<<root,course>>,code>>; {pp,yy} <- <<<<<<root,course>>,ug_pg>>,year>>;  rre <- [generateGID 's2' pp [nn,cco] 'results']]",
								 null);
    Schema s2g=t2_7.getOtherSchema(s2f);
    SchemaObject sg_year=t2_7.getSchemaObject(s2g);

    // Add "grade" node
    Transformation t2_8 = Transformation.createAddTransformation(s2g, yattanode, 
								    new Object[] {sg_results,"grade","string","?"},
								    "[{rre,gg} | {cc,pp} <- <<<<root,course>>,ug_pg>>; {pp,nn} <- <<<<<<root,course>>,ug_pg>>,name>>; {cc,cco} <- <<<<root,course>>,code>>; {pp,gg} <- <<<<<<root,course>>,ug_pg>>,grade>>;  rre <- [generateGID 's2' pp [nn,cco] 'results']]",
								    null);
    Schema s2h=t2_8.getOtherSchema(s2g);
    SchemaObject sg_grade=t2_8.getSchemaObject(s2h);

    // Add "dept" node
    Transformation t2_9 = Transformation.createAddTransformation(s2h, yattanode,
								  new Object[] {s2_root,"dept","set","+"},
								  "[{rr,dde} | {rr,cc} <- <<root,course>>; {cc,dd} <- <<<<root,course>>,dept>>; dde <- [generateGID 's2' cc [dd] 'dept']]",
								  null);
    Schema s2i=t2_9.getOtherSchema(s2h);
    SchemaObject sg_dept=t2_9.getSchemaObject(s2i);

    // Add "dname" node
    Transformation t2_10 = Transformation.createAddTransformation(s2i, yattanode,
								    new Object[] {sg_dept,"dname","string","k"},
								    "[{dde,dd} | {rr,cc} <- <<root,course>>; {cc,dd} <- <<<<root,course>>,dept>>; dde <- [generateGID 's2' cc [dd] 'dept']]",   
								    null);
    Schema s2j=t2_10.getOtherSchema(s2i);
    SchemaObject sg_dname=t2_10.getSchemaObject(s2j);

    // Add "building" node
    Transformation t2_11 = Transformation.createAddTransformation(s2j, yattanode,
								    new Object[] {sg_dept,"building","string","?"},
								    "[{dde,bb} | {rr,cc} <- <<root,course>>; {cc,dd} <- <<<<root,course>>,dept>>; {cc,bb} <- <<<<root,course>>,building>>; dde <- [generateGID 's2' cc [dd] 'dept']]",    
								    null);
    Schema s2k=t2_11.getOtherSchema(s2j);
    SchemaObject sg_building=t2_11.getSchemaObject(s2k);

    // Add "course" node
    Transformation t2_12 = Transformation.createAddTransformation(s2k, yattanode,
								  new Object[] {sg_dept,"course","set","+"},
								  "[{dde,cc1} | {cc,dd} <- <<<<root,course>>,dept>>; {cc,cco} <- <<<<root,course>>,code>>; dde <- [generateGID 's2' cc [dd] 'dept']; cc1 <- [generateGID 's2' cc [cco] 'course']]", 
								  null);
    Schema s2l=t2_12.getOtherSchema(s2k);
    SchemaObject sg_course=t2_12.getSchemaObject(s2l);

    // Add "course,code" node								 
    Transformation t2_13 = Transformation.createAddTransformation(s2l, yattanode,
								  new Object[] {sg_course,"code","string","k"},
								  "[{cc1,cco} | {cc,cco} <- <<<<root,course>>,code>>; cc1 <- [generateGID 's2' cc [cco] 'course']]", 
								  null); 		
    Schema s2m=t2_13.getOtherSchema(s2l);
    SchemaObject sg_course_code=t2_13.getSchemaObject(s2m);


    // EXTEND "lecturer" node
    Transformation t2_14 = Transformation.createExtendTransformation(s2m, yattanode,
								  new Object[] {sg_course,"lecturer","string","?"},
								  null,
								  null);
    Schema s2n=t2_14.getOtherSchema(s2m);
    SchemaObject sg_lecturer=t2_14.getSchemaObject(s2n);


    //  Shrinking Phrase
    //--------------------
    // Contract sequence: year-grade
    Transformation t2_15 = Transformation.createContractTransformation(s2n, s2_seq_year_grade,
								       null, null);
    Schema s2o=t2_15.getOtherSchema(s2n);

    // Contract sequence: level-year
    Transformation t2_16 = Transformation.createContractTransformation(s2o, s2_seq_level_year,
								       null, null);
    Schema s2p=t2_16.getOtherSchema(s2o);

    // Contract sequence: name-level
    Transformation t2_17 = Transformation.createContractTransformation(s2p, s2_seq_name_level,
								       null, null);
    Schema s2q=t2_17.getOtherSchema(s2p);

    // Contract sequence: building-ug_pg
    Transformation t2_18 = Transformation.createContractTransformation(s2q, s2_seq_building_ug_pg,
								       null, null);
    Schema s2r=t2_18.getOtherSchema(s2q);

    // Contract sequence: dept-building
    Transformation t2_19 = Transformation.createContractTransformation(s2r, s2_seq_dept_building,
								       null, null);
    Schema s2s=t2_19.getOtherSchema(s2r);

    // Contract sequence: code-dept
    Transformation t2_20 = Transformation.createContractTransformation(s2s, s2_seq_code_dept,
								       null, null);
    Schema s2t=t2_20.getOtherSchema(s2s);

    // Contract "grade" node
    Transformation t2_21 = Transformation.createContractTransformation(s2t, s2_grade,
								       "[{pp,gg} | {ss,nn} <- <<<<root,student>>,name>>; {ss,rre} <- <<<<root,student>>,results>>; {rre,cco} <- <<<<<<root,student>>,results>>,code>>; {rre,gg} <- <<<<<<root,student>>,results>>,grade>>; pp <- [generateSID 's2' [nn,cco] 'results']]",
								       null);
    Schema s2u=t2_21.getOtherSchema(s2t);

    // Delete "year" node
    Transformation t2_22 = Transformation.createDeleteTransformation(s2u, s2_year,
								       "[{pp,yy} | {ss,nn} <- <<<<root,student>>,name>>; {ss,rre} <- <<<<root,student>>,results>>; {rre,cco} <- <<<<<<root,student>>,results>>,code>>; {rre,yy} <- <<<<<<root,student>>,results>>,year>>; pp <- [generateSID 's2' [nn,cco] 'results']]",
								       null);
    Schema s2v=t2_22.getOtherSchema(s2u);

    // Delete "level" node
    Transformation t2_23 = Transformation.createDeleteTransformation(s2v, s2_level,
								       "[{pp,ll} | {ss,nn} <- <<<<root,student>>,name>>; {ss,ll} <- <<<<root,student>>,level>>; {ss,rre} <- <<<<root,student>>,results>>; {rre,cco} <- <<<<<<root,student>>,results>>,code>>; pp <- [generateSID 's2' [nn,cco] 'results']]",
								       null);
    Schema s2w=t2_23.getOtherSchema(s2v);

    // Delete "name" node
    Transformation t2_24 = Transformation.createDeleteTransformation(s2w, s2_name,
								     "[{pp,nn} | {ss,nn} <- <<<<root,student>>,name>>; {ss,rre} <- <<<<root,student>>,results>>; {rre,cco} <- <<<<<<root,student>>,results>>,code>>; pp <- [generateSID 's2' [nn,cco] 'results']]",
								     null);
    Schema s2x=t2_24.getOtherSchema(s2w);

    // Delete "ug_pg" node
    Transformation t2_25 = Transformation.createDeleteTransformation(s2x, s2_ug_pg,
								     "[{cc1,pp} | {ss,nn} <- <<<<root,student>>,name>>; {ss,rre} <- <<<<root,student>>,results>>; {rre,cco} <- <<<<<<root,student>>,results>>,code>>; {cc,cco} <- <<<<<<root,dept>>,course>>,code>>; pp <- [generateSID 's2' [nn,cco] 'results']; cc1 <- [generateSID 's2' [cco] 'course']]",
								     null);
    Schema s2y=t2_25.getOtherSchema(s2x);

    // Delete "building" node
    Transformation t2_26 = Transformation.createDeleteTransformation(s2y, s2_building,
								     "[{cc1,bb} | {dde,bb} <- <<<<root,dept>>,building>>; {dde,cc} <- <<<<root,dept>>,course>>; {cc,cco} <- <<<<<<root,dept>>,course>>,code>>; cc1 <- [generateSID 's2' [cco] 'course']]",
								     null);
    Schema s2z=t2_26.getOtherSchema(s2y);

    // Delete "dept" node
    Transformation t2_27 = Transformation.createDeleteTransformation(s2z, s2_dept,
								     "[{cc1,dd} | {dde,dd} <- <<<<root,dept>>,dname>>; {dde,cc} <- <<<<root,dept>>,course>>; {cc,cco} <- <<<<<<root,dept>>,course>>,code>>; cc1 <- [generateSID 's2' [cco] 'course']]",
								     null);
    Schema s2aa=t2_27.getOtherSchema(s2z);

    // Delete "code" node
    Transformation t2_28 = Transformation.createDeleteTransformation(s2aa, s2_code,
								     "[{cc1,cco} | {cc,cco} <- <<<<<<root,dept>>,course>>,code>>; cc1 <- [generateSID 's2' [cco] 'course']]",
								     null);
    Schema s2ab=t2_28.getOtherSchema(s2aa);

    // Delete "course" node
    Transformation t2_29 = Transformation.createDeleteTransformation(s2ab, s2_course,
								     "[{rr,cc1} | {rr,dde} <- <<root,dept>>; {dde,cc} <- <<<<root,dept>>,course>>; {cc,cco} <- <<<<<<root,dept>>,course>>,code>>; cc1 <- [generateSID 's2' [cco] 'course']]",
								     null);
    Schema s2ac=t2_29.getOtherSchema(s2ab);

    // EXTEND SEQUENCE in Sg
    //------------------------
    // EXTEND sequence: name-level
    Transformation t2_30 = Transformation.createExtendTransformation(s2ac, sequence,
								     new Object[] {"",sg_name,sg_level},
								     null,
								     null);
    Schema s2ad=t2_30.getOtherSchema(s2ac);

    // EXTEND sequence: level-tutor
    Transformation t2_31 = Transformation.createExtendTransformation(s2ad, sequence,
								  new Object[] {"",sg_level,sg_tutor},
								  null,
								  null);
    Schema s2ae=t2_31.getOtherSchema(s2ad);

    // EXTEND sequence: tutor-results
    Transformation t2_32 = Transformation.createExtendTransformation(s2ae, sequence,
								  new Object[] {"",sg_tutor,sg_results},
								  null,
								  null);
    Schema s2af=t2_32.getOtherSchema(s2ae);


    // EXTEND sequence: code-year
    Transformation t2_33 = Transformation.createExtendTransformation(s2af, sequence,
								  new Object[] {"",sg_results_code,sg_year},
								  null,
								  null);
    Schema s2ag=t2_33.getOtherSchema(s2af);

    // EXTEND sequence: year-grade
    Transformation t2_34 = Transformation.createExtendTransformation(s2ag, sequence,
								  new Object[] {"",sg_year,sg_grade},
								  null,
								  null);
    Schema s2ah=t2_34.getOtherSchema(s2ag);

    // EXTEND sequence: student-dept
    Transformation t2_35 = Transformation.createExtendTransformation(s2ah, sequence,
								  new Object[] {"",sg_student,sg_dept},
								  null,
								  null);
    Schema s2ai=t2_35.getOtherSchema(s2ah);

    // EXTEND sequence: dname-building
    Transformation t2_36 = Transformation.createExtendTransformation(s2ai, sequence,
								  new Object[] {"",sg_dname,sg_building},
								  null,
								  null);
    Schema s2aj=t2_36.getOtherSchema(s2ai);

    // EXTEND sequence: building-course
    Transformation t2_37 = Transformation.createExtendTransformation(s2aj, sequence,
								  new Object[] {"",sg_building,sg_course},
								  null,
								  null);
    Schema s2ak=t2_37.getOtherSchema(s2aj);

    // EXTEND sequence: code-lecturer
    Transformation t2_38 = Transformation.createExtendTransformation(s2ak, sequence,
								  new Object[] {"",sg_course_code,sg_lecturer},
								  null,
								  null);
    Schema s2al=t2_38.getOtherSchema(s2ak);

    return(s2al);

  }

  // This is a fairly standard check to see if two schemas can be
  // "integrated" via ID transformations
  public static void integrateSchemas(Schema s1,Schema s2)  
    throws AutoMedException {
      SchemaObject[] aLessB=s1.differenceByName(s2);
      SchemaObject[] bLessA=s2.differenceByName(s1);
      boolean integrationOK=true;

      if (aLessB.length>0) {
	System.out.println(s1.getName()+"-"+s2.getName()+"="+aLessB);
	integrationOK=false;
      }
	  
      if (bLessA.length>0) {
	System.out.println(s2.getName()+"-"+s1.getName()+"="+bLessA);
	integrationOK=false;
      }

      if (integrationOK) {	
	try {
	  Transformation.createIdentTransformation(s1,s2,null,null);
	  System.out.println("Integration of "+s1.getName()+" and "+
			     s2.getName()+" succeeded");
	}
	catch (SchemasNotIdenticalException e) {
	  System.out.println(e.toString());
	  e.printStackTrace(System.out);
	  System.out.println("================");
	  System.out.println("*** Schema " + e.getFromSchema().getName());
	  System.out.println(e.getFromSchema().getAllSchemeNamesString(true, -1, -1));
	  //	  s1.listSchema();
	  System.out.println("----------------");
	  System.out.println("*** Objects not matched");
	  SchemaObject[] fromSo = e.getFromObjectsUnmatched();
	  for (int i=0; i<fromSo.length; i++)
	    System.out.println(fromSo[i].getSchemeNamesString(-1, -1));
	  System.out.println("================");
	  System.out.println("*** Schema " + e.getToSchema().getName());
	  System.out.println(e.getToSchema().getAllSchemeNamesString(true, -1, -1));
	  //	  s2.listSchema();
	  System.out.println("----------------");
	  System.out.println("*** Objects not matched");
	  SchemaObject[] toSo = e.getToObjectsUnmatched();
	  for (int i=0; i<toSo.length; i++)
	    System.out.println(toSo[i].getSchemeNamesString(-1, -1));

	  System.out.println("================");
	}
	catch (Throwable t) {
	  System.out.println("================");
	  System.out.println("*** Schema " + s1.getName());
	  System.out.println(s1.getAllSchemeNamesString(true, -1, -1));
	  System.out.println("----------------");
	  System.out.println("*** Schema " + s2.getName());
	  System.out.println(s2.getAllSchemeNamesString(true, -1, -1));
	  System.out.println("================");
	  System.out.println(t.toString());
	  t.printStackTrace(System.out);
	}
      }
      else
	System.out.println("Integration failed, since it is "+
			   "only allowed if schemas identical");
  }

  public static void main(String[] args) {
    try {
      System.out.println("AutoMed Repository: Transformation and "+
			 "Integration of UG and STUDENT");

      // level 5 prints all the old debug information, 0 makes it silent
      //STR.setDebugLevel(0);

      Schema s1=Schema.getSchema("ug");
      Schema s2=Schema.getSchema("student");

      Schema sg1=transformS1ToSg(s1);
      sg1.listSchema();
      Schema sg2=transformS2ToSg(s2);
      sg2.listSchema();
      integrateSchemas(sg1,sg2);
    }
    catch (AutoMedException ame) {
      ame.printStackTrace();
    }
    catch (Throwable t) {
      System.err.println(t.toString());
      t.printStackTrace();
    }
  }
}



