<#--
   ******************************************************
   *
   *                       NOTICE
   *
   *  THIS SOFTWARE IS THE PROPERTY OF AND CONTAINS
   *  CONFIDENTIAL INFORMATION OF INFOR, AND SHALL NOT BE
   *  COPIED, USED, NOR DISCLOSED WITHOUT EXPRESS WRITTEN
   *  AUTHORIZATION.  ALTHOUGH PUBLICATION IS NOT
   *  INTENDED, IN THE EVENT OF PUBLICATION, THE
   *  FOLLOWING NOTICE IS APPLICABLE:
   *
   *  Copyright © 2009 Infor. All rights reserved.
   *  The word and design marks set forth herein are
   *  trademarks and/or registered trademarks of Infor
   *  and/or related affiliates and subsidiaries.
   *  All rights reserved. All other trademarks listed
   *  herein are the property of their respective owners.
   *  www.infor.com.
   *
   ******************************************************
  -->

<#-- If an 'include hook' exists, then the hook can contain defines, functions or includes
     to be used in other hooks. The hook contents for this hook is simply included here.
     This hook is used to solve the following problems:
     1  In a hook you cannot declare functions (because it will generate a function within
        a function, which results in compilation errors).
     2  You cannot reuse the same logic in multiple hooks (except by creating a library in ERP LN).
     3  In some cases you cannot use the same include in multiple hooks. The reason is that the
        include is only included in the first hook and skipped for the next hook(s).
        Normally this is not a problem, but if in one of the defines from the include a variable
        is used, that variable is unknown in the second hook, because it will be included as a
        local variable in the first hook.
-->
<#if object.includeHookExpression?exists && object.includeHookExpression?has_content>
|------------------------------ Include Hook ----------------------------------
#context_on "HOOK:includeHook"

${object.includeHookExpression}

#context_off
|------------------------------ End of Include Hook ----------------------------
</#if><#--object.includeHookExpression?exists && object.includeHookExpression?has_content-->
<#list protected.listProtectedComponents() as c>
	<#list c.componentImplementation.attributeImplementation as ai>
		<#assign fieldname = c.componentName + "." + common.getAttributeName(ai)>
		<#assign fieldattributename = common.getAttributeName(ai)>
		<#assign domain = common.getDatatypeName(common.getDatatype(ai))>
		<#-- OnGet -->
		<#if ai.onGetHookExpression?exists && ai.onGetHookExpression?has_content>
#context_on "HOOK:onGetHook; ATTRIBUTE:${fieldname}"
function long Hook.OnGet.${fieldname}(
			<@printHookArguments iAttributeImplementation=ai/>
			<@printHookOutputs iAttributeImplementation=ai iDomain=domain iFieldName=fieldattributename iIO=false iWithConversionInput=false/>
{
			<@printIsSetDefaults iAttributeImplementation=ai iFieldName=fieldattributename iName=fieldname/>
	<#-- Hook content... -->
${ai.onGetHookExpression}
}
#context_off
		</#if>
		<#if ai.onSetHookExpression?exists && ai.onSetHookExpression?has_content>
#context_on "HOOK:onSetHook; ATTRIBUTE:${fieldname}"
function long Hook.OnSet.${fieldname}(
			<@printHookArguments iAttributeImplementation=ai/>
			<@printHookOutputs iAttributeImplementation=ai iDomain=domain iFieldName=fieldattributename iIO=false iWithConversionInput=false/>
{
			<@printIsSetDefaults iAttributeImplementation=ai iFieldName=fieldattributename iName=fieldname/>
	<#-- Hook content... -->
${ai.onSetHookExpression}
}
#context_off
		</#if>
		<#if ai.beforeSetHookExpression?exists && ai.beforeSetHookExpression?has_content>
#context_on "HOOK:beforeSetHook; ATTRIBUTE:${fieldname}"
function long Hook.BeforeSet.${fieldname}(
			<@printHookArguments iAttributeImplementation=ai/>
<#if common.getMandatoryDatatype(ai).dimensions?exists && common.getMandatoryDatatype(ai).dimensions?number == 0>
		long	i.size,
</#if>
	ref boolean	io.cancel)
{
	<#-- Hook content... -->
${ai.beforeSetHookExpression}
}
#context_off
		</#if>
		<#if ai.afterSetHookExpression?exists && ai.afterSetHookExpression?has_content>
#context_on "HOOK:afterSetHook; ATTRIBUTE:${fieldname}"
function long Hook.AfterSet.${fieldname}(
			<@printHookArguments iAttributeImplementation=ai/>
			<#if common.getMandatoryDatatype(ai).dimensions?exists>
	ref	domain ${domain}	i.${fieldattributename}(),
				<#if common.getMandatoryDatatype(ai).dimensions?exists && common.getMandatoryDatatype(ai).dimensions?number == 0>
	ref	boolean				i.${fieldattributename}.isSet(),
		long	i.size)
				<#else>
	ref	boolean				i.${fieldattributename}.isSet())
				</#if>
			<#else>
		domain ${domain}	i.${fieldattributename},
		boolean				i.${fieldattributename}.isSet)
			</#if><#--if common.getMandatoryDatatype(ai).dimensions?exists-->
{
	<#-- Hook content... -->
${ai.afterSetHookExpression}
}
#context_off
		</#if>
		<#if ai.beforeGetHookExpression?exists && ai.beforeGetHookExpression?has_content>
