/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package compile.scomp.detailed;

import compile.scomp.common.CompileTestBase;
import compile.scomp.common.mockobj.TestBindingConfig;
import compile.scomp.common.mockobj.TestFiler;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.xb.xmlconfig.ConfigDocument;
import org.junit.After;
import org.junit.Test;

import javax.xml.namespace.QName;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import static org.junit.Assert.assertTrue;


/**
 * Ensure that several compilation mechanisms all generate
 * the same schematypesystem
 */
public class XmlBeanCompilationTests extends CompileTestBase {
    private final List<XmlError> xm_errors = new ArrayList<>();
    private final XmlOptions xm_opts = new XmlOptions();

    public XmlBeanCompilationTests() {
        xm_opts.setErrorListener(xm_errors);
        xm_opts.setSavePrettyPrint();
    }

    @After
    public void tearDown() throws Exception {
        if (xm_errors.size() > 0) {
            xm_errors.clear();
        }
    }

    /**
     * Filer != null for BindingConfig to be used
     */
    @Test
    public void test_bindingconfig_extension_compilation() throws Exception {
        TestFiler f = new TestFiler();
        //initialize all of the values
        String extCaseDir = XBEAN_CASE_ROOT + P + "extensions" + P;
        String extSrcDir = getRootFile() + P +
                           "src" + P + "test" + P + "java" + P + "xmlobject" + P + "extensions" + P;
        File[] cPath = CompileTestBase.getClassPath();
        String dir = extCaseDir + P + "interfaceFeature" + P + "averageCase";
        String dir2 = extCaseDir + P + "prePostFeature" + P +
                      "ValueRestriction";

        ConfigDocument.Config bConf = ConfigDocument.Factory.parse(
            new File(dir + P + "po.xsdconfig"))
            .getConfig();
        ConfigDocument.Config cConf = ConfigDocument.Factory.parse(
            new File(dir2 + P + "company.xsdconfig"))
            .getConfig();

        String simpleConfig = "<xb:config " +
                              "xmlns:xb=\"http://xml.apache.org/xmlbeans/2004/02/xbean/config\"\n" +
                              " xmlns:ep=\"http://xbean.interface_feature/averageCase/PurchaseOrder\">\n" +
                              "<xb:namespace uri=\"http://xbean.interface_feature/averageCase/PurchaseOrder\">\n" +
                              "<xb:package>com.easypo</xb:package>\n" +
                              "</xb:namespace></xb:config>";
        ConfigDocument.Config confDoc = ConfigDocument.Factory.parse(simpleConfig).getConfig();
        ConfigDocument.Config[] confs = new ConfigDocument.Config[]{bConf, confDoc, cConf};

        String fooHandlerPath = extSrcDir + P + "interfaceFeature" + P +
                                "averageCase" + P + "existing" + P + "FooHandler.java";
        String iFooPath = extSrcDir + P + "interfaceFeature" + P +
                          "averageCase" + P + "existing" + P + "IFoo.java";
        String iSetterPath = extSrcDir + P + "prePostFeature" + P +
                             "ValueRestriction" + P + "existing" + P + "ISetter.java";
        String setterHandlerPath = extSrcDir + P + "prePostFeature" + P +
                                   "ValueRestriction" + P + "existing" + P + "SetterHandler.java";


        File[] fList = new File[]{new File(fooHandlerPath), new File(iFooPath),
            new File(iSetterPath),
            new File(setterHandlerPath)};

        //use created BindingConfig
        TestBindingConfig bind = new TestBindingConfig(confs, fList, cPath);

        //set XSDs
        XmlObject obj1 = XmlObject.Factory.parse(new File(dir + P + "po.xsd"));
        XmlObject obj2 = XmlObject.Factory.parse(
            new File(dir2 + P + "company.xsd"));
        XmlObject[] schemas = new XmlObject[]{obj1, obj2};

        //filer must be present on this method
        SchemaTypeSystem apiSts = XmlBeans.compileXmlBeans("apiCompile", null,
            schemas, bind, XmlBeans.getBuiltinTypeSystem(), f, xm_opts);

        if (!bind.isIslookupPrefixForNamespace()) {
            throw new Exception("isIslookupPrefixForNamespace not invoked");
        }
        if (!bind.isIslookupPackageForNamespace()) {
            throw new Exception("isIslookupPackageForNamespace not invoked");
        }
        if (!bind.isIslookupSuffixForNamespace()) {
            throw new Exception("isIslookupSuffixForNamespace not invoked");
        }
        if (!bind.isIslookupJavanameForQName()) {
            throw new Exception("isIslookupJavanameForQName not invoked");
        }
        if (!bind.isIsgetInterfaceExtensionsString()) {
            throw new Exception("isIsgetInterfaceExtensionsString not invoked");
        }
        if (!bind.isIsgetInterfaceExtensions()) {
            throw new Exception("isIsgetInterfaceExtensions not invoked");
        }
        if (!bind.isIsgetPrePostExtensions()) {
            throw new Exception("isIsgetPrePostExtensions not invoked");
        }
        if (!bind.isIsgetPrePostExtensionsString()) {
            throw new Exception("isIsgetPrePostExtensionsString not invoked");
        }
    }

