/*
 * 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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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 Log __log = LogFactory.getLog(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();
        }
    }
}
