/*
 * 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.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import javax.wsdl.Definition;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.Part;
import javax.wsdl.PortType;
import javax.wsdl.WSDLException;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;

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.CompilerContext;
import org.apache.ode.bpel.compiler.api.ExpressionCompiler;
import org.apache.ode.bpel.compiler.api.ExpressionValidator;
import org.apache.ode.bpel.compiler.api.SourceLocation;
import org.apache.ode.bpel.compiler.bom.Activity;
import org.apache.ode.bpel.compiler.bom.Bpel11QNames;
import org.apache.ode.bpel.compiler.bom.Bpel20QNames;
import org.apache.ode.bpel.compiler.bom.BpelObject;
import org.apache.ode.bpel.compiler.bom.Catch;
import org.apache.ode.bpel.compiler.bom.CompensationHandler;
import org.apache.ode.bpel.compiler.bom.Correlation;
import org.apache.ode.bpel.compiler.bom.CorrelationSet;
import org.apache.ode.bpel.compiler.bom.Expression;
import org.apache.ode.bpel.compiler.bom.Expression11;
import org.apache.ode.bpel.compiler.bom.FaultHandler;
import org.apache.ode.bpel.compiler.bom.Import;
import org.apache.ode.bpel.compiler.bom.LinkSource;
import org.apache.ode.bpel.compiler.bom.LinkTarget;
import org.apache.ode.bpel.compiler.bom.OnAlarm;
import org.apache.ode.bpel.compiler.bom.OnEvent;
import org.apache.ode.bpel.compiler.bom.PartnerLink;
import org.apache.ode.bpel.compiler.bom.PartnerLinkType;
import org.apache.ode.bpel.compiler.bom.Process;
import org.apache.ode.bpel.compiler.bom.Property;
import org.apache.ode.bpel.compiler.bom.PropertyAlias;
import org.apache.ode.bpel.compiler.bom.Scope;
import org.apache.ode.bpel.compiler.bom.ScopeActivity;
import org.apache.ode.bpel.compiler.bom.ScopeLikeActivity;
import org.apache.ode.bpel.compiler.bom.TerminationHandler;
import org.apache.ode.bpel.compiler.bom.Variable;
import org.apache.ode.bpel.compiler.wsdl.Definition4BPEL;
import org.apache.ode.bpel.compiler.wsdl.WSDLFactory4BPEL;
import org.apache.ode.bpel.obj.DebugInfo;
import org.apache.ode.bpel.obj.OActivity;
import org.apache.ode.bpel.obj.OAssign;
import org.apache.ode.bpel.obj.OCatch;
import org.apache.ode.bpel.obj.OCompensate;
import org.apache.ode.bpel.obj.OConstantExpression;
import org.apache.ode.bpel.obj.OConstantVarType;
import org.apache.ode.bpel.obj.OConstants;
import org.apache.ode.bpel.obj.OElementVarType;
import org.apache.ode.bpel.obj.OEventHandler;
import org.apache.ode.bpel.obj.OExpression;
import org.apache.ode.bpel.obj.OExpressionLanguage;
import org.apache.ode.bpel.obj.OExtVar;
import org.apache.ode.bpel.obj.OFlow;
import org.apache.ode.bpel.obj.OLValueExpression;
import org.apache.ode.bpel.obj.OLink;
import org.apache.ode.bpel.obj.OMessageVarType;
import org.apache.ode.bpel.obj.OPartnerLink;
import org.apache.ode.bpel.obj.OProcess;
import org.apache.ode.bpel.obj.ORethrow;
import org.apache.ode.bpel.obj.OScope;
import org.apache.ode.bpel.obj.OSequence;
import org.apache.ode.bpel.obj.OVarType;
import org.apache.ode.bpel.obj.OXsdTypeVarType;
import org.apache.ode.bpel.obj.OXslSheet;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.NSContext;
import org.apache.ode.utils.Namespaces;
import org.apache.ode.utils.StreamUtils;
import org.apache.ode.utils.fs.FileUtils;
import org.apache.ode.utils.msg.MessageBundle;
import org.apache.ode.utils.stl.CollectionsX;
import org.apache.ode.utils.stl.MemberOfFunction;
import org.apache.ode.utils.stl.UnaryFunction;
import org.apache.ode.utils.xsd.SchemaModel;
import org.apache.ode.utils.xsd.XSUtils;
import org.apache.ode.utils.xsd.XsdException;
import org.apache.ode.utils.xsl.XslTransformHandler;
import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

/**
 * Compiler for converting BPEL process descriptions (and their associated WSDL and XSD documents) into compiled representations
 * suitable for execution by the ODE BPEL Service Provider. TODO: Move process validation into this class.
 */
public abstract class BpelCompiler implements CompilerContext {
    /** Class-severity logger. */
    protected static final Logger __log = LoggerFactory.getLogger(BpelCompiler.class);

    /** Standardized compiler messages. */
    private static final CommonCompilationMessages __cmsgs = MessageBundle.getMessages(CommonCompilationMessages.class);

    private org.apache.ode.bpel.compiler.bom.Process _processDef;

    private Date _generatedDate;

    @SuppressWarnings("unchecked")
    private HashMap<Class, ActivityGenerator> _actGenerators = new HashMap<Class, ActivityGenerator>();

    private boolean _supressJoinFailure = false;

    /** Are we currently in an atomic scope context? */
    private boolean _atomicScope = false;

    /** Are we currently compiling an isolated scope context. */
    private boolean _isolatedScope = false;

    /** Syntactic scope stack. */
    private StructureStack _structureStack = new StructureStack();

    /** Fault/compensate recovery stack. */
    private Stack<OScope> _recoveryContextStack = new Stack<OScope>();

    /** History of compiled activities */
    private List<OActivity> _compiledActivities = new ArrayList<OActivity>();

    private OProcess _oprocess;

    private ResourceFinder _resourceFinder;

    private WSDLRegistry _wsdlRegistry;

    private final List<CompilationMessage> _errors = new ArrayList<CompilationMessage>();

    private CompileListener _compileListener;

    private final HashMap<String, ExpressionCompiler> _expLanguageCompilers = new HashMap<String, ExpressionCompiler>();

    private final HashMap<String, OExpressionLanguage> _expLanguages = new HashMap<String, OExpressionLanguage>();

    private ExpressionValidatorFactory _expressionValidatorFactory = new ExpressionValidatorFactory(System.getProperties());

    private WSDLFactory4BPEL _wsdlFactory;

    private OExpressionLanguage _konstExprLang;

    private Map<QName, Node> _customProcessProperties;

    private URI _processURI;

    BpelCompiler(WSDLFactory4BPEL wsdlFactory) {
        _wsdlFactory = wsdlFactory;
        _wsdlRegistry = new WSDLRegistry(this);
    }

    public void addWsdlImport(URI from, URI wsdlImport, SourceLocation sloc) {
        Definition4BPEL def;
        try {
            WSDLReader r = _wsdlFactory.newWSDLReader();
            WSDLLocatorImpl locator = new WSDLLocatorImpl(_resourceFinder, _resourceFinder.resolve(from, wsdlImport));
            def = (Definition4BPEL) r.readWSDL(locator);
        } catch (WSDLException e) {
            recoveredFromError(sloc, new CompilationException(__cmsgs.errWsdlParseError(e.getFaultCode(), e.getLocation(), e
                    .getMessage())));
            throw new CompilationException(__cmsgs.errWsdlImportFailed(wsdlImport.toASCIIString(), e.getFaultCode())
                    .setSource(sloc), e);
        }

        try {
            _wsdlRegistry.addDefinition(def, _resourceFinder, _resourceFinder.resolve(from, wsdlImport));
            if (__log.isDebugEnabled())
                __log.debug("Added WSDL Definition: " + wsdlImport);
        } catch (CompilationException ce) {
            recoveredFromError(sloc, ce);
        }
    }

    public void addXsdImport(URI from, URI location, SourceLocation sloc) {
        URI resFrom = _resourceFinder.resolve(from, location);
        if (__log.isDebugEnabled())
            __log.debug("Adding XSD import from " + resFrom + " location " + location);
        XMLEntityResolver resolver = new WsdlFinderXMLEntityResolver(_resourceFinder,
                location, new HashMap<URI,byte[]>(), true);
        try {
            InputStream xsdStream = _resourceFinder.openResource(resFrom);
            byte[] data;
            try {
                data = StreamUtils.read(xsdStream);
            } finally {
                xsdStream.close();
            }

            Map<URI, byte[]> schemas = XSUtils.captureSchema(resFrom, data, resolver, 0);
            _wsdlRegistry.addSchemas(schemas);
        } catch (XsdException e) {
            CompilationException ce = new CompilationException(__cmsgs.errInvalidImport(location.toString()));
            recoveredFromError(sloc, ce);
        } catch (MalformedURLException e) {
            CompilationException ce = new CompilationException(__cmsgs.errInvalidImport(location.toString()));
            recoveredFromError(sloc, ce);
        } catch (IOException e) {
            CompilationException ce = new CompilationException(__cmsgs.errInvalidImport(location.toString()));
            recoveredFromError(sloc, ce);
        }
    }

