##
## The Velocity code generation template for the Initializer class generated from a Control
## implementation class
##
## Licensed to the Apache Software Foundation (ASF) under one or more
## contributor license agreements.  See the NOTICE file distributed with
## this work for additional information regarding copyright ownership.
## The ASF licenses this file to You under the Apache License, Version 2.0
## (the "License"); you may not use this file except in compliance with
## the License.  You may obtain a copy of the License at
## 
##     http://www.apache.org/licenses/LICENSE-2.0
## 
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
## $Header:$
##
## The following context variables are used by this template:
##      $init - a ImplInitializer instance that defines the attributes of the intializer
##
## The actual class template apears at the end of this file, and is preceded by a number of
## supporting macros that define elements of the template.
##
## SUPPORTING MACROS
##
##
## This macro defines any static final Field values needed for field initialization
##
#macro (declareReflectFields)
    #foreach ($field in $init.reflectFields)
        static final Field $field.reflectField;
    #end
#end
##
## This macro initializes the value of any static final Field values for field initialization
##
#macro (initReflectFields)
    try
    {
    #foreach ($field in $init.reflectFields)
        $field.reflectField = ${impl.className}.class.getDeclaredField("$field.name");
        ${field.reflectField}.setAccessible(true);
    #end
    }
    catch (NoSuchFieldException __bc_nsfe)
    {
        throw new ExceptionInInitializerError(__bc_nsfe);
    }
#end
##
## This macro declares a new event adaptor class that maps events from an EventSet to
## a set of implemented handlers on a control implementation
##
#macro (declareEventAdaptor $adaptor)
    #set ($eventSet = $adaptor.eventSet)
    protected static class $adaptor.className implements $eventSet.className, java.io.Serializable
    {
        private static final long serialVersionUID = 1L;

        $impl.className __bc_impl;

        ${adaptor.className}($impl.className impl) { __bc_impl = impl; }

        #foreach ($event in $eventSet.events)
            public ${event.returnType} ${event.name}(${event.argDecl}) $event.throwsClause
            {
            #if ($adaptor.hasHandler($event))
                #if ($event.returnType != "void") return #end __bc_impl.${adaptor.getHandler($event).name}(${event.argList});
            #elseif ($event.returnType != "void")
                return $event.defaultReturnValue;
            #end
            }
        #end
    }

#end
##
## This macros declares any generated class that act as event adaptors between an event
## source (control or context) and implementation class event handlers.
##
#macro (declareEventAdaptors)
    #foreach ($context in $impl.contexts)
        #foreach ($adaptor in $context.eventAdaptors)
            #declareEventAdaptor($adaptor)
        #end
    #end
#end
##
## This macro initializes any event adaptors for a nested control
##
#macro (initEventAdaptors $control)
    #foreach ($adaptor in $control.eventAdaptors)
        ${control.localName}.${adaptor.eventSet.addListenerMethod}(new ${adaptor.className}(__bc_impl));
    #end
#end
##
## This macro defines the initialization of a contextual service
##
#macro (initContext $context)
    #if ($context.getType().equals("org.apache.beehive.controls.api.context.ControlBeanContext"))
    $context.type $context.localName = __bc_beanContext;
    #else
    $context.type $context.localName = ($context.type)__bc_beanContext.getService(${context.type}.class, null);
    #end
    if ($context.localName == null)
        throw new ControlException("Contextual service $context.type is not available");
    #initEventAdaptors($context)
    #if ($init.needsReflection($context))
    ${context.reflectField}.set(__bc_impl, $context.localName);
    #else
    __bc_impl.$context.name = $context.localName;
    #end
#end
##
## This macro defines the initialization of a contextual service
##
#macro (resetContext $context)
    #if ($init.needsReflection($context))
    ${context.reflectField}.set(__bc_impl, null);
    #else
    __bc_impl.$context.name = null;
    #end
