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

package oracle.portal.provider.v2;

import java.util.*;
import oracle.portal.provider.v2.*;
import oracle.portal.provider.v2.render.PortletContainerRenderer;
import oracle.portal.utils.xml.v2.*;
import oracle.portal.provider.v2.preference.PreferenceStore;
import oracle.portal.provider.v2.preference.PreferenceStoreException;
import oracle.webdb.provider.v2.builder.BuilderMetaData;

/**
 * <code>DefaultProviderDefinition</code> extends the base
 * <code>ProviderDefinition</code> meta data class with a set of accessors
 * compatible with the {@link
 * oracle.portal.provider.v2.http.DefaultProviderLoader} mechanism that loads
 * provider definitions from XML files. This is the class most commonly used in
 * the PDK-Java samples to define a provider.
 */
public class DefaultProviderDefinition extends ProviderDefinition
    implements InitializableXMLObject
{

    /**
     * Defines the {@link ProviderInstance} subclass that implements the
     * provider's behaviour.
     * @param className the fully qualified name of the {@link
     * ProviderInstance} class or subclass that implements the provider's
     * behaviour.
     */
    public void setProviderInstanceClass(String className)
        throws ClassNotFoundException
    {
        // We have to use the the current thread's 'context class loader'
        // (i.e. the web app's class loader) to load the class, so that it can
        // be picked up from within the web app
        setProviderInstanceClass(Class.forName(className, true,
                                               Thread.currentThread().getContextClassLoader()));
    }

    /**
     * Controls whether the <code>ProviderInstance</code> starts a (servlet)
     * session in its {@link ProviderInstance#initSession} method.
     *
     * @param session String representation of boolean value. Should be
     * <code>"true"</code> if this provider is to start a session in
     * <code>initSession</code>, or <code>"false"</code> otherwise.
     */     
    public void setSession(String session)
    {
        setHasSession(XMLUtil.getBooleanValue(session));
    }

    /**
     * Specifies whether or not {@link
     * oracle.portal.provider.v2.render.PortletRendererUtil} should render
     * headers and footers for this provider's portlets in the style used by a
     * 3.0.6 portal or earlier, rather than the style used by a post-3.0.6
     * portal.
     *
     * @param useOldStyleHeaders String representation of boolean (<code>"true"</code> or
     * <code>"false"</code>) indicating which style of form headers and footers should be
     * rendered by <code>PortletRendererUtil</code>.
     * @see ProviderDefinition#setUseOldStyleHeaders
     * 
     * @deprecated use {@link #addContainerRenderer} with {@link
     * oracle.portal.provider.v2.render.ContainerRenderer306} to get equivalent
     * behavior. Alternatively, create your own container renderer by extending
     * {@link PortletContainerRenderer}
     */
    public void setUseOldStyleHeaders(String useOldStyleHeaders)
    {
        setUseOldStyleHeaders(XMLUtil.getBooleanValue(useOldStyleHeaders));
    }


    /**
     * Sets the default portlet container renderer.<p>
     *
     * The container renderer is responsible for rendering the portlet
     * container in each of the show modes the portlet supports.<p>
     *
     * Each portlet can specify its own container renderer and you can specify
     * a default at the provider level to be used by any portlet that does not
     * explicitly specify it's own container renderer.<p>
     *
     * <b>Note</b>: This method uses the "add" prefix instead of "set" to
     * prevent ambiguous method errors during compilation. Calling the parent
     * method using "super" could be used within this class to resolve the
     * ambiguity, but if you are calling this method on an instance of
     * DefaultProviderDefinition you cannot use that technique to resolve it.
     *
     * @param renderer the default portlet container renderer. Even though the
     * type of the parameter is Object, the parameter must be an instance of
     * {@link PortletContainerRenderer}
     * @exception ProviderException if the given object is not a valid
     * <code>PortletContainerRenderer</code>.
     */
    public void addContainerRenderer(Object renderer) throws ProviderException
    {
        if (renderer != null && renderer instanceof PortletContainerRenderer)
        {
            setContainerRenderer((PortletContainerRenderer)renderer);
        }
        else
        {
            throw new ProviderException("Object must be an instance of PortletContainerRenderer");
        }
    }


    /**
     * Controls whether Portal will pass the requested page's URL parameters to
     * the provider's portlets by default.<p>
     *
     * @param value String representation of a boolean value indicating whether
     * Portal will pass the requested page's URL parameters to portlets by
     * default.
     *
     * <ul><li>If <code>"true"</code>, then each portlet whose definition doesn't
     *         explicitly override this setting will receive all the
     *         (non-system) parameters from the page URL.</li>
     *
     *     <li>If <code>"false"</code> (the default), then each portlet which
     *         declares input parameters and doesn't explicitly override this
     *         setting (with {@link PortletDefinition#setPassAllUrlParams})
     *         will only receive values for its declared input parameters and
     *         private parameters which have been generated using {@link
     *         oracle.portal.provider.v2.render.PortletRendererUtil#portletParameter}. The
     *         parameter values will be determined by the usage of the portlet
     *         on a particular page.</li></ul>
     */
    public void setPassAllUrlParams(String value)
    {
        setPassAllUrlParams(XMLUtil.getBooleanValue(value));
    }

    /**
     * Sets the caching level used for portlet render requests for
     * portlets belonging to this provider.
     *
     * This controls the set of parameters sent to the provider in a 
     * render request and hence the "cache key" under which the returned
     * markup is stored. This overrides the User/Session information
     * entered for the provider on registration.
     *
     * The possible settings are:
     *
     * <ul>
     * <li>
     *    <code>session</code>: both user and portal session information
     *    is required.
     * </li>
     * <li>
     *    <code>user</code>: user information is required but no session
     *    information is required.
     *
     * </li>
     * <li>
     *    <code>system</code>: neither user information nor portal session
     *    information is required.
     * </li>
     * </ul>
     *
     * @param cacheLevel int indicates the caching level - should be one of
     *                    PortletConstants.CACHE_LEVEL_SYSTEM_STR,
     *                    PortletConstants.CACHE_LEVEL_USER_STR,  or
     *                    PortletConstants.CACHE_LEVEL_SESSION_STR.
     *
     * The cache level for a portlet render request is determined using
     * the following order of precedence:
     *
     * <ul>
     * <li> If specified, the portlet setting is used</li>
     * <li> If specified, the provider setting is used</li>
     * <li> If the provider is registered as "public" then the portlet will be
     *      called using the "public" user and cached at the system level</li>
     * <li> If the provider is registered as "user" and "portal session data"
     *      is requested then portlet will be cached at the session level</li>
     * <li> Otherwise, the portlet will be cached at user level</li>
     * </ul>
     */
    public void setCacheLevel(String cacheLevel) throws ProviderException
    {
        if (cacheLevel.equalsIgnoreCase(
            PortletConstants.CACHE_LEVEL_SYSTEM_STR))
        {
            setCacheLevel(PortletConstants.CACHE_LEVEL_SYSTEM);
        }
        else if (cacheLevel.equalsIgnoreCase(
            PortletConstants.CACHE_LEVEL_USER_STR))
        {
            setCacheLevel(PortletConstants.CACHE_LEVEL_USER);
        }
        else if (cacheLevel.equalsIgnoreCase(
            PortletConstants.CACHE_LEVEL_SESSION_STR))
        {
            setCacheLevel(PortletConstants.CACHE_LEVEL_SESSION);
        }
        else
        {
            throw new ProviderException("Invalid cacheLevel value. Must be one of: system, user, or session.");
        }
    }

    /**
     * Controls whether or not URL rewriting will be performed on the results
     * of portlet render requests for portlets belonging to this provider.<p>
     *
     * @param rewriteUrls String "true" if URL rewriting is to be performed.
     *        Otherwise "false".
     * @see ProviderDefinition#setRewriteUrls
     * @see PortletDefinition#setRewriteUrls
     */
    public void setRewriteUrls(String value)
    {
        setRewriteUrls(XMLUtil.getBooleanValue(value));
    }

    /**
     * Sets the locale personalization level which will be used for portlets
     * whose defintion does not include a portlet specific setting. For more
     * detail on the locale personalization level, see {@link
     * PortletDefinition#setLocalePersonalizationLevel(int)}.
     * 
     * @param value the required locale personalization level. See,
     * {@link DefaultPortletDefinition#setLocalePersonalizationLevel(String)}
     */
    public void setLocalePersonalizationLevel(String value)
        throws ProviderException
    {
        if (PortletConstants.PERSONALIZATION_LEVEL_NONE_STR.equalsIgnoreCase(value))
        {
            setLocalePersonalizationLevel(PortletConstants.PERSONALIZATION_LEVEL_NONE);
        }
        else if (PortletConstants.PERSONALIZATION_LEVEL_LANGUAGE_STR.equalsIgnoreCase(value))
        {
            setLocalePersonalizationLevel(PortletConstants.PERSONALIZATION_LEVEL_LANGUAGE);
        }
        else if (PortletConstants.PERSONALIZATION_LEVEL_LOCALE_STR.equalsIgnoreCase(value))
        {            
            setLocalePersonalizationLevel(PortletConstants.PERSONALIZATION_LEVEL_LOCALE);
        }
        else
        {
            throw new ProviderException("Invalid localPersonalizationLevel");
        }
    }

    /**
     * Sets the default Locale for this {@link ProviderDefinition}. The Locale
     * is specified using the standard ISO two-letter language and country
     * codes, e.g. <code>en.US</code>. See {@link
     * ProviderDefinition#setDefaultLocale(Locale)}.
     *
     * @param lang a String specifying a Locale
     */
    public void setDefaultLocale(String defaultLocale)
    {
        setDefaultLocale(translateLocaleString(defaultLocale));
    }

    /**
     * Associates with the provider a <code>PortletDefinition</code> object
     * containing the meta data for one of the portlets it owns. Note that each
     * <code>PortletDefinition</code> added should have a unique id.
     * @param portlet an object containing the portlet-level meta data for one
     * of the provider's portlets. Should be a {@link PortletDefinition} or a
     * subclass.
     * @exception ProviderException if the given object is not a
     * <code>PortletDefinition</code>
     */
    public void addPortlet(Object portlet) throws ProviderException
    {
        if (!(portlet instanceof PortletDefinition))
  
        {
            throw new ProviderException("Object not a PortletDefinition");
        }
        addPortletDefinition((PortletDefinition)portlet);
    }

    /**
     * Adds to the set of <code>PreferenceStore</code> objects that may be used by
     * the provider for persistent storage. Note that each
     * <code>PreferenceStore</code> added should have a unique identifying
     * name.
     * @param pd a preference store object. Should be a {@link PreferenceStore}
     * or subclass.
     * @exception ProviderException if the given object is not a
     * <code>PreferenceStore</code>
     */
    public void addPreferenceStore(Object ps) throws ProviderException
    {
        if (!(ps instanceof PreferenceStore))
        {
            throw new ProviderException("Object not a PreferenceStore");
        }
        super.addPreferenceStore((PreferenceStore)ps);
    }

    /**
     * Should be called immediately after construction of a
     * <code>DefaultProviderDefinition</code> to associate it with its parent
     * {@link ProviderContext} object describing its deployment
     * environment. Generally, all providers running in the same environment
     * (e.g. within the same adapter servlet) share the same
     * <code>ProviderContext</code>.
     * @param parent an object describing the deployment environment of the
     * provider. Should be a {@link ProviderContext}.
     * @exception NodeHandlerException if the given object is not a
     * <code>ProviderContext</code>
     */
    public void preInitialize(Object parent) throws NodeHandlerException
    {
        if(!(parent instanceof ProviderContext))
        {
            throw new NodeHandlerException ("Parent of a ProviderDefinition must be a ProviderContext");
        }
        init((ProviderContext)parent);
    }

    /**
     * Should be called once initialization of this
     * <code>DefaultProviderDefinition</code> is complete, to complete
     * initialization and perform any necessary validation.
     * @exception NodeHandlerException if validation is unsuccessful
     */
    public void postInitialize() throws NodeHandlerException
    {
    }

    /**
    * Each provider can specifiy the builder attached to edit this provider.
    * This method sets a ProviderBuilder with this providerdefintion.
    * @param providerBuilder the ProviderBuilder attribute for this Provider
    * @exception ProviderException if the given Object is not a valid {@link
    * oracle.webdb.provider.v2.builder.BuilderMetaData}.
    */
    public void setProviderBuilder(Object providerBuilder) 
         throws ProviderException
    {
          if (!(providerBuilder instanceof BuilderMetaData))
          {
              throw new ProviderException("Object is not an instance of  "+
                 " BuilderMetadata");
          }
          super.setProviderBuilder( (BuilderMetaData) providerBuilder );
    }    

    protected static Locale translateLocaleString(String locale)
    {
        String language = "", country = "";
        int i = locale.indexOf(".");
        if (i == -1)
        {
            language = locale;
        }
        else
        {
            language = locale.substring(0, i);
            country = locale.substring(i+1);
        }
        return new Locale(language, country);
    }

}