    public void setResourceFinder(ResourceFinder finder) {
        if (finder == null) {
            _resourceFinder = new DefaultResourceFinder();
        } else {
            _resourceFinder = finder;
        }

    }

    public void setCompileListener(CompileListener compileListener) {
        _compileListener = compileListener;
    }

    public CompileListener getCompileListener() {
        return _compileListener;
    }

    public void setCustomProperties(Map<QName, Node> customProperties) {
        _customProcessProperties = customProperties;
    }

    /**
     * Get the process definition.
     *
     * @return the process definition
     */
    public Process getProcessDef() {
        return _processDef;
    }

    public PortType resolvePortType(final QName portTypeName) {
        if (portTypeName == null)
            throw new NullPointerException("Null portTypeName argument!");

        PortType portType = _wsdlRegistry.getPortType(portTypeName);
        if (portType == null)
            throw new CompilationException(__cmsgs.errUndeclaredPortType(portTypeName));
        return portType;
    }

    public OLink resolveLink(String linkName) {
        OLink ret = null;

        // Fist find where the link is declared.
        for (Iterator<OActivity> i = _structureStack.iterator(); i.hasNext();) {
            OActivity oact = i.next();
            if (oact instanceof OFlow)
                ret = ((OFlow) oact).getLocalLink(linkName);
            if (ret != null)
                return ret;
        }

        throw new CompilationException(__cmsgs.errUndeclaredLink(linkName));
    }

    public OScope.Variable resolveVariable(String varName) {
        for (Iterator<OScope> i = _structureStack.oscopeIterator(); i.hasNext();) {
            OScope.Variable var = i.next().getLocalVariable(varName);
            if (var != null)
                return var;
        }
        // A "real" variable couldn't be found, checking if we're dealing with a
        // process custom property
        if (_customProcessProperties != null && _customProcessProperties.get(QName.valueOf(varName)) != null) {

        }
        throw new CompilationException(__cmsgs.errUndeclaredVariable(varName));
    }

    public List<OScope.Variable> getAccessibleVariables() {
        ArrayList<OScope.Variable> result = new ArrayList<OScope.Variable>();
        for (Iterator<OScope> i = _structureStack.oscopeIterator(); i.hasNext();) {
            result.addAll(i.next().getVariables().values());
        }
        return result;
    }

    public OScope.Variable resolveMessageVariable(String inputVar) throws CompilationException {
        OScope.Variable var = resolveVariable(inputVar);
        if (!(var.getType() instanceof OMessageVarType))
            throw new CompilationException(__cmsgs.errMessageVariableRequired(inputVar));
        return var;
    }

    public OScope.Variable resolveMessageVariable(String inputVar, QName messageType) throws CompilationException {
        OScope.Variable var = resolveMessageVariable(inputVar);
        if (!((OMessageVarType) var.getType()).getMessageType().equals(messageType))
            throw new CompilationException(__cmsgs.errVariableTypeMismatch(var.getName(), messageType,
                    ((OMessageVarType) var.getType()).getMessageType()));
        return var;
    }

    public OProcess.OProperty resolveProperty(QName name) {

        for (OProcess.OProperty prop : _oprocess.getProperties()) {
            if (prop.getName().equals(name))
                return prop;
        }
        throw new CompilationException(__cmsgs.errUndeclaredProperty(name));
    }

    public OProcess.OPropertyAlias resolvePropertyAlias(OScope.Variable variable, QName propertyName) {
        if (!(variable.getType() instanceof OMessageVarType))
            throw new CompilationException(__cmsgs.errMessageVariableRequired(variable.getName()));

        OProcess.OProperty property = resolveProperty(propertyName);
        OProcess.OPropertyAlias alias = property.getAlias(variable.getType());
        if (alias == null)
            throw new CompilationException(__cmsgs.errUndeclaredPropertyAlias(variable.getType().toString(), propertyName));

        return alias;
    }

    public OScope resolveCompensatableScope(final String scopeToCompensate) throws CompilationException {
        if (_recoveryContextStack.isEmpty())
            throw new CompilationException(__cmsgs.errCompensateNAtoContext());
        OScope recoveryContext = _recoveryContextStack.peek();

        OScope scopeToComp = CollectionsX.find_if(recoveryContext.getCompensatable(), new MemberOfFunction<OScope>() {
            public boolean isMember(OScope o) {
                return o.getName() != null && o.getName().equals(scopeToCompensate);
            }
        });
        if (scopeToComp == null)
            throw new CompilationException(__cmsgs.errCompensateOfInvalidScope(scopeToCompensate));

        return scopeToComp;
    }

    public String getSourceLocation() {
        return _processDef.getSource() == null ? null : _processDef.getSource();
    }

    public OScope.CorrelationSet resolveCorrelationSet(String csetName) {
        for (Iterator<OScope> i = _structureStack.oscopeIterator(); i.hasNext();) {
            OScope.CorrelationSet cset = i.next().getCorrelationSet(csetName);
            if (cset != null)
                return cset;
        }

        throw new CompilationException(__cmsgs.errUndeclaredCorrelationSet(csetName));
    }

    @SuppressWarnings("unchecked")
    public OMessageVarType resolveMessageType(QName messageType) {
        OMessageVarType msgType = _oprocess.getMessageTypes().get(messageType);
        if (msgType == null) {
            Message msg = _wsdlRegistry.getMessage(messageType);
            if (msg == null) {
                throw new CompilationException(__cmsgs.errUndeclaredMessage(messageType.getLocalPart(), messageType
                        .getNamespaceURI()));
            }

            List<OMessageVarType.Part> parts = new ArrayList<OMessageVarType.Part>();
            CollectionsX.transform(parts, ((List<Part>) msg.getOrderedParts(null)),
                    new UnaryFunction<Part, OMessageVarType.Part>() {
                        public OMessageVarType.Part apply(Part part) {
                            OVarType partType;
                            if (part.getElementName() != null) {
                                partType = resolveElementType(part.getElementName());
                            } else {
                                partType = resolveXsdType(part.getTypeName());
                            }

                            OMessageVarType.Part opart = new OMessageVarType.Part(_oprocess, part.getName(), partType);
                            opart.setDebugInfo(createDebugInfo(_processDef, ("Message Variable Part: " + (part.getName()))));
                            return opart;
                        }
                    });
            msgType = new OMessageVarType(_oprocess, msg.getQName(), parts);
            msgType.setDebugInfo(createDebugInfo(_processDef, ("Message Type: " + (msg.getQName()))));
            _oprocess.getMessageTypes().put(msg.getQName(), msgType);
        }
        return msgType;
    }

    public OXsdTypeVarType resolveXsdType(QName typeName) throws CompilationException {
        OXsdTypeVarType type = _oprocess.getXsdTypes().get(typeName);
        if (type == null) {
            __log.debug("Resolving XSD type " + typeName);
            SchemaModel model = null;
            try {
                model = _wsdlRegistry.getSchemaModel();
            } catch (IllegalArgumentException iaa) { }
            if (model == null || !model.knowsSchemaType(typeName))
                throw new CompilationException(__cmsgs.errUndeclaredXsdType(typeName));

            type = new OXsdTypeVarType(_oprocess);
            type.setDebugInfo(createDebugInfo(_processDef, ("XSD Type: " + typeName)));
            type.setXsdType(typeName);
            type.setSimple(_wsdlRegistry.getSchemaModel().isSimpleType(typeName));
            _oprocess.getXsdTypes().put(typeName, type);
        }

        return type;
    }

    public OMessageVarType.Part resolvePart(OScope.Variable var, String partname) {
        if (!(var.getType() instanceof OMessageVarType))
            throw new CompilationException(__cmsgs.errMessageVariableRequired(var.getName()));
        OMessageVarType msgVarType = (OMessageVarType) var.getType();
        OMessageVarType.Part part = msgVarType.getParts().get(partname);
        if (part == null)
            throw new CompilationException(__cmsgs.errUndeclaredMessagePart(var.getName(), ((OMessageVarType) var.getType()).getMessageType(),
                    partname));
        return part;
    }

    public OMessageVarType.Part resolveHeaderPart(OScope.Variable var, String partname) {
        if (!(var.getType() instanceof OMessageVarType))
            throw new CompilationException(__cmsgs.errMessageVariableRequired(var.getName()));
        OMessageVarType msgVarType = (OMessageVarType) var.getType();
        return msgVarType.getParts().get(partname);
    }

    public PartnerLinkType resolvePartnerLinkType(QName partnerLinkType) {

        PartnerLinkType plinkType = _wsdlRegistry.getPartnerLinkType(partnerLinkType);
        if (plinkType == null)
            throw new CompilationException(__cmsgs.errUndeclaredPartnerLinkType(partnerLinkType));
        return plinkType;
    }

    public OPartnerLink resolvePartnerLink(String name) {
        for (Iterator<OScope> i = _structureStack.oscopeIterator(); i.hasNext();) {
            OPartnerLink oplink = i.next().getLocalPartnerLink(name);
            if (oplink != null)
                return oplink;
        }

        throw new CompilationException(__cmsgs.errUndeclaredPartnerLink(name));
    }

