
package org.jibx.schema.codegen;

import java.io.IOException;
import java.util.ArrayList;

import org.jibx.runtime.JiBXException;
import org.jibx.schema.SchemaTestBase;
import org.jibx.schema.codegen.custom.SchemasetCustom;
import org.jibx.schema.elements.SchemaElement;

/**
 * Test code generation from schemas.
 */
public class CodeGenerationTest extends SchemaTestBase
{
    static final StringObjectPair[] DATA1 = new StringObjectPair[] {
        new StringObjectPair("something.Element", new StringPair[] { 
            new StringPair("DATE_FORM", "int"),
            new StringPair("DATE_TIME_FORM", "int"),
            new StringPair("RATING_FORM", "int"),
            new StringPair("date", "Date"),
            new StringPair("dateTime", "java.util.Date"),
            new StringPair("male", "boolean"),
            new StringPair("mixedSelectSelect", "int"),
            new StringPair("name", "String"),
            new StringPair("rated", "int"),
            new StringPair("rated1", "Integer"),
            new StringPair("rating", "int")})
    };
    static final StringObjectPair[] DATA2 = new StringObjectPair[] {
    };
    static final StringObjectPair[] DATA3_A = new StringObjectPair[] {
        new StringObjectPair("something.Element", new StringPair[] { 
            new StringPair("DATE_FORM", "int"),
            new StringPair("DATE_TIME_FORM", "int"),
            new StringPair("_INT_FORM", "int"),
            new StringPair("_int", "int"),
            new StringPair("date", "Date"),
            new StringPair("dateTime", "java.util.Date"),
            new StringPair("enum1", "Enum1"),
            new StringPair("enum2", "Enum2"),
            new StringPair("enum3", "Enum3"),
            new StringPair("male", "boolean"),
            new StringPair("mixedSelectSelect", "int"),
            new StringPair("name", "String"),
            new StringPair("rated", "int"),
            new StringPair("rated1", "Integer")}),
        new StringObjectPair("something.Element.Enum1", new StringPair[] { 
            new StringPair("A1", "Enum1"),
            new StringPair("B2", "Enum1"),
            new StringPair("instances", "Enum1[]"),
            new StringPair("value", "String"),
            new StringPair("values", "String[]")}),
        new StringObjectPair("something.Element.Enum2", new StringPair[] { 
            new StringPair("A1", "Enum2"),
            new StringPair("B2", "Enum2"),
            new StringPair("instances", "Enum2[]"),
            new StringPair("value", "String"),
            new StringPair("values", "String[]")}),
        new StringObjectPair("something.Element.Enum3", new StringPair[] { 
            new StringPair("A1", "Enum3"),
            new StringPair("B2", "Enum3"),
            new StringPair("instances", "Enum3[]"),
            new StringPair("value", "String"),
            new StringPair("values", "String[]")}),
    };
    static final StringObjectPair[] DATA3_B = new StringObjectPair[] {
        new StringObjectPair("anything.Enum1", new StringPair[] { 
            new StringPair("A1", "Enum1"),
            new StringPair("B2", "Enum1"),
            new StringPair("instances", "Enum1[]"),
            new StringPair("value", "String"),
            new StringPair("values", "String[]")}),
        new StringObjectPair("anything.Enum2", new StringPair[] { 
            new StringPair("A1", "Enum2"),
            new StringPair("B2", "Enum2"),
            new StringPair("instances", "Enum2[]"),
            new StringPair("value", "String"),
            new StringPair("values", "String[]")}),
        new StringObjectPair("anything.Enum3", new StringPair[] { 
            new StringPair("X1", "Enum3"),
            new StringPair("Y2", "Enum3"),
            new StringPair("Z3", "Enum3"),
            new StringPair("instances", "Enum3[]"),
            new StringPair("value", "String"),
            new StringPair("values", "String[]")}),
        new StringObjectPair("something.Element", new StringPair[] { 
            new StringPair("DATE_FORM", "int"),
            new StringPair("DATE_TIME_FORM", "int"),
            new StringPair("_INT_FORM", "int"),
            new StringPair("_int", "int"),
            new StringPair("date", "Date"),
            new StringPair("dateTime", "java.util.Date"),
            new StringPair("enum1", "Enum1"),
            new StringPair("enum1a", "Enum1"),
            new StringPair("enum2", "Enum2"),
            new StringPair("enum2a", "Enum2"),
            new StringPair("enum3", "Enum3"),
            new StringPair("enum3a", "Enum3"),
            new StringPair("male", "boolean"),
            new StringPair("mixedUnionSelect", "int"),
            new StringPair("name", "String"),
            new StringPair("rated", "int"),
            new StringPair("rated1", "Integer")}),
    };
    static final StringObjectPair[] DATA4 = new StringObjectPair[] {
    };
    static final StringObjectPair[] DATA5 = new StringObjectPair[] {
    };
    