#context_on "HOOK:beforeGetHook; ATTRIBUTE:${fieldname}"
function long Hook.BeforeGet.${fieldname}(
			<@printHookArguments iAttributeImplementation=ai/>
	ref boolean	io.cancel)
{
	io.cancel = false
	<#-- Hook content... -->
${ai.beforeGetHookExpression}
}
#context_off
		</#if>
		<#if ai.afterGetHookExpression?exists && ai.afterGetHookExpression?has_content>
#context_on "HOOK:afterGetHook; ATTRIBUTE:${fieldname}"
function long Hook.AfterGet.${fieldname}(
			<@printHookArguments iAttributeImplementation=ai/>
			<#if common.getMandatoryDatatype(ai).dimensions?exists>
	ref	domain ${domain}	i.${fieldattributename}(),
	ref	boolean				i.${fieldattributename}.isSet())
			<#else>
		domain ${domain}	i.${fieldattributename},
		boolean				i.${fieldattributename}.isSet)
			</#if><#--if common.getMandatoryDatatype(ai).dimensions?exists-->
{
	<#-- Hook content... -->
${ai.afterGetHookExpression}
}
#context_off
		</#if>
		<#if ai.defaultValueHookExpression?exists && ai.defaultValueHookExpression?has_content>
#context_on "HOOK:defaultValueHook; ATTRIBUTE:${fieldname}"
function long Hook.DefaultValue.${fieldname}(
			<#list protected.getAttributeHookArguments(ai) as hookarg>
				<#if hookarg.hasDimensions>
		ref domain	${hookarg.domain}	i.${hookarg.name}(),
				<#else>
			domain	${hookarg.domain}	i.${hookarg.name},
				</#if><#--if hookarg.hasDimensions-->
			</#list>
			<@printHookOutputs iAttributeImplementation=ai iDomain=domain iFieldName=fieldattributename iIO=true iWithConversionInput=false/>
{
	<#-- Hook content... -->
${ai.defaultValueHookExpression}
}
#context_off

		</#if>
		<#if ai.conversionSetHookExpression?exists && ai.conversionSetHookExpression?has_content>
#context_on "HOOK:conversionSetHook; ATTRIBUTE:${fieldname}"
function extern long <@names.ST_DLLCode/>.Hook.ConversionSet.${fieldname}(
			<@printHookOutputs iAttributeImplementation=ai iDomain=domain iFieldName=fieldattributename iIO=false iWithConversionInput=true/>
{
	<#-- Hook content... -->
${ai.conversionSetHookExpression}
}
#context_off
		</#if>
		<#if ai.conversionGetHookExpression?exists && ai.conversionGetHookExpression?has_content>
#context_on "HOOK:conversionGetHook; ATTRIBUTE:${fieldname}"
function extern long <@names.ST_DLLCode/>.Hook.ConversionGet.${fieldname}(
			<#if common.getMandatoryDatatype(ai).dimensions?exists>
	ref	domain ${domain}	i.${fieldattributename}(),
	ref string	o.${fieldattributename}(,),
				<#if common.getMandatoryDatatype(ai).dimensions?number == 0>
	ref boolean	io.${fieldattributename}.isSet(),
		long	i.${fieldattributename}.size)
				<#else>
	ref boolean	io.${fieldattributename}.isSet())
				</#if><#--if common.getMandatoryDatatype(ai).dimensions?exists-->
			<#else>
		domain ${domain}	i.${fieldattributename},
	ref string	o.${fieldattributename},
	ref boolean	io.${fieldattributename}.isSet)
			</#if><#--if common.getMandatoryDatatype(ai).dimensions?exists-->
{
	<#-- Hook content... -->
${ai.conversionGetHookExpression}
}
#context_off
		</#if>
	</#list><#--list c.componentImplementation.attributeImplementation as attributeImplementation-->
