/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.ode.bpel.compiler;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.Map;

import javax.xml.namespace.QName;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.bpel.compiler.api.CompilationException;
import org.apache.ode.bpel.compiler.api.CompilationMessage;
import org.apache.ode.bpel.compiler.api.CompileListener;
import org.apache.ode.bpel.compiler.api.SourceLocation;
import org.apache.ode.bpel.compiler.bom.BpelObjectFactory;
import org.apache.ode.bpel.compiler.bom.Process;
import org.apache.ode.bpel.obj.OProcess;
import org.apache.ode.bpel.obj.OProcessWrapper;
import org.apache.ode.bpel.obj.serde.DeSerializer;
import org.apache.ode.bpel.obj.serde.OmSerdeFactory;
import org.apache.ode.bpel.obj.serde.OmSerializer;
import org.apache.ode.utils.StreamUtils;
import org.apache.ode.utils.msg.MessageBundle;
import org.apache.ode.utils.xsl.XslTransformHandler;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

/**
 * <p>
 * Wrapper for {@link org.apache.ode.bpel.compiler.BpelCompiler} implementations,
 * providing basic utility methods and auto-detection of BPEL version.
 * </p>
s */
public class BpelC {
    private static final Logger __log = LoggerFactory.getLogger(BpelC.class);
    private static final CommonCompilationMessages __cmsgs =
            MessageBundle.getMessages(CommonCompilationMessages.class);

    public static final String PROCESS_CUSTOM_PROPERTIES = "customProps";

    private CompileListener _compileListener;
    public OutputStream _outputStream = null;

    private File _bpelFile;
    private File _suDir;
    private ResourceFinder _wsdlFinder;
    private URI _bpel11wsdl;
    private Map<String,Object> _compileProperties;
    private boolean _dryRun = false;

    public static BpelC newBpelCompiler() {
        return new BpelC();
    }

    private BpelC() {
    }

    protected void finalize() throws Throwable
    {
        this.invalidate();
        super.finalize();
    }

    private void invalidate() {
        this.setResourceFinder(null);
        this.setCompileListener(null);
        this.setOutputStream(null);
        XslTransformHandler.getInstance().setErrorListener( new net.sf.saxon.StandardErrorListener() );
    }

    /**
     * <p>
     * Set a non-default target {@link CompileListener} implementation.
     * </p>
     * @param cl the listener.
     */
    public void setCompileListener(CompileListener cl) {
        _compileListener = cl;
    }

    /**
     * Configures the compiler to run a dry compilation, doesn't generate the produced
     * compiled process.
     * @param dryRun
     */
    public void setDryRun(boolean dryRun) {
        _dryRun = dryRun;
    }

    /**
     * <p>
     * Tell the compiler how to locate WSDL imports for a BPEL process.  Setting this
     * to <code>null</code> will cause the default behavior.
     * </p>
     * @param finder the {@link ResourceFinder} implementation to use.
     */
    public void setResourceFinder(ResourceFinder finder) {
        _wsdlFinder = finder;
    }


    /**
     * Register a "global" WSDL import for compilation. This is used to specify WSDL
     * imports for BPEL 1.1 processes that do not support the <code>&lt;import&gt;</code>
     * BPEL construct.
     * @param wsdl the WSDL URI (resolvable against the resource repository)
     */
    public void setProcessWSDL(URI wsdl) {
        if (__log.isDebugEnabled()) {
            __log.debug("Adding WSDL import: \"" + wsdl.toASCIIString() + "\".");
        }
        _bpel11wsdl = wsdl;
    }

    /**
     * Compilation properties eventually retrieved by the compiler
     * @param compileProperties
     */
    public void setCompileProperties(Map<String, Object> compileProperties) {
        _compileProperties = compileProperties;
    }

    /**
     * Set the output stream to which the compiled representation will be generated.
     * @param os compiled representation output stream
     */
    public void setOutputStream(OutputStream os) {
        if (_outputStream != null) {
            try {
                _outputStream.close();
            }
            catch (IOException ioex) {
                // ignore
            }
        }

        _outputStream = os;

        if (__log.isDebugEnabled()) {
            __log.debug("Set output to stream " + os);
        }
    }

