package semistructured.xml;

import org.w3c.dom.Document;

import uk.ac.bbk.dcs.automed.xml.NodeUtility;
import uk.ac.bbk.dcs.automed.xml.XMLConstants;
import uk.ac.bbk.dcs.automed.xml.XMLTransformer;
import uk.ac.bbk.dcs.automed.xml.wrappers.DOMWrapper;
import uk.ac.bbk.dcs.automed.xml.wrappers.DOMWrapperFactory;
import uk.ac.ic.doc.automed.reps.Schema;

/**
 * Class Task Description
 * 
 * @author <a href="mailto:lucas@dcs.bbk.ac.uk">Lucas Zamboulis</a>
 */
public class XMLBankIntegration {

	private static void printSource(String label, Document doc, Document schemaUIDDoc, Schema schema) {
		System.out.println();
		NodeUtility.prettyPrint(doc, label + " XML file:");
		System.out.println();

		System.out.println();
		NodeUtility.prettyPrint(schemaUIDDoc, label + " XML DataSource Schema file:");
		System.out.println();

		NodeUtility.title(label + " XML DataSource Schema");
		schema.listSchema();
		NodeUtility.banner();
		System.out.println();
	}

	private static void deleteOldSchema(String schemaName) {
		try {
			System.out.print("Deleting old schema named " + schemaName + "...");
			Schema sourceSchema = Schema.getSchema(schemaName);
			sourceSchema.removeAccessMethods();
			sourceSchema.retract();
			System.out.println("done.");
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		Schema sourceSchema1 = null, sourceSchema2 = null, targetSchema = null;
		Document source1Doc = null, source2Doc = null, targetDoc = null;
		Document source1SchemaUIDDoc = null, source2SchemaUIDDoc = null, targetSchemaUIDDoc = null;

		String URI1 = "http://www.dcs.bbk.ac.uk/~lucas/automed/bank1.xml";
		String URI2 = "http://www.dcs.bbk.ac.uk/~lucas/automed/bank2.xml";
		String URI3 = "http://www.dcs.bbk.ac.uk/~lucas/automed/bank3.xml";
		String targetSchemaName = "bank1";
		String source1SchemaName = "bank2";
		String source2SchemaName = "bank3";

		//Extract XML DataSource Schema and create target (global) schema
		try {
			if (Schema.exists(targetSchemaName))
				deleteOldSchema(targetSchemaName);

			DOMWrapperFactory xwfTarget = new DOMWrapperFactory();
			DOMWrapper xwTarget =
				(DOMWrapper)DOMWrapper.selectNewAutoMedWrapper("", "", null, XMLConstants.domDriver, URI1, targetSchemaName, xwfTarget);
			targetDoc = xwTarget.getDoc();
			targetSchemaUIDDoc = xwTarget.getSchemaUIDDoc();
			targetSchema = xwTarget.getSchema();
		}
		catch (Exception e) {
			e.printStackTrace();
		}

		//Extract XML DataSource Schema and create the first source schema
		try {
			if (Schema.exists(source1SchemaName))
				deleteOldSchema(source1SchemaName);
			if (Schema.exists(source2SchemaName))
				deleteOldSchema(source2SchemaName);

			DOMWrapperFactory xwfSource = new DOMWrapperFactory();

			DOMWrapper xwSource1 =
				(DOMWrapper)DOMWrapper.selectNewAutoMedWrapper("", "", null, XMLConstants.domDriver, URI2, source1SchemaName, xwfSource);
			source1Doc = xwSource1.getDoc();
			source1SchemaUIDDoc = xwSource1.getSchemaUIDDoc();
			sourceSchema1 = xwSource1.getSchema();

			DOMWrapper xwSource2 =
				(DOMWrapper)DOMWrapper.selectNewAutoMedWrapper("", "", null, XMLConstants.domDriver, URI3, source2SchemaName, xwfSource);
			source2Doc = xwSource2.getDoc();
			source2SchemaUIDDoc = xwSource2.getSchemaUIDDoc();
			sourceSchema2 = xwSource2.getSchema();
		}
		catch (Exception e) {
			e.printStackTrace();
		}

		//Print input XML files, XML Datasource Schema files, and AutoMed schemas
		printSource(source1SchemaName, source1Doc, source1SchemaUIDDoc, sourceSchema1);
		printSource(source2SchemaName, source2Doc, source2SchemaUIDDoc, sourceSchema2);
		printSource(targetSchemaName, targetDoc, targetSchemaUIDDoc, targetSchema);

		//Transformation

		XMLTransformer t1 = new XMLTransformer(sourceSchema1, source1SchemaUIDDoc, targetSchema, targetSchemaUIDDoc, true);
		t1.transform(false, false);
		Schema source1MadeAsTarget = t1.getFinalSchema();

		System.out.println();
		NodeUtility.title("Source1 schema made as target:");
		source1MadeAsTarget.listSchema();
		NodeUtility.banner();

		XMLTransformer t2 = new XMLTransformer(sourceSchema2, source2SchemaUIDDoc, targetSchema, targetSchemaUIDDoc, true);
		t2.transform(false, false);
		Schema source2MadeAsTarget = t2.getFinalSchema();

		System.out.println();
		NodeUtility.title("Source2 schema made as target:");
		source2MadeAsTarget.listSchema();
		NodeUtility.banner();

		/////////////////////////////////
		//LIST THE TRANSFORMATION PATHWAY
		t1.listTransformationPathway();
		t2.listTransformationPathway();
		

		////////////////////////////////////
		//TEST WITH QUERY PROCESSOR
		String schemeIQL[] = { "<<AutoMedXMLPCData>>", "<<AutoMedXMLOrder>>", "<<university3:member:1>>" };
		String simpleIQL[] =
			{
				"distinct [{x} | {x}<-<<AutoMedXMLOrder>>]",
				"distinct [{x} | {x}<-<<AutoMedXMLPCData>>]",
				"distinct [{x} | {x}<-<<university3:AutoMed:1>>]",
				"distinct [{x} | {x}<-<<university3:member:1>>]",
				"distinct [{x} | {x}<-<<university3:firstName:1>>]",
				"distinct [{x} | {x}<-<<university3:lastName:1>>]",
				"distinct [{x} | {x}<-<<university3:sex:1>>]",
				"distinct [{x} | {x}<-<<university3:college:1>>]" };
		String edgeIQL[] =
			{
				"distinct [{x} | {x}<-<<university3:AutoMed:1,university3:members:1>>]",
				"distinct [{x} | {x}<-<<university3:member:1,university3:firstName:1>>]",
				"distinct [{x} | {x}<-<<university3:sex:1,AutoMedXMLPCData>>]" };
		String funcIQL[] = { "count [{x} | {x} <- distinct <<university3:members:1,university3:member:1>>]" };
		String complexIQL[] =
			{
				"[{d} | {a,b}<-<<university3:member:1,university3:lastName:1>>; "
					+ "{c,d}<-<<university3:lastName:1,AutoMedXMLPCData>>;"
					+ " (=) b c]",
				"distinct [{d} | {a,b}<-<<university3:member:1,university3:lastName:1>>; "
					+ "{c,d}<-<<university3:lastName:1,AutoMedXMLPCData>>;"
					+ " (=) b c]",
				"[{d} | {a,b}<- distinct <<university3:member:1,university3:lastName:1>>; "
					+ "{c,d}<- distinct <<university3:lastName:1,AutoMedXMLPCData>>;"
					+ " (=) b c]" };
		String problemIQL[] =
			{
				"[{d,h} | {a,b}<-<<university3:member:1,university3:firstName:1>>; "
					+ "{c,d}<-<<university3:firstName:1,AutoMedXMLPCData>>;"
					+ "{e,f}<-<<university3:member:1,university3:lastName:1>>;"
					+ "{g,h}<-<<university3:lastName:1,AutoMedXMLPCData>>;"
					+ " (=) b c; (=) f g; (=) a e]" };

		//		try {
		//			Schema src = Schema.getSchema(source2MadeAsTarget.getName());
		//			Schema[] tgts = new Schema[2];
		//			tgts[0] = Schema.getSchema(sourceSchema1.getName());
		//			tgts[1] = Schema.getSchema(sourceSchema2.getName());
		//			QueryReformulator qr = new QueryReformulator(src, tgts);
		//			FragmentProcessor fp = new FragmentProcessor();
		//			FunctionTable ft = new StandardFunctionTable();
		//			Evaluator e = new Evaluator(ft);
		//
		//			ASG q;
		//			System.out.println();
		//			NodeUtility.title("IQL Scheme Queries");
		//			for (int z = 0; z < schemeIQL.length; z++) {
		//				try {
		//					q = new ASG(schemeIQL[z]);
		//					System.out.println("\nOriginal query: " + q);
		//					qr.reformulate(q);
		//					System.out.println("Query after query reformulator: " + q);
		//					fp.process(q);
		//					System.out.println("Query after fragment processor: " + q);
		//					e.evaluate(q);
		//					System.out.println("Query after evaluator: " + q);
		//				}
		//				catch (NotFoundException e1) {
		//					e1.printStackTrace();
		//				}
		//			}
		//
		//			System.out.println();
		//			NodeUtility.title("Simple IQL Queries");
		//			for (int z = 0; z < simpleIQL.length; z++) {
		//				try {
		//					q = new ASG(simpleIQL[z]);
		//					System.out.println("\nOriginal query: " + q);
		//					qr.reformulate(q);
		//					System.out.println("Query after query reformulator: " + q);
		//					fp.process(q);
		//					System.out.println("Query after fragment processor: " + q);
		//					e.evaluate(q);
		//					System.out.println("Query after evaluator: " + q);
		//				}
		//				catch (NotFoundException e1) {
		//					e1.printStackTrace();
		//				}
		//			}
		//
		//			System.out.println();
		//			NodeUtility.title("IQL Edge Queries");
		//			for (int z = 0; z < edgeIQL.length; z++) {
		//				try {
		//					q = new ASG(edgeIQL[z]);
		//					System.out.println("\nOriginal query: " + q);
		//					qr.reformulate(q);
		//					System.out.println("Query after query reformulator: " + q);
		//					fp.process(q);
		//					System.out.println("Query after fragment processor: " + q);
		//					e.evaluate(q);
		//					System.out.println("Query after evaluator: " + q);
		//				}
		//				catch (NotFoundException e1) {
		//					e1.printStackTrace();
		//				}
		//			}
		//
		//			System.out.println();
		//			NodeUtility.title("IQL Function Queries");
		//			for (int z = 0; z < funcIQL.length; z++) {
		//				try {
		//					q = new ASG(funcIQL[z]);
		//					System.out.println("\nOriginal query: " + q);
		//					qr.reformulate(q);
		//					System.out.println("Query after query reformulator: " + q);
		//					fp.process(q);
		//					System.out.println("Query after fragment processor: " + q);
		//					e.evaluate(q);
		//					System.out.println("Query after evaluator: " + q);
		//				}
		//				catch (NotFoundException e1) {
		//					e1.printStackTrace();
		//				}
		//			}
		//
		//			System.out.println();
		//			NodeUtility.title("Complex IQL Queries");
		//			for (int z = 0; z < complexIQL.length; z++) {
		//				try {
		//					q = new ASG(complexIQL[z]);
		//					System.out.println("\nOriginal query: " + q);
		//					qr.reformulate(q);
		//					System.out.println("Query after query reformulator: " + q);
		//					fp.process(q);
		//					System.out.println("Query after fragment processor: " + q);
		//					e.evaluate(q);
		//					System.out.println("Query after evaluator: " + q);
		//				}
		//				catch (NotFoundException e1) {
		//					e1.printStackTrace();
		//				}
		//			}
		//
		//			System.out.println();
		//			NodeUtility.title("Problematic IQL Queries");
		//			for (int z = 0; z < problemIQL.length; z++) {
		//				try {
		//					q = new ASG(problemIQL[z]);
		//					System.out.println("\nOriginal query: " + q);
		//					qr.reformulate(q);
		//					System.out.println("Query after query reformulator: " + q);
		//					fp.process(q);
		//					System.out.println("Query after fragment processor: " + q);
		//					e.evaluate(q);
		//					System.out.println("Query after evaluator: " + q);
		//				}
		//				catch (NotFoundException e1) {
		//					e1.printStackTrace();
		//				}
		//			}
		//		}
		//		catch (Exception e) {
		//			e.printStackTrace();
		//		}
	}
}