    @SuppressWarnings("unchecked")
    public Operation resolvePartnerRoleOperation(final OPartnerLink partnerLink, final String operationName) {
        if (partnerLink.getPartnerRolePortType() == null) {
            throw new CompilationException(__cmsgs.errPartnerLinkDoesNotDeclarePartnerRole(partnerLink.getName()));
        }

        Operation found = CollectionsX.find_if((List<Operation>) partnerLink.getPartnerRolePortType().getOperations(),
                new MemberOfFunction<Operation>() {
                    public boolean isMember(Operation o) {
                        // Guard against WSDL4j funny business.
                        if ((o.getInput() == null || o.getInput().getMessage() == null)
                                && (o.getOutput() == null || o.getOutput().getMessage() == null)) {
                            return false;
                        }
                        return o.getName().equals(operationName);
                    }
                });

        if (found == null)
            throw new CompilationException(__cmsgs
                    .errUndeclaredOperation(partnerLink.getPartnerRolePortType().getQName(), operationName));
        return found;
    }

    @SuppressWarnings("unchecked")
    public Operation resolveMyRoleOperation(final OPartnerLink partnerLink, final String operationName) {
        if (partnerLink.getMyRolePortType() == null) {
            throw new CompilationException(__cmsgs.errPartnerLinkDoesNotDeclareMyRole(partnerLink.getName()));
        }

        Operation found = CollectionsX.find_if((List<Operation>) partnerLink.getMyRolePortType().getOperations(),
                new MemberOfFunction<Operation>() {
                    public boolean isMember(Operation o) {
                        // Again, guard against WSDL4J's "help"
                        if ((o.getInput() == null || o.getInput().getMessage() == null)
                                && (o.getOutput() == null || o.getOutput().getMessage() == null))
                            return false;
                        return o.getName().equals(operationName);
                    }
                });
        if (found == null) {
            throw new CompilationException(__cmsgs.errUndeclaredOperation(partnerLink.getMyRolePortType().getQName(), operationName));
        }
        return found;
    }

    /**
     * Produce a boolean {@link OExpression} expression that returns a constant
     * value.
     *
     * @param value
     *            constant value to return
     * @return {@link OExpression} returning a constant value.
     */
    public OExpression constantExpr(boolean value) {
        OConstantExpression ce = new OConstantExpression(_oprocess, value ? Boolean.TRUE : Boolean.FALSE);
        ce.setDebugInfo(createDebugInfo(_processDef, ("Constant Boolean Expression: " + value)));
        ce.setExpressionLanguage(_konstExprLang);
        return ce;
    }

    public OLValueExpression compileLValueExpr(Expression expression) throws CompilationException {
        return compileLValueExpr(expression, null, null, new Object[1]);
    }

    public OLValueExpression compileLValueExpr(Expression expression, OVarType rootNodeType, Object requestedResultType, Object[] resultType) throws CompilationException {
        return (OLValueExpression) compileExpr(expression, false, true, rootNodeType, requestedResultType, resultType);
    }

    public OExpression compileJoinCondition(Expression expression) throws CompilationException {
        return compileExpr(expression, true, false, null, null, new Object[1]);
    }

    public OExpression compileExpr(Expression expression) throws CompilationException {
        return compileExpr(expression, null, null, new Object[1]);
    }

    public OExpression compileExpr(Expression expression, OVarType rootNodeType, Object requestedResultType, Object[] resultType) throws CompilationException {
        return compileExpr(expression, false, false, rootNodeType, requestedResultType, resultType);
    }

    public OExpression compileExpr(String expr, NSContext nc) {
        // Does this really work?
        BpelObject cur = _structureStack.topSource();
        return compileExpr(new Expression11(cur.getElement(),cur.getElement().getOwnerDocument().createTextNode(expr)), false, false, null, null, new Object[1]);
    }

    private OExpression compileExpr(Expression expression, boolean isJoinCondition, boolean isLValue, OVarType rootNodeType, Object requestedResultType, Object[] resultType) {
        String expLang = getExpressionLanguage(expression);
        ExpressionCompiler ec = findExpLangCompiler(expLang);
        ec.setCompilerContext(this);
        ExpressionValidator ev = _expressionValidatorFactory.getValidator();

        try {
            OExpression oexpr;
            if (isJoinCondition) {
                oexpr = ec.compileJoinCondition(expression);
            } else {
                oexpr = ec.compile(expression);
                resultType[0] = ev.validate(expression, rootNodeType, requestedResultType);
            }

            oexpr.setDebugInfo(createDebugInfo(expression, expression.toString()));

            OExpressionLanguage expLanguage = _expLanguages.get(expLang);
            if (expLanguage == null) {
                expLanguage = new OExpressionLanguage(_oprocess, ec.getProperties());
                expLanguage.setDebugInfo(createDebugInfo(_processDef, ("Expression Language: " + expLang)));
                expLanguage.setExpressionLanguageUri(expLang);
                _expLanguages.put(expLang, expLanguage);
                _oprocess.getExpressionLanguages().add(expLanguage);
            }
            oexpr.setExpressionLanguage(expLanguage);

            // Cleaning up expression compiler for furter compilation
            ec.setCompilerContext(null);

            return oexpr;
        } catch (CompilationException ce) {
            if (ce.getCompilationMessage().source == null)
                ce.getCompilationMessage().setSource(expression);
            throw ce;
        }
    }

    public OProcess getOProcess() throws CompilationException {
        return _oprocess;
    }

    public void recoveredFromError(SourceLocation where, CompilationException bce) throws CompilationException {
        if (bce.getCompilationMessage().source == null)
            bce.getCompilationMessage().source = where;

        if (_compileListener == null) {
            switch (bce.getCompilationMessage().severity) {
            case CompilationMessage.INFO:
                if (__log.isInfoEnabled()) {
                    __log.info(bce.toErrorMessage());
                }
                break;
            case CompilationMessage.WARN:
                if (__log.isWarnEnabled()) {
                    __log.warn(bce.toErrorMessage());
                }
                break;
            case CompilationMessage.ERROR:
                if (__log.isErrorEnabled()) {
                    __log.error(bce.toErrorMessage());
                }
            }
        } else {
            if (__log.isDebugEnabled()) {
                __log.debug(bce.toErrorMessage(), bce);
            }
            _compileListener.onCompilationMessage(bce.getCompilationMessage());
        }

        _errors.add(bce.getCompilationMessage());
    }

    public static long getVersion(String dirName) {
        try {
            return Integer.parseInt(dirName.substring(dirName.lastIndexOf("-") + 1));
        } catch (Throwable t) {
            return 0;
        }
    }

