//*****************************************************************************
/*
** FILE:   xc_CustomizerFactory.java
**
** (c) 1997 Steve Withall.
**
** HISTORY:
**    06Jun98  stevew  Created, based on xe_ParserFactory.
*/
package xc;

import xm.xm_NodeTypeDefn;
import xm.xm_NodeTypeRegistry;

import xg.xg_Node;

import eh.eh_Debug;

import java.lang.Class;

//*****************************************************************************
/** Factory for generating customizers for displaying and editing XML nodes.
 *
 *  Given the name/type of an XML node (or a node itself), it creates a customizer
 *  object suitable for displaying and editing it.
 */
public class xc_CustomizerFactory
{
    //*****************************************************************************
    /** <p>Create a customizer of a type suitable for displaying a node whose name is
     *  'InputNodeName'. If the InputExistingCustomizer exists and is of the right
     *  type (ie. is an instance of the same class which we would construct), then
     *  it will be re-used.</p>
     *
     *  <p>Non-standard customizers can be added by registering them with
     *  xm_NodeTypeRegistry.</p>
     *
     * @param      InputNode                The node for which we need a customizer
     * @param      InputExistingCustomizer  An existing customizer, to be re-used
     *                                       if possible. It may be null - in which
     *                                       case a new customizer will be created.
     * @return                              The newly-created customizer for the InputNode
     * @exception  xc_CustomizerCreationException Either no customizer class is
     *                                             registered or it cannot be instantiated
     */
    public xc_NodeCustomizer createCustomizer(xg_Node            InputNode,
                                              xc_NodeCustomizer  InputExistingCustomizer)
                     throws xc_CustomizerCreationException
    {
//	    eh_Debug.add(8, "xc_CustomizerFactory.createCustomizer: for node " + InputNode);
        boolean  ReUseCustomizerFlag = false;
        if (InputExistingCustomizer != null)
        {
            Class   ExistingCustomizerClass     = InputExistingCustomizer.getClass();
            String  ExistingCustomizerClassName = ExistingCustomizerClass.getName();
            String  NewCustomizerClassName      = getCustomizerClassName(InputNode.getName(),
                                                                         InputNode.getType() );
            if (NewCustomizerClassName.equals(ExistingCustomizerClassName) )
                ReUseCustomizerFlag = true;
        }

        xc_NodeCustomizer NewCustomizer = null;
        if (ReUseCustomizerFlag)
            // The existing customizer can be re-used.
            NewCustomizer = InputExistingCustomizer;
        else
            NewCustomizer = createCustomizer(InputNode.getName(),
                                             InputNode.getType() );
        NewCustomizer.setNode(InputNode);
        return NewCustomizer;
    }

    //*****************************************************************************
    /** <p>Create a customizer of a type suitable for displaying a node whose name is
     *  'InputNodeName'. If no customizer is registered for InputNodeName, then a
     *  custopmizer suitable for InputNodeType is created. This dual-level scheme
     *  allows special customizers to be added, while still creating customizers of
     *  the correct standard type the rest of the time.</p>
     *
     *  <p>Non-standard customizers can be added by registering them with
     *  xm_NodeTypeRegistry.</p>
     *
     *  @param      InputNodeName  The name of the node for which we need a customizer
     *  @param      InputNodeType  The type of node for which we need a customizer
     *  @return                    The newly-created customizer for the named entity
     *  @exception  xc_CustomizerCreationException  Either no customizer class is
     *                                               registered or it cannot be instantiated
     */
    public xc_NodeCustomizer createCustomizer(String InputNodeName,
                                              int    InputNodeType)
                      throws xc_CustomizerCreationException
    {
        String  NewCustomizerClassName = getCustomizerClassName(InputNodeName,
                                                                InputNodeType);
        return (createCustomizer(NewCustomizerClassName));
    }

