All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tangosol.dev.component.Behavior Maven / Gradle / Ivy

There is a newer version: 24.03
Show newest version
/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

package com.tangosol.dev.component;


import com.tangosol.dev.assembler.Method;

import com.tangosol.util.ClassHelper;
import com.tangosol.util.ErrorList;
import com.tangosol.util.StringTable;
import com.tangosol.util.UID;
import com.tangosol.util.ChainedEnumerator;
import com.tangosol.util.SimpleEnumerator;
import com.tangosol.run.xml.XmlElement;

import java.beans.PropertyVetoException;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.PrintWriter;

import java.text.CollationKey;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;
import java.util.List;
import java.util.Iterator;


/**
* A Behavior represents the set of information that describes a component's
* method or event handler declaration and definition.
*
* A Behavior and its contained hierarchy are kept or discarded as a unit.
* This allows any level that has any information specified at that level to
* recover the entire Behavior if the super/base level discards the Behavior.
*
* @version 0.50, 11/11/97
* @version 1.00, 08/17/98
* @author  Cameron Purdy
*/
public class Behavior
        extends Trait
    {
    // ----- construction ---------------------------------------------------

    /**
    * Construct a behavior.  This is the "default" constructor.
    *
    * @param cd         the containing Component Definition
    * @param dtRet      the return value's data type
    * @param sName      the name of the behavior
    * @param fStatic    the behavior's scope (static or instance)
    * @param nAccess    the behavior's accessibility
    * @param adtParam   the behavior's parameter data types
    * @param asParam    the parameter names (or null for defaults)
    * @param anDir      the parameter directions (or null for defaults)
    */
    protected Behavior(Component cd,
            DataType dtRet, String sName, boolean fStatic, int nAccess,
            DataType[] adtParam, String[] asParam, int[] anDir)
        {
        super(cd, RESOLVED);

        m_nFlags     |= EXISTS_INSERT | nAccess        | (fStatic ? SCOPE_STATIC : SCOPE_INSTANCE);
        m_nPrevFlags |= EXISTS_NOT    | ACCESS_PRIVATE | SCOPE_INSTANCE;

        m_sName  = sName;
        m_retval = new ReturnValue(this, dtRet);

        if (adtParam != null)
            {
            int c = adtParam.length;
            for (int i = 0; i < c; ++i)
                {
                DataType  dt     = adtParam[i];
                String    sParam = (asParam == null ? "Param_" + i : asParam[i]);
                int       nDir   = (anDir   == null ? DIR_IN       : anDir  [i]);
                Parameter param  = new Parameter(this, dt, sParam, nDir);
                m_vectParam.addElement(param);
                }
            }
        updateSignature();

        // all INSERT behaviors for non-Signatures are assigned UID's
        if (!cd.isSignature())
            {
            assignUID();
            }
        }

    /**
    * Construct a Behavior for an integration method.
    *
    * @param cd      containing Component
    * @param map     the Integration trait
    * @param sName   Behavior name that the method mapped to (allowing
    *                name collisions to be resolved)
    * @param method  interface method to integrate
    */
    protected Behavior(Component cd, Integration map, String sName, Behavior method)
        {
        this(cd, method.m_retval.getDataType(), sName, method.isStatic(), method.getAccess(),
                method.getParameterTypes(), method.getParameterNames(), null);
        this.addOriginTrait(map);

        // copy exceptions
        for (Enumeration enmr = method.m_tblExcept.elements(); enmr.hasMoreElements(); )
            {
            Throwee except  = (Throwee) enmr.nextElement();
            Throwee throwee = new Throwee(this, except.getDataType());
            throwee.addOriginTrait(map);
            m_tblExcept.put(throwee.getUniqueName(), throwee);
            }
        }

    /**
    * Construct a Behavior for an interface (implements/dispatches) method.
    *
    * @param cd      containing Component (or JCS)
    * @param iface   declaring interface
    * @param method  interface method
    */
    protected Behavior(Component cd, Interface iface, Behavior method)
        {
        this(cd, method.m_retval.getDataType(), method.m_sName, method.isStatic(), method.getAccess(),
                method.getParameterTypes(), method.getParameterNames(), null);
        this.addOriginTrait(iface);

        // for a JCS of an interface that implements an interface,
        // the resulting methods are abstract unless it's a default method (Java 8)
        if (cd.isInterface() && method.isAbstract())
            {
            m_nFlags = m_nFlags & ~IMPL_MASK | IMPL_ABSTRACT;
            }

        // copy exceptions
        for (Enumeration enmr = method.m_tblExcept.elements(); enmr.hasMoreElements(); )
            {
            Throwee except  = (Throwee) enmr.nextElement();
            Throwee throwee = new Throwee(this, except.getDataType());
            throwee.addOriginTrait(iface);
            m_tblExcept.put(throwee.getUniqueName(), throwee);
            }
        }

    /**
    * Construct a Behavior for event registration.
    *
    * @param cd     containing Component
    * @param iface  event interface
    * @param sSig   behavior signature
    */
    protected Behavior(Component cd, Interface iface, String sSig)
        {
        this(cd, DataType.VOID, Interface.getDispatchesVerb(sSig) +
                Interface.getDispatchesName(sSig) + "Listener", false,
                ACCESS_PUBLIC, new DataType[] {DataType.getClassType(iface.getName())},
                EVENT_REG_PARAM, null);
        addOriginTrait(iface);
        }

    /**
    * Construct a Java Class Signature (JCS) Behavior from a JASM method.
    *
    * @param cdJCS     the containing JCS
    * @param method    the method object
    * @param mapParam  a Map that may contain String[] of param names per signature
    */
    protected Behavior(Component cdJCS, Method method, Map mapParam)
        {
        super(cdJCS, RESOLVED);

        // convert method information to Behavior flags
        int nFlags = EXISTS_INSERT | DIST_LOCAL;

        // access, visible
        if (method.isPublic())
            {
            nFlags |= ACCESS_PUBLIC    | VIS_VISIBLE;
            }
        else if (method.isProtected())
            {
            nFlags |= ACCESS_PROTECTED | VIS_VISIBLE;
            }
        else if (method.isPackage())
            {
            nFlags |= ACCESS_PACKAGE   | VIS_VISIBLE;
            }
        else if (method.isPrivate())
            {
            nFlags |= ACCESS_PRIVATE   | VIS_VISIBLE;
            }

        // mark synthetic methods as "advanced"
        if (method.isSynthetic())
            {
            nFlags |= VIS_ADVANCED;
            }

        nFlags |= (method.isDeprecated()   ? ANTIQ_DEPRECATED : ANTIQ_CURRENT   );
        nFlags |= (method.isStatic()       ? SCOPE_STATIC     : SCOPE_INSTANCE  );
        nFlags |= (method.isSynchronized() ? SYNC_MONITOR     : SYNC_NOMONITOR  );
        nFlags |= (method.isAbstract()     ? IMPL_ABSTRACT    : IMPL_CONCRETE   );
        nFlags |= (method.isFinal()        ? DERIVE_FINAL     : DERIVE_DERIVABLE);

        if (method.isBridge() && method.isSynthetic())
            {
            // use the ISINTERFACE bit for behaviors to indicate the generated
            // nature of the method (generated by a compiler or tool)
            nFlags |= MISC_ISINTERFACE;
            }

        // to allow modification of final JCS methods
        // the last line has to be commented out

        // initialize Behavior info
        m_sName  = method.getName();
        m_nFlags = nFlags;

        String[] asTypes = method.getTypes();
        String[] asNames = method.getNames();

        // Return Value
        m_retval = new ReturnValue(this, DataType.getJVMType(asTypes[0]));

        // Parameters
        int     cParams = asTypes.length - 1;
        Vector  vect    = m_vectParam;
        vect.setSize(cParams);
        for (int i = 1; i <= cParams; ++i)
            {
            DataType dt    = DataType.getJVMType(asTypes[i]);
            String   sName = "Param_" + i;
            if (asNames[i] != null)
                {
                sName = asNames[i];
                }

            vect.setElementAt(new Parameter(this, dt, sName, DIR_IN), i - 1);
            }
        updateSignature();

        // 2002-07-22 cp - fill in parameter names
        if (!mapParam.isEmpty())
            {
            // look up the source code for the behavior
            StringBuffer sb = new StringBuffer(getComponent().getName());
            sb.append('.')
              .append(getName())
              .append('(');
            DataType[] adt = getParameterTypes();
            for (int i = 0, c = adt.length; i < c; ++i)
                {
                if (i > 0)
                    {
                    sb.append(',');
                    }
                sb.append(Component.toSimpleSignature(adt[i].getType()));
                }
            sb.append(')');

            String[] asParam = (String[]) mapParam.get(sb.toString());
            if (asParam != null)
                {
                for (int i = 0, c = Math.min(asParam.length, getParameterCount()); i < c; ++i)
                    {
                    Parameter param    = getParameter(i);
                    String    sOldName = param.getName();
                    String    sNewName = asParam[i];
                    if (sNewName != null && sNewName.length() > 0 && sOldName.startsWith("Param_"))
                        {
                        try
                            {
                            param.setName(sNewName, false);
                            }
                        catch (PropertyVetoException e)
                            {
                            }
                        }
                    }
                }
            }

        // Exceptions
        StringTable tbl = m_tblExcept;
        for (Enumeration enmr = method.getExceptions(); enmr.hasMoreElements(); )
            {
            DataType dt = DataType.getClassType(((String) enmr.nextElement()).replace('/', '.'));
            tbl.put(dt.getClassName(), new Throwee(this, dt));
            }
        }

    /**
    * Construct a blank Behavior Trait.
    *
    * @param base   the base Behavior to derive from
    * @param cd     the containing Component
    * @param nMode  one of RESOLVED, DERIVATION, MODIFICATION
    *
    * @see #getBlankDerivedTrait(Trait, int)
    */
    protected Behavior(Behavior base, Component cd, int nMode)
        {
        super(base, cd, nMode);

        // only temporary; will be immediately resolved or extracted
        // (don't bother creating blank params, return value, or exceptions)
        this.m_sName  = base.m_sName;
        this.m_sSig   = base.m_sSig;
        this.m_nFlags = EXISTS_UPDATE;
        }

    /**
    * Copy constructor.
    *
    * @param cd    the Component containing the new Behavior
    * @param that  the Behavior to copy from
    */
    protected Behavior(Component cd, Behavior that)
        {
        super(cd, that);

        this.m_sName             = that.m_sName;
        this.m_sSig              = that.m_sSig;
        this.m_nFlags            = that.m_nFlags;
        this.m_nPrevFlags        = that.m_nPrevFlags;
        this.m_fOverrideBase     = that.m_fOverrideBase;
        this.m_fPrevOverrideBase = that.m_fPrevOverrideBase;
        this.m_cBaseLevelImpl    = that.m_cBaseLevelImpl;

        this.m_retval = new ReturnValue(this, that.m_retval);

        if (!that.m_vectParam.isEmpty())
            {
            Vector src  = that.m_vectParam;
            Vector dest = this.m_vectParam;
            int c = src.size();
            dest.setSize(c);
            for (int i = 0; i < c; ++i)
                {
                dest.setElementAt(new Parameter(this, (Parameter) src.elementAt(i)), i);
                }
            }

        if (!that.m_vectScript.isEmpty())
            {
            Vector src  = that.m_vectScript;
            Vector dest = this.m_vectScript;
            int c = src.size();
            dest.setSize(c);
            for (int i = 0; i < c; ++i)
                {
                dest.setElementAt(new Implementation(this, (Implementation) src.elementAt(i)), i);
                }
            }

        if (!that.m_tblExcept.isEmpty())
            {
            StringTable tblThat = that.m_tblExcept;
            StringTable tblThis = this.m_tblExcept;
            for (Enumeration enmr = tblThat.keys(); enmr.hasMoreElements(); )
                {
                String  sExcept = (String)  enmr.nextElement();
                Throwee throwee = new Throwee(this, (Throwee) tblThat.get(sExcept));
                if (cd.isSignature())
                    {
                    // TODO: explain why
                    throwee.addOriginTrait(cd);
                    }
                tblThis.put(sExcept, throwee);
                }
            this.m_tblExcept = tblThis;
            }
        }

    /**
    * Construct the behavior from a stream.
    *
    * This is a custom serialization implementation that is unrelated to the
    * Serializable interface and the Java implementation of persistence.
    *
    * @param cd        the containing Component Definition
    * @param stream    the stream to read this Behavior from
    * @param nVersion  version of the data structure in the stream
    *
    * @exception IOException An IOException is thrown if an error occurs
    *            reading the Behavior information from the stream
    */
    protected Behavior(Component cd, DataInput stream, int nVersion)
            throws IOException
        {
        super(cd, stream, nVersion);

        // name
        m_sName = stream.readUTF();

        // bit flags (various attributes)
        m_nFlags     = stream.readInt();
        m_nPrevFlags = stream.readInt();

        // return value trait
        m_retval = new ReturnValue(this, stream, nVersion);

        // parameter traits
        int cParam = stream.readInt();
        m_vectParam.setSize(cParam);
        for (int i = 0; i < cParam; ++i)
            {
            Parameter param = new Parameter(this, stream, nVersion);
            m_vectParam.setElementAt(param, i);
            }
        updateSignature();

        // exception traits
        int cExcept = stream.readInt();
        for (int i = 0; i < cExcept; ++i)
            {
            Throwee except = new Throwee(this, stream, nVersion);
            m_tblExcept.put(except.getUniqueName(), except);
            }

        // implementation traits
        int cImpl = stream.readInt();
        m_vectScript.setSize(cImpl);
        for (int i = 0; i < cImpl; ++i)
            {
            Implementation impl = new Implementation(this, stream, nVersion);
            m_vectScript.setElementAt(impl, i);
            }

        // override etc.
        m_fOverrideBase  = stream.readBoolean();
        m_cBaseLevelImpl = stream.readInt();
        }

    /**
    * Construct a Trait object from persistent data.  All traits implement
    * implement a constructor from persistent data.
    *
    * @param parent    the trait that contains this trait
    * @param xml       the XmlElement to read the persistent information from
    * @param nVersion  version of the data structure in the stream
    *
    * @throws IOException if an exception occurs reading the trait data
    */
    protected Behavior(Trait parent, XmlElement xml, int nVersion)
            throws IOException
        {
        super(parent, xml, nVersion);

        // name
        String sName = readString(xml.getElement("name"));
        if (sName == BLANK)
            {
            throw new IOException("name is missing");
            }
        m_sName = sName;

        // bit flags (various attributes)
        m_nFlags     = readFlags(xml, "flags", 0);
        m_nPrevFlags = readFlags(xml, "prev-flags", 0);

        // return value trait
        XmlElement xmlRetVal = xml.getElement("return-value");
        if (xmlRetVal == null)
            {
            throw new IOException("return value is missing");
            }
        m_retval = new ReturnValue(this, xmlRetVal, nVersion);

        // parameter traits
        XmlElement xmlParams = xml.getElement("params");
        if (xmlParams != null)
            {
            Vector vect = m_vectParam;
            for (Iterator iter = xmlParams.getElements("param"); iter.hasNext(); )
                {
                XmlElement xmlParam = (XmlElement) iter.next();
                Parameter  param    = new Parameter(this, xmlParam, nVersion);
                vect.add(param);
                }
            }
        updateSignature();

        // exception traits
        XmlElement xmlExcepts = xml.getElement("exceptions");
        if (xmlExcepts != null)
            {
            StringTable tbl = m_tblExcept;
            for (Iterator iter = xmlExcepts.getElements("exception"); iter.hasNext(); )
                {
                XmlElement xmlExcept = (XmlElement) iter.next();
                Throwee    except    = new Throwee(this, xmlExcept, nVersion);
                tbl.put(except.getUniqueName(), except);
                }
            }

        // implementation traits
        Vector vectScript = m_vectScript;
        for (Iterator iter = xml.getElements("implementation"); iter.hasNext(); )
            {
            XmlElement     xmlImpl = (XmlElement) iter.next();
            Implementation impl    = new Implementation(this, xmlImpl, nVersion);
            vectScript.add(impl);
            }

        // override etc.
        m_fOverrideBase  = readBoolean(xml.getElement("override-base"));
        m_cBaseLevelImpl = xml.ensureElement("base-implementations").getInt();
        }


    // ----- persistence ----------------------------------------------------

    /**
    * Save the Behavior to a stream.
    *
    * This is a custom serialization implementation that is unrelated to the
    * Serializable interface and the Java implementation of persistence.
    *
    * @param stream   the stream to write this behavior to
    *
    * @exception IOException An IOException is thrown if an error occurs
    *            writing the Behavior contents to the stream
    */
    protected synchronized void save(DataOutput stream)
            throws IOException
        {
        super.save(stream);

        // name
        stream.writeUTF(m_sName);

        // bit flags (various attributes)
        stream.writeInt(m_nFlags);
        stream.writeInt(m_nPrevFlags);

        // return value trait
        m_retval.save(stream);

        // parameter traits
        int cParam = m_vectParam.size();
        stream.writeInt(cParam);
        for (int i = 0; i < cParam; ++i)
            {
            ((Parameter) m_vectParam.elementAt(i)).save(stream);
            }

        // exception traits
        int cExcept = m_tblExcept.getSize();
        stream.writeInt(cExcept);
        Enumeration enmrExcept = m_tblExcept.elements();
        for (int i = 0; i < cExcept; ++i)
            {
            ((Throwee) enmrExcept.nextElement()).save(stream);
            }

        // implementation traits
        int cImpl = m_vectScript.size() - m_cBaseLevelImpl;
        stream.writeInt(cImpl);
        for (int i = 0; i < cImpl; ++i)
            {
            ((Implementation) m_vectScript.elementAt(i)).save(stream);
            }

        // override etc.
        stream.writeBoolean(m_fOverrideBase);
        stream.writeInt(m_cBaseLevelImpl);
        }

    /**
    * Save the Trait information to XML.  If derived traits have any
    * data of their own, then they must implement (i.e. supplement) this
    * method.
    *
    * This is a custom serialization implementation that is unrelated to the
    * Serializable interface and the Java implementation of persistence.
    *
    * @param xml  an XmlElement to write the persistent information to
    *
    * @throws IOException if an exception occurs saving the trait data
    */
    protected synchronized void save(XmlElement xml)
            throws IOException
        {
        // name
        xml.addElement("name").setString(m_sName);

        super.save(xml);

        // bit flags (various attributes)
        saveFlags(xml, "flags", m_nFlags, 0);
        saveFlags(xml, "prev-flags", m_nPrevFlags, 0);

        // REVIEW: jhowes 2007.10.18:
        // Added a human-readable description attribute to the flags elements
        XmlElement xmlFlags = xml.getElement("flags");
        if (xmlFlags != null)
            {
            xmlFlags.addAttribute("desc").setString(flagsDescription(m_nFlags,
                    ACCESS_SPECIFIED | SCOPE_SPECIFIED | SYNC_SPECIFIED, false));
            }
        xmlFlags = xml.getElement("prev-flags");
        if (xmlFlags != null)
            {
            xmlFlags.addAttribute("desc").setString(flagsDescription(m_nPrevFlags,
                    ACCESS_SPECIFIED | SCOPE_SPECIFIED | SYNC_SPECIFIED, false));
            }

        // return value trait
        m_retval.save(xml.addElement("return-value"));

        // parameter traits
        List list = m_vectParam;
        if (list != null && !list.isEmpty())
            {
            XmlElement xmlParams = xml.addElement("params");
            for (Iterator iter = list.iterator(); iter.hasNext(); )
                {
                ((Parameter) iter.next()).save(xmlParams.addElement("param"));
                }
            }

        // exception traits
        saveTable(xml, m_tblExcept, "exceptions", "exception");

        // implementation traits
        int cImpl = m_vectScript.size() - m_cBaseLevelImpl;
        if (cImpl > 0)
            {
            for (int i = 0; i < cImpl; ++i)
                {
                // expect only one, so don't nest them; however, any number
                // is supported
                ((Implementation) m_vectScript.elementAt(i)).save(xml.addElement("implementation"));
                }
            }

        // override etc.
        if (m_fOverrideBase)
            {
            xml.addElement("override-base").setBoolean(true);
            }
        if (m_cBaseLevelImpl != 0)
            {
            xml.addElement("base-implementations").setInt(m_cBaseLevelImpl);
            }
        }


    // ----- derivation/modification ----------------------------------------

    /**
    * Construct a blank Behavior from this base.
    *
    * @param parent  the containing Component
    * @param nMode   RESOLVED, DERIVATION or MODIFICATION
    *
    * @return a new blank derived trait of this trait's class with the
    *         specified parent and mode
    */
    protected Trait getBlankDerivedTrait(Trait parent, int nMode)
        {
        Behavior beh = new Behavior(this, (Component) parent, nMode);

        // for signature, create blank derived traits for exceptions
        // (see special processing in resolve() for exceptions on signature
        // behaviors)
        if (getComponent().isSignature() && !m_tblExcept.isEmpty())
            {
            StringTable tblExcept = (StringTable) m_tblExcept.clone();
            for (Enumeration enmr = tblExcept.keys(); enmr.hasMoreElements(); )
                {
                String  sExcept = (String) enmr.nextElement();
                Throwee throwee = (Throwee) tblExcept.get(sExcept);
                tblExcept.put(sExcept, throwee.getBlankDerivedTrait(this, nMode));
                }
            beh.m_tblExcept = tblExcept;
            }

        return beh;
        }

    /**
    * Create a derived/modified Trait by combining the information from this
    * Trait with the super or base level's Trait information.  Neither the
    * base ("this") nor the delta may be modified in any way.
    *
    * Note:  resolve must be invoked with a null derivation when the base
    *        behavior is final
    *
    * @param traitDelta  the Trait derivation or modification
    * @param parent      the Trait which will contain the resulting Trait or
    *                    null if the resulting Trait will not be contained
    * @param loader      the Loader object for JCS, CIM, and CD dependencies
    * @param errlist     the error list object to log error information to
    *
    * @return the result of applying the specified delta Trait to this Trait
    *
    * @exception ComponentException  thrown only if a fatal error occurs
    */
    protected Trait resolve(Trait traitDelta, Trait parent, Loader loader, ErrorList errlist)
            throws ComponentException
        {
        Behavior base    = this;
        Behavior delta   = (Behavior) resolveDelta(traitDelta, loader, errlist);
        Behavior derived = (Behavior) super.resolve(delta, parent, loader, errlist);

        // for general use below
        boolean fSignature = base.getComponent().isSignature();

        // verify that behavior attributes match
        delta.verifyMatch(base, true, errlist);

        // if the base is resolved, this will be resolved when resolve
        // completes (otherwise it will be a derivation/modification)
        int nBaseMode  = base .getMode();
        boolean fBaseResolved = (nBaseMode == RESOLVED);
        int nDeltaMode = delta.getMode();
        if (nDeltaMode == RESOLVED)
            {
            // this can happen when the Behavior is an INSERT with the
            // same name as a Behavior later added to the base
            nDeltaMode = delta.getExtractMode(base);
            }

        // attributes represented as bit flags
        int nBaseFlags    = base.m_nFlags;
        int nDeltaFlags   = delta.m_nFlags;
        int nPrevFlags    = derived.resolveFlags(nBaseFlags, delta.m_nPrevFlags);
        int nDerivedFlags = derived.resolveFlags(nPrevFlags, nDeltaFlags);

        // resolve exists
        // if delta is a modification of an insert, then keep it as an insert
        int nExists = EXISTS_UPDATE;
        if (nDeltaMode == MODIFICATION && (nBaseFlags & EXISTS_MASK) == EXISTS_INSERT)
            {
            nExists = EXISTS_INSERT;
            }

        // gg: 2003.11.24 Behavior is EXISTS_NOT if the method is not present
        //                in the class represented by the JCS.
        if (fSignature && (nDeltaFlags & EXISTS_MASK) == EXISTS_NOT)
            {
            nExists = EXISTS_NOT;
            }
        nDerivedFlags = nDerivedFlags & ~EXISTS_FULLMASK | nExists;

        // behavior attributes
        derived.m_sName      = base.m_sName;
        derived.m_nFlags     = nDerivedFlags;
        derived.m_nPrevFlags = nPrevFlags;

        // return value
        ReturnValue retBase  = base.m_retval;
        ReturnValue retDelta = delta.m_retval;
        if (retDelta == null)
            {
            retDelta = (ReturnValue) retBase.getNullDerivedTrait(delta, nDeltaMode);
            }
        derived.m_retval = (ReturnValue) retBase.resolve(retDelta, derived, loader, errlist);

        // parameters
        Vector vectBaseParam    = base.m_vectParam;
        Vector vectDeltaParam   = delta.matchParameters(base, true, errlist);
        Vector vectDerivedParam = derived.m_vectParam;
        int cParam = vectBaseParam.size();
        vectDerivedParam.setSize(cParam);
        for (int i = 0; i < cParam; ++i)
            {
            Parameter paramBase  = (Parameter) vectBaseParam .get(i);
            Parameter paramDelta = (Parameter) vectDeltaParam.get(i);
            if (paramDelta == null)
                {
                paramDelta = (Parameter) paramBase.getNullDerivedTrait(delta, nDeltaMode);
                }
            vectDerivedParam.set(i, paramBase.resolve(paramDelta, derived, loader, errlist));
            }
        updateSignature();

        // exceptions (note:  delta exceptions may be a superset of base)

        StringTable tblBaseExcept    = base.m_tblExcept;
        StringTable tblDeltaExcept   = delta.matchExceptions(base, true, errlist);
        StringTable tblDerivedExcept = derived.m_tblExcept; // empty
        for (Enumeration enmr = tblDeltaExcept.keys(); enmr.hasMoreElements(); )
            {
            String  sExcept       = (String) enmr.nextElement();
            Throwee exceptBase    = (Throwee) tblBaseExcept .get(sExcept);
            Throwee exceptDelta   = (Throwee) tblDeltaExcept.get(sExcept);
            Throwee exceptDerived = null;

            if (exceptBase == null)
                {
                // just copy exception information (nothing to apply it to)
                exceptDerived = new Throwee(derived, exceptDelta);

                // if the base is resolved, the derived exception must be
                // marked as deleted (see matchExceptions)
                if (fBaseResolved)
                    {
                    nExists = exceptDerived.getExists();
                    if (nExists == EXISTS_INSERT)
                        {
                        // originated at this level, so mark as removed at this
                        // level
                        exceptDerived.setExists(EXISTS_DELETE);
                        }
                    else if (nExists == EXISTS_UPDATE)
                        {
                        // not originated at this level
                        exceptDerived.setExists(EXISTS_NOT);
                        }
                    }
                }
            else
                {
                if (exceptDelta == null)
                    {
                    if (fSignature && nDeltaMode == DERIVATION)
                        {
                        // the sub-class declared the method without the
                        // exception, implying that the exception has been
                        // removed; this occurs only with signatures because
                        // Java classes do not store exception declarations
                        // as a delta from the super, rather they store the
                        // list in its fully resolved form
                        exceptDerived = new Throwee(derived, exceptBase);
                        exceptDerived.setExists(EXISTS_DELETE);
                        }
                    else
                        {
                        // create a null derivation if no delta exists
                        exceptDelta = (Throwee) exceptBase.getNullDerivedTrait(delta, nDeltaMode);
                        }
                    }

                // apply the delta
                if (exceptDelta != null)
                    {
                    exceptDerived = (Throwee) exceptBase.resolve(exceptDelta, derived, loader, errlist);
                    }
                }

            tblDerivedExcept.put(sExcept, exceptDerived);
            }

        // implementations
        Vector vectBaseScript    = base.m_vectScript;
        Vector vectDeltaScript   = delta.m_vectScript;
        Vector vectDerivedScript = derived.m_vectScript; // empty
        // copy the delta implementations to the derived behavior
        int cScripts = vectDeltaScript.size();
        vectDerivedScript.setSize(cScripts);
        for (int i = 0; i < cScripts; ++i)
            {
            Implementation script = (Implementation) vectDeltaScript.get(i);
            vectDerivedScript.set(i, new Implementation(derived, script));
            }
        // if the delta is a modification, that means that some of the
        // implementations may have come from a base of the delta (i.e. the
        // delta itself may be a result of resolve processing)
        if (nDeltaMode == MODIFICATION && !delta.m_fPrevOverrideBase)
            {
            // determine the number of scripts on the base
            int cBaseImpl = vectBaseScript.size();

            // if the base overrode its base then only keep the reachable
            // base scripts
            if (base.m_fOverrideBase)
                {
                cBaseImpl -= base.m_cBaseLevelImpl;
                }

            // get the base scripts
            for (int i = 0; i < cBaseImpl; ++i)
                {
                Implementation scriptBase    = (Implementation) vectBaseScript.get(i);
                Implementation scriptDelta   = (Implementation) scriptBase.getNullDerivedTrait(delta, MODIFICATION);
                Implementation scriptDerived = (Implementation) scriptBase.resolve(scriptDelta, derived, loader, errlist);
                vectDerivedScript.addElement(scriptDerived);
                }

            derived.m_cBaseLevelImpl    = delta.m_cBaseLevelImpl + cBaseImpl;
            derived.m_fOverrideBase     = delta.m_fOverrideBase;
            derived.m_fPrevOverrideBase = base.m_fOverrideBase || base.m_fPrevOverrideBase;
            }
        else
            {
            derived.m_cBaseLevelImpl    = delta.m_cBaseLevelImpl;
            derived.m_fOverrideBase     = delta.m_fOverrideBase;
            derived.m_fPrevOverrideBase = delta.m_fPrevOverrideBase;
            }

        return derived;
        }

    /**
    * Resolve delta in flags.
    *
    * implementation note:  a flag value is always meaningful if the
    * behavior is resolved; otherwise it is meaningful only if the
    * specific attribute is specified; for example:
    *
    *      (fBaseResolved || (nBaseFlags & _SPECIFIED) != 0)
    *
    * @param nBaseFlags   the flags to use as the base flags
    * @param nDeltaFlags  the flags to use as the delta flags
    *
    * @return the derived flags
    */
    protected int resolveFlags(int nBaseFlags, int nDeltaFlags)
        {
        // for general use below
        boolean fSignature = getComponent().isSignature();

        // derived flags always start as the base flags; then the delta flags
        // are applied
        int nDerivedFlags = nBaseFlags;

        // optimization: check for nothing specified
        if (!fSignature && nDeltaFlags == 0)
            {
            return nDerivedFlags;
            }

        // flags cannot be changed if the base flags are final
        boolean fBaseResolved = (getMode() == RESOLVED);
        if ((fBaseResolved || (nBaseFlags & DERIVE_SPECIFIED) != 0)
                && (nBaseFlags & DERIVE_MASK) == DERIVE_FINAL)
            {
            return nDerivedFlags;
            }

        // the visible attribute is flexible
        if ((nDeltaFlags & VIS_SPECIFIED) != 0)
            {
            nDerivedFlags = nDerivedFlags & ~VIS_FULLMASK | nDeltaFlags & VIS_FULLMASK;
            }

        // the access attribute is one-way:  private to protected to public
        if (fSignature || (nDeltaFlags & ACCESS_SPECIFIED) != 0)
            {
            int nBaseAccess    = (nBaseFlags  & ACCESS_MASK);
            int nDeltaAccess   = (nDeltaFlags & ACCESS_MASK);
            int nDerivedAccess = nDeltaAccess;

            if ((fBaseResolved || (nBaseFlags & ACCESS_SPECIFIED) != 0)
                    && nDeltaAccess != nBaseAccess)
                {
                // specified on base and in delta; verify delta is legal
                switch (nBaseAccess)
                    {
                    case ACCESS_PRIVATE:
                        // from private to protected or public is allowed for
                        // modification only -- otherwise delta is an error
                        // since private behaviors from the super are dropped
                        // altogether in a derivation
                        break;
                    case ACCESS_PACKAGE:
                        // from package to protected is legal (for JCSs only)
                        if (nDeltaAccess == ACCESS_PROTECTED)
                            {
                            break;
                            }
                        // no break;
                    case ACCESS_PROTECTED:
                        // from protected to public is legal
                        if (nDeltaAccess == ACCESS_PUBLIC)
                            {
                            break;
                            }
                        // no break;
                    case ACCESS_PUBLIC:
                        // from public to protected or private is not legal
                        nDerivedAccess = nBaseAccess;
                        break;
                    }
                }

            nDerivedFlags = nDerivedFlags & ~ACCESS_MASK | ACCESS_SPECIFIED | nDerivedAccess;
            }

        // the synchronized attribute is flexible
        if (fSignature || (nDeltaFlags & SYNC_SPECIFIED) != 0)
            {
            nDerivedFlags = nDerivedFlags & ~SYNC_FULLMASK | nDeltaFlags & SYNC_FULLMASK;
            }

        // the scope attribute is never overridden (a Behavior cannot change
        // from static to instance or vice versa due to a derivation)

        // the abstract attribute is flexible
        if ((nDeltaFlags & IMPL_SPECIFIED) != 0)
            {
            nDerivedFlags = nDerivedFlags & ~IMPL_FULLMASK | nDeltaFlags & IMPL_FULLMASK;
            }

        // the final attribute is one-way
        if ((fSignature || (nDeltaFlags & DERIVE_SPECIFIED) != 0)
                && (nDeltaFlags & DERIVE_MASK) == DERIVE_FINAL)
            {
            nDerivedFlags = nDerivedFlags & ~DERIVE_FULLMASK | nDeltaFlags & DERIVE_FULLMASK;
            }

        // the antiquity (deprecated) attribute is flexible
        if (fSignature || (nDeltaFlags & ANTIQ_SPECIFIED) != 0)
            {
            nDerivedFlags = nDerivedFlags & ~ANTIQ_FULLMASK | nDeltaFlags & ANTIQ_FULLMASK;
            }

        // the distribution (remote) attribute is one-way, and is specifiable
        // only for Behaviors on global remote Components
        if ((nDeltaFlags & DIST_SPECIFIED) != 0
                && (nDeltaFlags & DIST_MASK) == DIST_REMOTE)
            {
            // only process if base is not already remote
            if (!((fBaseResolved || (nBaseFlags & DIST_SPECIFIED) != 0)
                    && (nBaseFlags & DIST_MASK) == DIST_REMOTE))
                {
                // remote behaviors only on global remote Components
                Component cd = getComponent();
                if (cd.isGlobal() && (cd.getMode() != RESOLVED || cd.isRemote()))
                    {
                    // determine accessibility of the method
                    boolean fPublic = (nDerivedFlags & ACCESS_MASK) == ACCESS_PUBLIC;
                    if (!fBaseResolved && (nDerivedFlags & ACCESS_SPECIFIED) == 0)
                        {
                        // if no access information is available, assume public
                        // until a resolve occurs in which information is available
                        fPublic = true;
                        }

                    // 2001.05.08 cp  allow static behaviors to be remote in order to
                    //                support ejb home design using static methods
                    /*
                    // determine scope of the behavior
                    boolean fInstance = (nDerivedFlags & SCOPE_MASK) == SCOPE_INSTANCE;
                    if (!fBaseResolved && (nDerivedFlags & SCOPE_SPECIFIED) == 0)
                        {
                        // if no scope information is available, assume instance
                        // until a resolve occurs in which information is available
                        fInstance = true;
                        }

                    // only allow remote to be set if behavior is non-static and public
                    if (fPublic && fInstance)
                    */
                    if (fPublic)
                        {
                        nDerivedFlags = nDerivedFlags & ~DIST_FULLMASK | nDeltaFlags & DIST_FULLMASK;
                        }
                    }
                }
            }

        return nDerivedFlags;
        }

    /**
    * Complete the resolve processing for this Behavior and its sub-traits,
    * discarding any Behavior Exceptions that have no origin.
    *
    * @param loader    the Loader object for JCS, CIM, and CD dependencies
    * @param errlist   the error list object to log error information to
    *
    * @exception ComponentException  thrown only if a fatal error occurs
    */
    protected synchronized void finalizeResolve(Loader loader, ErrorList errlist)
            throws ComponentException
        {
        super.finalizeResolve(loader, errlist);

        // remove all "specified" flags
        m_nFlags     &= ~ALL_SPECIFIED;
        m_nPrevFlags &= ~ALL_SPECIFIED;

        // discard transient (resolve only) data
        m_fPrevOverrideBase = false;

        // resolve sub-traits:  return value
        m_retval.finalizeResolve(loader, errlist);

        // resolve sub-traits:  parameters
        int c = m_vectParam.size();
        for (int i = 0; i < c; ++i)
            {
            ((Parameter) m_vectParam.elementAt(i)).finalizeResolve(loader, errlist);
            }

        // resolve sub-traits:  exceptions
        if (!m_tblExcept.isEmpty())
            {
            for (Enumeration enmr = m_tblExcept.elements(); enmr.hasMoreElements(); )
                {
                Throwee except = (Throwee) enmr.nextElement();
                except.finalizeResolve(loader, errlist);

                // discard un-needed exceptions
                if (except.isDiscardable())
                    {
                    m_tblExcept.remove(except.getUniqueName());
                    except.invalidate();
                    }
                }
            }
        }

    /**
    * Create a derivation/modification Trait by determining the differences
    * between the derived Trait ("this") and the passed base Trait.  Neither
    * the derived Trait ("this") nor the base may be modified in any way.
    *
    * @param traitBase  the base Trait to extract
    * @param parent     the Trait which will contain the resulting Trait or
    *                   null if the resulting Trait will not be contained
    * @param loader     the Loader object for JCS, CIM, and CD dependencies
    * @param errlist    the error list object to log error information to
    *
    * @return the delta between this derived Trait and the base Trait
    *
    * @exception ComponentException  thrown only if a fatal error occurs
    */
    protected Trait extract(Trait traitBase, Trait parent, Loader loader, ErrorList errlist)
            throws ComponentException
        {
        Behavior derived = this;
        Behavior base    = (Behavior) traitBase;
        Behavior delta   = (Behavior) super.extract(base, parent, loader, errlist);

        // for general use below
        boolean fSignature = getComponent().isSignature();

        // verify that behavior attributes match
        derived.verifyMatch(base, false, errlist);

        // determine if the base is resolved (which means all base attributes
        // are specified, i.e. have a value)
        boolean fBaseResolved = (base.getMode() == RESOLVED);

        // determine if extracting a DERIVATION or MODIFICATION
        int nDeltaMode = delta.getMode();

        // attributes represented as bit flags; see the length note in the
        // corresponding section of the extract method in Component.java
        int nBaseFlags    = base   .m_nFlags;
        int nDerivedFlags = derived.m_nFlags;
        int nDifFlags     = nBaseFlags ^ nDerivedFlags;
        int nDeltaFlags   = nDerivedFlags & ~ALL_SPECIFIED;

        // exists (always update for Behavior)
        nDeltaFlags = nDeltaFlags & ~EXISTS_FULLMASK | EXISTS_UPDATE;

        // visible
        if ((nDifFlags & VIS_MASK) != 0 &&
                (fBaseResolved || (nBaseFlags & VIS_SPECIFIED) != 0))
            {
            nDeltaFlags |= VIS_SPECIFIED;
            }

        // access
        if ((nDifFlags & ACCESS_MASK) != 0 &&
                (fBaseResolved || (nBaseFlags & ACCESS_SPECIFIED) != 0))
            {
            nDeltaFlags |= ACCESS_SPECIFIED;
            }

        // synchronized
        if ((nDifFlags & SYNC_MASK) != 0 &&
                (fBaseResolved || (nBaseFlags & SYNC_SPECIFIED) != 0))
            {
            nDeltaFlags |= SYNC_SPECIFIED;
            }

        // scope is not specifiable

        // abstract
        if ((nDifFlags & IMPL_MASK) != 0 &&
                (fBaseResolved || (nBaseFlags & IMPL_SPECIFIED) != 0))
            {
            nDeltaFlags |= IMPL_SPECIFIED;
            }

        // final
        if ((nDifFlags & DERIVE_MASK) != 0 &&
                (fBaseResolved || (nBaseFlags & DERIVE_SPECIFIED) != 0))
            {
            nDeltaFlags |= DERIVE_SPECIFIED;
            }

        // antiquity
        if ((nDifFlags & ANTIQ_MASK) != 0 &&
                (fBaseResolved || (nBaseFlags & ANTIQ_SPECIFIED) != 0))
            {
            nDeltaFlags |= ANTIQ_SPECIFIED;
            }

        // distribution
        if ((nDifFlags & DIST_MASK) != 0 &&
                (fBaseResolved || (nBaseFlags & DIST_SPECIFIED) != 0))
            {
            nDeltaFlags |= DIST_SPECIFIED;
            }

        // behavior attributes
        delta.m_sName      = base.m_sName;
        delta.m_nFlags     = nDeltaFlags;
        delta.m_nPrevFlags = 0;

        // extract sub-trait:  return value
        delta.m_retval = (ReturnValue) derived.m_retval.extract(
                base.m_retval, delta, loader, errlist);

        // extract sub-traits:  parameters
        Vector vectBaseParam    = base.m_vectParam;
        Vector vectDerivedParam = derived.matchParameters(base, false, errlist);
        Vector vectDeltaParam   = delta.m_vectParam;
        int cParam = vectBaseParam.size();
        vectDeltaParam.setSize(cParam);
        for (int i = 0; i < cParam; ++i)
            {
            Parameter paramBase    = (Parameter) vectBaseParam   .get(i);
            Parameter paramDerived = (Parameter) vectDerivedParam.get(i);
            Parameter paramDelta;

            // derived parameter is null to imply a resulting null derivation
            if (paramDerived == null)
                {
                paramDelta = (Parameter) paramBase.getNullDerivedTrait(delta, nDeltaMode);
                }
            else
                {
                paramDelta = (Parameter) paramDerived.extract(
                        paramBase, delta, loader, errlist);
                }

            vectDeltaParam.set(i, paramDelta);
            }
        delta.updateSignature();

        // extract sub-traits:  exceptions
        // (note:  derived exceptions may be a superset of base)
        StringTable tblBaseExcept    = base.m_tblExcept;
        StringTable tblDerivedExcept = derived.matchExceptions(base, false, errlist);
        StringTable tblDeltaExcept   = delta.m_tblExcept; // empty
        for (Enumeration enmr = tblDerivedExcept.keys(); enmr.hasMoreElements(); )
            {
            String  sExcept       = (String) enmr.nextElement();
            Throwee exceptBase    = (Throwee) tblBaseExcept   .get(sExcept);
            Throwee exceptDerived = (Throwee) tblDerivedExcept.get(sExcept);
            Throwee exceptDelta   = null;

            if (exceptBase == null)
                {
                // just copy derived exception information (nothing to extract)
                exceptDelta = new Throwee(delta, exceptDerived);
                }
            else
                {
                if (fSignature && exceptDerived == null)
                    {
                    // the super method has an exception type that is not on
                    // the derived method, meaning it has been deleted, so at
                    // this point reconstruct the "deleted derived" exception
                    exceptDerived = (Throwee) exceptBase.resolve(
                        exceptBase.getNullDerivedTrait(delta, nDeltaMode), derived, loader, errlist);
                    exceptDerived.setExists(EXISTS_DELETE);
                    }

                if (exceptDerived != null)
                    {
                    // extract the delta
                    exceptDelta = (Throwee) exceptDerived.extract(exceptBase, delta, loader, errlist);
                    }
                }

            if (exceptDelta != null)
                {
                tblDeltaExcept.put(sExcept, exceptDelta);
                }
            }

        // extract sub-traits:  implementations
        Vector vectBaseScripts    = base   .m_vectScript;
        Vector vectDerivedScripts = derived.m_vectScript;
        Vector vectDeltaScripts   = delta  .m_vectScript;   // empty

        // delta keeps only reachable implementations from derived
        int cScripts = vectDerivedScripts.size();
        if (cScripts > 0)
            {
            // the JCS implementations are not actually there; they are used only
            // for display in the tools
            if (isJcsImplementation(cScripts - 1))
                {
                cScripts--;
                }

            if (derived.m_fOverrideBase)
                {
                cScripts -= derived.m_cBaseLevelImpl;
                }
            }

        delta.m_fOverrideBase  = derived.m_fOverrideBase;
        delta.m_cBaseLevelImpl = nDeltaMode == DERIVATION ? derived.m_cBaseLevelImpl : 0;

        // deltas are never extracted for implementations; they are either
        // stored resolved (whole) or are discarded
Script: for (int i = 0; i < cScripts; ++i)
            {
            Implementation script = (Implementation) vectDerivedScripts.get(i);

            if (nDeltaMode == MODIFICATION)
                {
                int cBaseScripts = vectBaseScripts.size();
                for (int iBase = 0; iBase < cBaseScripts; ++iBase)
                    {
                    if (script.equalsUID((Implementation)vectBaseScripts.get(iBase)))
                        {
                        // this script belongs to the base; don't copy any
                        // more scripts to the delta
                        break Script;
                        }
                    }
                }

            vectDeltaScripts.add(new Implementation(delta, script));
            }

        return delta;
        }

    /**
    * Complete the extract processing for this Behavior and its sub-traits.
    *
    * @param loader    the Loader object for JCS, CIM, and CD dependencies
    * @param errlist   the error list object to log error information to
    *
    * @exception ComponentException  thrown only if a fatal error occurs
    */
    protected synchronized void finalizeExtract(Loader loader, ErrorList errlist)
            throws ComponentException
        {
        super.finalizeExtract(loader, errlist);

        // for general use below
        boolean fSignature = getComponent().isSignature();

        // finalize sub-trait:  return value
        m_retval.finalizeExtract(loader, errlist);

        // finalize sub-traits:  parameters
        int c = m_vectParam.size();
        for (int i = 0; i < c; ++i)
            {
            ((Parameter) m_vectParam.get(i)).finalizeExtract(loader, errlist);
            }

        // finalize sub-traits:  exceptions
        if (!m_tblExcept.isEmpty())
            {
            for (Enumeration enmr = m_tblExcept.elements(); enmr.hasMoreElements(); )
                {
                Throwee except = (Throwee) enmr.nextElement();
                except.finalizeExtract(loader, errlist);

                // check if the exception is discardable
                // (don't discard exceptions for signature methods:  see the
                // special resolve processing for signatures)
                if (!fSignature && except.isDiscardable())
                    {
                    m_tblExcept.remove(except.getUniqueName());
                    except.invalidate();
                    }
                }
            }

        // 2001.05.23  cp  this will break roll-up but will fix JCSs
        Vector vectScript = m_vectScript;
        int    cScripts   = vectScript.size();
        while (cScripts > 0 &&
               !((Implementation) vectScript.get(cScripts - 1)).isDeclaredAtThisLevel())
            {
            vectScript.remove(--cScripts);
            }
        m_cBaseLevelImpl = 0;
        }

    /**
    * Check for illegal mismatches between the base and this behavior.
    *
    * (Neither the base nor this behavior are modified by this method.)
    *
    * @param base      the super or base level's Behavior object
    * @param fResolve  true if being RESOLVED
    * @param errlist   the error list to log any mismatches to
    *
    * @exception DerivationException
    */
    protected void verifyMatch(Behavior base, boolean fResolve, ErrorList errlist)
            throws DerivationException
        {
        // check for name mismatch
        if (!this.m_sName.equals(base.m_sName))
            {
            String sCode = (fResolve ? RESOLVE_BEHAVIORNAMECHANGE
                                     : EXTRACT_BEHAVIORNAMECHANGE);
            Object[] aoParam = new Object[]
                {
                this.m_sName,
                base.m_sName,
                toPathString()
                };
            logError(sCode, WARNING, aoParam, errlist);
            }
        }

    /**
    * Match up the parameters from the base and this behavior.  Return a
    * Vector of parameters to resolve or extract from the base.  The returned
    * vector must not be modified.
    *
    * The returned vector may have null values which imply null derivations.
    *
    * (Neither the base nor this behavior are modified by this method.)
    *
    * @param base      the super or base level's Behavior object
    * @param fResolve  true if being RESOLVED
    * @param errlist   the error list to log any mismatches to
    *
    * @exception DerivationException
    */
    protected Vector matchParameters(Behavior base, boolean fResolve, ErrorList errlist)
            throws DerivationException
        {
        // get behavior parameters
        Vector  vectThisParam = this.m_vectParam;
        Vector  vectBaseParam = base.m_vectParam;
        int     cThisParam    = vectThisParam.size();
        int     cBaseParam    = vectBaseParam.size();

        if (cThisParam == cBaseParam)
            {
            boolean fMatch = true;
            if (!this.getComponent().isSignature())
                {
                for (int i = 0; i < cBaseParam; ++i)
                    {
                    Parameter pBase = (Parameter) vectBaseParam.get(i);
                    Parameter pThis = (Parameter) vectThisParam.get(i);
                    if (pThis.getUID() == null || !pThis.equalsUID(pBase))
                        {
                        fMatch = false;
                        break;
                        }
                    }
                }

            // most common:  parameters match
            if (fMatch)
                {
                return vectThisParam;
                }
            }

        // if parameters didn't match, create a new vector which does match
        // by adding, removing, and re-arranging parameters; this is assumed
        // to happen rarely
        Vector vectResultParam = new Vector(cBaseParam);
        vectResultParam.setSize(cBaseParam);

        // null derivations have no parameters in the delta to match
        if (cThisParam == 0)
            {
            return vectResultParam;
            }

        // build look up tables by UID and name
        Hashtable   tblParamByUID   = new Hashtable(cBaseParam);
        StringTable tblParamByName  = new StringTable(INSENS);
        for (int i = 0; i < cThisParam; ++i)
            {
            Parameter paramThis = (Parameter) vectThisParam.get(i);
            UID uid = paramThis.getUID();
            if (uid != null)
                {
                tblParamByUID .put(paramThis.getUID       (), paramThis);
                }
            tblParamByName.put(paramThis.getUniqueName(), paramThis);
            }

        // look up parameters by UID; remove each one found from the name
        // look up table
        if (!tblParamByUID.isEmpty())
            {
            for (int i = 0; i < cBaseParam; ++i)
                {
                Parameter paramBase = (Parameter) vectBaseParam.get(i);
                UID uid = paramBase.getUID();
                if (uid != null)
                    {
                    Parameter paramThis = (Parameter) tblParamByUID.get(uid);
                    if (paramThis != null)
                        {
                        vectResultParam.set(i, paramThis);
                        tblParamByName.remove(paramThis.getUniqueName());
                        }
                    }
                }
            }

        // fill in missing parameters by looking up by name; failing that
        // assume "null" derived traits
        for (int i = 0; i < cBaseParam; ++i)
            {
            if (vectResultParam.get(i) == null)
                {
                Parameter paramBase = (Parameter) vectBaseParam.get(i);
                Parameter paramThis = (Parameter) tblParamByName.get(paramBase.getUniqueName());
                if (paramThis != null)
                    {
                    vectResultParam.set(i, paramThis);

                    // only leave unmatched parameters in tblParamByName
                    // (so they can be discarded)
                    tblParamByName.remove(paramThis.getUniqueName());
                    }
                }
            }

        // discard remaining parameters
        for (Enumeration enmr = tblParamByName.elements(); enmr.hasMoreElements(); )
            {
            Parameter param = (Parameter) enmr.nextElement();

            String sCode = (fResolve ? RESOLVE_PARAMETERDISCARDED
                                     : EXTRACT_PARAMETERDISCARDED);
            Object[] aoParam = new Object[]
                {
                param.getName(),
                base.m_sSig,
                toPathString()
                };
            logError(sCode, WARNING, aoParam, errlist);
            }

        return vectResultParam;
        }

    /**
    * Match up the exceptions from the base and this behavior.  Return a
    * StringTable of exceptions to resolve or extract from the base.  The
    * returned StringTable must not be modified.
    *
    * The returned table may have null values which imply null derivations.
    *
    * The returned table may have additional exceptions.  Although the Java
    * Language Specification (8.4.4) states that there cannot be any
    * additional exceptions, it is possible that exception information was
    * added by an interface (for example) although such an exception will be
    * automatically marked as "deleted".
    *
    * (Neither the base nor this behavior are modified by this method.)
    *
    * @param base      the super or base level's Behavior object
    * @param fResolve  true if being RESOLVED
    * @param errlist   the error list to log any mismatches to
    *
    * @exception DerivationException
    */
    protected StringTable matchExceptions(Behavior base, boolean fResolve, ErrorList errlist)
            throws DerivationException
        {
        StringTable tblThis   = this.m_tblExcept;
        StringTable tblBase   = base.m_tblExcept;
        StringTable tblResult = tblThis;

        // most common case overall:  behavior has no declared exceptions
        // most common case for extract:  exact match
        if (tblThis.keysEquals(tblBase))
            {
            return tblResult;
            }

        // most common for resolve:  no exception information in the delta
        if (tblThis.isEmpty())
            {
            // copy keys from base (but leave exception traits null to
            // signify null derivations)
            tblResult = (StringTable) tblBase.clone();
            for (Enumeration enmr = tblResult.keys(); enmr.hasMoreElements(); )
                {
                tblResult.put((String) enmr.nextElement(), null);
                }
            return tblResult;
            }

        // create results table (since we cannot change the "this" table);
        // this extended processing will only happen at levels which add,
        // remove, or modify exceptions (considered to be rare)
        tblResult = new StringTable();

        // build look up tables by UID and name
        Hashtable   tblByUID  = new Hashtable();
        StringTable tblByName = new StringTable();
        for (Enumeration enmr = tblThis.elements(); enmr.hasMoreElements(); )
            {
            Throwee except = (Throwee) enmr.nextElement();
            UID uid = except.getUID();
            if (uid != null)
                {
                tblByUID.put(uid, except);
                }
            tblByName.put(except.getUniqueName(), except);
            }

        // look up by UID; remove each one found from the name look up table
        if (!tblByUID.isEmpty())
            {
            for (Enumeration enmr = tblBase.elements(); enmr.hasMoreElements(); )
                {
                Throwee exceptBase = (Throwee) enmr.nextElement();
                UID uid = exceptBase.getUID();
                if (uid != null)
                    {
                    Throwee exceptThis = (Throwee) tblByUID.get(uid);
                    if (exceptThis != null)
                        {
                        tblResult.put(exceptBase.getUniqueName(), exceptThis);
                        tblByName.remove(exceptThis.getUniqueName());
                        }
                    }
                }
            }

        // look up by name
        for (Enumeration enmr = tblBase.keys(); enmr.hasMoreElements(); )
            {
            String sExcept = (String) enmr.nextElement();
            if (!tblResult.contains(sExcept))
                {
                // find the exception on this behavior with the same name;
                // whether or not one exists, reserve the name in the result
                Throwee except = (Throwee) tblByName.get(sExcept);
                tblResult.put(sExcept, except);

                // only leave unmatched exceptions in tblByName
                // (so they can be added to the results or discarded)
                if (except != null)
                    {
                    tblByName.remove(sExcept);
                    }
                }
            }

        // keep additional exceptions (but discard any conflicting ones)
        for (Enumeration enmr = tblByName.elements(); enmr.hasMoreElements(); )
            {
            Throwee except = (Throwee) enmr.nextElement();
            String sExcept = except.getUniqueName();

            // check for conflict (this happens when a base exception is
            // renamed which conflicts if another exception was added at
            // this level and coincidentally has the same name)
            if (tblResult.contains(sExcept))
                {
                String sCode = (fResolve ? RESOLVE_EXCEPTIONDISCARDED
                                         : EXTRACT_EXCEPTIONDISCARDED);
                Object[] aoParam = new Object[]
                    {
                    except.getUniqueName(),
                    base.m_sSig,
                    toPathString()
                    };
                logError(sCode, WARNING, aoParam, errlist);
                }
            else
                {
                tblResult.put(sExcept, except);
                }
            }

        return tblResult;
        }

    /**
    * Determine whether this trait contains information that would cause
    * generation of a class that would operate differently than the class
    * generated from the information maintained by the super trait.
    *
    * @param base     the base (i.e. the super) Trait to compare to
    *
    * @return true if a delta between this trait and its super trait means
    *         that class generation should generate the class corresponding
    *         to this trait, otherwise false
    */
    protected boolean isClassDiscardable(Trait base)
        {
        Behavior that = (Behavior) base;
        if (that == null || !isFromSuper())
            {
            return false;
            }

        // attributes
        if (((this.m_nFlags ^ that.m_nFlags) & CLASSGEN_FLAGS) != 0)
            {
            return false;
            }

        // return value
        if (!this.m_retval.isClassDiscardable(that.m_retval))
            {
            return false;
            }

        // parameters
        Vector vectParamThis = this.m_vectParam;
        Vector vectParamThat = that.m_vectParam;
        for (int i = 0, c = vectParamThis.size(); i < c; ++i)
            {
            Parameter paramThis = (Parameter) vectParamThis.get(i);
            Parameter paramThat = (Parameter) vectParamThat.get(i);
            if (!paramThis.isClassDiscardable(paramThat))
                {
                return false;
                }
            }

        // exceptions
        if (!isClassDiscardableFromSubtraitTable(this.m_tblExcept, that.m_tblExcept))
            {
            return false;
            }

        // there must be no implementations
        if (this.m_vectScript.size() != (this.m_fOverrideBase ? this.m_cBaseLevelImpl : 0))
            {
            return false;
            }

        return super.isClassDiscardable(base);
        }


    // ----- miscellaneous Trait methods ------------------------------------

    /**
    * Determine if the Behavior is modifiable.  Behaviors that modify or
    * derive from final behaviors are not modifiable.
    *
    * @return true if the Trait is modifiable, false otherwise
    */
    public boolean isModifiable()
        {
        if ((m_nPrevFlags & DERIVE_MASK) == DERIVE_FINAL)
            {
            return false;
            }

        // gg: 2001.7.18 JCS constructors are not designable for now
        if (getComponent().isSignature() && getName().indexOf('<') != -1)
            {
            return false;
            }

        return super.isModifiable();
        }

    /**
    * Determines if this Behavior exists for any reason at all.  If a
    * Behavior exists, for example, as part of an interface, and the
    * interface changes, removing the Behavior, then the Behavior will be
    * discarded as part of the Component's resolve finalization processing.
    *
    * @return true if the Behavior is discardable
    */
    protected boolean isDiscardable()
        {
        switch (getMode())
            {
            case RESOLVED:
                {
                // Don't discard Java Class Signature Behaviors
                if (((Component) getParentTrait()).isSignature())
                    {
                    return false;
                    }
                break;
                }
            case DERIVATION:
            case MODIFICATION:
                {
                // check for delta information
                if ((m_nFlags & ALL_SPECIFIED) != 0 || m_fOverrideBase)
                    {
                    return false;
                    }
                break;
                }
            }

        return super.isDiscardable();
        }

    /**
    * Determine all traits contained by this behavior.
    *
    * @return the an enumeration of traits contained by this trait
    */
    protected Enumeration getSubTraits()
        {
        ChainedEnumerator enmr = new ChainedEnumerator();

        enmr.addEnumeration(new SimpleEnumerator(new Object[] {m_retval}));
        enmr.addEnumeration(m_vectParam.elements());
        enmr.addEnumeration(m_tblExcept.elements());
        enmr.addEnumeration(m_vectScript.elements());

        return enmr;
        }

    /**
    * Reset state, discarding all information.
    */
    protected synchronized void invalidate()
        {
        super.invalidate();

        m_sName      = null;
        m_sSig       = null;
        m_retval     = null;
        m_vectParam  = null;
        m_tblExcept  = null;
        m_vectScript = null;
        }

    /**
    * Determine the unique name for this trait.
    *
    * A sub-trait that exists within a collection of sub-traits must have
    * two ways of being identified:
    *
    *   1)  A unique name, which is a string identifier
    *   2)  A UID as a secondary identifier (dog tag)
    *
    * @return the primary string identifier of the trait
    */
    protected String getUniqueName()
        {
        // note:  unique name _can_ change but not behavior is not used as a
        // trait origin for other traits
        return m_sSig;
        }

    /**
    * Determine the unique description for this trait.
    *
    * All traits must be uniquely identifiable by a "description string".
    * This enables the origin implementation built into Trait to use the
    * description string to differentiate between Trait origins.
    *
    * @return the description string for the trait
    */
    protected String getUniqueDescription()
        {
        return DESCRIPTOR + ' ' + getUniqueName();
        }


    // ----- accessors ------------------------------------------------------

    /**
    * Determine the component which contains this behavior.
    *
    * @return the Component Definition that contains this behavior or null
    *         if this behavior is not part of a component
    */
    public Component getComponent()
        {
        return (Component) getParentTrait();
        }


    // ----- Signature

    /**
    * Build a behavior signature from a behavior name and parameter types.
    *
    * @param sName    the name of the behavior
    * @param adtParam the behavior's parameter data types
    *
    * @return the behavior signature built from the passed information
    */
    public static String getSignature(String sName, DataType[] adtParam)
        {
        return getSignature(sName, adtParam, 0);
        }

    /**
    * Build a behavior signature from a behavior name and parameter types.
    *
    * @param sName    the name of the behavior
    * @param adtParam the behavior's parameter data types
    * @param iFirst   the index of the first parameter in the array
    *
    * @return the behavior signature built from the passed information
    */
    public static String getSignature(String sName, DataType[] adtParam, int iFirst)
        {
        StringBuffer sb = new StringBuffer();

        sb.append(sName)
          .append('(');

        int cParam = (adtParam != null ? adtParam.length : 0);
        for (int i = iFirst; i < cParam; ++i)
            {
            sb.append(adtParam[i].getTypeString());
            }

        sb.append(')');

        return sb.toString();
        }

    /**
    * Get the signature for the behavior.  The signature uniquely identifies
    * the behavior.
    *
    * @return the signature for the behavior
    */
    public String getSignature()
        {
        return m_sSig;
        }

    /**
    * Update the signature for the behavior.  This method is called
    * internally when the behavior or a sub-trait of the behavior is
    * changed in such a way that the behavior signature is changed.
    */
    protected void updateSignature()
        {
        // get old signature (could be null if this has been called to ensure
        // that the signature is cached)
        String sOldSig = m_sSig;

        // get new signature
        StringBuffer sb = new StringBuffer();
        sb.append(m_sName)
          .append('(');
        int c = getParameterCount();
        for (int i = 0; i < c; ++i)
            {
            sb.append(getParameter(i).getSignature());
            }
        sb.append(')');
        String sNewSig = sb.toString();

        if (!sNewSig.equals(sOldSig))
            {
            // store new signature
            m_sSig = sNewSig;

            // update component's list of behaviors
            if (sOldSig != null)
                {
                getComponent().renameBehavior(sOldSig, sNewSig);
                }
            }
        }

    /**
    * Get the JVM signature for the behavior.  The JVM signature for a method
    * is composed of the JVM signatures for each of the parameters (within
    * parenthesis) plus the JVM signature for the method return type.
    *
    * @return the JVM signature for the behavior
    */
    public String getJVMSignature()
        {
        StringBuffer sb = new StringBuffer();

        sb.append('(');

        int c = getParameterCount();
        for (int i = 0; i < c; ++i)
            {
            sb.append(getParameter(i).getDataType().getJVMSignature());
            }

        sb.append(')')
          .append(m_retval.getDataType().getJVMSignature());

        return sb.toString();
        }


    // ----- origin:  helper for interface origins

    /**
    * Resolve any conflicts such that this Behavior matches the passed
    * method declaration for integration.
    *
    * @param map     declaring integration
    * @param method  the Java method information
    */
    protected void setDeclaredByIntegration(Integration map, Behavior method)
        {
        setDeclaredByTrait(map, true, method);
        }

    /**
    * Resolve any conflicts such that this Behavior matches the passed
    * method declaration for an interface.
    *
    * @param iface   declaring interface
    * @param method  the Java method information, or null if the method is
    *                implied (e.g. add/remove listener)
    */
    protected void setDeclaredByInterface(Interface iface, Behavior method)
        {
        setDeclaredByTrait(iface, false, method);
        }

    /**
    * Resolve any conflicts such that this Behavior matches the passed
    * method declaration for an interface or integration.
    *
    * @param trait        declaring interface or integration
    * @param fIntegration true if the integration trait
    * @param method       the Java method information, or null if the method is
    *                     implied (e.g. add/remove listener)
    */
    private void setDeclaredByTrait(Trait trait, boolean fIntegration, Behavior method)
        {
        // add/remove listener methods are implied; assume defaults
        DataType    dtRet      = DataType.VOID;
        String      sParamDirs = "I";
        StringTable tblExcept  = null;
        if (method != null)
            {
            dtRet      = method.m_retval.getDataType();
            sParamDirs = method.getParameterDirections();
            tblExcept  = method.m_tblExcept;
            }

        try
            {
            // update access
            if (fIntegration)
                {
                // integrates requires at least protected access
                if (getAccess() == ACCESS_PRIVATE)
                    {
                    // TODO - uncomment the following when the tools mature
                    // (Gene creates prop first then integrates second to save time)
                    // setAccess(ACCESS_PROTECTED, false);
                    setAccess(ACCESS_PUBLIC, false);
                    }
                }
            else
                {
                // implements/dispatches require public methods
                if (getAccess() != ACCESS_PUBLIC)
                    {
                    setAccess(ACCESS_PUBLIC, false);
                    }
                }

            // cannot be static for Component,
            // but as of Java 8 static extension methods are allowed
            setStatic(method != null && method.isStatic() && getComponent().isSignature(), false);

            // match up return value data type and parameter directions
            m_retval.setDataType(dtRet, false);
            setParameterDirections(sParamDirs, false);

            // the exceptions that currently exist must be merged with the
            // exceptions from the interface/integrates method, and if the
            // Behavior has a non-manual origin, then only the intersection
            // of the exceptions are permitted to remain throwable
            StringTable tblThrowee = m_tblExcept;

            if (getComponent().isSignature())
                {
                // assuming the signature is correct, we can safely
                // ignore any exceptions declared by the interface
                // TODO: the logic below doesn't really do what the comment above
                // claims, but to validate covariant types we need to have a loader
                // (e.g. to figure out that SocketException is an IOException)
                }
            else
                {
                if (tblExcept != null && !tblExcept.isEmpty())
                    {
                    if (getComponent().isSignature())
                        {
                        return;
                        }

                    // copy method exceptions to the Behavior
                    for (Enumeration enmr = tblExcept.keys(); enmr.hasMoreElements(); )
                        {
                        String sExcept = (String) enmr.nextElement();
                        Throwee except = (Throwee) tblExcept.get(sExcept);
                        Throwee throwee = (Throwee) tblThrowee.get(sExcept);

                        // create the exception if is not declared by the Behavior
                        if (throwee == null)
                            {
                            throwee = new Throwee(this, except.getDataType());

                            // if the behavior is declared elsewhere (base or
                            // super level or from an interface), the exception
                            // cannot be thrown
                            if (isFromSuper() || isFromImplements()
                                || isFromDispatches() || isFromIntegration())
                                {
                                throwee.setExists(EXISTS_DELETE);
                                }
                            tblThrowee.put(sExcept, throwee);
                            throwee.validate();
                            }

                        // update exception origin
                        throwee.addOriginTrait(trait);
                        }
                    }

                // remove previously existing declared exceptions that are not
                // declared by the interface/integrates method
                for (Enumeration enmr = tblThrowee.keys(); enmr.hasMoreElements(); )
                    {
                    String sExcept = (String) enmr.nextElement();
                    if (!tblExcept.contains(sExcept))
                        {
                        removeException(sExcept, false);
                        }
                    }
                }

            // update Behavior origin
            addOriginTrait(trait);
            }
        catch (PropertyVetoException e)
            {
            throw new IllegalStateException(e.toString());
            }
        }

    /**
    * Merge the exceptions lists from two behaviors, modifying this behavior.
    * This is used by JCS from ClassFile creation.
    *
    * @param that  the other behavior
    */
    protected void mergeJCSExceptions(Behavior that)
        {
        if (!this.m_tblExcept.equals(that.m_tblExcept))
            {
            this.m_tblExcept.retainAll(that.m_tblExcept);
            }
        }


    // ----- origin:  behavior implements interface(s)

    /**
    * Determine if this behavior is from an interface.
    *
    * @return true if this behavior results from an interface at this level
    */
    public boolean isFromImplements()
        {
        return isFromTraitDescriptor(Interface.DESCRIPTOR_IMPLEMENTS);
        }

    /**
    * Enumerate the interface names that exist at this level which declare
    * this behavior.
    *
    * @return an enumeration of interface names
    */
    public Enumeration enumImplements()
        {
        return getOriginTraits(Interface.DESCRIPTOR_IMPLEMENTS);
        }


    // ----- origin:  behavior dispatches interface(s)

    /**
    * Determine if this behavior is from a dispatched interface.
    *
    * @return true if this behavior results from a dispatched interface at
    *         this level
    */
    public boolean isFromDispatches()
        {
        return isFromTraitDescriptor(Interface.DESCRIPTOR_DISPATCHES);
        }

    /**
    * Enumerate the dispatch interface names that exist at this level which
    * declare this behavior.
    *
    * @return an enumeration of dispatch interface names
    */
    public Enumeration enumDispatches()
        {
        return getOriginTraits(Interface.DESCRIPTOR_DISPATCHES);
        }


    // ----- origin:  behavior integrates

    /**
    * Determine if this behavior exists as a result of integration at this
    * level.
    *
    * @return true if this behavior results from integration at this level
    */
    public boolean isFromIntegration()
        {
        return isFromTraitDescriptor(Integration.DESCRIPTOR);
        }


    // ----- origin:  behavior from a property

    /**
    * Determine if this behavior exists due to a property.
    *
    * @return true if this behavior results from a property
    */
    public boolean isFromProperty()
        {
        return isFromTraitDescriptor(Property.DESCRIPTOR);
        }

    /**
    * Determine the name of the property that this behavior implements.
    *
    * @return the property name
    */
    public String getPropertyName()
        {
        String sProp;
        if (m_sName.startsWith("is"))
            {
            sProp = m_sName.substring("is".length());
            }
        else if (m_sName.startsWith("get"))
            {
            sProp = m_sName.substring("get".length());
            }
        else if (m_sName.startsWith("set"))
            {
            sProp = m_sName.substring("set".length());
            }
        else
            {
            return null;
            }

        Property prop = getComponent().getProperty(sProp);
        return (prop == null ? null : sProp);
        }


    // ----- origin:  behavior declared "manually"

    /**
    * Determine if the manual origin flag can be set.  It cannot be set if
    * the behavior's only origin is manual.
    *
    * @return true if the manual origin flag can be set
    */
    public boolean isFromManualSettable()
        {
        return isDeclaredAtThisLevel() && isFromNonManual() && isModifiable();
        }

    /**
    * Set whether or not this behavior exists at this level regardless of
    * whether it exists from derivation, implements, dispatches, or
    * integrates.
    *
    * @param fManual
    */
    public void setFromManual(boolean fManual)
            throws PropertyVetoException
        {
        setFromManual(fManual, true);
        }

    /**
    * Set whether or not this behavior exists at this level regardless of
    * whether it exists from derivation, implements, dispatches, or
    * integrates.
    *
    * @param fManual
    * @param fVetoable  true if the setter can veto the value
    */
    protected synchronized void setFromManual(boolean fManual, boolean fVetoable)
            throws PropertyVetoException
        {
        boolean fPrev = isFromManual();

        if (fManual == fPrev)
            {
            return;
            }

        Boolean prev  = toBoolean(fPrev);
        Boolean value = toBoolean(fManual);

        if (fVetoable)
            {
            if (!isFromManualSettable())
                {
                readOnlyAttribute(ATTR_FROMMANUAL, prev, value);
                }

            fireVetoableChange(ATTR_FROMMANUAL, prev, value);
            }

        if (fManual)
            {
            setFromManual();
            }
        else
            {
            clearFromManual();
            }

        firePropertyChange(ATTR_FROMMANUAL, prev, value);
        }


    // ----- Exists

    /**
    * Get the exists flag for this Behavior.
    *
    * For a JCS, a Behavior is EXISTS_NOT if a super or interface declares
    * the method but the method is not present in the class represented by
    * the JCS.
    *
    * @return either EXISTS_INSERT or EXISTS_UPDATE (or EXISTS_NOT if a JCS)
    */
    public int getExists()
        {
        return m_nFlags & EXISTS_MASK;
        }

    /**
    * Set the exists flag for this Behavior.
    *
    * @param nExists  the exists flag for this Behavior
    */
    protected void setExists(int nExists)
        {
        m_nFlags = m_nFlags & ~EXISTS_MASK | nExists;
        }


    // ----- Access

    /**
    * Determine the current accessibility of the Behavior.
    *
    * @return either ACCESS_PUBLIC, ACCESS_PROTECTED, or ACCESS_PRIVATE
    *
    * @see com.tangosol.dev.component.Constants#ACCESS_PUBLIC
    * @see com.tangosol.dev.component.Constants#ACCESS_PROTECTED
    * @see com.tangosol.dev.component.Constants#ACCESS_PRIVATE
    */
    public int getAccess()
        {
        return m_nFlags & ACCESS_MASK;
        }

    /**
    * Determine if the accessibility of the Behavior can be modified.
    *
    * The accessibility cannot be set if the Behavior is declared final at
    * a super level or if the Behavior originates from an interface.
    *
    * @return true if the access attribute of the Behavior can be set
    */
    public boolean isAccessSettable()
        {
        // if Behavior is part of an "interface", it can only be public
        return isModifiable()
            && !isFromImplements()
            && !isFromDispatches();
        }

    /**
    * Determine if the specified value is acceptable for the access
    * attribute.
    *
    * The accessibility can only be increased from the super level; access
    * is a one-way attribute (private -> protected -> public).
    *
    * @return true if the specified value is acceptable for the access
    *         attribute
    *
    * @see com.tangosol.dev.component.Constants#ACCESS_PUBLIC
    * @see com.tangosol.dev.component.Constants#ACCESS_PROTECTED
    * @see com.tangosol.dev.component.Constants#ACCESS_PRIVATE
    */
    public boolean isAccessLegal(int nAccess)
        {
        switch (nAccess)
            {
            case ACCESS_PUBLIC:
            case ACCESS_PROTECTED:
            case ACCESS_PRIVATE:
                break;

            default:
                return false;
            }

        // remote methods must be public
        if (isRemote() && nAccess != ACCESS_PUBLIC)
            {
            return false;
            }

        // flexible at declaration level
        if (isDeclaredAtThisLevel())
            {
            if (isFromImplements() || isFromDispatches())
                {
                // interface Behaviors must be public
                return false;
                }

            if (isFromIntegration())
                {
                // integrated Behaviors must be protected or public in order
                // to be called from the integratee
                return (nAccess != ACCESS_PRIVATE);
                }

            return true;
            }

        // one-way access validation
        switch (m_nPrevFlags & ACCESS_MASK)
            {
            case ACCESS_PUBLIC:
                if (nAccess == ACCESS_PROTECTED)
                    {
                    return false;
                    }
                // no break;
            case ACCESS_PROTECTED:
                if (nAccess == ACCESS_PRIVATE)
                    {
                    return false;
                    }
                // no break;
            case ACCESS_PRIVATE:
            default:
                return true;
            }
        }

    /**
    * Set the accessibility of the Behavior.
    *
    * @param nAccess  ACCESS_PUBLIC, ACCESS_PROTECTED, or ACCESS_PRIVATE
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    *
    * @see com.tangosol.dev.component.Constants#ACCESS_PUBLIC
    * @see com.tangosol.dev.component.Constants#ACCESS_PROTECTED
    * @see com.tangosol.dev.component.Constants#ACCESS_PRIVATE
    */
    public void setAccess(int nAccess)
            throws PropertyVetoException
        {
        setAccess(nAccess, true);
        }

    /**
    * Set the accessibility of the Behavior.
    *
    * @param nAccess    ACCESS_PUBLIC, ACCESS_PROTECTED, or ACCESS_PRIVATE
    * @param fVetoable  true if the setter can veto the value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void setAccess(int nAccess, boolean fVetoable)
            throws PropertyVetoException
        {
        int nPrev = getAccess();

        if (nAccess == nPrev)
            {
            return;
            }

        Integer prev  = Integer.valueOf(nPrev);
        Integer value = Integer.valueOf(nAccess);

        if (fVetoable)
            {
            if (!isAccessSettable())
                {
                readOnlyAttribute(ATTR_ACCESS, prev, value);
                }

            if (!isAccessLegal(nAccess))
                {
                illegalAttributeValue(ATTR_ACCESS, prev, value);
                }

            fireVetoableChange(ATTR_ACCESS, prev, value);
            }

        m_nFlags = m_nFlags & ~ACCESS_MASK | nAccess;
        firePropertyChange(ATTR_ACCESS, prev, value);
        }


    // ----- Visible

    /**
    * Get the visibility attribute of the Behavior.
    *
    * @return the value of the Behavior's visibility attribute
    *
    * @see com.tangosol.dev.component.Constants#VIS_SYSTEM
    * @see com.tangosol.dev.component.Constants#VIS_HIDDEN
    * @see com.tangosol.dev.component.Constants#VIS_ADVANCED
    * @see com.tangosol.dev.component.Constants#VIS_VISIBLE
    */
    public int getVisible()
        {
        return m_nFlags & VIS_MASK;
        }

    /**
    * Determine whether the Visible attribute of the Behavior can be set.
    *
    * @return true if the Behavior attribute can set with a valid value
    */
    public boolean isVisibleSettable()
        {
        return isModifiable();
        }

    /**
    * Determine whether the Visible attribute of the Behavior can be set to
    * the specified value.  The Visible attribute is flexible.
    *
    * @param nVis the new value of the visibility attribute
    *
    * @return true if the specified value is acceptable
    *
    * @see com.tangosol.dev.component.Constants#VIS_SYSTEM
    * @see com.tangosol.dev.component.Constants#VIS_HIDDEN
    * @see com.tangosol.dev.component.Constants#VIS_ADVANCED
    * @see com.tangosol.dev.component.Constants#VIS_VISIBLE
    */
    public boolean isVisibleLegal(int nVis)
        {
        switch (nVis)
            {
            case VIS_SYSTEM:
            case VIS_HIDDEN:
            case VIS_ADVANCED:
            case VIS_VISIBLE:
                return true;
            default:
                return false;
            }
        }

    /**
    * Set the visible attribute of the Behavior.
    *
    * @param nVis the new visibility value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    *
    * @see com.tangosol.dev.component.Constants#VIS_SYSTEM
    * @see com.tangosol.dev.component.Constants#VIS_HIDDEN
    * @see com.tangosol.dev.component.Constants#VIS_ADVANCED
    * @see com.tangosol.dev.component.Constants#VIS_VISIBLE
    */
    public void setVisible(int nVis)
            throws PropertyVetoException
        {
        setVisible(nVis, true);
        }

    /**
    * Set the visible attribute of the Behavior.
    *
    * @param nVis       the new visibility value
    * @param fVetoable  true if the setter can veto the value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void setVisible(int nVis, boolean fVetoable)
            throws PropertyVetoException
        {
        int nPrevVis = getVisible();

        if (nVis == nPrevVis)
            {
            return;
            }

        Integer prev  = Integer.valueOf(nPrevVis);
        Integer value = Integer.valueOf(nVis);

        if (fVetoable)
            {
            if (!isVisibleSettable())
                {
                readOnlyAttribute(ATTR_VISIBLE, prev, value);
                }

            if (!isVisibleLegal(nVis))
                {
                illegalAttributeValue(ATTR_VISIBLE, prev, value);
                }

            fireVetoableChange(ATTR_VISIBLE, prev, value);
            }

        m_nFlags = m_nFlags & ~VIS_MASK | nVis;
        firePropertyChange(ATTR_VISIBLE, prev, value);
        }


    // ----- Synchronized

    /**
    * Get the synchronized attribute of the Behavior.
    *
    * @return true if the Behavior is synchronized
    */
    public boolean isSynchronized()
        {
        return (m_nFlags & SYNC_MASK) == SYNC_MONITOR;
        }

    /**
    * Determine whether the synchronized attribute of the Behavior can be
    * set.  Since the synchronized attribute is expressed as a boolean, this
    * method doubles for both the "is settable" and "is legal" questions. The
    * synchronized attribute of the Behavior is flexible.
    *
    * @return true if the synchronized attribute can set
    */
    public boolean isSynchronizedSettable()
        {
        return isModifiable();
        }

    /**
    * Set the synchronized attribute of the Behavior.
    *
    * @param fSync  the new synchronized attribute value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public void setSynchronized(boolean fSync)
            throws PropertyVetoException
        {
        setSynchronized(fSync, true);
        }

    /**
    * Set the synchronized attribute of the Behavior.
    *
    * @param fSync      the new synchronized attribute value
    * @param fVetoable  true if the setter can veto the value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void setSynchronized(boolean fSync, boolean fVetoable)
            throws PropertyVetoException
        {
        boolean fPrevSync = isSynchronized();

        if (fSync == fPrevSync)
            {
            return;
            }

        Boolean prev  = toBoolean(fPrevSync);
        Boolean value = toBoolean(fSync);

        if (fVetoable)
            {
            if (!isSynchronizedSettable())
                {
                readOnlyAttribute(ATTR_SYNCHRONIZED, prev, value);
                }

            fireVetoableChange(ATTR_SYNCHRONIZED, prev, value);
            }

        m_nFlags = m_nFlags & ~SYNC_MASK | (fSync ? SYNC_MONITOR : SYNC_NOMONITOR);
        firePropertyChange(ATTR_SYNCHRONIZED, prev, value);
        }


    // ----- Abstract

    /**
    * Get the Behavior implementation attribute.
    *
    * @return true if the Behavior is abstract
    */
    public boolean isAbstract()
        {
        return (m_nFlags & IMPL_MASK) == IMPL_ABSTRACT;
        }

    /**
    * Determine whether the implementation attribute of the Behavior can
    * be set.  Since the implementation attribute is expressed as a boolean,
    * this method doubles for both the "is settable" and "is legal"
    * questions. The implementation attribute of the Behavior is flexible
    * for instance-scope Behaviors but cannot be set for static-scope.
    *
    * @return true if the implementation attribute can set
    */
    public boolean isAbstractSettable()
        {
        return isModifiable() && !(isStatic() || isFinal());
        }

    /**
    * Set the Behavior's implementation attribute.
    *
    * @param fAbstract the new implementation attribute value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public void setAbstract(boolean fAbstract)
            throws PropertyVetoException
        {
        setAbstract(fAbstract, true);
        }

    /**
    * Set the Behavior's implementation attribute.
    *
    * @param fAbstract  the new implementation attribute value
    * @param fVetoable  true if the setter can veto the value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void setAbstract(boolean fAbstract, boolean fVetoable)
            throws PropertyVetoException
        {
        boolean fPrevAbstract = isAbstract();

        if (fAbstract == fPrevAbstract)
            {
            return;
            }

        Boolean prev  = toBoolean(fPrevAbstract);
        Boolean value = toBoolean(fAbstract);

        if (fVetoable)
            {
            if (!isAbstractSettable())
                {
                readOnlyAttribute(ATTR_ABSTRACT, prev, value);
                }

            fireVetoableChange(ATTR_ABSTRACT, prev, value);
            }

        m_nFlags = m_nFlags & ~IMPL_MASK | (fAbstract ? IMPL_ABSTRACT : IMPL_CONCRETE);
        firePropertyChange(ATTR_ABSTRACT, prev, value);
        }


    // ----- Static

    /**
    * Determine the current scope of the Behavior.
    *
    * @return true if the Behavior is static (not instance)
    */
    public boolean isStatic()
        {
        return (m_nFlags & SCOPE_MASK) == SCOPE_STATIC;
        }

    /**
    * Determine if the scope of the Behavior can be modified.
    *
    * Static cannot co-exist with abstract or remote.
    * Static cannot be set if the  Behavior is from an "interface",
    * a Property, or from a super level.
    *
    * @return true if the scope attribute of the Behavior can be set
    */
    public boolean isStaticSettable()
        {
        // 2001.05.08 cp  allow static behaviors to be remote in order to
        //                support ejb home design using static methods
        return isModifiable() && !isFromNonManual() && !isAbstract(); // && !isRemote();
        }

    /**
    * Set the scope attribute of the Behavior.
    *
    * @param fStatic the new scope value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public void setStatic(boolean fStatic)
            throws PropertyVetoException
        {
        setStatic(fStatic, true);
        }

    /**
    * Set the scope attribute of the Behavior.
    *
    * @param fStatic    the new scope value
    * @param fVetoable  true if the setter can veto the value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void setStatic(boolean fStatic, boolean fVetoable)
            throws PropertyVetoException
        {
        boolean fPrevStatic = isStatic();

        if (fStatic == fPrevStatic)
            {
            return;
            }

        Boolean prev  = toBoolean(fPrevStatic);
        Boolean value = toBoolean(fStatic);

        if (fVetoable)
            {
            if (!isStaticSettable())
                {
                readOnlyAttribute(ATTR_STATIC, prev, value);
                }

            fireVetoableChange(ATTR_STATIC, prev, value);
            }

        m_nFlags = m_nFlags & ~SCOPE_MASK | (fStatic ? SCOPE_STATIC : SCOPE_INSTANCE);
        firePropertyChange(ATTR_STATIC, prev, value);
        }


    // ----- Final

    /**
    * Determine the current finality of the Behavior.
    *
    * @return true if the Behavior is final
    */
    public boolean isFinal()
        {
        return (m_nFlags & DERIVE_MASK) == DERIVE_FINAL;
        }

    /**
    * Determine if the finality of the Behavior can be modified.
    *
    * @return true if the final attribute of the Behavior can be set
    */
    public boolean isFinalSettable()
        {
        return isModifiable() && !isAbstract();
        }

    /**
    * Set the finality attribute of the Behavior.
    *
    * @param fFinal the new finality value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public void setFinal(boolean fFinal)
            throws PropertyVetoException
        {
        setFinal(fFinal, true);
        }

    /**
    * Set the finality attribute of the Behavior.
    *
    * @param fFinal     the new finality value
    * @param fVetoable  true if the setter can veto the value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void setFinal(boolean fFinal, boolean fVetoable)
            throws PropertyVetoException
        {
        boolean fPrevFinal = isFinal();

        if (fFinal == fPrevFinal)
            {
            return;
            }

        Boolean prev  = toBoolean(fPrevFinal);
        Boolean value = toBoolean(fFinal);

        if (fVetoable)
            {
            if (!isFinalSettable())
                {
                readOnlyAttribute(ATTR_FINAL, prev, value);
                }

            fireVetoableChange(ATTR_FINAL, prev, value);
            }

        m_nFlags = m_nFlags & ~DERIVE_MASK | (fFinal ? DERIVE_FINAL : DERIVE_DERIVABLE);
        firePropertyChange(ATTR_FINAL, prev, value);
        }


    // ----- Deprecated

    /**
    * Get the antiquity attribute of the Behavior.
    *
    * @return true if the Behavior is deprecated
    */
    public boolean isDeprecated()
        {
        return (m_nFlags & ANTIQ_MASK) == ANTIQ_DEPRECATED;
        }

    /**
    * Determine whether the antiquity attribute of the Behavior can be set.
    * Since the antiquity attribute is expressed as a boolean,  this method
    * doubles for both the "is settable" and "is legal" questions. The
    * antiquity attribute of the Behavior is flexible.
    *
    * @return true if the antiquity attribute can set
    */
    public boolean isDeprecatedSettable()
        {
        return isModifiable();
        }

    /**
    * Set the antiquity attribute of the Behavior.
    *
    * @param fDeprecated the new antiquity attribute value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public void setDeprecated(boolean fDeprecated)
            throws PropertyVetoException
        {
        setDeprecated(fDeprecated, true);
        }

    /**
    * Set the antiquity attribute of the Behavior.
    *
    * @param fDeprecated  the new antiquity attribute value
    * @param fVetoable    true if the setter can veto the value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void setDeprecated(boolean fDeprecated, boolean fVetoable)
            throws PropertyVetoException
        {
        boolean fPrevDeprecated = isDeprecated();

        if (fDeprecated == fPrevDeprecated)
            {
            return;
            }

        Boolean prev  = toBoolean(fPrevDeprecated);
        Boolean value = toBoolean(fDeprecated);

        if (fVetoable)
            {
            if (!isDeprecatedSettable())
                {
                readOnlyAttribute(ATTR_DEPRECATED, prev, value);
                }

            fireVetoableChange(ATTR_DEPRECATED, prev, value);
            }

        m_nFlags = m_nFlags & ~ANTIQ_MASK | (fDeprecated ? ANTIQ_DEPRECATED : ANTIQ_CURRENT);
        firePropertyChange(ATTR_DEPRECATED, prev, value);
        }


    // ----- Remote

    /**
    * Get the Behavior distribution attribute.
    *
    * @return true if the Behavior is remotable
    */
    public boolean isRemote()
        {
        return (m_nFlags & DIST_MASK) == DIST_REMOTE;
        }

    /**
    * Determine whether the distribution attribute of the Behavior can be
    * set.  Since the distribution attribute is expressed as a boolean,  this
    * method doubles for both the "is settable" and "is legal" questions.
    * The distribution is one-way attribute (local -> remote).
    * Note that a behavior cannot be marked as remote if it is static or
    * non-public.
    *
    * @return true if the distribution attribute can set
    */
    public boolean isRemoteSettable()
        {
        Component cd = getComponent();
        // 2001.05.08 cp  allow static behaviors to be remote in order to
        //                support ejb home design using static methods
        // return isModifiable() && !isStatic() && getAccess() == ACCESS_PUBLIC
        //        && cd.isRemote() && cd.isGlobal()
        //        && (m_nPrevFlags & DIST_MASK) == DIST_LOCAL;
        return isModifiable() && getAccess() == ACCESS_PUBLIC
                && cd.isRemote() && cd.isGlobal()
                && (m_nPrevFlags & DIST_MASK) == DIST_LOCAL;
        }

    /**
    * Set the Behavior's distribution attribute.
    *
    * @param fRemote  the new distribution attribute value
    *
    * @exception PropertyVetoException if the new attribute value is not
    *            accepted
    */
    public void setRemote(boolean fRemote)
            throws PropertyVetoException
        {
        setRemote(fRemote, true);
        }

    /**
    * Set the Behavior's distribution attribute.
    *
    * @param fRemote    the new distribution attribute value
    * @param fVetoable  true if the setter can veto the value
    *
    * @exception PropertyVetoException if the new attribute value is not
    *            accepted
    */
    protected synchronized void setRemote(boolean fRemote, boolean fVetoable)
            throws PropertyVetoException
        {
        boolean fPrevRemote = isRemote();

        if (fRemote == fPrevRemote)
            {
            return;
            }

        Boolean prev  = toBoolean(fPrevRemote);
        Boolean value = toBoolean(fRemote);

        if (fVetoable)
            {
            if (!isRemoteSettable())
                {
                readOnlyAttribute(ATTR_REMOTE, prev, value);
                }

            fireVetoableChange(ATTR_REMOTE, prev, value);
            }

        m_nFlags = m_nFlags & ~DIST_MASK | (fRemote ? DIST_REMOTE : DIST_LOCAL);

        if (fPrevRemote)
            {
            // local Behaviors cannot have inout or out Parameters
            int c = getParameterCount();
            for (int i = 0; i < c; ++i)
                {
                Parameter param = getParameter(i);
                if (param.getDirection() != DIR_IN)
                    {
                    param.setDirection(DIR_IN, false);
                    }
                }
            }

        firePropertyChange(ATTR_REMOTE, prev, value);
        }


    // ----- return value

    /**
    * Access the return value sub-trait.  All modifications are done to the
    * sub-trait itself so there is no add/remove/set etc. for the return
    * value here.
    *
    * @return the return value sub-trait
    */
    public ReturnValue getReturnValue()
        {
        return m_retval;
        }


    // ----- name

    /**
    * Determine the name of this behavior.
    *
    * @return the name of this behavior
    */
    public String getName()
        {
        return m_sName;
        }

    /**
    * Determine if this behavior is a constructor,
    * only valid for Java Class Signatures.
    *
    * @return true if it is a constructor
    */
    public boolean isConstructor()
        {
        return isConstructor(m_sName);
        }

    /**
    * Determine if this behavior name or signature is a
    * constructor, only valid for Java Class Signatures.
    *
    * @param  sName the name or signature to check
    * @return true if is is a constructor
    */
    public static boolean isConstructor(String sName)
        {
        return sName.charAt(0) == '<';
        }

    /**
    * Determine if the behavior name can be set.  It cannot be set if
    * the behavior originates from anything except manual addition.
    *
    * @return true if the behavior name can be set
    */
    public boolean isNameSettable()
        {
        return isModifiable() && !isFromNonManual();
        }

    /**
    * Determine if the specified name is a legal behavior name and that
    * it won't conflict with other behavior signatures.
    *
    * @return true if the specified name is legal for this behavior
    */
    public boolean isNameLegal(String sName)
        {
        // must be a legal Java identifier
        if (sName == null || sName.length() == 0 ||
                !ClassHelper.isSimpleNameLegal(sName))
            {
            return false;
            }

        // check if name is unchanged
        if (sName.equals(m_sName))
            {
            return true;
            }

        // build the proposed signature
        String sSig = getSignature(sName, getParameterTypes());

        return !isSignatureReserved(sSig);
        }

    /**
    * Set the behavior name.
    *
    * @param sName the new name for the behavior
    *
    * @exception PropertyVetoException if the new attribute value is not
    *            accepted
    */
    public void setName(String sName)
            throws PropertyVetoException
        {
        setName(sName, true);
        }

    /**
    * Set the behavior name.
    *
    * @param sName      the new name for the behavior
    * @param fVetoable  true if the setter can veto the value
    *
    * @exception PropertyVetoException if the new attribute value is not
    *            accepted
    */
    protected synchronized void setName(String sName, boolean fVetoable)
            throws PropertyVetoException
        {
        String sPrev = m_sName;

        if (sName.equals(sPrev))
            {
            return;
            }

        if (fVetoable)
            {
            if (!isNameSettable())
                {
                readOnlyAttribute(ATTR_NAME, sPrev, sName);
                }

            if (!isNameLegal(sName))
                {
                illegalAttributeValue(ATTR_NAME, sPrev, sName);
                }

            fireVetoableChange(ATTR_NAME, sPrev, sName);
            }

        m_sName = sName;
        updateSignature();

        firePropertyChange(ATTR_NAME, sPrev, sName);
        }


    // ----- parameters

    /**
    * Get all behavior parameters.
    *
    * @return an array of behavior parameters
    */
    public Parameter[] getParameter()
        {
        int c = getParameterCount();
        Parameter[] aparam = new Parameter[c];
        for (int i = 0; i < c; ++i)
            {
            aparam[i] = getParameter(i);
            }

        return aparam;
        }

    /**
    * Determine if the parameter array can be set.  The parameter array
    * can only be changed if the behavior is declared at this level
    * and isn't part of an interface or the result of integration.
    *
    * @return true if the array of parameters can be set
    */
    public boolean isParameterSettable()
        {
        return isModifiable() && !isFromNonManual();
        }

    /**
    * Determine if the specified array of parameters is a legal array of
    * parameters for this behavior.
    *
    * @param aparam  an array of behavior parameters; this must be the same
    *                set of parameters as returned from the corresponding
    *                accessor, but can be in a different order
    *
    * @return true if the specified array of parameters is legal
    */
    public boolean isParameterLegal(Parameter[] aparam)
        {
        int c = getParameterCount();
        if (aparam == null || aparam.length != c)
            {
            return false;
            }

        // verify that all parameters are accounted for and then build the
        // proposed signature
        StringBuffer sb = new StringBuffer(m_sName);
        sb.append('(');

        boolean[] afFound = new boolean [c];
        for (int i = 0; i < c; ++i)
            {
            Parameter param = aparam[i];
            int iCurrent = getParameterPosition(param);
            if (iCurrent < 0 || afFound[iCurrent])
                {
                return false;
                }

            afFound[iCurrent] = true;
            sb.append(param.getSignature());
            }

        sb.append(')');
        String sSig = sb.toString();
        return !isSignatureReserved(sSig);
        }

    /**
    * Set all behavior parameters, allowing parameter re-ordering.
    *
    * @param aparam  an array of behavior parameters; this must be the same
    *                set of parameters as returned from the corresponding
    *                accessor, but can be in a different order
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public void setParameter(Parameter[] aparam)
            throws PropertyVetoException
        {
        setParameter(aparam, true);
        }

    /**
    * Set all behavior parameters, allowing parameter re-ordering.
    *
    * @param aParam     an array of behavior parameters; this must be the
    *                   same set of parameters as returned from the
    *                   corresponding accessor, but can be in a different
    *                   order
    * @param fVetoable  true if the setter can veto the value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void setParameter(Parameter[] aParam, boolean fVetoable)
            throws PropertyVetoException
        {
        Parameter[] aPrev = getParameter();
        int cParam = (fVetoable ? aPrev : aParam).length;

        // check if the passed set of parameters is in a different order
        try
            {
            boolean fSame = true;
            for (int i = 0; i < cParam; ++i)
                {
                if (aParam[i] != aPrev[i])
                    {
                    fSame = false;
                    break;
                    }
                }
            if (fSame)
                {
                return;
                }
            }
        catch (NullPointerException e)
            {
            // handled by legal check below
            }
        catch (ArrayIndexOutOfBoundsException e)
            {
            // handled by legal check below
            }

        if (fVetoable)
            {
            if (!isParameterSettable())
                {
                readOnlyAttribute(ATTR_PARAMETER, aPrev, aParam);
                }

            if (!isParameterLegal(aParam))
                {
                illegalAttributeValue(ATTR_PARAMETER, aPrev, aParam);
                }

            fireVetoableChange(ATTR_PARAMETER, aPrev, aParam);
            }

        m_vectParam.removeAllElements();
        for (int i = 0; i < cParam; ++i)
            {
            m_vectParam.addElement(aParam[i]);
            }
        updateSignature();

        firePropertyChange(ATTR_PARAMETER, aPrev, aParam);
        }

    /**
    * Helper to modify/add/remove parameters using only names and data types.
    *
    * @param adt     parameter data types
    * @param asName  parameter names
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public void setParameter(DataType[] adt, String[] asName)
            throws PropertyVetoException
        {
        // validate passed information is legal
        if (adt == null || asName == null)
            {
            adt    = new DataType[0];
            asName = new String  [0];
            }

        Parameter[] aPrev = getParameter();
        int         cPrev = aPrev.length;
        if (adt.length != asName.length)
            {
            illegalAttributeValue(ATTR_PARAMETER, aPrev, new Object[] {adt, asName});
            }

        // make sure information has been changed
        if (cPrev == adt.length)
            {
            boolean fSame = true;
            for (int i = 0; i < cPrev; ++i)
                {
                Parameter param = aPrev[i];
                if (param.getDataType() != adt[i] || !param.getName().equals(asName[i]))
                    {
                    fSame = false;
                    break;
                    }
                }
            if (fSame)
                {
                return;
                }
            }

        // make sure information can be changed
        if (!(isModifiable() && isDeclaredAtThisLevel()))
            {
            illegalAttributeValue(ATTR_PARAMETER, aPrev, new Object[] {adt, asName});
            }

        // verify that signature is legal
        StringBuffer sb = new StringBuffer(m_sName);
        sb.append('(');
        StringTable tblNames = new StringTable(INSENS);
        int cParam = adt.length;
        for (int i = 0; i < cParam; ++i)
            {
            // validate type and name
            DataType dt    = adt[i];
            String   sName = asName[i];
            if (dt == null || dt == DataType.VOID || sName == null
                    || !ClassHelper.isSimpleNameLegal(sName) || tblNames.contains(sName))
                {
                illegalAttributeValue(ATTR_PARAMETER, aPrev, new Object[] {adt, asName});
                }

            // build signature
            sb.append(dt.getTypeString());

            // keep track of names
            tblNames.put(sName, Integer.valueOf(i));
            }
        sb.append(')');
        String sSig = sb.toString();

        // verify that signature is available
        if (isSignatureReserved(sSig))
            {
            illegalAttributeValue(ATTR_PARAMETER, aPrev, new Object[] {adt, asName});
            }

        // new parameter list (not all the info is available at this time)
        Parameter[] aParam = new Parameter[cParam];

        // check if signature is changed
        boolean fOrderUnchanged = sSig.equals(getSignature());
        if (!fOrderUnchanged)
            {
            // verify that order can be changed
            if (!isParameterSettable())
                {
                readOnlyAttribute(ATTR_PARAMETER, aPrev, aParam);
                }
            }

        // notify veto listeners
        fireVetoableChange(ATTR_PARAMETER, aPrev, aParam);

        if (fOrderUnchanged)
            {
            // only name (if any) changes
            for (int i = 0; i < cParam; ++i)
                {
                aPrev[i].setName(asName[i], false);
                }
            }
        else
            {
            // match up old parameters to new ones
            Vector vectNoMatch = new Vector();
            for (int i = 0; i < cPrev; ++i)
                {
                Parameter prev  = aPrev[i];
                String    sPrev = prev.getName();
                Integer   index = (Integer) tblNames.get(sPrev);
                if (index == null)
                    {
                    vectNoMatch.add(prev);
                    }
                else
                    {
                    // name matched
                    int iParam = index.intValue();
                    aParam[iParam] = prev;

                    // update type and name (in case of a case sensitive change)
                    prev.setDataType(adt   [iParam], false);
                    prev.setName    (asName[iParam], false);
                    }
                }

            // check for unmatched parameters
            boolean fMatch = true;
            for (int i = 0, c = 0; i < cParam; ++i)
                {
                Parameter param = aParam[i];
                if (param == null)
                    {
                    // try to match by data type
                    DataType dt    = adt   [i];
                    String   sName = asName[i];
                    if (fMatch)
                        {
                        if (vectNoMatch.isEmpty())
                            {
                            fMatch = false;
                            }
                        else
                            {
                            Parameter prev = (Parameter) vectNoMatch.get(0);
                            if (dt == prev.getDataType())
                                {
                                prev.setName(sName, false);
                                param = prev;
                                vectNoMatch.remove(0);
                                }
                            else
                                {
                                fMatch = false;
                                }
                            }
                        }

                    // otherwise create a new one
                    if (param == null)
                        {
                        param = new Parameter(this, dt, sName, DIR_IN);
                        param.validate();
                        }

                    aParam[i] = param;
                    }
                }

            // destroy left-overs
            if (!vectNoMatch.isEmpty())
                {
                for (Enumeration enmr = vectNoMatch.elements(); enmr.hasMoreElements(); )
                    {
                    ((Parameter) enmr.nextElement()).invalidate();
                    }
                }

            // store new set of Parameters
            Vector vectParam = new Vector(cParam);
            for (int i = 0; i < cParam; ++i)
                {
                vectParam.add(aParam[i]);
                }
            m_vectParam = vectParam;
            updateSignature();
            }

        // notify
        firePropertyChange(ATTR_PARAMETER, aPrev, aParam);
        }

    /**
    * Determine if a parameter can be added to the behavior.
    *
    * @param iParam  position for the new parameter (-1 to add to end)
    * @param dt      proposed parameter data type
    * @param sName   proposed parameter name
    *
    * @return true if it is possible to add the parameter as specified
    */
    public boolean isParameterAddable(int iParam, DataType dt, String sName)
        {
        // check if the signature is alterable; verify proposed index;
        // parameter name must be a unique legal Java identifier
        int c = getParameterCount();
        if (iParam < 0)
            {
            iParam = c;
            }
        if (!isParameterSettable()
                || iParam > c
                || sName == null
                || sName.length() == 0
                || !ClassHelper.isSimpleNameLegal(sName)
                || getParameter(sName) != null
                || dt == null
                || dt == DataType.VOID)
            {
            return false;
            }

        // build the proposed signature
        StringBuffer sb = new StringBuffer(m_sName);
        sb.append('(');
        for (int i = 0; i < c; ++i)
            {
            if (i == iParam)
                {
                sb.append(dt.getTypeString());
                }
            sb.append(getParameter(i).getSignature());
            }
        if (iParam == c)
            {
            sb.append(dt.getTypeString());
            }
        sb.append(')');
        String sSig = sb.toString();

        return !isSignatureReserved(sSig);
        }

    /**
    * Add the specified parameter to the behavior.
    *
    * @param iParam  position for the new parameter (-1 to add to end)
    * @param dt      proposed parameter data type
    * @param sName   proposed parameter name
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public Parameter addParameter(int iParam, DataType dt, String sName)
            throws PropertyVetoException
        {
        return addParameter(iParam, dt, sName, true);
        }

    /**
    * Add the specified parameter to the behavior.
    *
    * @param iParam     position for the new parameter (-1 to add to end)
    * @param dt         proposed parameter data type
    * @param sName      proposed parameter name
    * @param fVetoable  true if the method can veto the change
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized Parameter addParameter(int iParam, DataType dt, String sName, boolean fVetoable)
            throws PropertyVetoException
        {
        if (fVetoable && !isParameterAddable(iParam, dt, sName))
            {
            subNotAddable(ATTR_PARAMETER, sName);
            }

        // create parameter
        Parameter param = new Parameter(this, dt, sName, DIR_IN);
        param.setUID(new UID(), fVetoable);

        // notify veto listeners
        if (fVetoable)
            {
            try
                {
                fireVetoableSubChange(param, SUB_ADD);
                }
            catch (PropertyVetoException e)
                {
                param.invalidate();
                throw e;
                }
            }

        // add parameter
        if (iParam < 0)
            {
            m_vectParam.addElement(param);
            }
        else
            {
            m_vectParam.insertElementAt(param, iParam);
            }
        updateSignature();

        // notify listeners
        param.validate();
        fireSubChange(param, SUB_ADD);

        return param;
        }

    /**
    * Determine if a parameter can be removed to the behavior.
    *
    * @param iParam  position of the parameter to remove
    *
    * @return true if it is possible to remove the specified parameter
    */
    public boolean isParameterRemovable(int iParam)
        {
        // check if the signature is alterable; verify index;
        int c = getParameterCount();
        if (!isParameterSettable()
                || iParam < 0
                || iParam >= c)
            {
            return false;
            }

        // build the proposed signature
        StringBuffer sb = new StringBuffer(m_sName);
        sb.append('(');
        for (int i = 0; i < c; ++i)
            {
            if (i != iParam)
                {
                sb.append(getParameter(i).getSignature());
                }
            }
        sb.append(')');
        String sSig = sb.toString();

        return !isSignatureReserved(sSig);
        }

    /**
    * Remove the specified parameter from the behavior.
    *
    * @param iParam  the parameter index to remove
    *
    * @exception PropertyVetoException  if removal is illegal or if removal
    *            is vetoed
    */
    public void removeParameter(int iParam)
            throws PropertyVetoException
        {
        removeParameter(iParam, true);
        }

    /**
    * Remove the specified parameter from the behavior.
    *
    * @param iParam     the parameter index to remove
    * @param fVetoable  true if the method can veto the change
    *
    * @exception PropertyVetoException  if removal is illegal or if removal
    *            is vetoed
    */
    protected synchronized void removeParameter(int iParam, boolean fVetoable)
            throws PropertyVetoException
        {
        Parameter param;
        try
            {
            // get the parameter information
            param = getParameter(iParam);
            }
        catch (IndexOutOfBoundsException e)
            {
            if (fVetoable)
                {
                // the caller handed us garbage (so report garbage)
                subNotRemovable(ATTR_PARAMETER, e);
                }
            return;
            }

        if (fVetoable)
            {
            // verify that the parameter can be removed
            if (!isParameterRemovable(iParam))
                {
                subNotRemovable(ATTR_PARAMETER, param);
                }

            // notify veto listeners
            fireVetoableSubChange(param, SUB_REMOVE);
            }

        // remove the parameter
        m_vectParam.removeElementAt(iParam);
        updateSignature();

        // notify listeners
        fireSubChange(param, SUB_REMOVE);

        // discard the parameter
        param.invalidate();
        }

    /**
    * Get the number of behavior parameters.
    *
    * @return the number of behavior parameters
    */
    public int getParameterCount()
        {
        return m_vectParam.size();
        }

    /**
    * Get parameter by position.
    *
    * @param i the parameter number, zero based
    *
    * @return the specified parameter
    */
    public Parameter getParameter(int i)
        {
        return (Parameter) m_vectParam.elementAt(i);
        }

    /**
    * Get position by parameter.
    *
    * @param param  the parameter to search for
    *
    * @return the parameter position, zero based, or -1 if not found
    */
    public int getParameterPosition(Parameter param)
        {
        return m_vectParam.indexOf(param);
        }

    /**
    * Get parameter by name, case insensitive.
    *
    * @param sName the parameter name
    *
    * @return the specified parameter or null if no parameter exists by that
    *         name
    */
    public Parameter getParameter(String sName)
        {
        CollationKey ckName = INSENS.getCollationKey(sName);

        int c = getParameterCount();
        for (int i = 0; i < c; ++i)
            {
            Parameter    param   = getParameter(i);
            CollationKey ckParam = INSENS.getCollationKey(param.getName());
            if (ckName.compareTo(ckParam) == 0)
                {
                return param;
                }
            }

        return null;
        }

    /**
    * Build an array of the Parameter data types.
    *
    * @return an array of the Parameter data types
    */
    public DataType[] getParameterTypes()
        {
        int        cdt = m_vectParam.size();
        DataType[] adt = new DataType[cdt];
        for (int i = 0; i < cdt; ++i)
            {
            adt[i] = ((Parameter) m_vectParam.elementAt(i)).getDataType();
            }
        return adt;
        }

    /**
    * Extract the parameter names from an existing behavior.
    *
    * @return an array of the Parameter names
    */
    public String[] getParameterNames()
        {
        int      cNames = m_vectParam.size();
        String[] asName = new String[cNames];
        for (int i = 0; i < cNames; ++i)
            {
            asName[i] = ((Parameter) m_vectParam.elementAt(i)).getName();
            }
        return asName;
        }

    /**
    * Build a list of default parameter names for the given parameter data
    * types.
    *
    * @param  adtParam  an array of parameter Data Types
    *
    * @return an array of parameter names
    */
    public static String[] getDefaultParameterNames(DataType[] adtParam)
        {
        int      cParams = (adtParam != null ? adtParam.length : 0);
        String[] asParam = new String[cParams];
        for (int i = 0; i < cParams; ++i)
            {
            asParam[i] = "Param_" + (i + 1);
            }
        return asParam;
        }

    /**
    * Build a string representing the Parameter directions.  The string is
    * composed the characters 'I' (in), 'O' (out), and 'B' (both in and out).
    *
    * @return a string of characters representing the Parameter directions
    */
    protected String getParameterDirections()
        {
        int c = m_vectParam.size();
        char[] ach = new char[c];

        for (int i = 0; i < c; ++i)
            {
            switch (((Parameter) m_vectParam.elementAt(i)).getDirection())
                {
                default:
                case DIR_IN:
                    ach[i] = 'I';
                    break;
                case DIR_OUT:
                    ach[i] = 'O';
                    break;
                case DIR_INOUT:
                    ach[i] = 'B';
                    break;
                }
            }

        return new String(ach);
        }

    /**
    * Set the Parameter directions based on a string composed of the
    * characters 'I' (in), 'O' (out), and 'B' (both in and out).
    *
    * @param sDir       a string of characters representing the Parameter
    *                   directions
    * @param fVetoable  true if the method can veto the change
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected void setParameterDirections(String sDir, boolean fVetoable)
            throws PropertyVetoException
        {
        int c = m_vectParam.size();
        if (c != sDir.length())
            {
            throw new IllegalArgumentException(CLASS + ".setParameterDirections:"
                    + "  Invalid direction string (" + sDir + ")!");
            }

        for (int i = 0; i < c; ++i)
            {
            int nDir;
            switch (sDir.charAt(i))
                {
                case 'I':
                    nDir = DIR_IN;
                    break;
                case 'O':
                    nDir = DIR_OUT;
                    break;
                case 'B':
                    nDir = DIR_INOUT;
                    break;
                default:
                    throw new IllegalArgumentException(CLASS + ".setParameterDirections:"
                            + "  Invalid direction string (" + sDir + ")!");
                }
            ((Parameter) m_vectParam.elementAt(i)).setDirection(nDir, fVetoable);
            }
        }


    // ----- exceptions

    /**
    * Get a list of the names of all declared exceptions.
    *
    * @return an array of the qualified names of the exceptions declared for
    *         this behavior.
    */
    public String[] getExceptionNames()
        {
        return m_tblExcept.strings();
        }

    /**
    * Get an exceptions by its name.  For a list of names, see
    * getExceptionNames.
    *
    * @param sExcept  the qualified name of the exception to get
    *
    * @return the behavior exception corresponding to the passed name or null
    *         if the specified exception is not declared by this behavior
    */
    public Throwee getException(String sExcept)
        {
        Throwee except = (Throwee) m_tblExcept.get(sExcept);
        if (except != null)
            {
            int nExists = except.getExists();
            if (nExists == EXISTS_DELETE || nExists == EXISTS_NOT)
                {
                return null;
                }
            }

        return except;
        }

    /**
    * Determine if the exception array can be set.  The exception array
    * can be set iff at least one of the following is true:
    *
    *   1)  There are exceptions that can be added
    *   2)  There are exceptions that can be removed
    *   3)  There are exceptions that can be unremoved
    *
    * @return true if the array of exceptions can be set
    */
    public boolean isExceptionSettable()
        {
        if (!isModifiable())
            {
            return false;
            }

        // exceptions can be added iff the behavior is not inherited and
        // does not originate from an interface or from integration
        if (!(isFromSuper() || isFromImplements() || isFromDispatches() || isFromIntegration()))
            {
            return true;
            }

        // exceptions can be removed or unremoved iff the behavior says so
        for (Enumeration enmr = m_tblExcept.keys(); enmr.hasMoreElements(); )
            {
            String sExcept = (String) enmr.nextElement();
            if (isExceptionRemovable(sExcept) || isExceptionUnremovable(sExcept))
                {
                return true;
                }
            }

        // nothing can be set
        return false;
        }

    /**
    * Determine if the exception array can be set to the specified value.
    *
    * @param asExcept  an array of behavior exceptions names
    *
    * @return true if the array of exceptions can be set as specified
    */
    public boolean isExceptionLegal(String[] asExcept)
        {
        // get the old list of exceptions
        StringTable tblOld = new StringTable();
        for (Enumeration enmr = m_tblExcept.keys(); enmr.hasMoreElements(); )
            {
            String sExcept = (String) enmr.nextElement();
            if (getException(sExcept) != null)
                {
                tblOld.add(sExcept);
                }
            }

        // get the new list of exceptions
        StringTable tblNew = new StringTable();
        for (int i = asExcept.length - 1; i >= 0; --i)
            {
            tblNew.add(asExcept[i]);
            }

        // check if the set of exceptions is unchanged
        if (tblNew.keysEquals(tblOld))
            {
            return true;
            }

        // determine what exceptions were added (or "unremoved")
        StringTable tblAdded = (StringTable) tblNew.clone();
        tblAdded.removeAll(tblOld);
        for (Enumeration enmr = tblAdded.keys(); enmr.hasMoreElements(); )
            {
            String sExcept = (String) enmr.nextElement();
            if (!isExceptionAddable(sExcept) && !isExceptionUnremovable(sExcept))
                {
                return false;
                }
            }

        // determine what exceptions were removed
        StringTable tblRemoved = tblOld;
        tblRemoved.removeAll(tblNew);
        for (Enumeration enmr = tblRemoved.keys(); enmr.hasMoreElements(); )
            {
            if (!isExceptionRemovable((String) enmr.nextElement()))
                {
                return false;
                }
            }

        return true;
        }

    /**
    * Set all behavior exceptions.
    *
    * @param asExcept  an array of behavior exceptions names
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public void setException(String[] asExcept)
            throws PropertyVetoException
        {
        setException(asExcept, true);
        }

    /**
    * Set all behavior exceptions, allowing exception re-ordering.
    *
    * @param asExcept   an array of behavior exceptions names
    * @param fVetoable  true if the setter can veto the value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void setException(String[] asExcept, boolean fVetoable)
            throws PropertyVetoException
        {
        // get the old list of exceptions
        StringTable tblOld = new StringTable();
        for (Enumeration enmr = m_tblExcept.keys(); enmr.hasMoreElements(); )
            {
            String sExcept = (String) enmr.nextElement();
            if (getException(sExcept) != null)
                {
                tblOld.add(sExcept);
                }
            }

        // get the new list of exceptions
        StringTable tblNew = new StringTable();
        for (int i = asExcept.length - 1; i >= 0; --i)
            {
            tblNew.add(asExcept[i]);
            }

        // check if the set of exceptions is unchanged
        if (tblNew.keysEquals(tblOld))
            {
            return;
            }

        // for "previous vs. new" notifications
        String[] asOld = tblOld.strings();
        String[] asNew = tblNew.strings();

        // verify exceptions can be changed
        if (fVetoable)
            {
            if (!isExceptionSettable())
                {
                readOnlyAttribute(ATTR_EXCEPTION, asOld, asNew);
                }

            if (!isExceptionLegal(asExcept))
                {
                illegalAttributeValue(ATTR_EXCEPTION, asOld, asNew);
                }

            fireVetoableChange(ATTR_EXCEPTION, asOld, asNew);
            }

        // determine what exceptions were added (or "unremoved")
        StringTable tblAdded = (StringTable) tblNew.clone();
        tblAdded.removeAll(tblOld);
        for (Enumeration enmr = tblAdded.keys(); enmr.hasMoreElements(); )
            {
            String sExcept = (String) enmr.nextElement();
            if (isExceptionUnremovable(sExcept))
                {
                unremoveException(sExcept, false);
                }
            else
                {
                addException(sExcept, false);
                }
            }

        // determine what exceptions were removed
        StringTable tblRemoved = tblOld;
        tblRemoved.removeAll(tblNew);
        for (Enumeration enmr = tblRemoved.keys(); enmr.hasMoreElements(); )
            {
            removeException((String) enmr.nextElement(), false);
            }

        firePropertyChange(ATTR_EXCEPTION, asOld, asNew);
        }

    /**
    * Determine if the specified exception can be added to this behavior.
    *
    * Unfortunately, there is no way to tell if a name actually references an
    * existing class or if that class is truly an exception (or actually, if
    * that class derives in some way from java.lang.Throwable).
    *
    * From the Java Language Specification (8.4.4):
    * A method that overrides or hides another method (8.4.6), including
    * methods that implement abstract methods defined in interfaces, may not
    * be declared to throw more checked exceptions than the overridden or
    * hidden method.  More precisely, suppose that B is a class or interface,
    * and A is a superclass or super interface of B, and a method declaration
    * n in B overrides or hides a method declaration m in A. If n has a
    * throws clause that mentions any checked exception types, then m must
    * have a throws clause, and for every checked exception type listed in
    * the throws clause of n, that same exception class or one of its super-
    * classes must occur in the throws clause of m; otherwise, a compile-time
    * error occurs.
    *
    * Behaviors resulting from property declarations can have additional
    * exceptions; from the JavaBeans 1.0 API Specification:
    * Both simple and indexed property accessor methods may throw checked
    * exceptions. This allows property setter/getter methods to report
    * exceptional conditions.
    *
    * @param sExcept  the qualified name of the exception to add
    *
    * @return true if it is possible to add the exception as specified
    */
    public boolean isExceptionAddable(String sExcept)
        {
        if (!isModifiable() || isFromSuper() || isFromImplements() || isFromDispatches() || isFromIntegration())
            {
            return false;
            }

        // check if an identically named exception already exists
        if (m_tblExcept.contains(sExcept))
            {
            return false;
            }

        // validate that sExcept is an acceptable class name
        try
            {
            return DataType.getClassType(sExcept) != null;
            }
        catch (IllegalArgumentException e)
            {
            return false;
            }
        }

    /**
    * Add the specified exception to the behavior.
    *
    * @param sExcept  the qualified name of the exception to add
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public Throwee addException(String sExcept)
            throws PropertyVetoException
        {
        return addException(sExcept, true);
        }

    /**
    * Add the specified exception to the behavior.
    *
    * @param sExcept    the qualified name of the exception to add
    * @param fVetoable  true if the method can veto the change
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized Throwee addException(String sExcept, boolean fVetoable)
            throws PropertyVetoException
        {
        if (fVetoable && !isExceptionAddable(sExcept))
            {
            subNotAddable(ATTR_EXCEPTION, sExcept);
            }

        // create exception
        Throwee except = new Throwee(this, DataType.getClassType(sExcept));
        except.setFromManual(true, false);
        except.setUID(new UID(), fVetoable);

        // notify veto listeners
        if (fVetoable)
            {
            try
                {
                fireVetoableSubChange(except, SUB_ADD);
                }
            catch (PropertyVetoException e)
                {
                except.invalidate();
                throw e;
                }
            }

        // add exception
        m_tblExcept.put(except.getUniqueName(), except);

        // notify listeners
        except.validate();
        fireSubChange(except, SUB_ADD);

        return except;
        }

    /**
    * Determine if the specified exception can be removed from the behavior.
    * Exceptions are basically always removable, since you can throw less
    * (but not more); see the Java Language Specification (8.4.4).
    *
    * @param sExcept  the qualified name of the exception to remove
    *
    * @return true if it is possible to remove the exception as specified
    */
    public boolean isExceptionRemovable(String sExcept)
        {
        if (!isModifiable())
            {
            return false;
            }

        Throwee except = getException(sExcept);
        if (except == null)
            {
            return false;
            }

        int nExists = except.getExists();
        return nExists == EXISTS_INSERT || nExists == EXISTS_UPDATE;
        }

    /**
    * Remove the specified exception from the behavior.
    *
    * @param sExcept  the qualified name of the exception to remove
    *
    * @exception PropertyVetoException  if removal is illegal or if
    *            removal is vetoed
    */
    public void removeException(String sExcept)
            throws PropertyVetoException
        {
        removeException(sExcept, true);
        }

    /**
    * Remove the specified exception from the behavior.
    *
    * @param sExcept    the qualified name of the exception to remove
    * @param fVetoable  if the removal can be vetoed
    *
    * @exception PropertyVetoException  if removal is illegal or if
    *            removal is vetoed
    */
    protected synchronized void removeException(String sExcept, boolean fVetoable)
            throws PropertyVetoException
        {
        // get the exception information
        Throwee except = getException(sExcept);
        if (except == null)
            {
            if (fVetoable)
                {
                subNotRemovable(ATTR_EXCEPTION, sExcept);
                }
            return;
            }

        // check if already removed
        int nExists = except.getExists();
        if (nExists != EXISTS_INSERT && nExists != EXISTS_UPDATE)
            {
            return;
            }

        if (fVetoable)
            {
            // verify the exception can be removed
            if (!isExceptionRemovable(sExcept))
                {
                subNotRemovable(ATTR_EXCEPTION, sExcept);
                }

            // notify veto listeners
            fireVetoableSubChange(except, SUB_REMOVE);
            }

        boolean fDestroy = isDeclaredAtThisLevel() && !except.isFromNonManual();
        if (fDestroy)
            {
            // remove the exception altogether
            m_tblExcept.remove(sExcept);
            }
        else
            {
            // just flag exception as removed
            except.setExists(EXISTS_DELETE);
            }

        // notify listeners
        fireSubChange(except, SUB_REMOVE);

        // if removed altogether, then destroy the exception information
        if (fDestroy)
            {
            except.invalidate();
            }
        }

    /**
    * Determine if the specified exception can be un-removed from the
    * behavior.  Exceptions that have been removed at this level can
    * be un-removed assuming they don't cause a behavior declaration
    * conflict (e.g. two interfaces define same method signature with
    * two different exceptions).
    *
    * @param sExcept  the qualified name of the exception to un-remove
    *
    * @return true if it is possible to un-remove the specified exception
    */
    public boolean isExceptionUnremovable(String sExcept)
        {
        // verify that exception has been removed
        Throwee except = (Throwee) m_tblExcept.get(sExcept);
        if (except == null || except.getExists() != EXISTS_DELETE)
            {
            return false;
            }

        // the non-manual origin of the exception must match the non-manual
        // origin of the behavior; in other words, if two interfaces declare
        // the behavior, then they must both declare the exception
        if (equalsOriginSansManual(except))
            {
            return true;
            }

        // could just be a difference in origins caused by a Property trait
        return this.isFromSuper()       == except.isFromSuper()
            && this.isFromIntegration() == except.isFromIntegration()
            && isEqual(this.enumImplements(), except.enumImplements())
            && isEqual(this.enumDispatches(), except.enumDispatches());
        }

    /**
    * Check for equality of two enumerations in terms of order and
    * contents.  All elements of the first enumeration must be non-null.
    *
    * TODO move to com.tangosol.util.Base
    */
    private static boolean isEqual(Enumeration enmr1, Enumeration enmr2)
        {
        while (enmr1.hasMoreElements() && enmr2.hasMoreElements())
            {
            if (!enmr1.nextElement().equals(enmr2.nextElement()))
                {
                return false;
                }
            }
        return !enmr1.hasMoreElements() && !enmr2.hasMoreElements();
        }

    /**
    * Compare the contents of a vector with the contents of an enumerator.
    *
    * @param vect an instance of java.util.Vector
    * @param enmr an instance of java.util.Enumeration
    *
    * @return true if the contents are identical (irregardless of order)
    */
    private static boolean VectMatchesEnum(Vector vect, Enumeration enmr)
        {
        int cEnum = 0;
        while (enmr.hasMoreElements())
            {
            if (!vect.contains(enmr.nextElement()))
                {
                return false;
                }
            ++cEnum;
            }
        return (cEnum == vect.size());
        }

    /**
    * Un-remove the specified exception from the behavior.
    *
    * @param sExcept  the qualified name of the exception to un-remove
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public void unremoveException(String sExcept)
            throws PropertyVetoException
        {
        unremoveException(sExcept, true);
        }

    /**
    * Un-remove the specified exception from the behavior.
    *
    * @param sExcept    the qualified name of the exception to un-remove
    * @param fVetoable  true if the method can veto the change
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void unremoveException(String sExcept, boolean fVetoable)
            throws PropertyVetoException
        {
        // get the exception information
        Throwee except = (Throwee) m_tblExcept.get(sExcept);
        if (except == null)
            {
            if (fVetoable)
                {
                subNotUnremovable(ATTR_EXCEPTION, sExcept);
                }
            return;
            }

        // check for no change
        int nExists = except.getExists();
        if (nExists == EXISTS_INSERT || nExists == EXISTS_UPDATE)
            {
            return;
            }

        if (fVetoable)
            {
            // verify that the exception can be un-removed
            if (!isExceptionUnremovable(sExcept))
                {
                subNotUnremovable(ATTR_EXCEPTION, sExcept);
                }

            // notify veto listeners
            fireSubChange(except, SUB_UNREMOVE);
            }

        // flag exception as no longer removed
        except.setExists(EXISTS_UPDATE);

        // notify listeners
        fireSubChange(except, SUB_UNREMOVE);
        }

    /**
    * Update the reference to an exception when the exception data type
    * changes.  This method is used internally by the Component Definition.
    *
    * @param sOld the old exception class name
    * @param sNew the new exception class name
    */
    protected void renameException(String sOld, String sNew)
        {
        m_tblExcept.put(sNew, m_tblExcept.remove(sOld));
        }


    // ----- implementations

    /**
    * Get all implementations at this derivation level.
    *
    * @return an array of this behavior's implementations
    */
    public Implementation[] getImplementation()
        {
        Vector           vect  = m_vectScript;
        int              cImpl = vect.size();
        Implementation[] aImpl = new Implementation[cImpl];
        while (cImpl-- > 0)
            {
            aImpl[cImpl] = (Implementation) vect.get(cImpl);
            }

        return aImpl;
        }

    /**
    * Get implementation by position.  The first implementation (index 0) is
    * the first implementation that will be executed at this derivation
    * level.  Each implementation can "super" to the next implementation.  If
    * a modification level of the behavior sets the OverrideBase attribute,
    * then the implementations from the base modification level(s) are not
    * available to "super" to, and thus described as "hidden" or "replaced"
    * or "overridden".  The "super" call from the last implementation in a
    * derivation level executes the first implementation of the behavior in
    * the next derivation level that contains an implementation of the
    * behavior.
    *
    * @param i the implementation number, zero based
    *
    * @return the specified implementation
    */
    public Implementation getImplementation(int i)
        {
        return (Implementation) m_vectScript.elementAt(i);
        }

    /**
    * Get the number of behavior implementations (at this derivation level).
    *
    * @return the number of behavior implementations
    */
    public int getImplementationCount()
        {
        return m_vectScript.size();
        }

    /**
    * Get the number of behavior implementations at this modification level.
    *
    * @return the number of implementations which are at this modification
    *         level
    */
    public int getModifiableImplementationCount()
        {
        return m_vectScript.size() - m_cBaseLevelImpl;
        }

    /**
    * Get the number of behavior implementations at this derivation level,
    * not including this modification level's implementations.
    *
    * Using the indexed accessor method getImplementation(int), the caller
    * can get any base level implementation by adding the return value from
    * getModifiableImplementationCount() to the desired base implementation index.
    *
    * @return the number of base level behavior implementations
    */
    public int getBaseImplementationCount()
        {
        return m_cBaseLevelImpl;
        }

    /**
    * Determine the number of reachable implementations at this derivation
    * level.
    *
    * @return the number of implementations at this modification level plus
    *         (if the base implementations are not overridden) the number
    *         of base implementations
    */
    public int getCallableImplementationCount()
        {
        int cImpl = m_vectScript.size();
        if (m_fOverrideBase)
            {
            cImpl -= m_cBaseLevelImpl;
            }
        return cImpl;
        }

    /**
    * Determine if the implementation array can be set.  The implementation array
    * can be changed if the behavior is modifiable.
    *
    * @return true if the array of implementations can be set
    */
    public boolean isImplementationSettable()
        {
        return isModifiable();
        }

    /**
    * Determine if the specified array of implementations is a legal array of
    * implementations for this behavior.
    *
    * @param aImpl  an array of behavior implementations; this must be the same
    *               set of implementations as returned from the corresponding
    *               accessor, but can be in a different order
    *
    * @return true if the specified array of implementations is legal
    */
    public boolean isImplementationLegal(Implementation[] aImpl)
        {
        Implementation[] aPrev = getImplementation();
        int              cImpl = aPrev.length;
        if (aImpl == null || aImpl.length != cImpl)
            {
            return false;
            }

        // verify that non-moveable implementations did not move
        int cMove = getModifiableImplementationCount();
        for (int i = cMove; i < cImpl; ++i)
            {
            if (aImpl[i] != aPrev[i])
                {
                return false;
                }
            }

        // verify that all moveable implementations are accounted for
        boolean[] afFound = new boolean [cMove];
        for (int i = 0; i < cMove; ++i)
            {
            Implementation impl = aImpl[i];
            if (impl == null)
                {
                return false;
                }

            int iCurrent = getImplementationPosition(impl);
            if (iCurrent < 0 || iCurrent >= cMove || afFound[iCurrent])
                {
                return false;
                }

            afFound[iCurrent] = true;
            }

        return true;
        }

    /**
    * Set all behavior implementations, allowing implementation re-ordering.
    *
    * @param aImpl  an array of behavior implementations; this must be the same
    *               set of implementations as returned from the corresponding
    *               accessor, but can be in a different order
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public void setImplementation(Implementation[] aImpl)
            throws PropertyVetoException
        {
        setImplementation(aImpl, true);
        }

    /**
    * Set all behavior implementations, allowing implementation re-ordering.
    *
    * @param aImpl      an array of behavior implementations; this must be
    *                   the same set of implementations as returned from the
    *                   corresponding accessor, but can be in a different
    *                   order
    * @param fVetoable  true if the setter can veto the value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void setImplementation(Implementation[] aImpl, boolean fVetoable)
            throws PropertyVetoException
        {
        Implementation[] aPrev = getImplementation();
        int cImpl = (fVetoable ? aPrev : aImpl).length;

        // check if the passed set of Implementations is in a different order
        try
            {
            boolean fSame = true;
            for (int i = 0; i < cImpl; ++i)
                {
                if (aImpl[i] != aPrev[i])
                    {
                    fSame = false;
                    break;
                    }
                }
            if (fSame)
                {
                return;
                }
            }
        catch (NullPointerException e)
            {
            // handled by legal check below
            }
        catch (ArrayIndexOutOfBoundsException e)
            {
            // handled by legal check below
            }

        if (fVetoable)
            {
            if (!isImplementationSettable())
                {
                readOnlyAttribute(ATTR_IMPLEMENTATION, aPrev, aImpl);
                }

            if (!isImplementationLegal(aImpl))
                {
                illegalAttributeValue(ATTR_IMPLEMENTATION, aPrev, aImpl);
                }

            fireVetoableChange(ATTR_IMPLEMENTATION, aPrev, aImpl);
            }

        // store new set of implementations
        Vector vectScript = new Vector();
        for (int i = 0; i < cImpl; ++i)
            {
            vectScript.add(aImpl[i]);
            }
        m_vectScript = vectScript;

        firePropertyChange(ATTR_IMPLEMENTATION, aPrev, aImpl);
        }


    /**
    * Determine if a implementation can be added to the behavior.
    *
    * @param iImpl    position for the new implementation (0 to insert at the
    *                 beginning or -1 to add to end of the execution "chain")
    * @param sLang    proposed implementation language
    * @param sScript  proposed implementation script
    *
    * @return true if it is possible to add the implementation as specified
    */
    public boolean isImplementationAddable(int iImpl, String sLang, String sScript)
        {
        return isImplementationSettable()
                && iImpl <= getModifiableImplementationCount()
                && Implementation.isLanguageLegal(sLang)
                && Implementation.isScriptLegal(sScript);
        }

    /**
    * Add the specified implementation to the behavior.
    *
    * @param iImpl    position for the new implementation (0 to insert at the
    *                 beginning or -1 to add to end of the execution "chain")
    * @param sLang    implementation language
    * @param sScript  implementation script
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public Implementation addImplementation(int iImpl, String sLang, String sScript)
            throws PropertyVetoException
        {
        return addImplementation(iImpl, sLang, sScript, true);
        }

    /**
    * Add the specified implementation to the behavior.
    *
    * @param iImpl      position for the new implementation (0 to insert at
    *                   the beginning or -1 to add to end of the execution
    *                   "chain")
    * @param sLang      implementation language
    * @param sScript    implementation script
    * @param fVetoable  true if the method can veto the change
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized Implementation addImplementation(int iImpl, String sLang, String sScript, boolean fVetoable)
            throws PropertyVetoException
        {
        // verify implementation can be added
        if (fVetoable && !isImplementationAddable(iImpl, sLang, sScript))
            {
            subNotAddable(ATTR_IMPLEMENTATION, sScript);
            }

        // create implementation
        Implementation impl = new Implementation(this, sLang, sScript);
        impl.assignUID();

        // notify veto listeners
        if (fVetoable)
            {
            try
                {
                fireVetoableSubChange(impl, SUB_ADD);
                }
            catch (PropertyVetoException e)
                {
                impl.invalidate();
                throw e;
                }
            }

        // add implementation
        if (iImpl < 0)
            {
            iImpl = getModifiableImplementationCount();
            }

        if (iImpl >= m_vectScript.size())
            {
            m_vectScript.addElement(impl);
            }
        else
            {
            m_vectScript.insertElementAt(impl, iImpl);
            }

        // check if abstract should be toggled to concrete automatically
        if ((m_nFlags     & IMPL_MASK) == IMPL_ABSTRACT &&
            (m_nPrevFlags & IMPL_MASK) == IMPL_ABSTRACT &&
            isFromSuper())
            {
            setAbstract(false, false);
            }

        // notify listeners
        fireSubChange(impl, SUB_ADD);

        return impl;
        }

    /**
    * Store the specified implementation on the JCS behavior.
    *
    * @param sLang      implementation language
    * @param sScript    implementation script
    */
    void setJcsImplementation(String sLang, String sScript)
        {
        azzert(sLang.indexOf('(') != -1);

        // create implementation
        Implementation impl = new Implementation(this, sLang, sScript);
        impl.assignUID();

        removeJcsImplementation();      // provides idempotency
        m_vectScript.addElement(impl);
        ++m_cBaseLevelImpl;             // assumed to be at base level
        }

    /**
    * Remove the JCS implementation.
    */
    void removeJcsImplementation()
        {
        Vector vectScript = m_vectScript;
        if (vectScript.isEmpty())
            {
            return;
            }

        int iScript = vectScript.size() - 1;
        if (isJcsImplementation(iScript))
            {
            vectScript.remove(iScript);
            if (m_cBaseLevelImpl > 0)
                {
                --m_cBaseLevelImpl;
                }
            }
        }

    /**
    * Check whether the implementation at the specified index
    * is an added "synthetic" implementation
    *
    * @return true if the implementation at the specified index
    *              is an added implementation; false otherwise
    *
    * @see #setJcsImplementation(String, String)
    */
    private boolean isJcsImplementation(int iImpl)
        {
        Implementation impl = (Implementation) m_vectScript.get(iImpl);

        return impl.getLanguage().indexOf('(') != -1;
        }


    /**
    * Determine if a implementation can be removed from the behavior.
    *
    * @param iImpl  position of the implementation to remove
    *
    * @return true if it is possible to remove the specified implementation
    */
    public boolean isImplementationRemovable(int iImpl)
        {
        return isImplementationSettable()
                && iImpl >= 0
                && iImpl < getModifiableImplementationCount();
        }

    /**
    * Remove the specified implementation from the behavior.
    *
    * @param iImpl  the implementation index to remove
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public void removeImplementation(int iImpl)
            throws PropertyVetoException
        {
        removeImplementation(iImpl, true);
        }

    /**
    * Remove the specified implementation from the behavior.
    *
    * @param iImpl      the implementation index to remove
    * @param fVetoable  true if the method can veto the change
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void removeImplementation(int iImpl, boolean fVetoable)
            throws PropertyVetoException
        {
        // get the implementation
        Implementation impl = null;
        try
            {
            impl = getImplementation(iImpl);
            }
        catch (IndexOutOfBoundsException e)
            {
            if (fVetoable)
                {
                // the caller handed us garbage (so report garbage)
                subNotRemovable(ATTR_PARAMETER, e);
                }
            return;
            }

        if (fVetoable)
            {
            // verify the implementation can be removed
            if (!isImplementationRemovable(iImpl))
                {
                subNotRemovable(ATTR_IMPLEMENTATION, getImplementation(iImpl));
                }

            // notify veto listeners
            fireVetoableSubChange(impl, SUB_REMOVE);
            }

        // remove the implementation
        m_vectScript.removeElementAt(iImpl);

        // check if abstract should be set automatically
        if ((m_nFlags     & IMPL_MASK) == IMPL_CONCRETE &&
            (m_nPrevFlags & IMPL_MASK) == IMPL_ABSTRACT &&
            isFromSuper())
            {
            setAbstract(true, false);
            }

        // notify listeners
        fireSubChange(impl, SUB_REMOVE);

        // discard the implementation
        impl.invalidate();
        }

    /**
    * Get position by implementation.
    *
    * @param impl  the implementation to search for
    *
    * @return the implementation position, zero based, or -1 if not found
    */
    public int getImplementationPosition(Implementation impl)
        {
        return m_vectScript.indexOf(impl);
        }


    // ----- override base

    /**
    * Determine if this modification level's implementations override (do not
    * super to) the base level's implementations.
    *
    * @return true if the implementations at this modification level override
    *         (i.e. hide) the base implementations, false if this level's
    *         implementations supplement (super to) the base implementations
    */
    public boolean isOverrideBase()
        {
        return m_fOverrideBase;
        }

    /**
    * Specify implementation override to either override (do not super to)
    * or supplement (allow super to) the base level's implementations.
    *
    * @param fOverride  true if the implementations at this modification
    *                   level should override (i.e. hide) the base
    *                   implementations, false if this level's implement-
    *                   ations supplement (super to) the base implementations
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    public void setOverrideBase(boolean fOverride)
            throws PropertyVetoException
        {
        setOverrideBase(fOverride, true);
        }

    /**
    * Specify implementation override to either override (do not super to)
    * or supplement (allow super to) the base level's implementations.
    *
    * @param fOverride  true if the implementations at this modification
    *                   level should override (i.e. hide) the base
    *                   implementations, false if this level's implement-
    *                   ations supplement (super to) the base implementations
    * @param fVetoable  true if the setter can veto the value
    *
    * @exception PropertyVetoException if the property cannot be set as
    *            specified or was vetoed by a property listener
    */
    protected synchronized void setOverrideBase(boolean fOverride, boolean fVetoable)
            throws PropertyVetoException
        {
        boolean fPrev = isOverrideBase();

        if (fOverride == fPrev)
            {
            return;
            }

        Boolean prev  = toBoolean(fPrev);
        Boolean value = toBoolean(fOverride);

        if (fVetoable)
            {
            if (!isModifiable())
                {
                readOnlyAttribute(ATTR_OVERRIDEBASE, prev, value);
                }

            fireVetoableChange(ATTR_OVERRIDEBASE, prev, value);
            }

        m_fOverrideBase = fOverride;
        firePropertyChange(ATTR_OVERRIDEBASE, prev, value);
        }


    // ----- synthetic

    /**
    * Determine whether this behavior was based on a compiler generated method
    * (({@link Method#isBridge()} && {@link Method#isSynthetic()}).
    *
    * @return whether this behavior was based on a compiler generated method
    */
    public boolean isSynthetic()
        {
        return (m_nFlags & MISC_ISINTERFACE) != 0;
        }


    // ----- helpers

    /**
    * Determine if the signature is reserved and cannot be used by this
    * Behavior.
    *
    * @param sSig  the proposed signature
    *
    * @return true if the signature cannot be used by this Behavior
    */
    protected boolean isSignatureReserved(String sSig)
        {
        // check for conflict with other behavior names
        Behavior behavior = getComponent().getBehavior(sSig);
        if (behavior != null && behavior != this)
            {
            return true;
            }

        // verify that the signature is not reserved
        return isSignatureReserved(getComponent(), sSig);
        }

    /**
    * Determine if the specified signature is reserved within the
    * specified Component.
    *
    * @param cd    the Component
    * @param sSig  the proposed signature
    *
    * @return true if the signature cannot be used within the specified Component
    */
    protected static boolean isSignatureReserved(Component cd, String sSig)
        {
        // gg 2001.5.3 -- no restrictions for a JCS
        if (cd.isSignature())
            {
            return false;
            }

        // compiler reserves double-underscore names
        if (sSig.startsWith("__"))
            {
            return true;
            }

        // check Property accessors
        String sProp = Property.getPropertyName(sSig);
        if (sProp != null)
            {
            Property prop = cd.getProperty(sProp);
            if (prop != null)
                {
                if (prop.isReservedBehaviorSignature(sSig))
                    {
                    if (!sProp.equals(prop.getName()))
                        {
                        // case sensitivity conflict
                        return false;
                        }

                    // accessors from super levels could be private ... in
                    // which case the signature cannot be created at this
                    // level
                    if (prop.isFromSuper())
                        {
                        return false;
                        }

                    // the Behavior cannot be created if the accessor is not
                    // applicable
                    for (int i = Property.PA_FIRST; i <= Property.PA_LAST; ++i)
                        {
                        if (sSig.equals(prop.getAccessorSignature(i))
                            && !prop.isAccessorApplicable(i))
                            {
                            return true;
                            }
                        }
                    }
                }
            }

        return false;
        }

    /**
    * Parse the behavior signature into discrete return and parameter data
    * types.
    *
    * @param sSig the behavior signature
    *
    * @return an array of DataType instances, where [0] is the return
    *         type and [1]..[c] are the parameter types.
    */
    public static DataType[] getParameterTypes(String sSig)
        {
        return DataType.parseSignature(sSig);
        }


    // ----- Object methods -------------------------------------------------

    /**
    * Compare this Behavior to another Object for equality.
    *
    * @param obj  the other Object to compare to this
    *
    * @return true if this Behavior equals that Object
    */
    public boolean equals(Object obj)
        {
        if (obj instanceof Behavior)
            {
            Behavior that = (Behavior) obj;
            return this                     == that
                || this.m_nFlags            == that.m_nFlags
                && this.m_nPrevFlags        == that.m_nPrevFlags
                && this.m_fOverrideBase     == that.m_fOverrideBase
                && this.m_cBaseLevelImpl    == that.m_cBaseLevelImpl
                && this.m_sName     .equals(that.m_sName     )
                && this.m_sSig      .equals(that.m_sSig      )
                && this.m_retval    .equals(that.m_retval    )
                && this.m_tblExcept .equals(that.m_tblExcept )
                && this.m_vectParam .equals(that.m_vectParam )
                && this.m_vectScript.equals(that.m_vectScript)
                && super.equals(that);

            // PJM Removed the following because they are not persistent fields
            //&& this.m_fPrevOverrideBase == that.m_fPrevOverrideBase
            }
        return false;
        }

    /**
    * Provide a human-readable description of the behavior.
    *
    * @return a string describing the behavior
    */
    public String toString()
        {
        StringBuffer sb = new StringBuffer();

        if (m_retval != null && !isConstructor())
            {
            sb.append(m_retval.getDataType().toString())
              .append(' ');
            }

        sb.append(m_sName)
          .append('(');

        int c = getParameterCount();
        for (int i = 0; i < c; ++i)
            {
            if (i > 0)
                {
                sb.append(", ");
                }
            Parameter parameter = getParameter(i);
            sb.append(parameter.getDataType().toString());
            sb.append(" " + parameter.getName());
            }

        sb.append(')');

        return sb.toString();
        }


    // ----- debugging ------------------------------------------------------

    /**
    * Provide the entire set of trait information in a printed format.
    *
    * @param out      PrintWriter object to dump the information to
    * @param sIndent  a string used to indent each line of dumped information
    */
    public void dump(PrintWriter out, String sIndent)
        {
        boolean fDerOrMod = (getMode() == MODIFICATION || getMode() == DERIVATION);

        out.println(sIndent + "Behavior " + toString());
        out.println(sIndent + "Signature=\"" + m_sSig + '\"');

        super.dump(out, sIndent);

        // Exists, Access, Visible, Synchronized, Abstract, Static, Final,
        // Deprecated, Remotable
        out.print  (sIndent + "flags=0x" + Integer.toHexString(m_nFlags));
        out.println(" (" + flagsDescription(m_nFlags, SPECABLE_FLAGS, fDerOrMod) + ')');
        out.print  (sIndent + "previous flags=0x" + Integer.toHexString(m_nPrevFlags));
        out.println(" (" + flagsDescription(m_nPrevFlags, SPECABLE_FLAGS, fDerOrMod) + ')');

        // return value
        out.print(sIndent + "Return Value:");
        if (m_retval == null)
            {
            out.println("  ");
            }
        else
            {
            out.println();
            m_retval.dump(out, nextIndent(sIndent));
            }

        // parameters
        out.println(sIndent + m_vectParam.size() + " parameter(s)");
        int i = 0;
        for (Enumeration enmr = m_vectParam.elements(); enmr.hasMoreElements(); )
            {
            Parameter param = (Parameter) enmr.nextElement();

            out.print(sIndent + "Parameter " + (++i) + ":");
            if (param == null)
                {
                out.println("  ");
                }
            else
                {
                out.println();
                param.dump(out, nextIndent(sIndent));
                }
            }

        // exceptions
        out.println(sIndent + m_tblExcept.getSize() + " exception(s)");
        for (Enumeration enmr = m_tblExcept.keys(); enmr.hasMoreElements(); )
            {
            String sExcept = (String) enmr.nextElement();
            Throwee except = (Throwee) m_tblExcept.get(sExcept);

            out.print(sIndent + "Exception \"" + sExcept + "\":");
            if (except == null)
                {
                out.println("  ");
                }
            else
                {
                out.println();
                except.dump(out, nextIndent(sIndent));
                }
            }

        // implementations
        out.print  (sIndent + m_vectScript.size() + " implementation(s), ");
        out.print  (m_cBaseLevelImpl + " at the base level (");
        out.println((m_fOverrideBase ? "overridden" : "supplemented") + ')');

        i = 0;
        for (Enumeration enmr = m_vectScript.elements(); enmr.hasMoreElements(); )
            {
            Implementation impl = (Implementation) enmr.nextElement();

            out.print(sIndent + "Implementation " + (++i) + ":");
            if (impl == null)
                {
                out.println("  ");
                }
            else
                {
                out.println();
                impl.dump(out, nextIndent(sIndent));
                }
            }
        }


    // ----- public constants  ----------------------------------------------

    /**
    * The FromManual attribute.
    */
    public static final String ATTR_FROMMANUAL      = "FromManual";

    /**
    * The Accessibility attribute.
    */
    public static final String ATTR_ACCESS          = "Access";

    /**
    * The Visible attribute.
    */
    public static final String ATTR_VISIBLE         = "Visible";

    /**
    * The Synchronized attribute.
    */
    public static final String ATTR_SYNCHRONIZED    = "Synchronized";

    /**
    * The Static attribute.
    */
    public static final String ATTR_STATIC          = "Static";

    /**
    * The Abstract attribute.
    */
    public static final String ATTR_ABSTRACT        = "Abstract";

    /**
    * The Final attribute.
    */
    public static final String ATTR_FINAL           = "Final";

    /**
    * The Deprecated attribute name.
    */
    public static final String ATTR_DEPRECATED      = "Deprecated";

    /**
    * The Remote attribute name.
    */
    public static final String ATTR_REMOTE          = "Remote";

    /**
    * The Name attribute.
    */
    public static final String ATTR_NAME            = "Name";

    /**
    * The Parameter attribute.
    */
    public static final String ATTR_PARAMETER       = "Parameter";

    /**
    * The Exception attribute.
    */
    public static final String ATTR_EXCEPTION       = "Exception";

    /**
    * The Implementation attribute.
    */
    public static final String ATTR_IMPLEMENTATION  = "Implementation";

    /**
    * The OverrideBase attribute.
    */
    public static final String ATTR_OVERRIDEBASE    = "OverrideBase";


    // ----- data members ---------------------------------------------------

    /**
    * The name of this class.
    */
    private static final String CLASS = "Behavior";

    /**
    * The Behavior's descriptor string.
    */
    protected static final String DESCRIPTOR = CLASS;

    /**
    * The default flags for the Behavior Trait.
    */
    private static final int DEFAULT_FLAGS  = VIS_VISIBLE      |
                                              SYNC_NOMONITOR   |
                                              IMPL_CONCRETE    |
                                              DERIVE_DERIVABLE |
                                              ANTIQ_CURRENT    |
                                              DIST_LOCAL;

    /**
    * The flags that the Behavior Trait can specify.
    */
    private static final int SPECABLE_FLAGS = EXISTS_SPECIFIED |
                                              ACCESS_SPECIFIED |
                                              VIS_SPECIFIED    |
                                              SYNC_SPECIFIED   |
                                              IMPL_SPECIFIED   |
                                              SCOPE_SPECIFIED  |
                                              DERIVE_SPECIFIED |
                                              ANTIQ_SPECIFIED  |
                                              DIST_SPECIFIED;

    /**
    * Flags that will cause a Behavior Trait to force compilation if modified.
    */
    private static final int CLASSGEN_FLAGS = ACCESS_MASK |
                                              VIS_MASK    |
                                              SYNC_MASK   |
                                              IMPL_MASK   |
                                              SCOPE_MASK  |
                                              DERIVE_MASK |
                                              ANTIQ_MASK  |
                                              DIST_MASK;

    /**
    * Parameter name for event listeners.
    */
    private static final String[] EVENT_REG_PARAM = new String[] {"l"};


    // ----- attributes

    /**
    * The behavior's name.
    */
    private String m_sName;

    /**
    * The behavior's signature (cached).
    */
    private String m_sSig;

    /**
    * Behavior attributes which are represented by bit flags, specifically
    * the Visible, Access, Synchronized, Static, Abstract, Final, Deprecated,
    * and Remotable attributes.
    *
    * @see com.tangosol.dev.component.Constants
    */
    private int m_nFlags = DEFAULT_FLAGS;

    /**
    * The legal ranges for this Behavior's attribute flags may be dependent
    * on the super (in the case of derivation) or base (in the case of
    * modification); those values are stored here for reference.
    */
    private int m_nPrevFlags = DEFAULT_FLAGS;

    /**
    * The behavior's return value.
    */
    private ReturnValue m_retval;

    /**
    * The behavior's parameters.
    */
    private Vector m_vectParam = new Vector();

    /**
    * The behavior's declared exceptions.
    */
    private StringTable m_tblExcept = new StringTable();

    /**
    * The behavior's implementation (scripts).  The order of the vector
    * reflects the order of "virtual method" execution in Java.  In other
    * words, the 0 element is executed, and if it super's, the 1 element
    * is executed, and so on.  The vector contains scripts only from this
    * derivation level (i.e. from this behavior and any modified base, but
    * not from a derived base aka "super").  This reflects .class generation
    * where a .class corresponds to a component, so all implementations at
    * a derivation level are incorporated into the .class.
    */
    private Vector m_vectScript = new Vector();

    /**
    * The number of implementations that do not belong to this behavior's
    * modification level.  These are the implementations which have null
    * modifications applied when the behavior is resolved.  They are
    * immutable at this level.  They can be "hidden" by setting the
    * override-base attribute of the behavior.
    */
    private int m_cBaseLevelImpl;

    /**
    * Does this behavior's modification level override (i.e. replace instead
    * of supplement) base implementations.  If true, the implementations from
    * modified base behaviors are not "reachable".
    */
    private boolean m_fOverrideBase;

    /**
    * The previous override of the implementations; this value is used only
    * during resolve processing.
    */
    private transient boolean m_fPrevOverrideBase;
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy