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

/**
 * An application to demonstrate how to create schemas in existing models
 */
public class DefineSchemas {
  public static Schema createERS1(String name) 
    throws NotFoundException,TypeMismatchException,IntegrityException {
    Schema s=Schema.createSchema(name,true);
    Model er=Model.getModel("er");

    Construct ent=er.getConstruct("entity");
    Construct att=er.getConstruct("attribute");
    Construct rel=er.getConstruct("relationship");

    // Now build the schema
    SchemaObject staff=s.createSchemaObject(ent,new Object[]{"staff"});
    s.createSchemaObject(att,new Object[] {staff,"id","key"});
    s.createSchemaObject(att,new Object[] {staff,"name","notnull"});
    s.createSchemaObject(att,new Object[] {staff,"sex","notnull"});
    SchemaObject dept=s.createSchemaObject(ent,new Object[] {"dept"});
    s.createSchemaObject(att,new Object[] {dept,"dname","key"});
    s.createSchemaObject(rel,
       new Object[]{"worksin",staff,dept,"1:1","1:N"});
    System.out.println("Created schema "+name+" succesfully");

    return s;
  }

  public static Schema createERS2(String name) 
    throws NotFoundException,TypeMismatchException,IntegrityException {
    Schema s=Schema.createSchema(name,true);
    Model er=Model.getModel("er");

    Construct ent=er.getConstruct("entity");
    Construct att=er.getConstruct("attribute");
    Construct gen=er.getConstruct("generalisation");

    // Now build the schema
    SchemaObject person=s.createSchemaObject(ent,new Object[]{"person"});
    s.createSchemaObject(att,new Object[] {person,"pid","key"});
    s.createSchemaObject(att,new Object[] {person,"name","notnull"});
    s.createSchemaObject(att,new Object[] {person,"dname","notnull"});
    SchemaObject male=s.createSchemaObject(ent,new Object[] {"male"});
    SchemaObject female=s.createSchemaObject(ent,new Object[] {"female"});
    s.createSchemaObject(gen,new Object[] {"sex","total",person,male,female});
    System.out.println("Created schema "+name+" succesfully");

    return s;
  }

  public static Schema createERS3(String name) 
    throws NotFoundException,TypeMismatchException,IntegrityException {
    Schema s=Schema.createSchema(name,true);
    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");

    // Now build the schema
    SchemaObject person=s.createSchemaObject(ent,new Object[]{"person"});
    s.createSchemaObject(att,new Object[]{person,"id","key"});
    SchemaObject male=s.createSchemaObject(ent,new Object[] {"male"});
    SchemaObject female=s.createSchemaObject(ent,new Object[] {"female"});
    s.createSchemaObject(gen,new Object[]{"sex","total",person,male,female});
    SchemaObject dept=s.createSchemaObject(ent,new Object[] {"dept"});
    s.createSchemaObject(att,new Object[]{dept,"dname","key"});
    s.createSchemaObject(rel,new Object[]{"worksin",person,dept,"1:1","1:N"});
    SchemaObject degree=s.createSchemaObject(ent,new Object[]{"degree"});
    s.createSchemaObject(att,new Object[]{degree,"code","key"});
    s.createSchemaObject(att,new Object[]{degree,"title","notnull"});
    s.createSchemaObject(rel,new Object[]{"runby",degree,dept,"1:1","1:N"});
    System.out.println("Created schema "+name+" succesfully");

    return s;
  }

  public static Schema createERS6(String name) 
    throws NotFoundException,TypeMismatchException,IntegrityException {
    Schema s=Schema.createSchema(name,true);
    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");

    // Now build the schema
    SchemaObject person=s.createSchemaObject(ent,new Object[]{"person"});
    s.createSchemaObject(att,new Object[]{person,"id","key"});
    SchemaObject male=s.createSchemaObject(ent,new Object[] {"male"});
    SchemaObject female=s.createSchemaObject(ent,new Object[] {"female"});
    s.createSchemaObject(gen,new Object[]{"sex","total",person,male,female});
    SchemaObject dept=s.createSchemaObject(ent,new Object[] {"dept"});
    s.createSchemaObject(att,new Object[]{dept,"dname","key"});
    s.createSchemaObject(rel,new Object[]{"worksin",person,dept,"1:1","1:N"});
    SchemaObject degree=s.createSchemaObject(ent,new Object[]{"degree"});
    s.createSchemaObject(att,new Object[]{degree,"code","key"});
    s.createSchemaObject(att,new Object[]{degree,"title","notnull"});
    s.createSchemaObject(rel,new Object[]{"runby",degree,dept,"1:1","1:N"});
    SchemaObject course=s.createSchemaObject(ent,new Object[]{"course"});
    s.createSchemaObject(att,new Object[]{course,"code","key"});
    s.createSchemaObject(att,new Object[]{course,"title","notnull"});
    s.createSchemaObject(rel,new Object[]{"sits",person,course,"0:N","0:N"});
    SchemaObject lecturer=s.createSchemaObject(ent,new Object[]{"lecturer"});
    s.createSchemaObject(att,new Object[]{lecturer,"staff_no","key"});
    s.createSchemaObject(att,new Object[]{lecturer,"name","notnull"});
    s.createSchemaObject(att,new Object[]{lecturer,"office","null"});
    s.createSchemaObject(rel,new Object[]{"teaches",
					    lecturer,course,"0:N","0:1"});

    System.out.println("Created schema "+name+" succesfully");

    return s;
  }

