/*  Copyright (c) 2001 by Oracle Corporation. All Rights Reserved. */

package oracle.portal.provider.v2;

import java.util.*;
import oracle.portal.provider.v2.Validateable;
import oracle.portal.provider.v2.utils.ValidationError;

/**
 * An EventDefinition represents the metadata which describes an event that
 * can be raised by this portlet.
 */
public class EventDefinition implements Validateable
{
    /**
     * mName stores the name for this event.
     */
    private String mName;

    /**
     * mDescription stores the description for this event.
     */
    private String mDescription;

    /**
     * mDescriptionKey stores the string value for the key used to look
     * up the portlet's description in a resource bundle.
     */
    private String mDescriptionKey;

    /**
     * mDisplayName stores the display name for this event.
     */
    private String mDisplayName;

    /**
     * mDisplayNameKey stores the string value for the key used to look
     * up the portlet's display name in a resource bundle.
     */
    private String mDisplayNameKey;

    /**
     * mParameter stores the set of parameters definied for this event.
     */
    private List mParameters;

    /**
     * mResource stores a string of the resource location for this parameter.
     */
    private String mResource;

    /**
     * mBundle stores a cached ResourceBundle for this parameter.
     */
    private ResourceBundle mBundle;

    /**
     * mBundleLocale stores a cached Locale for mBundle
     */
    private Locale mBundleLocale;


    /**
     * Default constructor.
     */
    public EventDefinition()
    {
    }

    /**
     * Gets the resource bundle for this Portlet in the given Locale.
     *
     * @param l the Locale of the resource bundle being requested.
     * @return the resource bundle for this parameter.  <b>null</b> if
     * there isn't one.
     */
    public ResourceBundle getResourceBundle(Locale l)
    {
        if (mResource == null) return null;

        if (l == null)
        {
            l = Locale.getDefault();
        }

        if (mBundle == null || mBundleLocale == null || !l.equals(mBundleLocale))
        {
            // We have to use the the current thread's 'context class loader'
            // (i.e. the web app's class loader) to load the resource, so that
            // it can be picked up from within the web app
            mBundle = ResourceBundle.getBundle(mResource, l,
                                               Thread.currentThread().getContextClassLoader());
            mBundleLocale = l;
        }

        return mBundle;
    }

    /**
     * Sets the name of the default resource bundle class for this parameter
     *
     * @param resourceClassName full name of class extending {@link
     * java.util.ResourceBundle}.
     */
    public void setResource(String resourceClassName)
    {
        mResource = resourceClassName;
    }

    /**
     * @return this event's name.
     */
    public String getName()
    {
        return mName;
    }

    /**
     * Set the event's name.
     *
     * This name must be unique across all events defined for this portlet.
     *
     * @param name the event's name.
     */
    public void setName(String name)
    {
        mName = name;
    }

    /**
     * @return this event's display name.
     */
    public String getDisplayName(Locale l)
    {
        if (mDisplayName != null)
        {
            return mDisplayName;
        }
        else
        {
            ResourceBundle b = getResourceBundle(l);
            if (b != null)
            {
                String key = getDisplayNameKey();

                if (key != null)
                {
                    // get string from bundle.
                    // If none present, null is returned.
                    try
                    {
                        return b.getString(key);
                    }
                    catch (MissingResourceException mre)
                    {
                    }
                }
            }
        }
        return null;
    }

    /**
     * Sets the event's display name.
     *
     * This is a short name used in the Portal UI.
     *
     * @param displayName a friendly name to be used in the Portal UI.
     */
    public void setDisplayName(String displayName)
    {
        mDisplayName = displayName;
    }

    /**
     * @return the key used to look up this event's display name from a
     * resource bundle.
     */
    public String getDisplayNameKey()
    {
        return mDisplayNameKey;
    }

    /**
     * Sets the event's display name key.
     *
     * @param displayNameKey the string value for the key used to look up 
     * the event's display name in a resource bundle.
     */
    public void setDisplayNameKey(String displayNameKey)
    {
        mDisplayNameKey = displayNameKey;
    }

    /**
     * @return this event's description .
     */
    public String getDescription(Locale l)
    {
        if (mDescription != null)
        {
            return mDescription;
        }
        else
        {
            ResourceBundle b = getResourceBundle(l);
            if (b != null)
            {
                String key = getDescriptionKey();

                if (key != null)
                {
                    // get string from bundle.
                    // If none present, null is returned.
                    try
                    {
                        return b.getString(key);
                    }
                    catch (MissingResourceException mre)
                    {
                    }
                }
            }
        }
        return null;
    }

    /**
     * Sets the event's description.
     *
     * This is displayed in the Portal UI to give the page designer 
     * a better idea of what it will be used for.
     *
     * @param description a short description of what this event is.
     */
    public void setDescription(String description)
    {
        mDescription = description;
    }

    /**
     * @return the key used to look up this event's description from a
     * resource bundle.
     */
    public String getDescriptionKey()
    {
        return mDescriptionKey;
    }

    /**
     * Sets the event's description key.
     *
     * @param descriptionKey the string value for the key used to look up 
     * the event's description in a resource bundle.
     */
    public void setDescriptionKey(String descriptionKey)
    {
        mDescriptionKey = descriptionKey;
    }

    /**
     * @return the parameters passed as part of this event.
     */
    public ParameterDefinition[] getParameters()
    {
        if (mParameters == null)
        {
            return null;
        }

        // Make copy and return
        ParameterDefinition[] parameters =
            new ParameterDefinition[mParameters.size()];

        mParameters.toArray(parameters);

        return parameters;
    }

    /**
     * Add a parameter to the event.
     *
     * These are the parameters which will be passed with the event when 
     * it is raised.  They are rendered by the portlet with the event.
     *
     * @param parameter a ParameterDefinition to passed as part of this event.
     */
    public void addParameter(ParameterDefinition parameter)
    {
        if (mParameters == null)
        {
            mParameters = new ArrayList();
        }
        mParameters.add(parameter);
    }

    /**
     * Validates the internal state of this <code>EventDefinition</code>
     * instance. Errors found are reported using the supplied {@link
     * oracle.portal.provider.v2.utils.ValidationError} instance.
     *
     * @param context The context of the calling instance.
     * @param errors The current list of errors.
     */
    public void validate(String context, ValidationError errors)
    {
        String ctx = ValidationError.newContext(context, "EventDefinition",
                                                mName);

        // Check the validity of the member variables
        if( mName == null || mName.length() == 0 )
        {
            errors.addError(ctx, "name must not be null", null);
        }

        // Validate the event's parameters.
        if (mParameters != null)
        {
            Iterator it = mParameters.iterator();
            ParameterDefinition pd = null;
            String name = null;
            Map names = new HashMap(5);
            while (it.hasNext())
            {
                pd = (ParameterDefinition)it.next();
                name = pd.getName();
                if (names.containsKey(name))
                {
                    errors.addError(ctx, "Parameter name is not unique within" +
                                    "event", name);
                }
                else
                {
                    names.put(name, null);
                }
                if (pd instanceof Validateable)
                {
                    ((Validateable)pd).validate(ctx, errors);
                }
            }
        }
    }
}