    //*****************************************************************************
    /** <p>Create a customizer of a type suitable for displaying a node whose name is
     *  'InputNodeName'. If no customizer is registered for InputNodeName, then a
     *  custopmizer suitable for InputNodeType is created. This dual-level scheme
     *  allows special customizers to be added, while still creating customizers of
     *  the correct standard type the rest of the time.</p>
     *
     *  <p>Non-standard customizers can be added by registering them with
     *  xm_NodeTypeRegistry.</p>
     *
     *  @param      InputNode         The node for which we need a customizer
     *  @return                       The newly-created customizer for the InputNode
     *  @exception  xc_CustomizerCreationException  Either no customizer class is
     *                                               registered or it cannot be instantiated
     */
    public xc_NodeCustomizer createCustomizer(xg_Node  InputNode)
                     throws xc_CustomizerCreationException
    {
        xc_NodeCustomizer NewCustomizer = createCustomizer(InputNode.getName(),
                                                           InputNode.getType() );
        NewCustomizer.setNode(InputNode);
        return NewCustomizer;
    }

    //*****************************************************************************
    /** Create a customizer of as an instance of the named class.
     *
     *  @param      InputCustomizerClassName  The name of the customizer class
     *  @return                               The newly-created customizer
     *  @exception  xc_CustomizerCreationException  The customizer class cannot be
     *                                               instantiated
     */
    public xc_NodeCustomizer createCustomizer(String InputCustomizerClassName)
                      throws xc_CustomizerCreationException
    {
//        eh_Debug.add(8, "xc_CustomizerFactory: Create customizer of type "
//                                + InputCustomizerClassName);

        xc_NodeCustomizer  NewCustomizer = null;
        try
        {
            // Create a customizer.
            Class  CustomizerClass = Class.forName(InputCustomizerClassName);
            NewCustomizer = (xc_NodeCustomizer)CustomizerClass.newInstance();
        }
        catch (Exception  InputException)
        {
            eh_Debug.add(2, "xc_CustomizerFactory: Error creating customizer of type "
                                 + InputCustomizerClassName + " (" + InputException + ")");
            throw new xc_CustomizerCreationException("Error creating customizer of type "
                                                        + InputCustomizerClassName
                                                        + " (" + InputException + ")");
        }

        return NewCustomizer;
    }

    //*****************************************************************************
    /** Get the name of the customizer class suitable for displaying a node
     *  whose name is 'InputNodeName'. If no customizer is registered for
     *  InputNodeName, get the name of a custopmizer suitable for InputNodeType.
     *
     *  @param      InputNodeName  The name of the node for which we need a customizer
     *  @param      InputNodeType  The type of node for which we need a customizer
     *  @return                    The newly-created customizer for the named entity
     *  @exception  xc_CustomizerCreationException  Either no customizer class is
     *                                               registered or it cannot be instantiated
     */
    public String getCustomizerClassName(String InputNodeName,
                                         int    InputNodeType)
                      throws xc_CustomizerCreationException
    {
//	    eh_Debug.add(8, "xc_CustomizerFactory.getCustomizerClassName: for node name '"
//	                            + InputNodeName + "', type " + InputNodeType);
        xm_NodeTypeDefn     EntityNodeTypeDefn = xm_NodeTypeRegistry.getDefn(InputNodeName);
        if (EntityNodeTypeDefn == null)
            // No entry for this node name - so get one for this node type.
            EntityNodeTypeDefn = xm_NodeTypeRegistry.getDefn(InputNodeType);

        if (EntityNodeTypeDefn == null)
            throw new xc_CustomizerCreationException("No customizer class registered for "
                                                           + InputNodeName + "/"
                                                           + InputNodeType);

        // Get the name of the class used to customize nodes of this type.
        String  NewCustomizerClassName = EntityNodeTypeDefn.getCustomizerClassName();
        if (NewCustomizerClassName == null)
        {
            eh_Debug.add(2, "xc_CustomizerFactory: No customizer class registered for "
                                 + InputNodeName);
            throw new xc_CustomizerCreationException("No customizer class registered for "
                                                           + InputNodeName);
        }

        return NewCustomizerClassName;
    }
}

//*****************************************************************************