  public static Schema createEERS6(String name) 
    throws NotFoundException,TypeMismatchException,IntegrityException {
    Schema s=Schema.createSchema(name,true);
    Model eer=Model.getModel("eer");
    Construct ent=eer.getConstruct("entity");
    Construct att=eer.getConstruct("attribute");
    Construct rel=eer.getConstruct("relationship");
    Construct gen=eer.getConstruct("generalisation");

    // Now build the schema
    SchemaObject person=s.createSchemaObject(ent,new Object[]{"person"});
    s.createSchemaObject(att,new Object[]{person,"id","key"});
    SchemaObject male=s.createSchemaObject(ent,new Object[] {"male"});
    SchemaObject female=s.createSchemaObject(ent,new Object[] {"female"});
    s.createSchemaObject(gen,new Object[]{"sex","total",person,male,female});
    SchemaObject dept=s.createSchemaObject(ent,new Object[] {"dept"});
    s.createSchemaObject(att,new Object[]{dept,"dname","key"});
    //s.createSchemaObject(rel,
    //		 new Object[]{"worksin",
    //			      new Object[]{person,"1:1"},
    //			      new Object[]{dept,"1:N"}});
    Construct relend=eer.getConstruct("relationship_target");
    SchemaObject pend=s.createSchemaObject(relend,new Object[]{person,"1:1"});
    SchemaObject dend=s.createSchemaObject(relend,new Object[]{dept,"1:N"});
    //s.createSchemaObject(rel,new Object[]{"worksin",pend,dend});
    s.createSchemaObject(rel,new Object[]{"worksin",person,"1:1",dept,"1:N"});
    SchemaObject degree=s.createSchemaObject(ent,new Object[]{"degree"});
    s.createSchemaObject(att,new Object[]{degree,"code","key"});
    s.createSchemaObject(att,new Object[]{degree,"title","notnull"});
    s.createSchemaObject(rel,new Object[]{"runby",degree,"1:1",dept,"1:N"});
    SchemaObject course=s.createSchemaObject(ent,new Object[]{"course"});
    s.createSchemaObject(att,new Object[]{course,"code","key"});
    s.createSchemaObject(att,new Object[]{course,"title","notnull"});
    SchemaObject sits=
      s.createSchemaObject(rel,new Object[]{"sits",person,"0:N",course,"0:N"});
    s.createSchemaObject(att,new Object[]{sits,"year","notnull"});
    s.createSchemaObject(att,new Object[]{sits,"result","null"});
    SchemaObject lecturer=s.createSchemaObject(ent,new Object[]{"lecturer"});
    s.createSchemaObject(att,new Object[]{lecturer,"staff_no","key"});
    s.createSchemaObject(att,new Object[]{lecturer,"name","notnull"});
    s.createSchemaObject(att,new Object[]{lecturer,"office","null"});
    s.createSchemaObject(rel,new Object[]{"teaches",
					    lecturer,"0:N",course,"0:1"});

    System.out.println("Created schema "+name+" succesfully");

    return s;
  }

  public static Schema createHDMS1(String schemaName) 
    throws NotFoundException,TypeMismatchException,IntegrityException {
    Schema s=Schema.createSchema(schemaName,true);
    Model hdm=Model.getModel("hdm");

    Construct node=hdm.getConstruct("node");
    Construct edge=hdm.getConstruct("edge");
    Construct cons=hdm.getConstruct("constraint");

    // Now build the schema
    SchemaObject person=s.createSchemaObject(node,new Object[]{"person"});
    SchemaObject name=s.createSchemaObject(node,new Object[]{"name"});
    SchemaObject sex=s.createSchemaObject(node,new Object[]{"sex"});
    s.createSchemaObject(edge,new Object[]{"",person,name});
    s.createSchemaObject(edge,new Object[]{"",person,sex});
    SchemaObject dept=s.createSchemaObject(node,new Object[] {"dept"});
    s.createSchemaObject(edge,new Object[]{"worksin",person,dept});
    s.createSchemaObject(cons,new Object[]{"makeCard(<<worksin,person,dept>>,"+
					     "1:1,0:N)"});
    System.out.println("Created schema "+schemaName+" succesfully");

    return s;
  }

