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

package oracle.portal.utils.v1;

import java.lang.reflect.*;
import org.w3c.dom.Element;
import oracle.portal.utils.xml.v1.*;

// At the moment this class is only used by ConnectionManager, so we have not
// made it public

/**
 * This class extends {@link DefaultNodeHandler} for the specific purpose of
 * configuring a DefaultConnectionManager from its XML configuration file.
 */
class ConnectionManagerNodeHandler extends DefaultNodeHandler
{
    private static final String ADD_METHOD_PREFIX = "add";
    private static final String SET_METHOD_PREFIX = "set";
    private static final String ELEMENT_CONNECTION = "connection";

    /** 
     * For a given 'complex' element, returns an instance of the type of object
     * it represents. In this connection manager specific implementation, the
     * method simply has to create new {@link DefaultConnectionPool} objects
     * for each <code>connection</code> element.
     * @param e the 'complex' element for which a corresponing object is to be
     * created
     * @return a {@link DefaultConnectionPool} if the element tag name is
     * <code>connection</code>, or <code>null</code> otherwise.
     * @exception NodeHandlerException if an error occurs while trying to
     * create an appropriate object.
     */
    public Object getApplicationObjectForElement(Element e)
        throws NodeHandlerException
    {
        if(e.getTagName().equalsIgnoreCase(ELEMENT_CONNECTION))
        {
            return new DefaultConnectionPool();
        }
        return null;
    }

    // We override setCustomValue and attachObject so that we are invoking the
    // method from this package, and can therefore call methods with package
    // level protection
    protected void setCustomValue(String name, String value, Object o) throws NodeHandlerException
    {
        Method m = findMethod(o, name, sCustomParamType);
        Object[] params = {value};
        try
        {
            m.invoke(o, params);
        }
        // 'unwrap' InvocationTargetExceptions so that we can get at their message
        catch (InvocationTargetException ite)
        {
            throw new NodeHandlerException(ite.getTargetException());
        }
        catch (Exception ex)
        {
            throw new NodeHandlerException(ex);
        }
    }

    protected void attachObject(Object o, Object childObject, Element e) throws NodeHandlerException
    {
        String name = e.getTagName();
        Method m = findMethod(o, name, sObjectParamType);
        Object[] params = {childObject};
        try
        {
            m.invoke(o, params);
        }
        catch (Exception ex)
        {
            throw new NodeHandlerException(ex);
        }
    }

    // We override findMethod so that it uses getDeclaredMethod, rather than
    // getMethod, and can therefore find methods with package level protection
    protected Method findMethod(Object o, String tagName, Class[] paramTypes)
        throws NodeHandlerException
    {
        String methodName;
        try
        {
            methodName = getMethodName(SET_METHOD_PREFIX, tagName);
            return o.getClass().getDeclaredMethod(methodName, paramTypes);
        }
        catch (NoSuchMethodException nssme)
        {
            try
            {
                methodName = getMethodName(ADD_METHOD_PREFIX, tagName);
                return o.getClass().getDeclaredMethod(methodName, paramTypes);
            }
            catch (NoSuchMethodException nsame)
            {
                throw new NodeHandlerException("Class " + o.getClass().getName() +
                                               " has no set or add method for tag \"" +
                                               tagName + "\"");
            }
        }
    }
    
}