</#list><#--list protected.listProtectedComponents() as c-->
<#macro printHookArguments iAttributeImplementation>
	<#list protected.getAttributeHookArguments(iAttributeImplementation) as hookarg>
		<#if hookarg.hasDimensions>
	ref domain	${hookarg.domain}	i.${hookarg.name}(),
	ref boolean			i.${hookarg.name}.isSet(),
			<#if hookarg.hasDynamicDimensions>
		long			i.${hookarg.name}.size,
			</#if>
		<#else>
		domain	${hookarg.domain}	i.${hookarg.name},
		boolean			i.${hookarg.name}.isSet,
		</#if><#--if hookarg.hasDimensions-->
	</#list>
</#macro><#--printHookArguments-->
<#macro printHookOutputs iAttributeImplementation iDomain iFieldName iIO iWithConversionInput>
	<#if iIO>
		<#assign prefix="io">
	<#else>
		<#assign prefix="o">
	</#if>
	<#if common.getMandatoryDatatype(iAttributeImplementation).dimensions?exists>
		<#if iWithConversionInput>
	ref string 	i.${iFieldName}(,),
		</#if>
		<#if common.getMandatoryDatatype(iAttributeImplementation).dimensions?number == 0>
			<#if iIO>
	ref domain	${iDomain}	io.${iFieldName}(),
	ref boolean	io.${iFieldName}.isSet(),
	ref long	io.${iFieldName}.size)
			<#else>
	ref domain	${iDomain}	o.${iFieldName}(),
	ref boolean	o.${iFieldName}.isSet(),
	ref long	o.${iFieldName}.size)
			</#if>
		<#else>
	ref domain	${iDomain}	${prefix}.${iFieldName}(),
	ref boolean	io.${iFieldName}.isSet())
		</#if>
	<#else>
		<#if iWithConversionInput>
	const string 	i.${iFieldName},
		</#if>
	ref domain	${iDomain}	${prefix}.${iFieldName},
	ref boolean	io.${iFieldName}.isSet)
	</#if><#--if common.getMandatoryDatatype(iAttributeImplementation).dimensions?exists-->
</#macro><#--printHookOutputs-->
<#macro printIsSetDefaults iAttributeImplementation iFieldName iName>
	<#if common.getMandatoryDatatype(iAttributeImplementation).dimensions?exists>
long	duml

		<#if common.getMandatoryDatatype(iAttributeImplementation).dimensions?number == 0>
o.${iFieldName}.size = 0
| Arrays o.${iFieldName} and o.${iFieldName}.isSet must be allocated and filled within this hook.
| o.${iFieldName}.size must be set to the size of these arrays.

		<#else>
duml = set.mem(io.${iFieldName}.isSet, true)
		</#if>

	<#else>
io.${iFieldName}.isSet = true

	</#if>