  public static Schema createHDMS2(String schemaName) 
    throws NotFoundException,TypeMismatchException,IntegrityException {
    Schema s=Schema.createSchema(schemaName,true);
    Model hdm=Model.getModel("hdm");

    Construct node=hdm.getConstruct("node");
    Construct edge=hdm.getConstruct("edge");
    Construct cons=hdm.getConstruct("constraint");

    // Now build the schema
    SchemaObject person=s.createSchemaObject(node,new Object[]{"person"});
    SchemaObject name=s.createSchemaObject(node,new Object[]{"name"});
    SchemaObject male=s.createSchemaObject(node,new Object[]{"male"});
    SchemaObject female=s.createSchemaObject(node,new Object[]{"female"});
    s.createSchemaObject(edge,new Object[]{"",person,name});
    SchemaObject dept=s.createSchemaObject(node,new Object[] {"dept"});
    s.createSchemaObject(edge,new Object[]{"worksin",person,dept});
    s.createSchemaObject(cons,new Object[]{"makeCard(<<worksin,person,dept>>,"+
					     "1:1,0:N)"});
    s.createSchemaObject(cons,new Object[]{"subset(<<male>>,<<person>>)"});
    s.createSchemaObject(cons,new Object[]{"subset(<<female>>,<<person>>)"});
    System.out.println("Created schema "+schemaName+" succesfully");

    return s;
  }

  public static Schema createRelationalS1(String name) 
    throws NotFoundException,TypeMismatchException,IntegrityException {
    Schema s=Schema.createSchema(name,true);
    Model rel=Model.getModel("rel");

    Construct table=rel.getConstruct("table");
    Construct field=rel.getConstruct("field");
    Construct pk=rel.getConstruct("primary_key");

    // Now build the schema
    SchemaObject person=s.createSchemaObject(table,new Object[]{"person"});
    SchemaObject id=s.createSchemaObject(field,new Object[]{person,"id","1"});
    s.createSchemaObject(field,new Object[]{person,"name","2"});
    s.createSchemaObject(field,new Object[]{person,"sex","3"});
    s.createSchemaObject(pk,new Object[]{"person_pk",person,id});
    SchemaObject dept=s.createSchemaObject(table,new Object[] {"dept"});
    SchemaObject dname=
      s.createSchemaObject(field,new Object[]{dept,"dname","1"});
    s.createSchemaObject(pk,new Object[]{"dept_pk",dept,dname});
    System.out.println("Created schema "+name+" succesfully");

    return s;
  }

  public static Schema createRelationalS2(String name) 
    throws NotFoundException,TypeMismatchException,IntegrityException {
    Schema s=Schema.createSchema(name,true);
    Model rel=Model.getModel("rel");

    Construct table=rel.getConstruct("table");
    Construct field=rel.getConstruct("field");
    Construct pk=rel.getConstruct("primary_key");
    Construct fk=rel.getConstruct("foreign_key");

    // Now build the schema
    SchemaObject person=s.createSchemaObject(table,new Object[]{"person"});
    SchemaObject id=s.createSchemaObject(field,new Object[]{person,"id","1"});
    s.createSchemaObject(field,new Object[]{person,"name","2"});
    s.createSchemaObject(field,new Object[]{person,"dname","3"});
    s.createSchemaObject(pk,new Object[]{"person_pk",person,id});
    SchemaObject male=s.createSchemaObject(table,new Object[]{"male"});
    SchemaObject mid=s.createSchemaObject(field,new Object[]{male,"id","1"});
    s.createSchemaObject(pk,new Object[]{"male_pk",male,mid});
    s.createSchemaObject(fk,new Object[]{"male_fk",male,mid,person,id});
    SchemaObject female=s.createSchemaObject(table,new Object[]{"female"});
    SchemaObject fid=s.createSchemaObject(field,new Object[]{female,"id","1"});
    s.createSchemaObject(pk,new Object[]{"female_pk",female,fid});
    s.createSchemaObject(fk,new Object[]{"female_fk",female,fid,person,id});
    System.out.println("Created schema "+name+" succesfully");

    return s;
  }


  public static void main(String[] args) {
    try {
      System.out.println("AutoMed Repository: Creating Schemas Demo");

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

      Schema.retract("eer_s6");
      Schema es6=createEERS6("eer_s6");
      es6.listSchema();

      Schema.retract("er_s1");
      Schema s1=createERS1("er_s1");
      s1.listSchema();

      Schema.retract("er_s2");
      Schema s2=createERS2("er_s2");
      s2.listSchema();

      Schema.retract("er_s3");
      Schema s3=createERS3("er_s3");
      s3.listSchema();

      Schema.retract("er_s6");
      Schema s6=createERS6("er_s6");
      s6.listSchema();

      Schema.retract("rel_s1");
      Schema rels1=createRelationalS1("rel_s1");
      rels1.listSchema();

      Schema.retract("hdm_s1");
      Schema hdms1=createHDMS1("hdm_s1");
      hdms1.listSchema();

      Schema.retract("hdm_s2");
      Schema hdms2=createHDMS2("hdm_s2");
      hdms2.listSchema();

    }
    catch (AutoMedException ame) {
      ame.printStackTrace();
    }
  }
}