    public void setBaseDirectory(File baseDir) {
        if (baseDir == null) throw new IllegalArgumentException("Argument 'baseDir' is null");
        if (!baseDir.exists()) throw new IllegalArgumentException("Directory "+baseDir+" does not exist");
        _suDir = baseDir;
    }

    /**
     * <p>
     * Compile a BPEL process from a BOM {@link Process} object.
     * </p>
     *
     * @param process
     *          the BOM <code>Process</code> to compile.
     *
     * @throws IOException
     *           if one occurs while processing (e.g., getting imports) or writing
     *           output.
     * @throws CompilationException
     *           if one occurs while compiling.
     */
    public void compile(final Process process, String outputPath, long version) throws CompilationException, IOException {
        if (process == null)
            throw new NullPointerException("Attempt to compile NULL process.");

        logCompilationMessage(__cmsgs.infCompilingProcess());

        BpelCompiler compiler;
        ResourceFinder wf;

        if (_wsdlFinder != null) {
            wf = _wsdlFinder;
        } else {
            File suDir = _suDir != null ? _suDir : _bpelFile.getParentFile();
            wf = new DefaultResourceFinder(_bpelFile.getAbsoluteFile().getParentFile(), suDir.getAbsoluteFile());
        }

        CompileListener clistener = new CompileListener() {
            public void onCompilationMessage(CompilationMessage compilationMessage) {
                SourceLocation location = compilationMessage.source;
                if (location == null) {
                    compilationMessage.source = process;
                }
                logCompilationMessage(compilationMessage);
            }
        };

        try {
            switch (process.getBpelVersion()) {
                case BPEL20:
                    compiler = new BpelCompiler20();
                    compiler.setResourceFinder(wf);
                    if (_bpel11wsdl != null) {
                        CompilationMessage cmsg = __cmsgs.warnWsdlUriIgnoredFor20Process();
                        logCompilationMessage(cmsg);
                    }
                    break;
                case BPEL20_DRAFT:
                    compiler = new BpelCompiler20Draft();
                    compiler.setResourceFinder(wf);
                    if (_bpel11wsdl != null) {
                        CompilationMessage cmsg = __cmsgs.warnWsdlUriIgnoredFor20Process();
                        logCompilationMessage(cmsg);
                    }
                    break;
                case BPEL11:
                    compiler = new BpelCompiler11();
                    compiler.setResourceFinder(wf);
                    if (_bpel11wsdl != null) {
                        compiler.addWsdlImport(new URI(_bpelFile.getName()), _bpel11wsdl,null);
                    } else {
                        CompilationMessage cmsg = __cmsgs.errBpel11RequiresWsdl();
                        logCompilationMessage(cmsg);
                        this.invalidate();
                        throw new CompilationException(cmsg);
                    }
                    break;
                default:
                    CompilationMessage cmsg = __cmsgs.errUnrecognizedBpelVersion();
                    logCompilationMessage(cmsg);
                    this.invalidate();
                    throw new CompilationException(cmsg);
            }
            compiler.setCompileListener(clistener);
            if (_compileProperties != null) {
                if (_compileProperties.get(PROCESS_CUSTOM_PROPERTIES) != null)
                    compiler.setCustomProperties((Map<QName, Node>) _compileProperties.get(PROCESS_CUSTOM_PROPERTIES));
            }
        } catch (CompilationException ce) {
            this.invalidate();
            throw ce;
        } catch (Exception ex) {
            CompilationMessage cmsg = __cmsgs.errBpelParseErr();
            logCompilationMessage(cmsg);
            this.invalidate();
            throw new CompilationException(cmsg,ex);
        }

        OProcess oprocess;
        try {
            oprocess = compiler.compile(process,wf,version);
        }
        catch (CompilationException cex) {
            this.invalidate();
            throw cex;
        }

        if (!_dryRun) {
            if (outputPath != null) {
                this.setOutputStream(new BufferedOutputStream(new FileOutputStream(outputPath)));
                if (__log.isDebugEnabled()) {
                    __log.debug("Writing compilation results to " + outputPath);
                }
            } else if (_outputStream != null) {
                if (__log.isDebugEnabled()) {
                    __log.debug("Writing compilation results to " + _outputStream.getClass().getName());
                }
            } else {
                throw new IllegalStateException("must setOutputStream() or setOutputDirectory()!");
            }

            try {
            	DeSerializer serializer = new DeSerializer();
            	serializer.serialize(_outputStream, oprocess);
            } finally {
                // close & mark myself invalid
                this.invalidate();
            }
        }
    }