    /**
     * Compile a process.
     */
    public OProcess compile(final Process process, ResourceFinder rf, long version) throws CompilationException {
        if (process == null)
            throw new NullPointerException("Null process parameter");

        setResourceFinder(rf);
        _processURI = process.getURI();
        _processDef = process;
        _generatedDate = new Date();
        _structureStack.clear();

        String bpelVersionUri = null;
        switch (process.getBpelVersion()) {
        case BPEL11:
            bpelVersionUri = Bpel11QNames.NS_BPEL4WS_2003_03;
            break;
        case BPEL20_DRAFT:
            bpelVersionUri = Bpel20QNames.NS_WSBPEL2_0;
            break;
        case BPEL20:
            bpelVersionUri = Bpel20QNames.NS_WSBPEL2_0_FINAL_EXEC;
            break;
        default:
            throw new IllegalStateException("Bad bpel version: " + process.getBpelVersion());
        }

        _oprocess = new OProcess(bpelVersionUri);
        _oprocess.setGuid(null);
        _oprocess.setConstants(makeConstants());
        _oprocess.setDebugInfo(createDebugInfo(process, "process"));
        _oprocess.setNamespaceContext(process.getNamespaceContext());
        
        if (process.getTargetNamespace() == null) {
            _oprocess.setTargetNamespace("--UNSPECIFIED--");
            recoveredFromError(process, new CompilationException(__cmsgs.errProcessNamespaceNotSpecified()));
        } else {
            _oprocess.setTargetNamespace(_processDef.getTargetNamespace());
        }

        if (process.getName() == null) {
            _oprocess.setProcessName("--UNSPECIFIED--");
            recoveredFromError(process, new CompilationException(__cmsgs.errProcessNameNotSpecified()));
        } else {
            _oprocess.setProcessName(_processDef.getName());
        }

        _oprocess.setCompileDate(_generatedDate);

        _konstExprLang = new OExpressionLanguage(_oprocess, null);
        _konstExprLang.setDebugInfo(createDebugInfo(_processDef, "Constant Value Expression Language"));
        _konstExprLang.setExpressionLanguageUri("uri:www.fivesight.com/konstExpression");
        _konstExprLang.getProperties().put("runtime-class",
                "org.apache.ode.bpel.runtime.explang.konst.KonstExpressionLanguageRuntimeImpl");
        _oprocess.getExpressionLanguages().add(_konstExprLang);

        // Process the imports. Note, we expect all processes (Event BPEL 1.1)
        // to have an import declaration. This should be automatically generated
        // by the 1.1 parser.
        for (Import imprt : _processDef.getImports()) {
            try {
                compile(_processURI, imprt);
            } catch (CompilationException bce) {
                // We try to recover from import problems by continuing
                recoveredFromError(imprt, bce);
            }
        }

        _expressionValidatorFactory.getValidator().bpelImportsLoaded(_processDef, this);

        switch (_processDef.getSuppressJoinFailure()) {
        case NO:
        case NOTSET:
            _supressJoinFailure = false;
            break;
        case YES:
            _supressJoinFailure = true;
            break;
        }
        // compile ALL wsdl properties; needed for property extraction
        Definition4BPEL[] defs = _wsdlRegistry.getDefinitions();
        for (Definition4BPEL def : defs) {
            for (Property property : def.getProperties()) {
                compile(property);
            }
        }
        // compile ALL wsdl property aliases
        for (Definition4BPEL def1 : defs) {
            for (PropertyAlias propertyAlias : def1.getPropertyAliases()) {
                compile(propertyAlias);
            }
        }

        OScope procesScope = new OScope(_oprocess, null);
        procesScope.setName("__PROCESS_SCOPE:" + (process.getName()));
        procesScope.setDebugInfo(createDebugInfo(process, null));
        _oprocess.setProcesScope(compileScope(procesScope, process, new java.lang.Runnable() {
    public void run() {
    	 if (process.getRootActivity() == null) {
             throw new CompilationException(__cmsgs.errNoRootActivity());
         }
         // Process custom properties are created as variables associated
         // with the top scope
         if (_customProcessProperties != null) {
             for (Map.Entry<QName, Node> customVar : _customProcessProperties.entrySet()) {
                 final OScope oscope = _structureStack.topScope();
                 OVarType varType = new OConstantVarType(_oprocess, customVar.getValue());
                 OScope.Variable ovar = new OScope.Variable(_oprocess, varType);
                 ovar.setName(customVar.getKey().getLocalPart());
                 ovar.setDeclaringScope(oscope);
                 ovar.setDebugInfo(createDebugInfo(null, "Process custom property variable"));
                 oscope.addLocalVariable(ovar);
                 if (__log.isDebugEnabled())
                     __log.debug("Compiled custom property variable " + ovar);
             }
         }
         _structureStack.topScope().setActivity(compile(process.getRootActivity()));
     }
 }));


        assert _structureStack.size() == 0;

        boolean hasErrors = false;
        StringBuffer sb = new StringBuffer();
        for (CompilationMessage msg : _errors) {
            if (msg.severity >= CompilationMessage.ERROR) {
                hasErrors = true;
                sb.append('\t');
                sb.append(msg.toErrorString());
                sb.append('\n');
            }
        }

        XslTransformHandler.getInstance().clearXSLSheets(_oprocess.getQName());

        _expressionValidatorFactory.getValidator().bpelCompilationCompleted(_processDef);

        if (hasErrors) {
            throw new CompilationException(__cmsgs.errCompilationErrors(_errors.size(), sb.toString()));
        }

        {
            String digest = "version:" + version + ";" + _oprocess.digest();
            _oprocess.setGuid(org.apache.ode.utils.GUID.makeGUID(digest));
            if (__log.isDebugEnabled()) {
                __log.debug("Compiled process digest: " + digest + "\nguid: " + _oprocess.getGuid());
            }
        }
        return _oprocess;
    }

    private OConstants makeConstants() {
        OConstants constants = new OConstants(_oprocess);
        constants.setQnConflictingReceive(new javax.xml.namespace.QName(getBpwsNamespace() , "conflictingReceive"));
        constants.setQnConflictingRequest(new javax.xml.namespace.QName(getBpwsNamespace() , "conflictingRequest"));
        constants.setQnCorrelationViolation(new javax.xml.namespace.QName(getBpwsNamespace() , "correlationViolation"));
        constants.setQnForcedTermination(new javax.xml.namespace.QName(getBpwsNamespace() , "forcedTermination"));
        constants.setQnJoinFailure(new javax.xml.namespace.QName(getBpwsNamespace() , "joinFailure"));
        constants.setQnMismatchedAssignmentFailure(new javax.xml.namespace.QName(getBpwsNamespace() , "mismatchedAssignment"));
        constants.setQnMissingReply(new javax.xml.namespace.QName(getBpwsNamespace() , "missingReply"));
        constants.setQnMissingRequest(new javax.xml.namespace.QName(getBpwsNamespace() , "missingRequest"));
        constants.setQnSelectionFailure(new javax.xml.namespace.QName(getBpwsNamespace() , "selectionFailure"));
        constants.setQnUninitializedVariable(new javax.xml.namespace.QName(getBpwsNamespace() , "uninitializedVariable"));
        constants.setQnXsltInvalidSource(new javax.xml.namespace.QName(getBpwsNamespace() , "xsltInvalidSource"));
        constants.setQnSubLanguageExecutionFault(new javax.xml.namespace.QName(getBpwsNamespace() , "subLanguageExecutionFault"));
        constants.setQnUninitializedPartnerRole(new javax.xml.namespace.QName(getBpwsNamespace() , "uninitializedPartnerRole"));
        constants.setQnForEachCounterError(new javax.xml.namespace.QName(getBpwsNamespace() , "forEachCounterError"));
        constants.setQnInvalidBranchCondition(new javax.xml.namespace.QName(getBpwsNamespace() , "invalidBranchCondition"));
        constants.setQnInvalidExpressionValue(new javax.xml.namespace.QName(getBpwsNamespace() , "invalidExpressionValue"));

        constants.setQnRetiredProcess(new javax.xml.namespace.QName(getOdeNamespace() , "retiredProcess"));
        constants.setQnTooManyInstances(new javax.xml.namespace.QName(getOdeNamespace() , "tooManyInstances"));
        constants.setQnUnknownFault(new javax.xml.namespace.QName(getOdeNamespace() , "unknownFault"));
        constants.setQnTooManyProcesses(new javax.xml.namespace.QName(getOdeNamespace() , "tooManyProcesses"));
        constants.setQnTooHugeProcesses(new javax.xml.namespace.QName(getOdeNamespace() , "tooHugeProcesses"));
        return constants;
    }

    private String getOdeNamespace() {
        return Namespaces.ODE_EXTENSION_NS;
    }

    // TODO unused?
    // private String getBpelPartnerLinkUri(){
    // switch(_processDef.getBpelVersion()){
    // case Process.BPEL_V110:
    // return Constants.NS_BPEL4WS_PARTNERLINK_2003_05;
    // case Process.BPEL_V200:
    // return Constants.NS_WSBPEL_PARTNERLINK_2004_03;
    // default:
    // throw new IllegalStateException("Bad bpel version.");
    // }
    // }

    /**
     * Compile an import declaration. According to the specification:
     * <blockquote> A BPEL4WSWS-BPEL process definition relies on XML Schema and
     * WSDL 1.1 for the definition of datatypes and service interfaces. Process
     * definitions also rely on other constructs such as partner link types,
     * message properties and property aliases (defined later in this
     * specification) which are defined within WSDL 1.1 documents using the WSDL
     * 1.1 language extensibility feature.
     *
     * The &lt;import&gt; element is used within a BPEL4WSWS-BPEL process to
     * explicitly indicate a dependency on external XML Schema or WSDL
     * definitions. Any number of <import> elements may appear as initial
     * children of the <process> element, before any other child element. Each
     * <import> element contains three mandatory attributes:
     * <ol>
     * <li>namespace -- The namespace attribute specifies the URI namespace of
     * the imported definitions. </li>
     * <li>location -- The location attribute contains a URI indicating the
     * location of a document that contains relevant definitions in the
     * namespace specified. The document located at the URI MUST contain
     * definitions belonging to the same namespace as indicated by the namespace
     * attribute. </li>
     * <li>importType -- The importType attribute identifies the type of
     * document being imported by providing the URI of the encoding language.
     * The value MUST be set to "http://www.w3.org/2001/XMLSchema" when
     * importing XML Schema 1.0 documents, and to
     * "http://schemas.xmlsoap.org/wsdl/" when importing WSDL 1.1 documents.
     *
     * @param imprt
     *            BOM representation of the import
     */
    private void compile(URI current, Import imprt) {
        try {
            if (imprt.getImportType() == null)
                throw new CompilationException(__cmsgs.errUnspecifiedImportType().setSource(imprt));

            if (imprt.getLocation() == null)
                throw new CompilationException(__cmsgs.errMissingImportLocation().setSource(imprt));

            if (Import.IMPORTTYPE_WSDL11.equals(imprt.getImportType())) {
                addWsdlImport(current, imprt.getLocation(), imprt);
            } else if (Import.IMPORTTYPE_XMLSCHEMA10.equals(imprt.getImportType())) {
                addXsdImport(current, imprt.getLocation(), imprt);
            } else
                throw new CompilationException(__cmsgs.errUnknownImportType(imprt.getImportType()).setSource(imprt));
        } catch (CompilationException ce) {
            if (ce.getCompilationMessage().source == null)
                ce.getCompilationMessage().setSource(imprt);
            throw ce;
        }
    }

