/**
 * EasyBeans
 * Copyright (C) 2006 Bull S.A.S.
 * Contact: easybeans@objectweb.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id: SignatureBuiler.java 6007 2011-10-17 13:34:35Z benoitf $
 * --------------------------------------------------------------------------
 */

package org.ow2.spec.testengine;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.ow2.spec.testengine.metadata.ClassMetadata;


/**
 * Build a signature file for a given jar file and a given package.
 * @author Florent Benoit
 */
public class SignatureBuiler {

    /**
     * Jar File to analyze.
     */
    private JarFile jarFile = null;

    /**
     * Output directory for the report.
     */
    private File outputDir = null;

    /**
     * Analyzer visitor. (ASM visitor).
     */
    private AnalyzerClassVisitor analyzerClassVisitor = null;


    /**
     * Map between package name and Map of <className, classMetadata>.
     */
    private Map<String, Map<String, ClassMetadata>> packageClassesMetadataMap = null;

    /**
     * Build a new checker
     * @param args
     */
    private SignatureBuiler(String[] args) {
        if (args == null) {
            usage();
            throw new IllegalArgumentException("No arguments");
        }

        if (args.length < 2) {
            usage();
            throw new IllegalArgumentException("Needs at least 2 arguments");
        }

        // first arg = JAR File
        try {
            jarFile = new JarFile(args[0]);
        } catch (IOException e) {
            usage();
            throw new IllegalArgumentException("The argument '" + args[0] + "' is not a valid JAR file.", e);
        }

        // Second arg = output dir
        outputDir = new File(args[1]);
        if (!outputDir.exists()) {
            throw new IllegalArgumentException("No directory found for the path '" + outputDir + "'. Create it before.");
        }

        packageClassesMetadataMap = new HashMap<String, Map<String, ClassMetadata>>();
        analyzerClassVisitor = new AnalyzerClassVisitor(packageClassesMetadataMap);

    }

    public void start() throws IOException {

        ClassVisitor classVisitor = new SerialVersionUIDReader(analyzerClassVisitor);
        Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
            JarEntry jarEntry = entries.nextElement();
            if (jarEntry.getName().toLowerCase().endsWith(".class")) {
                InputStream inputStream = jarFile.getInputStream(jarEntry);
                new ClassReader(inputStream).accept(classVisitor, 0);
            }
        }

        // dump
        File outputFile = new File(outputDir, "api.xml");
        FileWriter writer = new FileWriter(outputFile);
        writer.write(getXML());
        writer.close();



    }

    public String getXML() {
        StringBuilder sb = new StringBuilder();
        String newIndent = "  ";

        sb.append("<analyzer xmlns=\"http://org.ow2.spec/ns/apicheck\">\n");

        // per package
        Set<String> packages = packageClassesMetadataMap.keySet();

        for (String packageName : packages) {
            sb.append(newIndent);
            sb.append("<package name=\"");
            sb.append(packageName);
            sb.append("\">\n");

            Map<String, ClassMetadata> classMetadataMap = packageClassesMetadataMap.get(packageName);
            Collection<ClassMetadata> collection = classMetadataMap.values();
            for (ClassMetadata classMetadata : collection) {
                sb.append(classMetadata.toXML(newIndent + "  "));
            }

            sb.append(newIndent);
            sb.append("</package>\n");

        }


        sb.append("</analyzer>");

        return sb.toString();
    }

    /**
     * @param args
     */
    public static void main(String[] args) throws IOException {
        SignatureBuiler signatureBuiler = new SignatureBuiler(args);
        signatureBuiler.start();


        System.out.println("result = \n" + signatureBuiler.getXML());

    }

    public void usage() {
        System.out.println("Usage : SignatureBuiler <Jar file to analyze> <output directory>");
        System.out.println("Usage : example : SignatureBuiler /tmp/ejb.jar /tmp/report");
    }

}