</#macro>
<#macro funHookArgs iHookType iMethodName iComponentName iCloseBracket=false>
<#assign hasHookArguments = false>
<#list protected.getMethodHookArguments(iHookType, iMethodName, iComponentName) as hookarg>
	<#assign hasHookArguments = true>
	<#if (iHookType == "on" && hookarg.scope?contains("out"))>
		<#assign line1="ref domain	">
		<#if hookarg.scope = "out">
			<#assign pref=" o.">
		<#else>
			<#assign pref="io.">
		</#if>
		<#assign line2="ref		boolean		">
		<#assign line3="ref		long		">
	<#else>
		<#assign pref=" i.">
		<#assign line1="    domain	">
		<#assign line2="		boolean		">
		<#assign line3="		long		">
	</#if>
	<#if hookarg.hasDimensions>
		<#assign line1="ref domain	">
		<#assign line2="ref		boolean		">
	</#if><#-- if hookarg.hasDimensions-->
	<#assign line1=line1+hookarg.domain+"	">
	<#if hookarg.hasDimensions>
		<#assign line1=line1+pref+hookarg.name+"()">
		<#assign line2=line2+pref+hookarg.name+".isSet()">
		<#assign line3=line3+pref+hookarg.name+".size">
	<#else>
		<#assign line1=line1+pref+hookarg.name>
		<#assign line2=line2+pref+hookarg.name+".isSet">
	</#if><#--if hookarg.hasDimensions-->
		${line1},
	<#if hookarg.hasDynamicDimensions>
		${line2},
		<#assign line2=line3>
	</#if><#--if hookarg.hasDynamicDimensions-->
	<#if iCloseBracket && !hookarg_has_next>
		${line2})
	<#else>
		<#if iHookType == "before" || iHookType =="on" || hookarg_has_next>
		${line2},
		<#else>
		${line2}
		</#if>
	</#if><#--if iCloseBracket && !hookarg_has_next-->
</#list><#--list hooklist(iMethodName, iComponentName) as hookarg-->
<#if !hasHookArguments && iCloseBracket>
<#-- Hook does not have any arguments, so print close bracket -->
		)
</#if>
</#macro>
<#list protected.listProtectedComponents() as c>
	<#list c.componentImplementation.methodImplementation as methodImplementation>
		<#assign methodName = common.getNameFromMethodImplementation(methodImplementation)>
		<#assign meth=methodImplementation>
		<#-- keep these checks consistent with their counterparts where the incvocation of the hook in generated -->
		<#assign hooksBeforeAfterUsed=false>
		<#--generation condition for before/after execute hook call from protected.st.events-->
		<#if methodName != "SubscribeList" && methodName != "SupportsProcessingScope">
			<#if (common.isEventMethod(methodName) || methodImplementation.processingOrder == "batch") && 
			     c.componentName == names.businessInterfaceName &&
			     protected.hasMethodAlternativeImplementation(methodName)=="">
				<#assign hooksBeforeAfterUsed=true>
			</#if>
		</#if>
		<#--generation condition for before/after execute hook call from protected.st.methods-->
		<#if !hooksBeforeAfterUsed>
			<#if !common.isQueryMethod(methodName) && !common.isPublishMethod(methodName) && !common.isEventMethod(methodName) &&
		    	 methodImplementation.processingOrder != "batch" &&
		     	protected.hasMethodAlternativeImplementation(methodName)=="">
				<#assign hooksBeforeAfterUsed=true>
			</#if>
		</#if>
		<#--generation condition for before/after execute hook call from protected.st.query-->
		<#if !hooksBeforeAfterUsed>
			<#-- this check is almost identical to the previous condition, but from consistency 
				point of view the checks are not combined in one check -->
			<#if common.isQueryMethod(methodName) && !common.isPublishMethod(methodName) && !common.isEventMethod(methodName) &&
			     methodImplementation.processingOrder != "batch" &&
			     protected.hasMethodAlternativeImplementation(methodName)=="">
				<#assign hooksBeforeAfterUsed=true>
			</#if>
		</#if>
		<#if hooksBeforeAfterUsed>
			<#if protected.executeMethodHookPresent("after", meth)>