    public OActivity compile(final Activity source) {
        if (source == null)
            throw new IllegalArgumentException("null-argument");

        boolean previousSupressJoinFailure = _supressJoinFailure;
        switch (source.getSuppressJoinFailure()) {
        case NO:
            _supressJoinFailure = false;
            break;
        case YES:
            _supressJoinFailure = true;
            break;
        }

        OActivity compiled;
        try {
            compiled = (source instanceof ScopeLikeActivity) ? compileSLC((ScopeLikeActivity) source, new OScope.Variable[0])
                    : compileActivity(true, source);
            compiled.setSuppressJoinFailure(_supressJoinFailure);
        } finally {
            _supressJoinFailure = previousSupressJoinFailure;
        }

        if (__log.isDebugEnabled())
            __log.debug("Compiled activity " + compiled);
        return compiled;
    }

    private OCompensate createDefaultCompensateActivity(BpelObject source, String desc) {
        OCompensate activity = new OCompensate(_oprocess, getCurrent());
        activity.setName("__autoGenCompensate:" + (_structureStack.topScope().getName()));
        activity.setDebugInfo(createDebugInfo(source, desc));
        return activity;
    }

    public OScope compileSLC(final ScopeLikeActivity source, final OScope.Variable[] variables) {
        final OScope implicitScope = new OScope(_oprocess, getCurrent());
        implicitScope.setImplicitScope(true);
        implicitScope.setName(createName(source, "implicit-scope"));
        implicitScope.setDebugInfo(createDebugInfo(source, ("Scope-like construct " + source)));
        compileScope(implicitScope, source.getScope(), new Runnable() {
            public void run() {
                compileLinks(source);
                for (OScope.Variable v : variables) {
                    v.setDeclaringScope(implicitScope);
                    implicitScope.addLocalVariable(v);
                }
                if (source instanceof ScopeActivity) {
                    Activity scopeChild = ((ScopeActivity) source).getChildActivity();
                    if (scopeChild == null)
                        throw new CompilationException(__cmsgs.errEmptyScope().setSource(source));
                    implicitScope.setActivity(compile(scopeChild));
                } else {
                    implicitScope.setActivity(compileActivity(false, source));
                }
            }
        });

        return implicitScope;
    }

    private OActivity compileActivity(final boolean doLinks, final Activity source) {
        final ActivityGenerator actgen = findActivityGen(source);
        final OActivity oact = actgen.newInstance(source);
        oact.setName(createName(source, "activity"));
        oact.setDebugInfo(createDebugInfo(source, ("Activity body for " + source)));
        _compiledActivities.add(oact);
        compile(oact, source, new Runnable() {
            public void run() {
                if (doLinks)
                    compileLinks(source);
                actgen.compile(oact, source);
            }
        });

        return oact;
    }

    private void compileLinks(Activity source) {
        /* Source Links Fixup */
        for (LinkSource ls : source.getLinkSources())
            compileLinkSource(ls);

        /* Target Links Fixup */
        for (LinkTarget lt : source.getLinkTargets())
            compileLinkTarget(lt);

        _structureStack.topActivity().setJoinCondition(((source.getJoinCondition()) == null) || (source.getLinkTargets().isEmpty()) ? null : compileJoinCondition(source.getJoinCondition()));
    }

    private String createName(Activity source, String type) {
        if (source.getName() != null)
            return source.getName();

        return source.getType().getLocalPart() + "-" + type + "-line-" + source.getLineNo();
    }

    private OProcess.OProperty compile(Property property) {
        OProcess.OProperty oproperty = new OProcess.OProperty(_oprocess);
        oproperty.setName(property.getName());
        oproperty.setDebugInfo(createDebugInfo(_processDef, ("Property " + (property.getName()))));

        if (!_wsdlRegistry.getSchemaModel().isSimpleType(property.getPropertyType()))
            throw new CompilationException(__cmsgs.errPropertyDeclaredWithComplexType(property.getName(),
                    property.getPropertyType()).setSource(property));

        _oprocess.getProperties().add(oproperty);

        if (__log.isDebugEnabled())
            __log.debug("Compiled property " + oproperty);

        return oproperty;
    }

    private OProcess.OPropertyAlias compile(PropertyAlias src) {
        OProcess.OProperty property = resolveProperty(src.getPropertyName());

        OProcess.OPropertyAlias alias = new OProcess.OPropertyAlias(_oprocess);
        alias.setDebugInfo(createDebugInfo(_processDef, ((("PropertyAlias " + (src.getPropertyName())) + " for ") + (src.getMessageType()))));
        if (src.getMessageType() == null) {
            throw new CompilationException(__cmsgs.errAliasUndeclaredMessage(src.getPropertyName(), src.getQuery().getPath()));
        }

        OMessageVarType messageType = resolveMessageType(src.getMessageType());
        OVarType rootNodeType = messageType;
        alias.setVarType(messageType);
        // bpel 2.0 excludes declaration of part;
        // bpel 1.1 requires it
        if (src.getPart() != null) {
            alias.setPart(messageType.getParts().get(src.getPart()));
            if (alias.getPart() == null)
                throw new CompilationException(__cmsgs.errUnknownPartInAlias(src.getPart(),
                        messageType.getMessageType().toString()));
            rootNodeType = alias.getPart().getType();
        } else if (src.getHeader() != null) {
            alias.setHeader(src.getHeader());
            rootNodeType = new OElementVarType(_oprocess, QName.valueOf("{http://www.w3.org/2001/XMLSchema}any"));
        }
        if (src.getQuery() != null)
            alias.setLocation(compileExpr(src.getQuery(), rootNodeType, null, new java.lang.Object[1]));
        property.getAliases().add(alias);
        alias.setDebugInfo(createDebugInfo(_processDef, (((src.getMessageType()) + " --> ") + (src.getPropertyName()))));
        return alias;
    }

    private void compileLinkTarget(LinkTarget target) {
        OLink ol = resolveLink(target.getLinkName());
        assert ol != null;
        ol.setDebugInfo(createDebugInfo(target, target.toString()));
        if (ol.getTarget() != null)
            throw new CompilationException(__cmsgs.errDuplicateLinkTarget(target.getLinkName()).setSource(target));
        ol.setTarget(_structureStack.topActivity());

        _structureStack.topActivity().getTargetLinks().add(ol);
    }

    private void compileLinkSource(LinkSource linksrc) {
        OLink ol = resolveLink(linksrc.getLinkName());
        assert ol != null;
        ol.setDebugInfo(createDebugInfo(linksrc, linksrc.toString()));
        if (ol.getSource() != null)
            throw new CompilationException(__cmsgs.errDuplicateLinkSource(linksrc.getLinkName()).setSource(linksrc));
        ol.setSource(_structureStack.topActivity());
        ol.setTransitionCondition((linksrc.getTransitionCondition()) == null ? constantExpr(true) : compileExpr(linksrc.getTransitionCondition()));

        _structureStack.topActivity().getSourceLinks().add(ol);
        _structureStack.topActivity().getOutgoingLinks().add(ol);
    }

    private void compile(final PartnerLink plink) {
        OPartnerLink oplink = new OPartnerLink(_oprocess);
        oplink.setDebugInfo(createDebugInfo(plink, plink.toString()));
        try {
            PartnerLinkType plinkType = resolvePartnerLinkType(plink.getPartnerLinkType());

            oplink.setPartnerLinkType(plinkType.getName());
            oplink.setName(plink.getName());
            oplink.setInitializePartnerRole(plink.isInitializePartnerRole());

            if (plink.hasMyRole()) {
                PartnerLinkType.Role myRole = plinkType.getRole(plink.getMyRole());
                if (myRole == null)
                    throw new CompilationException(__cmsgs.errUndeclaredRole(plink.getMyRole(), plinkType.getName()));
                oplink.setMyRoleName(myRole.getName());
                QName portType = myRole.getPortType();
                if (portType == null)
                    throw new CompilationException(__cmsgs.errMissingMyRolePortType(myRole.getPortType(), plink.getMyRole(), plinkType.getName()));
                oplink.setMyRolePortType(resolvePortType(portType));
            }

            if (plink.isInitializePartnerRole() && !plink.hasPartnerRole()) {
                throw new CompilationException(__cmsgs.errPartnerLinkNoPartnerRoleButInitialize(plink.getName()));
            }
            if (plink.hasPartnerRole()) {
                PartnerLinkType.Role partnerRole = plinkType.getRole(plink.getPartnerRole());
                if (partnerRole == null)
                    throw new CompilationException(__cmsgs.errUndeclaredRole(plink.getPartnerRole(), plinkType.getName()));
                oplink.setPartnerRoleName(partnerRole.getName());
                QName portType = partnerRole.getPortType();
                if (portType == null)
                    throw new CompilationException(__cmsgs.errMissingPartnerRolePortType(partnerRole.getPortType(), plink.getPartnerRole(), plinkType.getName()));
                oplink.setPartnerRolePortType(resolvePortType(portType));
            }

            oplink.setDeclaringScope(_structureStack.topScope());
            if (oplink.getDeclaringScope().getPartnerLinks().containsKey(oplink.getName()))
                throw new CompilationException(__cmsgs.errDuplicatePartnerLinkDecl(oplink.getName()));
            oplink.getDeclaringScope().getPartnerLinks().put(oplink.getName(), oplink);
            _oprocess.getAllPartnerLinks().add(oplink);
        } catch (CompilationException ce) {
            ce.getCompilationMessage().setSource(plink);
            throw ce;
        }
    }