    /**
     * <p>
     * Compile a BPEL process from a file.  This method uses a {@link BpelObjectFactory}
     * to parse the XML and then calls {@link #compile(Process,String)}.
     * </p>
     * @param bpelFile the file of the BPEL process to be compiled.
     * @throws IOException if one occurs while reading the BPEL process or writing the
     * output.
     * @throws CompilationException if one occurs while compiling the process.
     * @deprecated use compile(File bpelFile, long version) instead
     */
    public void compile(File bpelFile) throws CompilationException, IOException {
       compile(bpelFile, 0);
    }

    public OProcess compile(final Process process, long version){
        if (process == null)
            throw new NullPointerException("Attempt to compile NULL process.");

        logCompilationMessage(__cmsgs.infCompilingProcess());

        BpelCompiler compiler;
        ResourceFinder wf;

        if (_wsdlFinder != null) {
            wf = _wsdlFinder;
        } else {
            File suDir = _suDir != null ? _suDir : _bpelFile.getParentFile();
            wf = new DefaultResourceFinder(_bpelFile.getAbsoluteFile().getParentFile(), suDir.getAbsoluteFile());
        }

        CompileListener clistener = new CompileListener() {
            public void onCompilationMessage(CompilationMessage compilationMessage) {
                SourceLocation location = compilationMessage.source;
                if (location == null) {
                    compilationMessage.source = process;
                }
                logCompilationMessage(compilationMessage);
            }
        };

        try {
            switch (process.getBpelVersion()) {
                case BPEL20:
                    compiler = new BpelCompiler20();
                    compiler.setResourceFinder(wf);
                    if (_bpel11wsdl != null) {
                        CompilationMessage cmsg = __cmsgs.warnWsdlUriIgnoredFor20Process();
                        logCompilationMessage(cmsg);
                    }
                    break;
                case BPEL20_DRAFT:
                    compiler = new BpelCompiler20Draft();
                    compiler.setResourceFinder(wf);
                    if (_bpel11wsdl != null) {
                        CompilationMessage cmsg = __cmsgs.warnWsdlUriIgnoredFor20Process();
                        logCompilationMessage(cmsg);
                    }
                    break;
                case BPEL11:
                    compiler = new BpelCompiler11();
                    compiler.setResourceFinder(wf);
                    if (_bpel11wsdl != null) {
                        compiler.addWsdlImport(new URI(_bpelFile.getName()), _bpel11wsdl,null);
                    } else {
                        CompilationMessage cmsg = __cmsgs.errBpel11RequiresWsdl();
                        logCompilationMessage(cmsg);
                        this.invalidate();
                        throw new CompilationException(cmsg);
                    }
                    break;
                default:
                    CompilationMessage cmsg = __cmsgs.errUnrecognizedBpelVersion();
                    logCompilationMessage(cmsg);
                    this.invalidate();
                    throw new CompilationException(cmsg);
            }
            compiler.setCompileListener(clistener);
            if (_compileProperties != null) {
                if (_compileProperties.get(PROCESS_CUSTOM_PROPERTIES) != null)
                    compiler.setCustomProperties((Map<QName, Node>) _compileProperties.get(PROCESS_CUSTOM_PROPERTIES));
            }
        } catch (CompilationException ce) {
            this.invalidate();
            throw ce;
        } catch (Exception ex) {
            CompilationMessage cmsg = __cmsgs.errBpelParseErr();
            logCompilationMessage(cmsg);
            this.invalidate();
            throw new CompilationException(cmsg,ex);
        }

        OProcess oprocess;
        try {
            oprocess = compiler.compile(process,wf,version);
        }
        catch (CompilationException cex) {
            this.invalidate();
            throw cex;
        }
        return oprocess;
    }
    public OProcess compile2OProcess(File bpelFile, long version){
        if (__log.isDebugEnabled()) {
            __log.debug("compile(URL)");
        }

        if (bpelFile == null) {
            this.invalidate();
            throw new IllegalArgumentException("Null bpelFile");
        }

        _bpelFile = bpelFile;
        Process process;
        try {
            InputSource isrc = new InputSource(new ByteArrayInputStream(StreamUtils.read(bpelFile.toURL())));
            isrc.setSystemId(bpelFile.getAbsolutePath());

            process = BpelObjectFactory.getInstance().parse(isrc,_bpelFile.toURI());
        } catch (Exception e) {
            CompilationMessage cmsg = __cmsgs.errBpelParseErr().setSource(new SourceLocationImpl(bpelFile.toURI()));
            this.invalidate();
            throw new CompilationException(cmsg, e);
        }

        assert process != null;
    	return compile(process, version);
    }
    public void serializeOProcess(OProcess oprocess, String outputPath) throws IOException{
        if (!_dryRun) {
            if (outputPath != null) {
                this.setOutputStream(new BufferedOutputStream(new FileOutputStream(outputPath)));
                if (__log.isDebugEnabled()) {
                    __log.debug("Writing compilation results to " + outputPath);
                }
            } else if (_outputStream != null) {
                if (__log.isDebugEnabled()) {
                    __log.debug("Writing compilation results to " + _outputStream.getClass().getName());
                }
            } else {
                throw new IllegalStateException("must setOutputStream() or setOutputDirectory()!");
            }

            try {
               	DeSerializer serializer = new DeSerializer();
            	serializer.serialize(_outputStream, oprocess);
            } finally {
                // close & mark myself invalid
                this.invalidate();
            }
        }    	
    }
    /**
     * <p>
     * Compile a BPEL process from a file.  This method uses a {@link BpelObjectFactory}
     * to parse the XML and then calls {@link #compile(Process,String)}.
     * </p>
     * @param bpelFile the file of the BPEL process to be compiled.
     * @param version the version of the BPEL file.
     * @throws IOException if one occurs while reading the BPEL process or writing the
     * output.
     * @throws CompilationException if one occurs while compiling the process.
     */
    public void compile(File bpelFile, long version) throws CompilationException, IOException {
/*        if (__log.isDebugEnabled()) {
            __log.debug("compile(URL)");
        }

        if (bpelFile == null) {
            this.invalidate();
            throw new IllegalArgumentException("Null bpelFile");
        }

        _bpelFile = bpelFile;
        Process process;
        try {
            InputSource isrc = new InputSource(new ByteArrayInputStream(StreamUtils.read(bpelFile.toURL())));
            isrc.setSystemId(bpelFile.getAbsolutePath());

            process = BpelObjectFactory.getInstance().parse(isrc,_bpelFile.toURI());
        } catch (Exception e) {
            CompilationMessage cmsg = __cmsgs.errBpelParseErr().setSource(new SourceLocationImpl(bpelFile.toURI()));
            this.invalidate();
            throw new CompilationException(cmsg, e);
        }

        assert process != null;

        // Output file = bpel file with a cbp extension
        String bpelPath = bpelFile.getAbsolutePath();
        String cbpPath = bpelPath.substring(0, bpelPath.lastIndexOf(".")) + ".cbp";

        compile(process, cbpPath, version);
        this.invalidate();
        */
    	OProcess oProcess = compile2OProcess(bpelFile, version);
        // Output file = bpel file with a cbp extension
        String bpelPath = bpelFile.getAbsolutePath();
        String cbpPath = bpelPath.substring(0, bpelPath.lastIndexOf(".")) + ".cbp";
        serializeOProcess(oProcess, cbpPath);

    }


    /**
     * Logger a compilation message, both to the log, and to the listener (if any).
     * @param cmsg
     */
    private void logCompilationMessage(CompilationMessage cmsg) {
        if (_compileListener != null) {
            _compileListener.onCompilationMessage(cmsg);
        } else {
            switch (cmsg.severity) {
                case CompilationMessage.ERROR:
                    if (__log.isErrorEnabled())
                        __log.error(cmsg.toErrorString());
                    break;
                case CompilationMessage.INFO:
                    if (__log.isInfoEnabled())
                        __log.info(cmsg.toErrorString());
                    break;
                case CompilationMessage.WARN:
                    if (__log.isWarnEnabled())
                        __log.warn(cmsg.toErrorString());
            }
        }
    }

}
