package semistructured.xml;

import uk.ac.bbk.dcs.automed.qproc.ASG;
import uk.ac.bbk.dcs.automed.qproc.Evaluator;
import uk.ac.bbk.dcs.automed.qproc.FragmentProcessor;
import uk.ac.bbk.dcs.automed.qproc.FunctionTable;
import uk.ac.bbk.dcs.automed.qproc.QueryReformulator;
import uk.ac.bbk.dcs.automed.qproc.StandardFunctionTable;
import uk.ac.bbk.dcs.automed.xml.NodeUtility;
import uk.ac.bbk.dcs.automed.xml.XMLConstants;
import uk.ac.bbk.dcs.automed.xml.wrappers.DOMWrapper;
import uk.ac.bbk.dcs.automed.xml.wrappers.DOMWrapperFactory;
import uk.ac.ic.doc.automed.NotFoundException;
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 XMLBankIntegrationQueries {
	private static char s = '$';

	public static void main(String[] args) {
		boolean verbose = true;

		try {
			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";

			DOMWrapperFactory xwf = new DOMWrapperFactory();

			String schemeIQL[] = { "<<bank1" + s + "account" + s + "1>>" };
			String simpleIQL[] =
				{
					"[{x} | {x}<-<<bank1" + s + "site" + s + "1>>]",
					"[{x} | {x}<-<<bank1" + s + "sitecode" + s + "1>>]",
					"[{x} | {x}<-<<bank1" + s + "cname" + s + "1>>]",
					"[{x} | {x}<-<<bank1" + s + "customer" + s + "1>>]",
					"[{x} | {x}<-<<bank1" + s + "account" + s + "1>>]",
					"[{x} | {x}<-<<bank1" + s + "number" + s + "1>>]" };
			String edgeIQL[] = {
				//parent-child in GS is ancestor-descendant in source 					
				"[{x,y} | {x,y}<-<<bank1" + s + "root" + s + "1,bank1" + s + "customer" + s + "1>>]",
				//parent-child in GS is element-attribute in source
				"[{x,y} | {x,y}<-<<bank1" + s + "account" + s + "1,bank1" + s + "number" + s + "1>>]",
				//parent-child in GS is child-parent in source
				"[{x,y} | {x,y}<-<<bank1" + s + "customer" + s + "1,bank1" + s + "account" + s + "1>>]",
				//element-pcdata in GS is element-attribute in source
				"[{x,y} | {x,y}<-<<bank1" + s + "number" + s + "1," + XMLConstants.pcdata + ">>]", };

			String complexIQL[] =
				{
					//ancestor-descendant in GS is sibling elements in source:
					"[{acc,fun}|{acc,site}<-<<bank1"
						+ s
						+ "account"
						+ s
						+ "1,bank1"
						+ s
						+ "site"
						+ s
						+ "1>>; {site,fun}<-<<bank1"
						+ s
						+ "site"
						+ s
						+ "1,bank1"
						+ s
						+ "function"
						+ s
						+ "1>>]",
					//Get all customer names
					"[{nameData} | {cust,name}<-<<bank1"
						+ s
						+ "customer"
						+ s
						+ "1,bank1"
						+ s
						+ "cname"
						+ s
						+ "1>>; "
						+ "{name,nameData}<-<<bank1"
						+ s
						+ "cname"
						+ s
						+ "1,"
						+ XMLConstants.pcdata
						+ ">>]",
					//Get all distinct customer names
					"distinct [{nameData} | {cust,name}<-<<bank1"
						+ s
						+ "customer"
						+ s
						+ "1,bank1"
						+ s
						+ "cname"
						+ s
						+ "1>>; "
						+ "{name,nameData}<-<<bank1"
						+ s
						+ "cname"
						+ s
						+ "1,"
						+ XMLConstants.pcdata
						+ ">>]",
						//Get all account numbers
					"[{numData} | {cust,acc}<-<<bank1"
						+ s
						+ "customer"
						+ s
						+ "1,bank1"
						+ s
						+ "account"
						+ s
						+ "1>>; "
						+ "{acc,accNum}<-<<bank1"
						+ s
						+ "account"
						+ s
						+ "1,bank1"
						+ s
						+ "number"
						+ s
						+ "1>>; "
						+ "{accNum,numData}<-<<bank1"
						+ s
						+ "number"
						+ s
						+ "1,"
						+ XMLConstants.pcdata
						+ ">>]",
						//Get all distinct account numbers
					"distinct [{numData} | {cust,acc}<-<<bank1"
						+ s
						+ "customer"
						+ s
						+ "1,bank1"
						+ s
						+ "account"
						+ s
						+ "1>>; "
						+ "{acc,accNum}<-<<bank1"
						+ s
						+ "account"
						+ s
						+ "1,bank1"
						+ s
						+ "number"
						+ s
						+ "1>>; "
						+ "{accNum,numData}<-<<bank1"
						+ s
						+ "number"
						+ s
						+ "1,"
						+ XMLConstants.pcdata
						+ ">>]",
					//Get the names of customers with their account numbers
					"[{nameData,numData} | {cust,name}<-<<bank1"
						+ s
						+ "customer"
						+ s
						+ "1,bank1"
						+ s
						+ "cname"
						+ s
						+ "1>>; "
						+ "{name,nameData}<-<<bank1"
						+ s
						+ "cname"
						+ s
						+ "1,"
						+ XMLConstants.pcdata
						+ ">>;"
						+ "{cust,acc}<-<<bank1"
						+ s
						+ "customer"
						+ s
						+ "1,bank1"
						+ s
						+ "account"
						+ s
						+ "1>>; "
						+ "{acc,accNum}<-<<bank1"
						+ s
						+ "account"
						+ s
						+ "1,bank1"
						+ s
						+ "number"
						+ s
						+ "1>>; "
						+ "{accNum,numData}<-<<bank1"
						+ s
						+ "number"
						+ s
						+ "1,"
						+ XMLConstants.pcdata
						+ ">>]" };

			System.out.print("Initializing wrappers...");
			DOMWrapper xwTarget = (DOMWrapper)DOMWrapper.getAutoMedWrapper(Schema.getSchema("bank1").getAccessMethods()[0]);
			DOMWrapper xwSource1 = (DOMWrapper)DOMWrapper.getAutoMedWrapper(Schema.getSchema("bank2").getAccessMethods()[0]);
			DOMWrapper xwSource2 = (DOMWrapper)DOMWrapper.getAutoMedWrapper(Schema.getSchema("bank3").getAccessMethods()[0]);
			System.out.println("done.");

			Schema globalSchema = xwTarget.getSchema();
			Schema sourceSchema1 = xwSource1.getSchema();
			Schema sourceSchema2 = xwSource2.getSchema();

			System.out.print("Initializing query engine...");
			Schema src = Schema.getSchema(globalSchema.getName());
			Schema[] tgts = new Schema[3];
			tgts[0] = Schema.getSchema(sourceSchema1.getName());
			tgts[1] = Schema.getSchema(sourceSchema2.getName());
			tgts[2] = Schema.getSchema(globalSchema.getName());
			QueryReformulator qr = new QueryReformulator(src, tgts);
			FragmentProcessor fp = new FragmentProcessor();
			FunctionTable ft = new StandardFunctionTable();
			Evaluator e = new Evaluator(ft);
			System.out.println("done.");

			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);
					if (verbose)
						System.out.println("Query after query reformulator: " + q);
					fp.process(q);
					if (verbose)
						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);
					if (verbose)
						System.out.println("Query after query reformulator: " + q);
					fp.process(q);
					if (verbose)
						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);
					if (verbose)
						System.out.println("Query after query reformulator: " + q);
					fp.process(q);
					if (verbose)
						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);
					if (verbose)
						System.out.println("Query after query reformulator: " + q);
					fp.process(q);
					if (verbose)
						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();
		}
	}
}