    private void compile(CorrelationSet cset) {
        OScope oscope = _structureStack.topScope();
        OScope.CorrelationSet ocset = new OScope.CorrelationSet(_oprocess);
        ocset.setName(cset.getName());
        ocset.setDeclaringScope(oscope);
        ocset.setDebugInfo(createDebugInfo(cset, cset.toString()));
        QName[] setprops = cset.getProperties();
        for (int j = 0; j < setprops.length; ++j)
            ocset.getProperties().add(resolveProperty(setprops[j]));
        oscope.addCorrelationSet(ocset);
    }

    public OActivity getCurrent() {
        return _structureStack.topActivity();
    }

    public void compile(OActivity context, BpelObject source, Runnable run) {
        DefaultActivityGenerator.defaultExtensibilityElements(context, source);
        _structureStack.push(context, source);
        try {
            run.run();
        } finally {
            OActivity popped = _structureStack.pop();

            OActivity newtop = _structureStack.topActivity();
            OScope topScope = _structureStack.topScope();

            if (newtop != null) {
                newtop.getNested().add(popped);
                // Transfer outgoing and incoming links, excluding the locally defined links.
                newtop.getIncomingLinks().addAll(popped.getIncomingLinks());
                if (newtop instanceof OFlow) newtop.getIncomingLinks().removeAll(((OFlow) newtop).getLocalLinks());
                newtop.getOutgoingLinks().addAll(popped.getOutgoingLinks());

                if (newtop instanceof OFlow) newtop.getOutgoingLinks().removeAll(((OFlow) newtop).getLocalLinks());

                // Transfer variables read/writen
                newtop.getVariableRd().addAll(popped.getVariableRd());
                newtop.getVariableWr().addAll(popped.getVariableWr());
            }

            if (topScope != null && popped instanceof OScope) topScope.getCompensatable().add((OScope) popped);
        }
    }

    private OScope compileScope(final OScope oscope, final Scope src, final Runnable init) {
        if (oscope.getName() == null)
            throw new IllegalArgumentException("Unnamed scope:" + src);

        oscope.setDebugInfo(createDebugInfo(src, src.toString()));

        //TODO: Is the logic incorrect? 
        boolean previousAtomicScope = _atomicScope;
        if (src.getAtomicScope() != null) {
            boolean newValue = src.getAtomicScope().booleanValue();
            if (_atomicScope)
                throw new CompilationException(__cmsgs.errAtomicScopeNesting(newValue));

            oscope.setAtomicScope(_atomicScope = newValue);
        }

        if (src.getIsolatedScope() != null) {
            if (src.getIsolatedScope()) {
                if (_isolatedScope)
                    throw new CompilationException(__cmsgs.errIsolatedScopeNesting());

                oscope.setIsolatedScope(_isolatedScope = true);
            }
        }

        try {
            compile(oscope, src, new Runnable() {
                public void run() {
                    for (Variable var : src.getVariables()) {
                        try {
                            compile(var);
                        } catch (CompilationException ce) {
                            recoveredFromError(var, ce);
                        }
                    }

                    for (CorrelationSet cset : src.getCorrelationSetDecls()) {
                        try {
                            compile(cset);
                        } catch (CompilationException ce) {
                            recoveredFromError(cset, ce);
                        }
                    }

                    for (PartnerLink plink : src.getPartnerLinks()) {
                        try {
                            compile(plink);
                        } catch (CompilationException ce) {
                            recoveredFromError(plink, ce);
                        }
                    }

                    if (!src.getEvents().isEmpty() || !src.getAlarms().isEmpty()) {
                        oscope.setEventHandler(new org.apache.ode.bpel.obj.OEventHandler(_oprocess));
                        oscope.getEventHandler().setDebugInfo(createDebugInfo(src, ("Event Handler for " + src)));
                    }

                    for (OnEvent onEvent : src.getEvents()) {
                        try {
                            compile(onEvent);
                        } catch (CompilationException ce) {
                            recoveredFromError(src, ce);
                        }
                    }

                    for (OnAlarm onAlarm : src.getAlarms()) {
                        try {
                            compile(onAlarm);
                        } catch (CompilationException ce) {
                            recoveredFromError(src, ce);
                        }

                    }

                    if (init != null)
                        try {
                            init.run();
                        } catch (CompilationException ce) {
                            recoveredFromError(src, ce);
                        }

                    try {
                        compile(src.getCompensationHandler());
                    } catch (CompilationException bce) {
                        recoveredFromError(src.getCompensationHandler(), bce);
                    }

                    try {
                        compile(src.getTerminationHandler());
                    } catch (CompilationException bce) {
                        recoveredFromError(src.getTerminationHandler(), bce);
                    }

                    try {
                        compile(src.getFaultHandler());
                    } catch (CompilationException bce) {
                        recoveredFromError(src.getFaultHandler(), bce);
                    }
                }
            });
        } finally {
            _atomicScope = previousAtomicScope;
        }

        return oscope;
    }

    private void compile(final OnAlarm onAlarm) {
        OScope oscope = _structureStack.topScope();
        assert oscope.getEventHandler() != null;

        final OEventHandler.OAlarm oalarm = new OEventHandler.OAlarm(_oprocess);
        oalarm.setDebugInfo(createDebugInfo(onAlarm, ("OnAlarm Event Handler: " + onAlarm)));

        if (onAlarm.getFor() != null && onAlarm.getUntil() == null) {
            oalarm.setForExpr(compileExpr(onAlarm.getFor()));
        } else if (onAlarm.getFor() == null && onAlarm.getUntil() != null) {
            oalarm.setUntilExpr(compileExpr(onAlarm.getUntil()));
        } else if (onAlarm.getFor() != null && onAlarm.getUntil() != null) {
            throw new CompilationException(__cmsgs.errInvalidAlarm().setSource(onAlarm));
        } else if (onAlarm.getRepeatEvery() == null) {
            throw new CompilationException(__cmsgs.errInvalidAlarm().setSource(onAlarm));
        }

        if (onAlarm.getRepeatEvery() != null)
            oalarm.setRepeatExpr(compileExpr(onAlarm.getRepeatEvery()));

        if (onAlarm.getActivity() == null) throw new CompilationException(__cmsgs.errInvalidAlarm().setSource(onAlarm));
        oalarm.setActivity(compile(onAlarm.getActivity()));

        // Check links crossing restrictions.
        for (OLink link : oalarm.getIncomingLinks())
            try {
                throw new CompilationException(__cmsgs.errLinkCrossesEventHandlerBoundary(link.getName()).setSource(onAlarm));
            } catch (CompilationException ce) {
                recoveredFromError(onAlarm, ce);
            }

        for (OLink link : oalarm.getOutgoingLinks())
            try {
                throw new CompilationException(__cmsgs.errLinkCrossesEventHandlerBoundary(link.getName()).setSource(onAlarm));
            } catch (CompilationException ce) {
                recoveredFromError(onAlarm, ce);
            }

        oscope.getEventHandler().getOnAlarms().add(oalarm);
    }

