/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2007 Bull S.A.S.
 * 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.eclipse.compiler;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;

/**
 * JOnAS glue for Eclipse compiler integration.
 * @author Guillaume Sauthier
 */
public class JOnASCompiler {

    /**
     * Logger.
     */
    private static final Log log = LogFactory.getLog(JOnASCompiler.class);

    /**
     * CompilationContext with all required configuration.
     */
    private CompilationContext context;

    /**
     * Construct a new JOnAS Compiler based on Eclipse.
     * @param context CompoilationContext to use.
     */
    public JOnASCompiler(final CompilationContext context) {
        this.context = context;
        // fall-back on TCCL if none is specified
        if (context.getContextualClassLoader() == null) {
            context.setContextualClassLoader(Thread.currentThread().getContextClassLoader());
        }
    }

    /**
     * Compile the requested classes.
     * @return a compiler errors list (may be empty).
     */
    public List<CompilerError> compile() {

        // Creates the initial List of ICompilationUnit
        List<ICompilationUnit> compilationUnits = new ArrayList<ICompilationUnit>();
        List<CompilerError> errors = new ArrayList<CompilerError>();
        for (Iterator<String> it = context.getSources().iterator(); it.hasNext();) {
            String source = it.next();
            ICompilationUnit unit = new JOnASCompilationUnit(Util.getClassName(source),
                                                             new File(context.getSourceDirectory(),
                                                                      source).getAbsolutePath(),
                                                             context,
                                                             errors);

            compilationUnits.add(unit);
        }

        // Creates a Compiler with JOnAS Glue classes
        Compiler compiler = new Compiler(new JOnASNameEnvironment(context, errors),
                                         DefaultErrorHandlingPolicies.proceedWithAllProblems(),
                                         context.getCompilerOptions(),
                                         new JOnASCompilerRequestor(context.getOutputDirectory(), errors),
                                         new DefaultProblemFactory(Locale.getDefault()));

        log.debug("Compiling {0} units into {1} using {2} CLassLoader.",
                  compilationUnits.size(),
                  context.getOutputDirectory(),
                  context.getContextualClassLoader());

        // Compile
        ICompilationUnit[] units = (ICompilationUnit[]) compilationUnits.toArray(new ICompilationUnit[compilationUnits.size()]);
        compiler.compile(units);

        // Return the error list
        return errors;
    }
}