    /**
     * Verify basic incremental compilation
     * and compilation with partial SOM usages
     */
    @Test
    public void test_incrCompile() throws Exception {
        XmlObject obj1 = XmlObject.Factory.parse(forXsd);
        obj1.documentProperties().setSourceName("OBJ1");
        XmlObject[] schemas = new XmlObject[]{obj1};
        QName sts1 = new QName("http://baz", "elName");

        XmlObject obj2 = XmlObject.Factory.parse(incrXsd);
        obj2.documentProperties().setSourceName("OBJ2");
        XmlObject[] schemas2 = new XmlObject[]{obj2};
        QName sts2 = new QName("http://bar", "elName");

        XmlObject obj3 = XmlObject.Factory.parse(errXsd);
        obj3.documentProperties().setSourceName("OBJ3");
        XmlObject[] schemas3 = new XmlObject[]{obj3};
        QName sts3 = new QName("http://bar", "elErrName");

        SchemaTypeSystem sts;
        ArrayList err = new ArrayList();
        XmlOptions opt = new XmlOptions().setErrorListener(err);
        opt.setCompilePartialTypesystem();

        //BASIC COMPILATION
        sts = XmlBeans.compileXmlBeans(null,
            null, schemas, null,
            XmlBeans.getBuiltinTypeSystem(), null, opt);

        assertTrue("Errors should have been empty", err.isEmpty());
        // find element in the type System
        if (!findGlobalElement(sts.globalElements(), sts1)) {
            throw new Exception(
                "Could Not find Type from first Type System: " + sts1);
        }

        //SIMPLE INCR COMPILATION
        sts = XmlBeans.compileXmlBeans(null,
            sts, schemas2, null,
            XmlBeans.getBuiltinTypeSystem(), null, opt);
        assertTrue("Errors should have been empty", err.isEmpty());
        // find element in the type System

        if (!findGlobalElement(sts.globalElements(), sts1)) {
            throw new Exception("Could Not find Type from first Type System: " +
                                sts1);
        }

        if (!findGlobalElement(sts.globalElements(), sts2)) {
            throw new Exception("Could Not find Type from 2nd Type System: " +
                                sts2);
        }

        System.out.println("Building over Existing");
        //BUILDING OFF BASE SIMPLE INCR COMPILATION
        sts = XmlBeans.compileXmlBeans(null,
            sts, schemas2, null,
            sts, null, opt);
        assertTrue("Errors should have been empty", err.isEmpty());
        // find element in the type System

        if (!findGlobalElement(sts.globalElements(), sts1)) {
            throw new Exception("Could Not find Type from first Type System: " +
                                sts1);
        }

        if (!findGlobalElement(sts.globalElements(), sts2)) {
            throw new Exception("Could Not find Type from 2nd Type System: " +
                                sts2);
        }

        //INCR COMPILATION WITH RECOVERABLE ERROR
        err.clear();
        SchemaTypeSystem b = XmlBeans.compileXmlBeans(null,
            sts, schemas3, null,
            XmlBeans.getBuiltinTypeSystem(), null, opt);
        // find element in the type System
        if (!findGlobalElement(b.globalElements(), sts1)) {
            throw new Exception("Could Not find Type from first Type System: " +
                                sts1);
        }

        if (!findGlobalElement(b.globalElements(), sts2)) {
            throw new Exception("Could Not find Type from 2nd Type System: " +
                                sts2);
        }

        if (!findGlobalElement(b.globalElements(), sts3)) {
            throw new Exception("Could Not find Type from 3rd Type System: " +
                                sts3);
        }

        printSTS(b);

        //INSPECT ERRORS
        boolean psom_expError = false;
        // print out the recovered xm_errors
        if (!err.isEmpty()) {
            System.out.println(
                "Schema invalid: partial schema type system recovered");
            for (Iterator i = err.iterator(); i.hasNext(); ) {
                XmlError xErr = (XmlError) i.next();
                System.out.println(xErr);
                //compare to the expected xm_errors
                if ((xErr.getErrorCode().compareTo("src-resolve") == 0) &&
                    (xErr.getMessage().compareTo(
                        "type 'bType@http://baz' not found.") ==
                     0)) {
                    psom_expError = true;
                }
            }
        }
        if (!psom_expError) {
            throw new Exception("Error Code was not as Expected");
        }


    }

/*
    @Test
    public void test_diff_compilationMethods() throws IOException,
        XmlException, Exception {


        //initialize the schema compiler
        SchemaCompiler.Parameters params = new SchemaCompiler.Parameters();
        params.setXsdFiles(new File[]{scompFile});
        params.setSrcDir(scompDirFile);
        params.setClassesDir(scompDirFile);

        //save out schema for use in scomp later
        XmlObject obj1 = XmlObject.Factory.parse(forXsd);
        obj1.save(scompFile);

        //scomp saved out schema
        SchemaCompiler.compile(params);

        //use new api to get typesystem
        XmlObject[] schemas = new XmlObject[]{obj1};
        SchemaTypeSystem apiSts = XmlBeans.compileXmlBeans("apiCompile", null,
            schemas, null, XmlBeans.getBuiltinTypeSystem(), null, xm_opts);

        //use alternative api to get typesystem
        SchemaTypeSystem altSts = XmlBeans.compileXsd(schemas,
            XmlBeans.getBuiltinTypeSystem(), null);

        //save out sts for diff later
        SchemaCodeGenerator.saveTypeSystem(apiSts, apiDirFile, null, null,
            null);
        SchemaCodeGenerator.saveTypeSystem(altSts, baseDirFile, null, null,
            null);

        //diff new api to old api
        xm_errors = null;
        xm_errors = new ArrayList();
        Diff.dirsAsTypeSystems(apiDirFile, baseDirFile, xm_errors);
        if (xm_errors.size() >= 1)
            throw new Exception("API STS ERRORS: " + xm_errors.toString());

        //diff scomp sts to new api
        xm_errors = null;
        xm_errors = new ArrayList();
        Diff.dirsAsTypeSystems(apiDirFile, scompDirFile, xm_errors);
        if (xm_errors.size() >= 1)
            throw new Exception("API SCOMP ERRORS: " + xm_errors.toString());
    }
*/

}