    private void compile(final OnEvent onEvent) {
        final OScope oscope = _structureStack.topScope();
        assert oscope.getEventHandler() != null;

        final OEventHandler.OEvent oevent = new OEventHandler.OEvent(_oprocess, oscope);
        oevent.setName("__eventHandler:");
        oevent.setDebugInfo(createDebugInfo(onEvent, null));
        compile(oevent, onEvent, new Runnable() {
            public void run() {
                switch (_processDef.getBpelVersion()) {
                case BPEL11:
                    oevent.setVariable(resolveMessageVariable(onEvent.getVariable()));
                    break;
                case BPEL20_DRAFT:
                case BPEL20:
                    if (onEvent.getMessageType() == null && onEvent.getElementType() == null)
                        throw new CompilationException(__cmsgs.errVariableDeclMissingType(onEvent.getVariable()).setSource(onEvent));
                    if (onEvent.getMessageType() != null && onEvent.getElementType() != null)
                        throw new CompilationException(__cmsgs.errVariableDeclInvalid(onEvent.getVariable()).setSource(onEvent));

                    OVarType varType;
                    if (onEvent.getMessageType() != null)
                        varType = resolveMessageType(onEvent.getMessageType());
                    else if (onEvent.getElement() != null)
                        varType = resolveElementType(onEvent.getElementType());
                    else
                        throw new CompilationException(__cmsgs.errUnrecognizedVariableDeclaration(onEvent.getVariable()));

                    oevent.setVariable(new org.apache.ode.bpel.obj.OScope.Variable(_oprocess , varType));
                    oevent.getVariable().setName(onEvent.getVariable());
                    oevent.getVariable().setDeclaringScope(_structureStack.topScope());

                    oevent.addLocalVariable(oevent.getVariable());
                    break;
                default:
                    throw new AssertionError("Unexpected BPEL VERSION constatnt: " + _processDef.getBpelVersion());
                }

                oevent.setPartnerLink(resolvePartnerLink(onEvent.getPartnerLink()));
                oevent.setOperation(resolveMyRoleOperation(oevent.getPartnerLink(), onEvent.getOperation()));
                oevent.setMessageExchangeId(onEvent.getMessageExchangeId());
                oevent.setRoute(onEvent.getRoute());

                if (onEvent.getPortType() != null && !onEvent.getPortType().equals(oevent.getPartnerLink().getMyRolePortType().getQName()))
                    throw new CompilationException(__cmsgs.errPortTypeMismatch(onEvent.getPortType(),
                            oevent.getPartnerLink().getMyRolePortType().getQName()));

                Set<String> csetNames = new HashSet<String>(); // prevents duplicate cset in on one set of correlations
                for (Correlation correlation : onEvent.getCorrelations()) {
                    if( csetNames.contains(correlation.getCorrelationSet() ) ) {
                        throw new CompilationException(__cmsgs.errDuplicateUseCorrelationSet(correlation
                                .getCorrelationSet()));
                    }

                    OScope.CorrelationSet cset = resolveCorrelationSet(correlation.getCorrelationSet());

                    switch (correlation.getInitiate()) {
                    case UNSET:
                    case NO:
                        oevent.getMatchCorrelations().add(cset);
                        oevent.getPartnerLink().addCorrelationSetForOperation(oevent.getOperation(), cset, false);
                        break;
                    case YES:
                        oevent.getInitCorrelations().add(cset);
                        break;
                    case JOIN:
                        cset.setHasJoinUseCases(true);
                        oevent.getJoinCorrelations().add(cset);
                        oevent.getPartnerLink().addCorrelationSetForOperation(oevent.getOperation(), cset, true);
                    }

                    for (OProcess.OProperty property : cset.getProperties()) {
                        // Force resolution of alias, to make sure that we have
                        // one for this variable-property pair.
                        resolvePropertyAlias(oevent.getVariable(), property.getName());
                    }

                    csetNames.add(correlation.getCorrelationSet());
                }

                if (onEvent.getActivity() == null) throw new CompilationException(__cmsgs.errInvalidAlarm().setSource(onEvent));
                oevent.setActivity(compile(onEvent.getActivity()));
            }
        });

        // Check links crossing restrictions.
        for (OLink link : oevent.getIncomingLinks())
            try {
                throw new CompilationException(__cmsgs.errLinkCrossesEventHandlerBoundary(link.getName()));
            } catch (CompilationException ce) {
                recoveredFromError(onEvent, ce);
            }

        for (OLink link : oevent.getOutgoingLinks())
            try {
                throw new CompilationException(__cmsgs.errLinkCrossesEventHandlerBoundary(link.getName()));
            } catch (CompilationException ce) {
                recoveredFromError(onEvent, ce);
            }

        oscope.getEventHandler().getOnMessages().add(oevent);
    }

    private DebugInfo createDebugInfo(BpelObject bpelObject, String description) {
        int lineNo = bpelObject == null ? -1 : bpelObject.getLineNo();
        String str = description == null && bpelObject != null ? bpelObject.toString() : null;
        Map<QName, Object> extElmt = bpelObject == null ? null : bpelObject.getExtensibilityElements();
        DebugInfo debugInfo = new DebugInfo(_processDef.getSource(), lineNo, extElmt);
        debugInfo.setDescription(str);
        return debugInfo;
    }

    private void compile(final Variable src) {
        final OScope oscope = _structureStack.topScope();

        if (src.getKind() == null)
            throw new CompilationException(__cmsgs.errVariableDeclMissingType(src.getName()).setSource(src));

        if (oscope.getLocalVariable(src.getName()) != null)
            throw new CompilationException(__cmsgs.errDuplicateVariableDecl(src.getName()).setSource(src));

        if (src.getTypeName() == null) throw new CompilationException(__cmsgs.errUnrecognizedVariableDeclaration(src.getName()));
        OVarType varType;
        switch (src.getKind()) {
        case ELEMENT:
            varType = resolveElementType(src.getTypeName());
            break;
        case MESSAGE:
            varType = resolveMessageType(src.getTypeName());
            break;
        case SCHEMA:
            varType = resolveXsdType(src.getTypeName());
            break;
        default:
            throw new CompilationException(__cmsgs.errUnrecognizedVariableDeclaration(src.getName()));
        }

        OScope.Variable ovar = new OScope.Variable(_oprocess, varType);
        ovar.setName(src.getName());
        ovar.setDeclaringScope(oscope);
        ovar.setDebugInfo(createDebugInfo(src, null));

        ovar.setExtVar(compileExtVar(src));

        oscope.addLocalVariable(ovar);

        if (__log.isDebugEnabled())
            __log.debug("Compiled variable " + ovar);
    }


    private void compile(TerminationHandler terminationHandler) {
        OScope oscope = _structureStack.topScope();
        oscope.setTerminationHandler(new org.apache.ode.bpel.obj.OTerminationHandler(_oprocess , oscope));
        oscope.getTerminationHandler().setName("__terminationHandler:" + (oscope.getName()));
        oscope.getTerminationHandler().setDebugInfo(createDebugInfo(terminationHandler, null));
        if (terminationHandler == null) {
            oscope.getTerminationHandler().setActivity(createDefaultCompensateActivity(null, ("Auto-generated \'compensate all\' pseudo-activity for default termination handler on " + (oscope.toString()))));
        } else {
            _recoveryContextStack.push(oscope);
            try {
                oscope.getTerminationHandler().setActivity(compile(terminationHandler.getActivity()));
            } finally {
                _recoveryContextStack.pop();
            }
        }
    }

    private void compile(CompensationHandler compensationHandler) {
        OScope oscope = _structureStack.topScope();
        oscope.setCompensationHandler(new org.apache.ode.bpel.obj.OCompensationHandler(_oprocess , oscope));
        oscope.getCompensationHandler().setName("__compenationHandler_" + (oscope.getName()));
        oscope.getCompensationHandler().setDebugInfo(createDebugInfo(compensationHandler, null));
        if (compensationHandler == null) {
            oscope.getCompensationHandler().setActivity(createDefaultCompensateActivity(compensationHandler, ("Auto-generated \'compensate all\' pseudo-activity for default compensation handler on  " + (oscope.toString()))));
        } else {
            _recoveryContextStack.push(oscope);
            try {
                oscope.getCompensationHandler().setActivity(compile(compensationHandler.getActivity()));
            } finally {
                _recoveryContextStack.pop();
            }
        }
    }

    private void compile(FaultHandler fh) {
        OScope oscope = _structureStack.topScope();
        oscope.setFaultHandler(new org.apache.ode.bpel.obj.OFaultHandler(_oprocess));
        if (fh == null) {
            // The default fault handler compensates all child activities
            // AND then rethrows the fault!
            final OCatch defaultCatch = new OCatch(_oprocess, oscope);
            defaultCatch.setName("__defaultFaultHandler:" + (oscope.getName()));
            defaultCatch.setFaultName(null); // catch any fault
            defaultCatch.setFaultVariable(null);
            OSequence sequence = new OSequence(_oprocess, defaultCatch);
            sequence.setName("__defaultFaultHandler_sequence:" + (oscope.getName()));
            sequence.setDebugInfo(createDebugInfo(fh, "Auto-generated sequence activity."));
            ORethrow rethrow = new ORethrow(_oprocess, sequence);
            rethrow.setName("__defaultFaultHandler_rethrow:" + (oscope.getName()));
            rethrow.setDebugInfo(createDebugInfo(fh, "Auto-generated re-throw activity."));
            sequence.getSequence().add(createDefaultCompensateActivity(fh, "Default compensation handler for " + oscope));
            sequence.getSequence().add(rethrow);

            defaultCatch.setActivity(sequence);
            oscope.getFaultHandler().getCatchBlocks().add(defaultCatch);
            if (__log.isDebugEnabled())
                __log.debug("Compiled default catch block " + defaultCatch + " for " + oscope);

        } else {
            _recoveryContextStack.push(oscope);
            try {

                int i = 0;
                for (final Catch catchSrc : fh.getCatches()) {
                    final OCatch ctch = new OCatch(_oprocess, oscope);
                    ctch.setDebugInfo(createDebugInfo(catchSrc, catchSrc.toString()));
                    ctch.setName((("__catch#" + i) + ":") + (_structureStack.topScope().getName()));
                    ctch.setFaultName(catchSrc.getFaultName());
                    compile(ctch, catchSrc, new Runnable() {
                        public void run() {

                            if (catchSrc.getFaultVariable() != null) {
                                OScope.Variable faultVar;
                                switch (_processDef.getBpelVersion()) {
                                case BPEL11:
                                    faultVar = resolveVariable(catchSrc.getFaultVariable());
                                    if (!(faultVar.getType() instanceof OMessageVarType))
                                        throw new CompilationException(__cmsgs.errMessageVariableRequired(
                                                catchSrc.getFaultVariable()).setSource(catchSrc));
                                    break;
                                case BPEL20_DRAFT:
                                case BPEL20:
                                    if (catchSrc.getFaultVariableMessageType() == null
                                            && catchSrc.getFaultVariableElementType() == null)
                                        throw new CompilationException(__cmsgs.errVariableDeclMissingType(
                                                catchSrc.getFaultVariable()).setSource(catchSrc));
                                    if (catchSrc.getFaultVariableMessageType() != null
                                            && catchSrc.getFaultVariableElementType() != null)
                                        throw new CompilationException(__cmsgs.errVariableDeclMissingType(
                                                catchSrc.getFaultVariable()).setSource(catchSrc));

                                    OVarType faultVarType;
                                    if (catchSrc.getFaultVariableMessageType() != null)
                                        faultVarType = resolveMessageType(catchSrc.getFaultVariableMessageType());
                                    else if (catchSrc.getFaultVariableElementType() != null)
                                        faultVarType = resolveElementType(catchSrc.getFaultVariableElementType());
                                    else
                                        throw new CompilationException(__cmsgs.errUnrecognizedVariableDeclaration(catchSrc
                                                .getFaultVariable()));

                                    faultVar = new OScope.Variable(_oprocess, faultVarType);
                                    faultVar.setName(catchSrc.getFaultVariable());
                                    faultVar.setDeclaringScope(_structureStack.topScope());

                                    ctch.addLocalVariable(faultVar);
                                    break;
                                default:
                                    throw new AssertionError("Unexpected BPEL VERSION constatnt: " + _processDef.getBpelVersion());
                                }

                                ctch.setFaultVariable(faultVar);
                            }

                            if (catchSrc.getActivity() == null)
                                throw new CompilationException(__cmsgs.errEmptyCatch().setSource(catchSrc));
                            _structureStack.topScope().setActivity(compile(catchSrc.getActivity()));
                        }
                    });
                    oscope.getFaultHandler().getCatchBlocks().add(ctch);
                    ++i;
                }
            } finally {
                _recoveryContextStack.pop();
            }

        }
    }