    private static void dumpImage(StringObjectPair[] classdefs) {
        for (int i = 0; i < classdefs.length; i++) {
            StringObjectPair pair = classdefs[i];
            StringPair[] fielddefs = (StringPair[])pair.getValue();
            System.out.print("        new StringObjectPair(\"");
            System.out.print(pair.getKey());
            System.out.print("\", new StringPair[] { ");
            for (int j = 0; j < fielddefs.length; j++) {
                StringPair fielddef = fielddefs[j];
                System.out.println(j > 0 ? "," : "");
                System.out.print("            new StringPair(\"");
                System.out.print(fielddef.getKey());
                System.out.print("\", \"");
                System.out.print(fielddef.getValue());
                System.out.print("\")");
            }
            System.out.println("}),");
        }
    }
    
    private void testDump(SchemasetCustom custom, SchemaElement[] schemas) throws JiBXException, IOException {
        CodeGenerator generator = new CodeGenerator(custom, m_validationContext, schemas);
        assertTrue("Schema customization failure", generator.customizeSchemas());
        generator.applyExtensions();
        generator.pruneDefinitions();
        generator.validateSchemas(true);
        generator.generate();
        ArrayList packages = generator.getPackageDirectory().getPackages();
        System.out.println("Data model dump:");
        for (int i = 0; i < packages.size(); i++) {
            PackageHolder packhold = (PackageHolder)packages.get(i);
            StringObjectPair[] classdefs = packhold.getClassFields();
            dumpImage(classdefs);
        }
    }
    
    private void testGeneration(SchemasetCustom custom, SchemaElement[] schemas, StringObjectPair[] image)
        throws JiBXException, IOException {
        CodeGenerator generator = new CodeGenerator(custom, m_validationContext, schemas);
        assertTrue("Schema customization failure", generator.customizeSchemas());
        generator.applyExtensions();
        generator.pruneDefinitions();
        generator.validateSchemas(true);
        generator.generate();
        StringObjectPair[] classpairs = DataModelUtils.getImage(generator.getPackageDirectory());
        String diff = DataModelUtils.imageDiff(image, classpairs);
        if (diff != null) {
            fail(diff);
        }
    }
    
//    public void testGeneration1() throws Exception {
//        SchemaElement[] schemas = new SchemaElement[] { loadSchema(TypeReplacementTest.RESOLVER1) };
//        testGeneration(new SchemasetCustom(null), schemas, DATA1);
//    }
//    
//    public void testGeneration3() throws Exception {
//        SchemaElement[] schemas = new SchemaElement[] { loadSchema(TypeReplacementTest.RESOLVER3) };
//        SchemasetCustom custom = loadCustomization(TypeReplacementTest.CUSTOMIZATION3_B);
//        testGeneration(custom, schemas, DATA3_B);
//    }
    
    public void testGeneration3b() throws Exception {
        SchemaElement[] schemas = new SchemaElement[] { loadSchema(TypeReplacementTest.RESOLVER3) };
        SchemasetCustom custom = loadCustomization(TypeReplacementTest.CUSTOMIZATION3_B);
        testDump(custom, schemas);
        testGeneration(custom, schemas, DATA3_B);
//        testDump(custom, schemas);
    }
    
/*    public void testTypeReplacement() throws Exception {
        SchemaElement[] schemas = new SchemaElement[] { loadSchema(TypeReplacementTest.RESOLVER1) };
        SchemasetCustom custom = loadCustomization(TypeReplacementTest.CUSTOMIZATION2);
        testGeneration(custom, schemas);
    }
    
    public void testTypeRemoval() throws Exception {
        SchemaElement[] schemas = new SchemaElement[] { loadSchema(TypeReplacementTest.RESOLVER1) };
        SchemasetCustom custom = loadCustomization(TypeReplacementTest.CUSTOMIZATION3);
        testGeneration(custom, schemas);
    }
    
    public void testTypeReplacement2() throws Exception {
        SchemaElement[] schemas = new SchemaElement[] { loadSchema(TypeReplacementTest.RESOLVER2) };
        SchemasetCustom custom = loadCustomization(TypeReplacementTest.CUSTOMIZATION4);
        testGeneration(custom, schemas);
    }
    
    public void testCombinedRemovalReplacement() throws Exception {
        SchemaElement[] schemas = new SchemaElement[] { loadSchema(TypeReplacementTest.RESOLVER2) };
        SchemasetCustom custom = loadCustomization(TypeReplacementTest.CUSTOMIZATION5);
        testGeneration(custom, schemas);
    }   */
}