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.XMLConstants;
import uk.ac.bbk.dcs.automed.xml.utilities.PrintUtility;
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/examples/bank1.xml";
            String URI2 = "http://www.dcs.bbk.ac.uk/~lucas/automed/examples/bank2.xml";
            String URI3 = "http://www.dcs.bbk.ac.uk/~lucas/automed/examples/bank3.xml";

            DOMWrapperFactory xwf = new DOMWrapperFactory();

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

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

            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();
            PrintUtility.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();
            PrintUtility.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();
            PrintUtility.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();
            PrintUtility.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();
        }
    }
}