/********************************************************************
 * Copyright © 2005 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.fw.ui.valuelist;

// Java Classes
import java.util.Map;
import javax.servlet.jsp.PageContext;

// Library Classes
import net.mlw.vlh.web.tag.support.DefaultLinkEncoder;

// Framework Classes
import gov.va.med.fw.util.InvalidConfigurationException;

/**
 * Extends the default link encoder functionality by adding a caller key to the link. Each unique calling method can
 * define their own key to uniquely identify the action the user is performing.  For example, if the caller is a tag
 * that generates a link to sort, the method in that tag library can define a key of "sort".
 *
 * @author Andrew Pach
 * @version 1.0
 */
public class ExtendedDefaultLinkEncoder extends DefaultLinkEncoder
{
    /**
     * The methods that we should apply the functionality to.
     */
    private Map methodActionMap;

    /**
     * The attribute name that will be used to identify the caller.
     */
    public static final String CALLER_KEY = "callerKey";

    /**
     * @see net.mlw.vlh.web.tag.support.LinkEncoder#encode(javax.servlet.jsp.PageContext, java.util.Map)
     */
    public String encode(PageContext pageContext, Map parameters)
    {
        // ***** REVISIT *****
        // Consider using a Spring ControlFlowPointCut

        Throwable throwable = new Throwable();
        StackTraceElement[] stackTraceElements = throwable.getStackTrace();
        for (int i = 0; i < stackTraceElements.length; i++)
        {
            StackTraceElement stackTraceElement = stackTraceElements[i];
            String caller = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName();

            if (methodActionMap.containsKey(caller))
            {
                parameters.put(CALLER_KEY, methodActionMap.get(caller));
                break;
            }
        }

        return super.encode(pageContext, parameters);
    }

    /**
     * Checks if all required properties are set.
     *
     * @throws gov.va.med.fw.util.InvalidConfigurationException if all required properties are not set.
     */
    public void afterPropertiesSet() throws InvalidConfigurationException
    {
        if (methodActionMap == null)
        {
            throw new InvalidConfigurationException("The methodActionMap must be set.");
        }
    }

    /**
     * Sets the methods and their attributes to apply this functionality to.
     *
     * @param methodMap The caller methods
     */
    public void setMethodActionMap(Map methodMap)
    {
        this.methodActionMap = methodMap;
    }

    /**
     * Gets the methods and their attributes to apply this functionality to.
     *
     * @return The caller methods
     */
    public Map getMethodActionMap()
    {
        return methodActionMap;
    }
}