#end
##
## This macro defines the initialization of a event notification proxy
##
#macro (initEventProxy $proxy)
    $proxy.className $proxy.localName = ($proxy.className)getEventNotifier(bean, ${proxy.className}.class);
    #if ($init.needsReflection($proxy))
    ${proxy.reflectField}.set(__bc_impl, $proxy.localName);
    #else
    __bc_impl.$proxy.name = $proxy.localName;
    #end
#end
##
## This macro defines the initialization method for all nested contextual services
##
#macro (declareServiceInit)
    /**
     * Initializes the nested contextual services required by the implementation
     */
    public void initServices(ControlBean bean, Object target)
    {
        $impl.className __bc_impl = ($impl.className)target;

        super.initServices(bean, __bc_impl);

        ControlBeanContext __bc_beanContext = bean.getControlBeanContext();
        try
        {
            #foreach ($context in $impl.contexts)
                #initContext($context)
            #end
        }
        catch (RuntimeException __bc_re) { throw __bc_re; }
        catch (Exception __bc_e)
        {
            throw new ControlException("Contextual service initialization failure", __bc_e);
        }
    }

    /**
     * Resets all nested contextual services instances to null
     */
    public void resetServices(ControlBean bean, Object target)
    {
        $impl.className __bc_impl = ($impl.className)target;

        super.resetServices(bean, __bc_impl);

        try
        {
            #foreach ($context in $impl.contexts)
                #resetContext($context)
            #end
        }
        catch (RuntimeException __bc_re) { throw __bc_re; }
        catch (Exception __bc_e)
        {
            throw new ControlException("Contextual service reset failure", __bc_e);
        }
    }
#end
##
## This macro defines the initialization method for all nested control references
##
#macro (declareControlsInit)
    /**
     * Initializes the nested client event proxies required by the implementation
     */
    public void initControls(ControlBean bean, Object target)
    {
        $impl.className __bc_impl = ($impl.className)target;
        // DO NOT DELEGATE TO SUPERCLASS HERE.  THE CONTROL CLIENT INIT HIERARCHY
        // WILL INITIALIZE ALL THE WAY DOWN TO THE BASE CLASS!

        try
        {
            ${init.clientInitializerName}.initialize(bean.getControlBeanContext(), __bc_impl);
        }
        catch (RuntimeException __bc_re) { throw __bc_re; }
        catch (Exception __bc_e)
        {
            throw new ControlException("Client event proxy initialization failure", __bc_e);
        }
    }
#end
##
## This macro defines the initialization method for all nested event proxies
##
#macro (declareEventProxyInit)
    /**
     * Initializes the nested client event proxies required by the implementation
     */
    public void initEventProxies(ControlBean bean, Object target)
    {
        $impl.className __bc_impl = ($impl.className)target;

        super.initEventProxies(bean, __bc_impl);

        try
        {
            #foreach ($proxy in $impl.clients)
                #initEventProxy($proxy)
            #end
        }
        catch (RuntimeException __bc_re) { throw __bc_re; }
        catch (Exception __bc_e)
        {
            throw new ControlException("Client event proxy initialization failure", __bc_e);
        }
    }
#end
##
## THE CONTROL INITIALIZER CLASS TEMPLATE
##
#if (!$init.isRootPackage())
package $init.package;
#end

import java.lang.reflect.Field;
import org.apache.beehive.controls.api.ControlException;
import org.apache.beehive.controls.api.context.ControlBeanContext;
import org.apache.beehive.controls.runtime.bean.ControlBean;

@SuppressWarnings("all")
public class $init.shortName
    #if ($init.hasSuperClass())
             extends $init.superClass.className 
    #else
             extends org.apache.beehive.controls.runtime.bean.ImplInitializer
    #end
{
    #if ($init.reflectFields.size() != 0)
        #declareReflectFields()
        static
        {
            #initReflectFields()
        }
    #end

    #if ($impl.hasContexts() || $impl.hasClients())
        #declareEventAdaptors()
    #end

    #if ($impl.hasContexts()) 
        #declareServiceInit()
    #end

    #if ($impl.hasControls()) 
        #declareControlsInit()
    #end

    #if ($impl.hasClients())
        #declareEventProxyInit()
    #end
}