    public OXslSheet compileXslt(String docStrUri) throws CompilationException {
        URI docUri;
        try {
            docUri = new URI(FileUtils.encodePath(docStrUri));
        } catch (URISyntaxException e) {
            throw new CompilationException(__cmsgs.errInvalidDocXsltUri(docStrUri));
        }

        String sheetBody = loadXsltSheet(_processURI.resolve(docUri));
        if (sheetBody == null) {
            throw new CompilationException(__cmsgs.errCantFindXslt(docStrUri));
        }

        OXslSheet oXslSheet = new OXslSheet(_oprocess);
        oXslSheet.setUri(docUri);
        oXslSheet.setSheetBody(sheetBody);

        _oprocess.getXslSheets().put(oXslSheet.getUri(), oXslSheet);
        return oXslSheet;
    }

    private String loadXsltSheet(URI uri) {

        // TODO: lots of null returns, should have some better error messages.
        InputStream is;
        try {
            is = _resourceFinder.openResource(uri);
        } catch (Exception e1) {
            return null;
        }
        if (is == null)
            return null;

        try {
            // verify that sheet is well-formed and preserve encoding.
            Document doc = DOMUtils.parse(is);
            return DOMUtils.domToString(doc);
        } catch (Exception e) {
            __log.debug("IO error", e);
            // todo: this should produce a message
            return null;
        } finally {
            try {
                is.close();
            } catch (Exception ex) {
                // No worries.
            }
        }
    }

    public boolean isPartnerLinkAssigned(String plink) {
        for (OActivity act : _compiledActivities) {
            if (act instanceof OAssign) {
                OAssign assign = (OAssign) act;
                for (OAssign.Copy copy : assign.getCopy()) {
                    if (copy.getTo() instanceof OAssign.PartnerLinkRef) {
                        if (((OAssign.PartnerLinkRef) copy.getTo()).getPartnerLink().getName().equals(plink))
                            return true;
                    }
                }
            }
        }
        return false;
    }

    public Definition[] getWsdlDefinitions() {
        Definition[] result = new Definition[_wsdlRegistry.getDefinitions().length];
        for (int m = 0; m < _wsdlRegistry.getDefinitions().length; m++) {
            Definition4BPEL definition4BPEL = _wsdlRegistry.getDefinitions()[m];
            result[m] = definition4BPEL.getDefinition();
        }
        return result;
    }

    private OElementVarType resolveElementType(QName faultVariableElementType) {
        OElementVarType type = _oprocess.getElementTypes().get(faultVariableElementType);
        if (type == null) {
            type = new OElementVarType(_oprocess, faultVariableElementType);
            _oprocess.getElementTypes().put(faultVariableElementType, type);
        }
        return type;
    }

    @SuppressWarnings("unchecked")
    private ActivityGenerator findActivityGen(Activity source) {

        Class actClass = source.getClass();

        for (Map.Entry<Class, ActivityGenerator> me : _actGenerators.entrySet()) {
            Class<?> cls = me.getKey();
            if (cls.isAssignableFrom(actClass)) {
                ActivityGenerator gen = me.getValue();
                gen.setContext(this);
                return gen;
            }
        }

        throw new CompilationException(__cmsgs.errUnknownActivity(actClass.getName()).setSource(source));
    }

    @SuppressWarnings("unchecked")
    protected void registerActivityCompiler(Class defClass, ActivityGenerator generator) {
        if (__log.isDebugEnabled()) {
            __log.debug("Adding compiler for nodes class \"" + defClass.getName() + " = " + generator);
        }

        _actGenerators.put(defClass, generator);
    }

    private ExpressionCompiler findExpLangCompiler(String expLang) {
        ExpressionCompiler compiler = _expLanguageCompilers.get(expLang);
        if (compiler == null) {
            throw new CompilationException(__cmsgs.errUnknownExpressionLanguage(expLang));
        }
        return compiler;
    }

    private String getExpressionLanguage(Expression exp) {
        String expLang = exp.getExpressionLanguage();

        if (expLang == null)
            expLang = _processDef.getExpressionLanguage();
        if (expLang == null)
            expLang = getDefaultExpressionLanguage();
        return expLang;
    }

    protected abstract String getDefaultExpressionLanguage();

    protected abstract String getBpwsNamespace();

    protected void registerExpressionLanguage(String expLangUri, ExpressionCompiler expressionCompiler) {
        _expLanguageCompilers.put(expLangUri, expressionCompiler);
    }

    @SuppressWarnings("unchecked")
    protected void registerExpressionLanguage(String expLangUri, String classname) throws Exception {
        Class cls = Class.forName(classname);
        registerExpressionLanguage(expLangUri, (ExpressionCompiler) cls.newInstance());
    }

    public List<OActivity> getActivityStack() {
        ArrayList<OActivity> rval = new ArrayList<OActivity>(_structureStack._stack);
        Collections.reverse(rval);
        return rval;
    }

    public Map<URI, Source> getSchemaSources() {
        return _wsdlRegistry.getSchemaSources();
    }

    /**
     * Retrieves the base URI that the BPEL Process execution contextis running relative to.
     *
     * @return URI - the URI representing the absolute physical file path location that this process is defined within.
     * @throws IOException
     * @throws MalformedURLException
     */
     public URI getBaseResourceURI() {
        return _resourceFinder.getBaseResourceURI();
    }

    public NSContext tryCacheNamespaceContext(NSContext nsContext) {
        if (getOProcess().getNamespaceContext().equals(nsContext)) {
            return getOProcess().getNamespaceContext();
        } else {
            return nsContext;
        }
    }

    /**
     * Compile external variable declaration.
     * @param src variable object
     * @return compiled {@link OExtVar} representation.
     */
    private OExtVar compileExtVar(Variable src) {
        if (!src.isExternal())
            return null;

        OExtVar oextvar = new OExtVar(_oprocess);
        oextvar.setExternalVariableId(src.getExternalId());
        oextvar.setDebugInfo(createDebugInfo(src, null));

        if (src.getExternalId() == null)
            throw new CompilationException(__cmsgs.errMustSpecifyExternalVariableId(src.getName()));

        if (src.getRelated() == null)
            throw new CompilationException(__cmsgs.errMustSpecifyRelatedVariable(src.getName()));
        oextvar.setRelated(resolveVariable(src.getRelated()));

        return oextvar;
    }

    private static class StructureStack {
        private Stack<OActivity> _stack = new Stack<OActivity>();
        private Map<OActivity,BpelObject> _srcMap = new HashMap<OActivity,BpelObject>();

        public void push(OActivity act, BpelObject src) {
            _stack.push(act);
            _srcMap.put(act, src);
        }

        public BpelObject topSource() {
            return _srcMap.get(topActivity());
        }

        public OScope topScope() {
            List<OScope> scopeStack = scopeStack();
            return scopeStack.isEmpty() ? null : scopeStack.get(scopeStack.size() - 1);
        }

        public OScope rootScope() {
            for (OActivity oActivity : _stack)
                if (oActivity instanceof OScope)
                    return (OScope) oActivity;
            return null;
        }

        public OActivity pop() {
            return _stack.pop();
        }

        public void clear() {
            _stack.clear();
        }

        public int size() {
            return _stack.size();
        }

        public Iterator<OScope> oscopeIterator() {
            List<OScope> scopeStack = scopeStack();
            Collections.reverse(scopeStack);
            return scopeStack.iterator();
        }

        private List<OScope> scopeStack() {
            ArrayList<OScope> newList = new ArrayList<OScope>();
            CollectionsX.filter(newList, _stack.iterator(), OScope.class);
            return newList;
        }

        public OActivity topActivity() {
            return _stack.isEmpty() ? null : _stack.peek();
        }

        public Iterator<OActivity> iterator() {
            ArrayList<OActivity> rval = new ArrayList<OActivity>(_stack);
            Collections.reverse(rval);
            return rval.iterator();
        }
    }
}
