/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2003-2004 Bull S.A.
 * Contact: jonas-team@ow2.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$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.generators.genbase.generator;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import org.ow2.jonas.generators.genbase.GenBaseException;
import org.ow2.jonas.generators.genbase.archive.Archive;
import org.ow2.jonas.generators.genbase.utils.TempRepository;
import org.ow2.jonas.lib.util.I18n;
import org.ow2.jonas.lib.util.Log;
import org.ow2.util.file.FileUtils;
import org.ow2.util.url.URLUtils;

/**
 * Generators provide a structure to be extended for specific generation
 * mechanisms.
 * @author Guillaume Sauthier
 */
public abstract class AbsGenerator {

    /**
     * i18n
     */
    private static I18n i18n = I18n.getInstance(AbsGenerator.class);

    /**
     * logger
     */
    private static Logger logger = Log.getLogger(Log.JONAS_GENBASE_PREFIX);

    /**
     * Configuration to be used
     */
    private Config config;

    /**
     * compiled classes directory
     */
    private File classes;

    /**
     * generated files directory
     */
    private File sources;

    /**
     * Creates a new Generator with the given Config.
     * @param config internal configuration object.
     * @throws GenBaseException When sources and target temporary directory
     *         cannot be created
     */
    public AbsGenerator(final Config config) throws GenBaseException {
        this.config = config;

        // creates temporary directories
        TempRepository tr = TempRepository.getInstance();

        try {
            sources = tr.createDir();
            classes = tr.createDir();
        } catch (IOException ioe) {
            String err = i18n.getMessage("AbsGenerator.constr.ioe");
            logger.log(BasicLevel.ERROR, err);
            throw new GenBaseException(err, ioe);
        }
    }

    /**
     * Generate files.
     * @throws GenBaseException When generation fails.
     */
    public abstract void generate() throws GenBaseException;

    /**
     * Compile generated java files into classes directory.
     * @throws GenBaseException When compilation fails
     */
    public abstract void compile() throws GenBaseException;

    /**
     * Recursively walk a directory tree and return a List of all files found.
     * @param rootSrc root directory
     * @param src base directory
     * @return the list containing all found files
     */
    protected List<String> getJavaSources(final File rootSrc, final File src) {
        List<String> result = new ArrayList<String>();

        // add each java sources contained in the directory
        File[] files = src.listFiles(new FileFilter() {
            public boolean accept(File file) {
                return file.isFile() && file.getName().endsWith(".java");
            }
        });

        for (int i = 0; i < files.length; i++) {
            result.add(files[i].getPath().substring(rootSrc.getPath().length() + 1));
        }

        // reapply on subdirectories
        files = src.listFiles(new FileFilter() {
            public boolean accept(final File file) {
                return file.isDirectory();
            }
        });

        for (int i = 0; i < files.length; i++) {
            List<String> deeperList = getJavaSources(rootSrc, files[i]);
            result.addAll(deeperList);
        }

        return result;
    }

    /**
     * Add generated files into an Archive
     * @param archive the archive destination of generated files.
     * @throws GenBaseException When files cannot be added in the given Archive.
     */
    public abstract void addFiles(Archive archive) throws GenBaseException;

    /**
     * @return the config.
     */
    public Config getConfig() {
        return config;
    }

    /**
     * @return the logger.
     */
    public static Logger getLogger() {
        return logger;
    }

    /**
     * @return the classes.
     */
    public File getClasses() {
        return classes;
    }

    /**
     * @return the sources.
     */
    public File getSources() {
        return sources;
    }
}