package org.hamcrest.generator.config;

import org.hamcrest.generator.HamcrestFactoryWriter;
import org.hamcrest.generator.QuickReferenceWriter;
import org.hamcrest.generator.ReflectiveFactoryReader;
import org.hamcrest.generator.SugarConfiguration;
import org.hamcrest.generator.SugarGenerator;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class XmlConfigurator {

    private final SugarConfiguration sugarConfiguration;
    private final ClassLoader classLoader;
    private final SAXParserFactory saxParserFactory;

    public XmlConfigurator(SugarConfiguration sugarConfiguration, ClassLoader classLoader) {
        this.sugarConfiguration = sugarConfiguration;
        this.classLoader = classLoader;
        saxParserFactory = SAXParserFactory.newInstance();
        saxParserFactory.setNamespaceAware(true);
    }

    public void load(InputSource inputSource) throws ParserConfigurationException, SAXException, IOException {
        SAXParser saxParser = saxParserFactory.newSAXParser();
        saxParser.parse(inputSource, new DefaultHandler() {
            public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
                if (localName.equals("factory")) {
                    String className = attributes.getValue("class");
                    try {
                        addClass(className);
                    } catch (ClassNotFoundException e) {
                        throw new SAXException("Cannot find Matcher class : " + className);
                    }
                }
            }
        });
    }

    private void addClass(String className) throws ClassNotFoundException {
        Class cls = classLoader.loadClass(className);
        sugarConfiguration.addFactoryMethods(new ReflectiveFactoryReader(cls));
    }


    public static void main(String[] args) throws Exception {

        if (args.length != 3) {
            System.err.println("Args: config-file generated-class output-dir");
            System.err.println("");
            System.err.println("    config-file : Path to config file listing matchers to generate sugar for.");
            System.err.println("                e.g. path/to/matchers.xml");
            System.err.println("");
            System.err.println("generated-class : Full name of class to generate.");
            System.err.println("                e.g. org.myproject.MyMatchers");
            System.err.println("");
            System.err.println("     output-dir : Where to output generated code (package subdirs will be");
            System.err.println("                  automatically created).");
            System.err.println("                e.g. build/generated-code");
            System.exit(-1);
        }

        String configFile = args[0];
        String fullClassName = args[1];
        File outputDir = new File(args[2]);

        String fileName = fullClassName.replaceAll("\\.", File.separator) + ".java";
        int dotIndex = fullClassName.lastIndexOf(".");
        String packageName = dotIndex == -1 ? "" : fullClassName.substring(0, dotIndex);
        String shortClassName = fullClassName.substring(dotIndex + 1);

        if (!outputDir.isDirectory()) {
            System.err.println("Output directory not found : " + outputDir.getAbsolutePath());
            System.exit(-1);
        }

        File outputFile = new File(outputDir, fileName);
        outputFile.getParentFile().mkdirs();

        SugarGenerator sugarGenerator = new SugarGenerator();
        try {
            sugarGenerator.addWriter(new HamcrestFactoryWriter(
                    packageName, shortClassName, new FileWriter(outputFile)));
            sugarGenerator.addWriter(new QuickReferenceWriter(System.out));

            XmlConfigurator xmlConfigurator = new XmlConfigurator(sugarGenerator, XmlConfigurator.class.getClassLoader());
            xmlConfigurator.load(new InputSource(configFile));

            System.out.println("Generating " + fullClassName);
            sugarGenerator.generate();
        } finally {
            sugarGenerator.close();
        }
    }
}

@@ -3235,17 +3235,12 @@
 lace
-All(%22%5C%5C.%22
+('.'
 , Fi
@@ -3251,16 +3251,20 @@
 eparator
+Char
 ) + %22.ja

Fix for windows path separator (By Magne Rasmussen)