// Copyright 2001 (c) Oracle Corporation
package oracle.portal.provider.v1.http;

import java.io.*;
import oracle.portal.utils.xml.v1.*;
import oracle.portal.provider.v1.*;

/**
 * Class for describing individual pages owned by a {@link
 * PortletPageLocator}. Properties set at this level will override those set at
 * the parent ({@link PortletPageLocator}) level.
 */
public abstract class Page extends BaseManagedRenderer
{
    private String mAppPath;
    private String mAppRoot;
    private String mPageName;
    private String mPagePath;
    private String mPageRealPath;
    private String mPageParam;

    /**
     * Sets the name of the page described by this <code>Page</code>.
     * @param pageName <code>appPath</code> relative name of the page
     */
    public void setName(String pageName)
    {
        mPageName = pageName;
    }

    /**
     * Gets the name of the page described by this <code>Page</code>.
     * @return <code>appPath</code> relative name of the page
     */
    public String getName()
    {
        return mPageName;
    }

    /**
     *  Sets the root virtual path for the renderer's pages.
     *
     *  @param path the root virtual path for the render's pages.
     */
    public void setAppPath(String path)
    {
        mAppPath = path;
    }

    /**
     *  Gets the root virtual path for the renderer's pages. If a virtual path
     *  hasn't been set explicitly on this <code>BaseManagedRenderer</code>,
     *  then the value returned by calling the {@link
     *  PortletPageLocator#getAppPath()} method on the parent
     *  <code>PortletPageLocator</code> is returned.
     *
     *  @return the root virtual path for the renderer's pages.
     */
    public String getAppPath()
    {
        if(mAppPath == null)
        {
            return mParent.getAppPath();
        }
        return mAppPath;
    }

    /**
     *  Sets the root physical path for the renderer's pages.
     *
     *  @param path the root physical path for the renderer's pages.
     */
    public void setAppRoot(String path)
    {
        mAppRoot = path;
    }

    /**
     *  Gets the root physical path for the renderer's pages. If a physical
     *  path hasn't been set explicitly on this
     *  <code>BaseManagedRenderer</code>, then the value returned by calling
     *  the {@link PortletPageLocator#getAppRoot()} method on the parent
     *  <code>PortletPageLocator</code> is returned.
     *
     *  @return the root physical path for the renderer's pages.
     */
    public String getAppRoot()
    {
        if(mAppRoot == null)
        {
            return mParent.getAppRoot();
        }
        return mAppRoot;
    }

    /**
     * Sets the name of the request parameter that is used to override the name
     * of the registered page. Used to communicate the "next" page in a portlet
     * that uses multiple pages to render itself.
     *
     * @param paramName the name of the request parameter used to override the
     * name of the registered page.
     */
    public void setPageParameterName(String paramName)
    {
        mPageParam = paramName;
    }

    /**
     *  Gets the name of the request parameter used to override the name of the
     *  registered page. If a parameter name hasn't been set explicitly on this
     *  <code>BaseManagedRenderer</code>, then the value returned by calling
     *  the {@link PortletPageLocator#getPageParameterName()} method on the
     *  parent <code>PortletPageLocator</code> is returned.
     *
     *  @return the name of the request parameter used to override the name of
     *  the registered page.
     */
    public String getPageParameterName()
    {
        if (mPageParam == null)
        {
            return mParent.getPageParameterName();
        }
        return mPageParam;
    }

    /**
     *  Returns the virtual path to the page represented by this
     *  <code>Page</code>, overriding the page name if the given request
     *  contains a parameter with a name matching the name returned by the
     *  {@link #getPageParameterName()} method.
     *
     *  @param pr the current render request
     *  @return virtual path to the page
     */
    public String getPagePath(PortletRenderRequest pr)
    {
        // cache for performance
        if (mPagePath == null)
        {
            mPagePath = concatPaths(getAppPath(), mPageName, "/");
        }

        String page = getPage(pr);

        if (page != null)
        {
            return concatPaths(getAppPath(), page, "/");
        }
        else
        {
            return mPagePath;
        }
    }


    /**
     *  Returns the physical path to the page represented by this
     *  <code>Page</code>, overriding the page name if the given request
     *  contains a parameter with a name matching the name returned by the
     *  {@link #getPageParameterName()} method.
     *
     *  @param pr the current render request
     *  @return physical path to the page
     */
    public String getPageRealPath(PortletRenderRequest pr)
    {
        // cache for performance
        if (mPageRealPath == null)
        {
            mPageRealPath =
                concatPaths(getAppRoot(),
                            mPageName.replace('/', File.separatorChar),
                            File.separator);
        }

        String page = getPage(pr);

        if (page != null)
        {
            return concatPaths(getAppRoot(),
                               page.replace('/', File.separatorChar),
                               File.separator);
        }
        else
        {
            return mPageRealPath;
        }

    }

    protected String concatPaths(String root, String relative, String pathSep)
    {
        int sLen = root.length();
        boolean pathSuffixed = root.charAt(sLen - 1) == pathSep.charAt(0);
        boolean pathPrefixed = relative.charAt(0) == pathSep.charAt(0);

        if (sLen == 1 && pathSuffixed && pathPrefixed)
        {
            return relative;
        }
        else if ((pathSuffixed && !pathPrefixed) || 
                 (!pathSuffixed && pathPrefixed))
        {
            return root + relative;
        }
        else if (!pathSuffixed && !pathPrefixed)
        {
            return root + pathSep + relative;
        }
        else
        {
            // root path is suffixed and the relative path is prefixed
            return root.substring(0, sLen - 1) + relative;
        }
    }

    protected String getPage(PortletRenderRequest pr) 
    {
        String page = null;
        String pageParam = getPageParameterName();
        if (pageParam != null)
        {
            // first try with fully qualified name
            page = pr.getParameter(PortletRendererUtil.portletParameter(pr, 
                                   pageParam));
            if (page == null)
            {
                // else try the regular parameter name
                page = pr.getParameter(pageParam);
            }
        }
        return page;
    }
}