#context_on "HOOK:afterExecuteHook; Method:${c.componentName}.${methodName}"
function long Hook.AfterExecute.${c.componentName}.${methodName}(
				<#if !common.isEventMethod(methodName) && !common.isPublishMethod(methodName) && 
				     methodImplementation.processingOrder != "batch">
			<#if common.isQueryMethod(methodName)>
		<@funHookArgs iHookType="after" iMethodName=methodName iComponentName=c.componentName iCloseBracket=false/>
				,boolean 	i.anythingFetched)
			<#else>
		<@funHookArgs iHookType="after" iMethodName=methodName iComponentName=c.componentName iCloseBracket=true/>
			</#if>
				<#else>
					<#if common.isQueryMethod(methodName) && methodImplementation.processingOrder != "batch">
				boolean i.anythingFetched,
					</#if>
			const	long i.request,
			const	long i.response,
			ref	long o.result)
				</#if><#-- if !common.isEventMethod(methodName) && !common.isPublishMethod(methodName)  && 
				     methodImplementation.processingOrder != "batch"-->
{
	<#-- Hook content... -->
${meth.afterExecuteHookExpression}
}
#context_off
			</#if><#--if protected.executeMethodHookPresent("after", meth)-->
			<#if protected.executeMethodHookPresent("before", meth)>
#context_on "HOOK:beforeExecuteHook; Method:${c.componentName}.${methodName}"
function long Hook.BeforeExecute.${c.componentName}.${methodName}(
				<#if !common.isEventMethod(methodName) && !common.isPublishMethod(methodName) && 
				     methodImplementation.processingOrder != "batch">
		<@funHookArgs iHookType="before" iMethodName=methodName iComponentName=c.componentName/>
					<#if common.isQueryMethod(methodName) &&  methodImplementation.processingOrder != "batch">
		const		long		i.filter,
					</#if>
				<#else>
		const		long		i.request,
				</#if><#-- if !common.isEventMethod(methodName) && !common.isPublishMethod(methodName)  && 
				     methodImplementation.processingOrder != "batch">-->
		ref		boolean		io.cancel)
{
	<#-- Hook content... -->
	io.cancel = false
${meth.beforeExecuteHookExpression}
}
#context_off
			</#if><#-- protected.executeMethodHookPresent("before", meth) -->
		</#if><#--hooksBeforeAfterUsed-->
		<#if protected.executeMethodHookPresent("on", meth)>
#context_on "HOOK:onExecuteHook; Method:${c.componentName}.${methodName}"
function long Hook.OnExecute.${c.componentName}.${methodName}(
			<#assign hasIoDefault=protected.generateIoDefaultInOnExecuteHook(methodName, methodImplementation.processingOrder)>
			<#if !common.isEventMethod(methodName) && !common.isPublishMethod(methodName) && 
			     methodImplementation.processingOrder != "batch">
		<#assign closeBracket = !hasIoDefault && !common.isQueryMethod(methodName)>
		<@funHookArgs iHookType="on" iMethodName=methodName iComponentName=c.componentName iCloseBracket=closeBracket/>
			<#else>
		const		long		i.request,
		ref		long		o.response,
				<#if common.isEventMethod(methodName) || common.isPublishMethod(methodName) || (common.isQueryMethod(methodName) && methodImplementation.processingOrder != "batch")>
		ref		long		o.result,
				<#else>
					<#if hasIoDefault>
		ref		long		o.result,
		ref		boolean		io.default)
					<#else>
		ref		long		o.result)
					</#if><#--if hasIoDefault-->
				</#if><#--if common.isEventMethod(methodName) || common.isPublishMethod(methodName) || (common.isQueryMethod(methodName) && methodImplementation.processingOrder != "batch")-->
			</#if><#-- if !common.isEventMethod(methodName) && !common.isPublishMethod(methodName) && 
			     methodImplementation.processingOrder != "batch"> -->
			<#if methodName == "SubscribeEvent">
		ref		boolean		io.default,
		ref		string		o.suppressPublisherActions)
			<#else>
				<#if common.isQueryMethod(methodName) && methodImplementation.processingOrder != "batch">
		const		long		i.filter,
		ref		boolean		o.anythingFetched)
				<#else>
					<#if hasIoDefault>
		ref		boolean		io.default)
					</#if><#--if hasIoDefault-->
				</#if>
			</#if><#--methodName == "SubscribeEvent"-->
{
			<#if methodName == "SubscribeEvent">
				<#if object.businessInterfaceDefinition.idref.type!="bod">
| 'Internal' defines
#define getSuppressPublisherActions(event_action)	strip$(event_action)
#define getSuppressPublisherActions(event_action1, ...)	getSuppressPublisherActions(event_action1) & "|" & getSuppressPublisherActions(...)
| Defines that can be used in hook code
#define suppressStandardPublisher()	o.suppressPublisherActions = getSuppressPublisherActions("create", "change", "delete")
#define suppressStandardPublisher(...)	o.suppressPublisherActions = getSuppressPublisherActions(...)

	o.suppressPublisherActions = ""
				</#if><#--if object.businessInterfaceDefinition.idref.type!="bod"-->
			</#if><#--methodName == "SubscribeEvent"-->
			<#if (common.isEventMethod(methodName) || common.isPublishMethod(methodName)) && !(common.isQueryMethod(methodName) && methodImplementation.processingOrder != "batch")>
	io.default = false
			</#if><#--if (common.isEventMethod(methodName) || common.isPublishMethod(methodName)) && !common.isQueryMethod(methodName)-->
	<#-- Hook content... -->
${meth.onExecuteHookExpression}
			<#if methodName == "SubscribeEvent">
				<#if object.businessInterfaceDefinition.idref.type!="bod">
#undef getSuppressPublisherActions(event_action)
#undef getSuppressPublisherActions(event_action1, ...)
#undef suppressStandardPublisher()
#undef suppressStandardPublisher(...)
				</#if><#--if object.businessInterfaceDefinition.idref.type!="bod"-->
			</#if><#--methodName == "SubscribeEvent"-->
}
#context_off
		</#if><#-- if protected.executeMethodHookPresent("on", meth) -->
	</#list><#-- c.componentImplementation.methodImplementation as methodImplementation-->
