/*
 * 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.axis2.context;

import org.apache.axiom.om.util.UUIDGenerator;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.externalize.ActivateUtils;
import org.apache.axis2.context.externalize.ExternalizeConstants;
import org.apache.axis2.context.externalize.SafeObjectInputStream;
import org.apache.axis2.context.externalize.SafeObjectOutputStream;
import org.apache.axis2.context.externalize.SafeSerializable;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.util.MetaDataEntry;
import org.apache.axis2.wsdl.WSDLConstants.WSDL20_2004_Constants;
import org.apache.axis2.wsdl.WSDLConstants.WSDL20_2006Constants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

/**
 * An OperationContext represents a running "instance" of an operation, which is
 * represented by an AxisOperation object. This concept is needed to allow
 * messages to be grouped into operations as in WSDL 2.0-speak operations are
 * essentially arbitrary message exchange patterns. So as messages are being
 * exchanged the OperationContext remembers the state of where in the message
 * exchange pattern it is in.
 * <p/>
 * The base implementation of OperationContext
 * supports MEPs which have one input message and/or one output message. That
 * is, it supports the all the MEPs that are in the WSDL 2.0 specification. In
 * order to support another MEP one must extend this class and register its
 * creation in the OperationContexFactory.
 */
public class OperationContext extends AbstractContext 
    implements Externalizable, SafeSerializable {

    /*
     * setup for logging
     */
    private static final Log log = LogFactory.getLog(OperationContext.class);

    private static final String myClassName = "OperationContext";

    private boolean debugEnabled = log.isDebugEnabled();

    /**
     * An ID which can be used to correlate operations on an instance of
     * this object in the log files
     */
    private String logCorrelationIDString = null;


    /**
     * @serial The serialization version ID tracks the version of the class.
     * If a class definition changes, then the serialization/externalization
     * of the class is affected. If a change to the class is made which is
     * not compatible with the serialization/externalization of the class,
     * then the serialization version ID should be updated.
     * Refer to the "serialVer" utility to compute a serialization
     * version ID.
     */
    private static final long serialVersionUID = -7264782778333554350L;

    /**
     * @serial Tracks the revision level of a class to identify changes to the
     * class definition that are compatible to serialization/externalization.
     * If a class definition changes, then the serialization/externalization
     * of the class is affected.
     * Refer to the writeExternal() and readExternal() methods.
     */
    // supported revision levels, add a new level to manage compatible changes
    private static final int REVISION_2 = 2;
    // current revision level of this object
    private static final int revisionID = REVISION_2;


    /**
     * @serial isComplete flag
     */
    private boolean isComplete;

    /**
     * @serial key string
     */
    //The key value of the operationContextMap;
    private String key;

    // the AxisOperation of which this is a running instance. The MEP of this
    // AxisOperation must be one of the 8 predefined ones in WSDL 2.0.
    private transient AxisOperation axisOperation;

    /**
     * the set of message contexts associated with this operation
     */
    private transient HashMap<String, MessageContext> messageContexts;

    //----------------------------------------------------------------
    // MetaData for data to be restored in activate after readExternal
    //----------------------------------------------------------------

    /**
     * Indicates whether the message context has been reconstituted
     * and needs to have its object references reconciled
     */
    private transient boolean needsToBeReconciled = false;

    /**
     * Suppresses warning messages for activation
     * when doing internal reconciliation
     */
    private transient boolean suppressWarnings = false;

    /**
     * The AxisOperation metadata will be used during
     * activate to match up with an existing object
     */
    private transient MetaDataEntry metaAxisOperation = null;

    /**
     * The AxisService metadata will be used during
     * activate to match up with an existing object
     */
    private transient MetaDataEntry metaAxisService = null;

    /**
     * The ServiceContext metadata will be used during
     * activate to match up with an existing object
     */
    private transient ServiceContext metaParent = null;


    /**
     * This is used to hold information about message context objects
     * that are in the messageContexts map.  This allows message context
     * objects to be isolated from the object graph so that duplicate
     * copies of objects are not saved/restored.
     */
    private HashMap metaMessageContextMap = null;

    /**
     * This is used to hold temporarily any message context objects
     * that were isolated from the messageContexts map.
     */
    private transient HashMap isolatedMessageContexts = null;

    /**
     * This is used to hold temporarily any message context objects
     * from the messageContexts map for save/restore activities.
     */
    private transient HashMap workingSet = null;

    //----------------------------------------------------------------
    // end MetaData section
    //----------------------------------------------------------------

    /**
     * Simple constructor (needed for deserialization, shouldn't be used otherwise!)
     */
    public OperationContext() {
        super(null);
        this.messageContexts = new HashMap<String, MessageContext>();
    }

    /**
     * Constructs a new OperationContext.
     *
     * @param axisOperation  the AxisOperation whose running instances' state this
     *                       OperationContext represents.
     * @param serviceContext the parent ServiceContext representing any state related to
     *                       the set of all operations of the service.
     */
    public OperationContext(AxisOperation axisOperation,
                            ServiceContext serviceContext) {
        super(serviceContext);
        this.messageContexts = new HashMap<String, MessageContext>();
        this.axisOperation = axisOperation;
        this.setParent(serviceContext);
    }

    /**
     * When a new message is added to the <code>MEPContext</code> the logic
     * should be included remove the MEPContext from the table in the
     * <code>EngineContext</code>. Example: IN_IN_OUT At the second IN
     * message the MEPContext should be removed from the AxisOperation.
     *
     * @param msgContext
     */
    public void addMessageContext(MessageContext msgContext) throws AxisFault {
        if (axisOperation != null) {
            axisOperation.addMessageContext(msgContext, this);
            touch();
        }
    }


    /**
     * Removes the pointers to this <code>OperationContext</code> in the
     * <code>ConfigurationContext</code>'s OperationContextMap so that this
     * <code>OperationContext</code> will eventually get garbage collected
     * along with the <code>MessageContext</code>'s it contains. Note that if
     * the caller wants to make sure its safe to clean up this OperationContext
     * he should call isComplete() first. However, in cases like IN_OPTIONAL_OUT
     * and OUT_OPTIONAL_IN, it is possibe this will get called without the MEP
     * being complete due to the optional nature of the MEP.
     */
    public void cleanup() {
        ServiceContext serv = getServiceContext();

        if (serv != null) {
            serv.getConfigurationContext().unregisterOperationContext(key);
        }
    }

    /**
     * @return Returns the axisOperation.
     */
    public AxisOperation getAxisOperation() {
        if (needsToBeReconciled && !suppressWarnings && debugEnabled) {
            log.debug(getLogCorrelationIDString() +
                    ":getAxisOperation(): ****WARNING**** OperationContext.activate(configurationContext) needs to be invoked.");
        }

        return axisOperation;
    }

    /**
     * Returns the EngineContext in which the parent ServiceContext lives.
     *
     * @return Returns parent ServiceContext's parent EngineContext.
     */
    public ConfigurationContext getConfigurationContext() {
        if (parent != null) {
            return ((ServiceContext) parent).getConfigurationContext();
        } else {
            return null;
        }
    }


    /**
     * @param messageLabel
     * @return Returns MessageContext.
     * @throws AxisFault
     */
    public MessageContext getMessageContext(String messageLabel)
            throws AxisFault {
        if (messageContexts == null) {
            return null;
        }

        return (MessageContext) messageContexts.get(messageLabel);

    }

    /**
     * Remove the indicated message context.
     * Example Usage: The exchange is aborted and we need to 
     * undo the work and free resources.
     * @param label
     * @throws AxisFault
     */
    public void removeMessageContext(String label) throws AxisFault {

        MessageContext mc = getMessageContext(label);
        if (mc != null) {
            messageContexts.remove(mc);
            setComplete(false); 
            touch();
        }
    }
        

    public HashMap<String, MessageContext> getMessageContexts() {
        return messageContexts;
    }

    /**
     * Returns the ServiceContext in which this OperationContext lives.
     *
     * @return Returns parent ServiceContext.
     */
    public ServiceContext getServiceContext() {
        return (ServiceContext) parent;
    }

    /**
     * Checks to see if the MEP is complete. i.e. whether all the messages that
     * are associated with the MEP has arrived and MEP is complete.
     */
    public boolean isComplete() {
        return isComplete;
    }

    public void setComplete(boolean complete) {
        isComplete = complete;
    }

    public void setKey(String key) {
        this.key = key;
    }

    /* ===============================================================
    * Externalizable support
    * ===============================================================
    */


    /**
     * Save the contents of this object.
     * <p/>
     * NOTE: Transient fields and static fields are not saved.
     * Also, objects that represent "static" data are
     * not saved, except for enough information to be
     * able to find matching objects when the message
     * context is re-constituted.
     *
     * @param out The stream to write the object contents to
     * @throws IOException
     */
    public void writeExternal(ObjectOutput o) throws IOException {
        SafeObjectOutputStream out = SafeObjectOutputStream.install(o);
        //---------------------------------------------------------
        // in order to handle future changes to the message
        // context definition, be sure to maintain the
        // object level identifiers
        //---------------------------------------------------------
        // serialization version ID
        out.writeLong(serialVersionUID);

        // revision ID
        out.writeInt(revisionID);

        //---------------------------------------------------------
        // various simple fields
        //---------------------------------------------------------

        out.writeLong(getLastTouchedTime());

        out.writeBoolean(isComplete);
        out.writeObject(key);
        out.writeObject(logCorrelationIDString);

        //---------------------------------------------------------
        // properties
        //---------------------------------------------------------
        out.writeUTF("properties");  // write marker
        out.writeMap(getProperties());

        //---------------------------------------------------------
        // AxisOperation axisOperation
        //---------------------------------------------------------
        out.writeUTF("metaAxisOperation"); // write marker
        metaAxisOperation = null;
        if (axisOperation != null) {
            metaAxisOperation = new MetaDataEntry(axisOperation.getClass().getName(),
                                                  axisOperation.getName().toString());
        }
        out.writeObject(metaAxisOperation);

        //---------------------------------------------------------
        // AxisOperation axisService
        //---------------------------------------------------------
        // save the meta data for the corresponding axis service to better
        // match up the axis operation
        out.writeUTF("metaAxisService"); // write marker
        metaAxisService = null;
        AxisService axisService = axisOperation.getAxisService();

        if (axisService != null) {
            metaAxisService =
                    new MetaDataEntry(axisService.getClass().getName(), axisService.getName());
        }
        out.writeObject(metaAxisService);

        //---------------------------------------------------------
        // parent
        //---------------------------------------------------------
        out.writeUTF("parent"); // write marker
        out.writeObject(this.getServiceContext());

        //---------------------------------------------------------
        // HashMap messageContexts table
        //---------------------------------------------------------

        // NOTES: The assumption is that the table contains message contexts
        // that are in the OperationContext hierarchy.  To reduce overlap
        // of object information that is being saved, extract the
        // message context objects from the hierachy before saving.
        // When the OperationContext is restored, the "slimmed down"
        // message context objects are plugged back into the hierachy
        // using the restored OperationContext as a basis.

        // first deal with the original messageContexts table
        HashMap tmpMsgCtxMap = null;

        if ((messageContexts != null) && (!messageContexts.isEmpty())) {
            // create a table of the non-isolated message contexts
            workingSet = new HashMap();
            tmpMsgCtxMap = new HashMap();

            Set keySet = messageContexts.keySet();
            Iterator itKeys = keySet.iterator();

            while (itKeys.hasNext()) {
                // expect the key to be a string
                String keyObj = (String) itKeys.next();

                // get the message context associated with that label
                MessageContext value = (MessageContext) messageContexts.get(keyObj);

                boolean addToWorkingSet = true;

                // check to see if this message context was isolated
                if (isolatedMessageContexts != null) {
                    if (!isolatedMessageContexts.isEmpty()) {
                        // see if the message context was previously isolated
                        MessageContext valueIsolated =
                                (MessageContext) isolatedMessageContexts.get(keyObj);

                        if (valueIsolated != null) {
                            String idIsol = valueIsolated.getMessageID();

                            if (idIsol != null) {
                                if (idIsol.equals(value.getMessageID())) {
                                    // don't add to working set
                                    addToWorkingSet = false;
                                }
                            }
                        }
                    }
                }

                if (addToWorkingSet) {
                    // put the meta data entry in the list
                    workingSet.put(keyObj, value);
                }

            }

            // now we have a working set

            Set keySet2 = workingSet.keySet();
            Iterator itKeys2 = keySet2.iterator();

            while (itKeys2.hasNext()) {
                // expect the key to be a string
                String keyObj2 = (String) itKeys2.next();

                // get the message context associated with that label
                MessageContext mc = (MessageContext) workingSet.get(keyObj2);

                // construct a copy of the message context
                // that has been extracted from the object hierarchy
                MessageContext copyMC = mc.extractCopyMessageContext();
                
                // Don't persist the message of the other message contexts
                copyMC.setEnvelope(null);

                // put the modified entry in the list
                tmpMsgCtxMap.put(keyObj2, copyMC);

                // trace point
                if (log.isTraceEnabled()) {
                    log.trace(getLogCorrelationIDString() +
                              ":writeExternal():  getting working set entry  key [" + keyObj2 +
                              "]   message context ID[" + copyMC.getMessageID() + "]");
                }
            }

        }

        out.writeUTF("messagecontexts"); // write marker
        out.writeMap(tmpMsgCtxMap);
        out.writeUTF("metaMessageContextMap");
        out.writeMap(metaMessageContextMap);

        //---------------------------------------------------------
        // done
        //---------------------------------------------------------

    }


    /**
     * Restore the contents of the object that was previously saved.
     * <p/>
     * NOTE: The field data must read back in the same order and type
     * as it was written.  Some data will need to be validated when
     * resurrected.
     *
     * @param in The stream to read the object contents from
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public void readExternal(ObjectInput inObject) throws IOException, ClassNotFoundException {
        SafeObjectInputStream in = SafeObjectInputStream.install(inObject);
        // set the flag to indicate that the message context is being
        // reconstituted and will need to have certain object references
        // to be reconciled with the current engine setup
        needsToBeReconciled = true;

        // trace point
        log.trace(myClassName + ":readExternal():  BEGIN  bytes available in stream [" +
                in.available() + "]  ");

        //---------------------------------------------------------
        // object level identifiers
        //---------------------------------------------------------

        // serialization version ID
        long suid = in.readLong();

        // revision ID
        int revID = in.readInt();

        // make sure the object data is in a version we can handle
        if (suid != serialVersionUID) {
            throw new ClassNotFoundException(ExternalizeConstants.UNSUPPORTED_SUID);
        }

        // make sure the object data is in a revision level we can handle
        if (revID != REVISION_2) {
            throw new ClassNotFoundException(ExternalizeConstants.UNSUPPORTED_REVID);
        }

        //---------------------------------------------------------
        // various simple fields
        //---------------------------------------------------------

        long time = in.readLong();
        setLastTouchedTime(time);

        isComplete = in.readBoolean();
        key = (String) in.readObject();
        logCorrelationIDString = (String) in.readObject();
       
        // trace point
        if (log.isTraceEnabled()) {
            log.trace(myClassName + ":readExternal():  reading input stream for [" +
                      getLogCorrelationIDString() + "]  ");
        }

        //---------------------------------------------------------
        // properties
        //---------------------------------------------------------
        in.readUTF(); // read marker
        properties = in.readMap(new HashMapUpdateLockable());

        //---------------------------------------------------------
        // axis operation meta data
        //---------------------------------------------------------

        // axisOperation is not usable until the meta data has been reconciled
        axisOperation = null;
        in.readUTF(); // read marker
        metaAxisOperation = (MetaDataEntry) in.readObject();

        //---------------------------------------------------------
        // axis service meta data
        //---------------------------------------------------------
        // axisService is not usable until the meta data has been reconciled
        in.readUTF(); // read marker
        metaAxisService = (MetaDataEntry) in.readObject();

        //---------------------------------------------------------
        // parent
        //---------------------------------------------------------
        // ServiceContext is not usable until it has been activated
        in.readUTF(); // read marker
        metaParent = (ServiceContext) in.readObject();

        //---------------------------------------------------------
        // HashMap messageContexts table
        //---------------------------------------------------------

        // set to empty until this can be activiated
        messageContexts = new HashMap();
        in.readUTF(); // read marker
        workingSet = in.readHashMap();
        in.readUTF(); // read marker
        metaMessageContextMap = in.readHashMap();
        
        //---------------------------------------------------------
        // done
        //---------------------------------------------------------
    }


    /**
     * This method checks to see if additional work needs to be
     * done in order to complete the object reconstitution.
     * Some parts of the object restored from the readExternal()
     * cannot be completed until we have a configurationContext
     * from the active engine. The configurationContext is used
     * to help this object to plug back into the engine's
     * configuration and deployment objects.
     *
     * @param cc The configuration context object representing the active configuration
     */
    public void activate(ConfigurationContext cc) {
        // see if there's any work to do
        if (!needsToBeReconciled) {
            // return quick
            return;
        }

        // get the axis configuration
        AxisConfiguration axisConfig = cc.getAxisConfiguration();

        // We previously saved metaAxisService; restore it
        AxisService axisService = null;

        if (metaAxisService != null) {
            axisService = ActivateUtils.findService(axisConfig, metaAxisService.getClassName(),
                                                       metaAxisService.getQNameAsString());
        }

        // We previously saved metaAxisOperation; restore it
        if (metaAxisOperation != null) {
            if (axisService != null) {
                this.axisOperation = ActivateUtils.findOperation(axisService,
                                                                    metaAxisOperation.getClassName(),
                                                                    metaAxisOperation.getQName());
            } else {
                this.axisOperation = ActivateUtils.findOperation(axisConfig,
                                                                    metaAxisOperation.getClassName(),
                                                                    metaAxisOperation.getQName());
            }
        }

        // the parent ServiceContext object was saved
        // either use the restored object or sync up with
        // an existing ServiceContext object
        if (metaParent != null) {
            // find out if a copy of the ServiceContext object exists on this
            // engine where this OperationContext is being restored/activated
            // if so, use that object instead of the restored object
            // in order to make sure that future changes to service-level
            // properties are preserved for future operations
            String groupName = metaParent.getGroupName();
            String serviceName = metaParent.getName();

            ServiceContext existingSC = null;

            // first look for the ServiceContext via the ServiceContextGroup
            ServiceGroupContext sgc = cc.getServiceGroupContext(groupName);

            if (sgc != null) {
                existingSC = sgc.findServiceContext(serviceName);
            }

            if (existingSC == null) {
                // we couldn't find the ServiceContext via the ServiceContextGroup
                // try via the set of existing operation contexts
                OperationContext existingOC =
                        cc.findOperationContext(getOperationName(), serviceName, groupName);

                if (existingOC != null) {
                    existingSC = (ServiceContext) existingOC.getParent();
                }
            }

            if (existingSC == null) {
                // could not find an existing ServiceContext
                // use the restored object
                metaParent.activate(cc);

                // set parent
                this.setParent(metaParent);
            } else {
                // switch over to the existing object
                this.setParent(existingSC);

                // do a copy of the properties from the restored object
                // to the existing ServiceContext
                // Should the copy be a non-destructive one?  That is,
                // if the key already exists in the properties table of the
                // existing object, should the value be overwritten from the
                // restored ojbect? For now, the decision is that the state
                // that has been preserved for a saved context object is
                // is important to be restored.
                metaParent.putContextProperties(existingSC, true);
            }
        } else {
            // set parent  to null
            this.setParent(metaParent);
        }

        // reseed the operation context map

        ServiceContext serv = getServiceContext();
        ConfigurationContext activeCC;
        if (serv != null) {
            activeCC = serv.getConfigurationContext();
        } else {
            activeCC = cc;
        }

        if (key != null) {
            // We only want to (re)register this if it's an outbound message
            String mepString = getAxisOperation().getMessageExchangePattern();
            if (mepString.equals(WSDL20_2006Constants.MEP_URI_OUT_ONLY)
                || mepString.equals(WSDL20_2004_Constants.MEP_URI_OUT_ONLY)
                || ((mepString.equals(WSDL20_2006Constants.MEP_URI_OUT_IN)
                    || mepString.equals(WSDL20_2004_Constants.MEP_URI_OUT_IN))
                    && !isComplete)) {
                    
                // make sure this OperationContext object is registered in the 
                // list maintained by the ConfigurationContext object
                boolean registrationSuceeded = activeCC.registerOperationContext(key, this, true);
                if (!registrationSuceeded) {
                    // trace point
                    if (log.isTraceEnabled()) {
                        log.trace(getLogCorrelationIDString()+ ":activate():  " +
                                        "OperationContext key [" + key
                              + "] already exists in ConfigurationContext map.  " +
                                        "This OperationContext ["
                              + this.toString() + "] was not added to the table.");
                    }
                }
            }
        }

        //-------------------------------------------------------
        // update the modified entries in the messageContexts table
        //-------------------------------------------------------
        // NOTE: an entry in the metaMessageContextMap must wait
        // for its corresponding active message context object
        // to call this operation context object so we don't
        // need to handle the metaMessagecontextMap table here

        if ((workingSet != null) && (!workingSet.isEmpty())) {
            Set keySet = workingSet.keySet();
            Iterator itKeys = keySet.iterator();

            while (itKeys.hasNext()) {
                // expect the key to be a string
                String keyObj = (String) itKeys.next();

                // get the message context associated with that label
                MessageContext value = (MessageContext) workingSet.get((Object) keyObj);

                // activate that object
                if (value != null) {
                    // trace point
                    if (log.isTraceEnabled()) {
                        log.trace(getLogCorrelationIDString() + ":activate():  key [" + keyObj +
                            "]  message id [" + value.getMessageID() + "]");
                    }

                    suppressWarnings = true;
                    value.activateWithOperationContext(this);
                    suppressWarnings = false;

                    if (messageContexts == null) {
                        messageContexts = new HashMap();
                    }
                }

                // put the entry in the "real" table
                // note that the key or the value could be null
                messageContexts.put(keyObj, value);
            }
        }

        //-------------------------------------------------------
        // done, reset the flag
        //-------------------------------------------------------
        needsToBeReconciled = false;

    }

    /**
     * Isolate the specified message context object
     * to prepare for serialization.  Instead of
     * saving the entire message context object,
     * just setup some metadata about the message
     * context.
     * <p/>
     * Note: this will remove the specified
     * message context object from the message context
     * table.
     *
     * @param mc The message context object
     */
    public void isolateMessageContext(MessageContext mc) {
        if (mc == null) {
            return;
        }

        if ((messageContexts == null) || (messageContexts.isEmpty())) {
            return;
        }

        // get the message ID from the message context
        String messageID = mc.getMessageID();

        if (messageID == null) {
            // can't locate it without identification
            return;
        }


        Iterator it = messageContexts.keySet().iterator();

        while (it.hasNext()) {
            // get the key
            Object keyObj = it.next();

            // get the value associated with that key
            MessageContext value = (MessageContext) messageContexts.get(keyObj);

            if (value != null) {
                String valueID = value.getMessageID();

                if ((valueID != null) && valueID.equals(messageID)) {
                    // found the input message context in our table

                    if (metaMessageContextMap == null) {
                        metaMessageContextMap = new HashMap();
                    }

                    // build a meta data entry
                    //           MessageContext class name
                    //           MessageContext messageID
                    //           key used in the original hashmap that is associated with this MessageContext
                    //                    note: this is typically something like "In", "Out", "Fault"
                    //
                    MetaDataEntry metaData = new MetaDataEntry(value.getClass().getName(),
                                                               value.getMessageID(),
                                                               keyObj.toString());

                    // put the meta data entry in the list
                    // note that if the entry was already in the list,
                    // this will replace that entry
                    metaMessageContextMap.put(keyObj, metaData);

                    // don't change the original table - there's potentially lots of areas that
                    // grab the table
                    //  // now remove the original entry from the messageContexts table
                    //  messageContexts.remove(keyObj);

                    // put the original entry in the temporary list
                    if (isolatedMessageContexts == null) {
                        isolatedMessageContexts = new HashMap();
                    }

                    // note that if the entry was already in the list,
                    // this will replace that entry
                    isolatedMessageContexts.put(keyObj, value);

                    // trace point
                    if (log.isTraceEnabled()) {
                        log.trace(getLogCorrelationIDString() +
                            ":isolateMessageContext():  set up message context id[" + valueID +
                            "]  with key [" + keyObj.toString() +
                            "] from messageContexts table to prepare for serialization.");
                    }

                    break;
                }
            }
        }
    }


    /**
     * Restore the specified MessageContext object in the
     * table used to hold the message contexts associated
     * with this operation.
     *
     * @param msg The message context object
     */
    public void restoreMessageContext(MessageContext msg) {
        // see if the activation has been done
        if (needsToBeReconciled) {
            // nope, need to do the activation first
            if (debugEnabled) {
                log.debug(getLogCorrelationIDString() +
                          ":restoreMessageContext(): *** WARNING : need to invoke activate() prior to restoring the MessageContext to the list.");
            }

            return;
        }

        if (msg == null) {
            return;
        }

        String msgID = msg.getMessageID();

        if (msgID == null) {
            if (debugEnabled) {
                // can't identify message context
                log.debug(getLogCorrelationIDString() +
                        ":restoreMessageContext(): *** WARNING : MessageContext does not have a message ID.");
            }
            return;
        }

        // first check the metaMessageContextMap to see if
        // the specified message context object matches any
        // of the metadata entries.

        if ((metaMessageContextMap != null) && (!metaMessageContextMap.isEmpty())) {
            Iterator itMeta = metaMessageContextMap.keySet().iterator();

            while (itMeta.hasNext()) {
                String keyM = (String) itMeta.next();

                MetaDataEntry valueM = (MetaDataEntry) metaMessageContextMap.get(keyM);
                String valueM_ID;

                if (valueM != null) {
                    valueM_ID = valueM.getQNameAsString();

                    if (msgID.equals(valueM_ID)) {
                        String label = valueM.getExtraName();

                        if (messageContexts == null) {
                            messageContexts = new HashMap();
                        }

                        // put the message context into the messageContexts table
                        messageContexts.put(label, msg);

                        // remove the metadata from the metadata table
                        metaMessageContextMap.remove(keyM);

                        if (log.isTraceEnabled()) {
                            log.trace(getLogCorrelationIDString() +
                                ":restoreMessageContext():  restored   label [" + label +
                                "]    message ID [" + msg.getMessageID() + "]");
                        }

                        break;
                    }
                }
            }
        } else
            // see if we can put the msg directly in the messageContexts table
            if ((messageContexts != null) && (!messageContexts.isEmpty())) {
                Iterator itList = messageContexts.keySet().iterator();

                while (itList.hasNext()) {
                    String key = (String) itList.next();

                    MessageContext value = (MessageContext) messageContexts.get(key);
                    String valueID;

                    if (value != null) {
                        valueID = value.getMessageID();

                        if (msgID.equals(valueID)) {
                            // update the entry
                            messageContexts.put(key, msg);
                        }
                    }
                }
            }

    }

    /**
     * Get the name associated with the operation.
     *
     * @return The name String
     */
    public String getOperationName() {
        String opName = null;

        if (axisOperation != null) {
            QName qname = axisOperation.getName();
            if (qname != null) {
                opName = qname.getLocalPart();
            }
        }

        return opName;
    }

    /**
     * Get the name associated with the service.
     *
     * @return The name String
     */
    public String getServiceName() {
        String srvName = null;

        ServiceContext sc = (ServiceContext) getParent();

        if (sc == null) {
            sc = metaParent;
        }

        if (sc != null) {
            srvName = sc.getName();
        }

        return srvName;
    }

    /**
     * Get the name associated with the service group.
     *
     * @return The name String
     */
    public String getServiceGroupName() {
        String srvGroupName = null;

        ServiceContext sc = (ServiceContext) getParent();

        if (sc == null) {
            sc = metaParent;
        }

        if (sc != null) {
            srvGroupName = sc.getGroupName();
        }

        return srvGroupName;
    }


    /**
     * Compares key parts of the state from the current instance of
     * this class with the specified instance to see if they are
     * equivalent.
     * <p/>
     * This differs from the java.lang.Object.equals() method in
     * that the equals() method generally looks at both the
     * object identity (location in memory) and the object state
     * (data).
     * <p/>
     *
     * @param ctx The object to compare with
     * @return TRUE if this object is equivalent with the specified object
     *         that is, key fields match
     *         FALSE, otherwise
     */
    public boolean isEquivalent(OperationContext ctx) {
        // NOTE: the input object is expected to exist (ie, be non-null)

        if (this.isComplete != ctx.isComplete()) {
            return false;
        }

        if (!this.axisOperation.equals(ctx.getAxisOperation())) {
            return false;
        }

        // TODO: consider checking the parent objects for equivalency

        // TODO: consider checking fields from the super class for equivalency

        return true;
    }


    /**
     * Get the ID associated with this object instance.
     *
     * @return A string that can be output to a log file as an identifier
     *         for this object instance.  It is suitable for matching related log
     *         entries.
     */
    public String getLogCorrelationIDString() {
        if (logCorrelationIDString == null) {
            logCorrelationIDString = myClassName + "@" + UUIDGenerator.getUUID();
        }
        return logCorrelationIDString;
    }

    public ConfigurationContext getRootContext() {
        return this.getConfigurationContext();
    }

}