</#list><#-- protected.listProtectedComponents() as c-->
<#--generate component filter hook functions-->
<#--alternatively we could also generate for all filter hooks and leave out the component name-->
<#assign counter = 0>
<#list protected.listProtectedComponents() as c>
	<#assign rootTableFound=false>
	<#list c.componentImplementation.componentImplementationTable as cit>
		<#assign counter = counter + 1>
		<#if cit.isRootTable>
			<#assign rootTableFound=true>
			<#assign rootTable=cit.table.idref>
			<#assign rootCounter=counter>
		</#if>
	</#list>
	<#if c.componentImplementation.componentFilterHookExpression?exists && c.componentImplementation.componentFilterHookExpression?has_content>
		<#--a component filter hook is defined-->
		<#assign hookReference = c.componentImplementation.componentFilterHookExpression>
#context_on "HOOK:componentFilterHook; COMPONENT:${c.componentImplementation.component.value}"
	<#--added component name to function name to avoid duplicate functions (if the same hook is used in multiple components-->
function long Hook.Filter.${c.componentImplementation.component.value}(
			ref		string		o.hookFilter)
{
	<#-- Hook content... -->
	string  Value(1024)

	if getControlAttribute("useOldQuery", Value) and
	  (tolower$(strip$(Value)) = "true" or strip$(Value) = "1") then
|start standard hook

${hookReference}

|end standard hook
	else
|start new query hook

		<#if rootTableFound>
			<#if hookReference?upper_case?contains('${rootTable.name}.'?upper_case)>
${hookReference?replace('${rootTable.name}.', 't${rootCounter}.', 'i')}
			<#else>
				<#-- Note that multiple tables can be used 
					in a component, and a single table can 
					even be linked to a component multiple 
					times, but the filter hook must only use 
					the component’s root table. If the filter 
					hook uses a table that is not equal to 
					the component’s root table then a error 
					is raised during generation of the 
					ERP LN implementation. -->
${logger.error(object, "The roottable ${rootTable.name} must be used in component filter hook for Component ${c.componentImplementation.component.value}.")}			
			</#if>
		</#if>

|end new query hook
	endif
}
#context_off
	</#if>
</#list><#--list protected.listProtectedComponents() as c-->
