RequestHandler

Package: MachII.framework
Handles request to event conversion for the framework. The framework workhorse and controls the event-queue functionality.
Method Summary
public RequestHandler init(AppManager appManager, string eventParameter, string parameterPrecedence, string moduleDelimiter, numeric maxEvents)

Initializes the RequestHandler.

public Exception createException([string type=""], [string message=""], [string errorCode=""], [string detail=""], [string extendedInfo=""], [array tagContext="#ArrayNew(1)#"])

Creates an exception object (with no cfcatch).

private AppManager getAppManager()
public EventContext getEventContext()
public numeric getEventCount()

Returns the number of events that have been processed for this context.

private string getEventParameter()
private SizedQueue getEventQueue()
private string getIsException()
private boolean getIsProcessing()
private numeric getMaxEvents()
private string getModuleDelimiter()
private string getParameterPrecedence()
private struct getRequestEventArgs()

Builds a struct of incoming event args.

public string getRequestEventName()
public string getRequestModuleName()
private void handleEvent(Event event)

Handles the current event.

private void handleNextEvent()

Handles the next event in the queue.

public void handleRequest()

Handles a request made to the framework.

private boolean hasMoreEvents()

Checks if there are more events in the queue.

private void incrementEventCount()

Increments the current event count by 1.

private struct parseEventParameter(struct eventArgs)

Gets the module and event name from the incoming event arg struct.

private void processEvents()

Begins processing of queued events. Can only be called once.

private void resetEventCount()

Reset the current event count.

private void setAppManager(AppManager appManager)
private void setEventContext(EventContext eventContext)
private void setEventParameter(string eventParameter)
private void setEventQueue(SizedQueue eventQueue)
private void setIsException(boolean isException)
private void setIsProcessing(boolean isProcessing)
private void setMaxEvents(numeric maxEvents)
private void setModuleDelimiter(string moduleDelimiter)
private void setParameterPrecedence(string parameterPrecedence)
private void setRequestEventName(string requestEventName)
private void setRequestModuleName(string requestModuleName)
private void setupEventContext(AppManager appManager, [any currentEvent=""])

Setup an EventContext instance.

public Exception wrapException(any caughtException)

Creates an exception object (with cfcatch).

Method Detail
createException

public Exception createException( [string type=""], [string message=""], [string errorCode=""], [string detail=""], [string extendedInfo=""], [array tagContext="#ArrayNew(1)#"] )

Creates an exception object (with no cfcatch).

Parameters:
[string type=""]
[string message=""]
[string errorCode=""]
[string detail=""]
[string extendedInfo=""]
[array tagContext="#ArrayNew(1)#"]

Code:

	<cffunction name="createException" access="public" returntype="MachII.util.Exception" output="false"
		hint="Creates an exception object (with no cfcatch).">
		<cfargument name="type" type="string" required="false" default="" />
		<cfargument name="message" type="string" required="false" default="" />
		<cfargument name="errorCode" type="string" required="false" default="" />
		<cfargument name="detail" type="string" required="false" default="" />
		<cfargument name="extendedInfo" type="string" required="false" default="" />
		<cfargument name="tagContext" type="array" required="false" default="#ArrayNew(1)#" />
		
		<cfset var exception = CreateObject("component", "MachII.util.Exception").init(arguments.type, arguments.message, arguments.errorCode, arguments.detail, arguments.extendedInfo, arguments.tagContext) />
		<cfif NOT getIsException()>
			<cfset resetEventCount() />
		</cfif>
		<cfset setIsException(true) />
		
		<cfreturn exception />
	</cffunction> 

getAppManager

private AppManager getAppManager( )

Parameters:

Code:

	<cffunction name="getAppManager" access="private" returntype="MachII.framework.AppManager" output="false">
		<cfreturn variables.appManager />
	</cffunction> 

getEventContext

public EventContext getEventContext( )

Parameters:

Code:

	<cffunction name="getEventContext" access="public" returntype="MachII.framework.EventContext" output="false">
		<cfreturn variables.eventContext />
	</cffunction> 

getEventCount

public numeric getEventCount( )

Returns the number of events that have been processed for this context.

Parameters:

Code:

	<cffunction name="getEventCount" access="public" returntype="numeric" output="false"
		hint="Returns the number of events that have been processed for this context.">
		<cfreturn variables.eventCount />
	</cffunction> 

getEventParameter

private string getEventParameter( )

Parameters:

Code:

	<cffunction name="getEventParameter" access="private" returntype="string" output="false">
		<cfreturn variables.eventParameter />
	</cffunction> 

getEventQueue

private SizedQueue getEventQueue( )

Parameters:

Code:

	<cffunction name="getEventQueue" access="private" returntype="MachII.util.SizedQueue" output="false">
		<cfreturn variables.eventQueue />
	</cffunction> 

getIsException

private string getIsException( )

Parameters:

Code:

	<cffunction name="getIsException" access="private" returntype="string" output="false">
		<cfreturn variables.isException />
	</cffunction> 

getIsProcessing

private boolean getIsProcessing( )

Parameters:

Code:

	<cffunction name="getIsProcessing" access="private" returntype="boolean" output="false">
		<cfreturn variables.isProcessing />
	</cffunction> 

getMaxEvents

private numeric getMaxEvents( )

Parameters:

Code:

	<cffunction name="getMaxEvents" access="private" returntype="numeric" output="false">
		<cfreturn variables.maxEvents />
	</cffunction> 

getModuleDelimiter

private string getModuleDelimiter( )

Parameters:

Code:

	<cffunction name="getModuleDelimiter" access="private" returntype="string" output="false">
		<cfreturn variables.moduleDelimiter />
	</cffunction> 

getParameterPrecedence

private string getParameterPrecedence( )

Parameters:

Code:

	<cffunction name="getParameterPrecedence" access="private" returntype="string" output="false">
		<cfreturn variables.parameterPrecedence />
	</cffunction> 

getRequestEventArgs

private struct getRequestEventArgs( )

Builds a struct of incoming event args.

Parameters:

Code:

	<cffunction name="getRequestEventArgs" access="private" returntype="struct" output="false"
		hint="Builds a struct of incoming event args.">
		<cfset var eventArgs = StructNew() />
		<cfset var overwriteFormParams = (getParameterPrecedence() EQ "url") />
		
		
		<cfset StructAppend(eventArgs, form) />
		<cfset StructAppend(eventArgs, url, overwriteFormParams) />
		<cfset StructAppend(eventArgs, getAppManager().getRequestManager().parseSesParameters(cgi.PATH_INFO), overwriteFormParams) />
		
		
		<cfset StructAppend(eventArgs, getAppManager().getRequestManager().readPersistEventData(eventArgs), true) />
		
		<cfreturn eventArgs />
	</cffunction> 

getRequestEventName

public string getRequestEventName( )

Parameters:

Code:

	<cffunction name="getRequestEventName" access="public" returntype="string" output="false">
		<cfreturn variables.requestEventName />
	</cffunction> 

getRequestModuleName

public string getRequestModuleName( )

Parameters:

Code:

	<cffunction name="getRequestModuleName" access="public" returntype="string" output="false">
		<cfreturn variables.requestModuleName />
	</cffunction> 

handleEvent

private void handleEvent( Event event )

Handles the current event.

Parameters:
Event event

Code:

	<cffunction name="handleEvent" access="private" returntype="void" output="true"
		hint="Handles the current event.">
		<cfargument name="event" type="MachII.framework.Event" required="true" />
		
		<cfset var eventHandler = 0 />
		<cfset var topAppManager = 0 />
		<cfset var thisEventAppManager = 0 />
		
		<cfif IsObject(getAppManager().getParent())>
			<cfset topAppManager = getAppManager().getParent() />
		<cfelse>
			<cfset topAppManager = getAppManager() />
		</cfif>
		
		<cfif Len(arguments.event.getModuleName())>
			<cfset thisEventAppManager = topAppManager.getModuleManager().getModule(arguments.event.getModuleName()).getModuleAppManager() />
		<cfelse>
			<cfset thisEventAppManager = topAppManager />
		</cfif>
		
		<cfset setupEventContext(thisEventAppManager, arguments.event) />
		<cfset request.event = arguments.event />
		
		
		<cfset thisEventAppManager.getPluginManager().preEvent(getEventContext()) />

		
		<cfset eventHandler = thisEventAppManager.getEventManager().getEventHandler(arguments.event.getName(), arguments.event.getModuleName()) />		
		<cfset eventHandler.handleEvent(arguments.event, getEventContext()) />
		
		
		<cfset thisEventAppManager.getPluginManager().postEvent(getEventContext()) />
	</cffunction> 

handleNextEvent

private void handleNextEvent( )

Handles the next event in the queue.

Parameters:

Code:

	<cffunction name="handleNextEvent" access="private" returntype="void" output="true"
		hint="Handles the next event in the queue.">
		<cfset var exception = 0 />
		
		<cftry>
			<cfset incrementEventCount() />
			<cfset handleEvent(getEventQueue().get()) />
			
			<cfcatch type="AbortEventException">
				
			</cfcatch>
			<cfcatch type="any">
				<cfif getIsException()>
					<cfrethrow />
				<cfelse>
					<cfset exception = wrapException(cfcatch) />
					<cfset getEventContext().handleException(exception, true) />
				</cfif>
			</cfcatch>
		</cftry>
	</cffunction> 

handleRequest

public void handleRequest( )

Handles a request made to the framework.

Parameters:

Code:

	<cffunction name="handleRequest" access="public" returntype="void" output="true"
		hint="Handles a request made to the framework.">
		
		<cfset var eventArgs = getRequestEventArgs() />
		<cfset var result = parseEventParameter(eventArgs) />
		<cfset var appManager = getAppManager() />
		<cfset var moduleManager = getAppManager().getModuleManager() />
		<cfset var nextEvent = "" />
		<cfset var exception = "" />
		
		<cfset setRequestEventName(result.eventName) />
		<cfset setRequestModuleName(result.moduleName) />
		<cfset setupEventContext(appManager) />
		
		<cftry>
			
			<cfif Len(result.moduleName)>
				<cfif NOT moduleManager.isModuleDefined(result.moduleName)>
					<cfthrow type="MachII.framework.ModuleNotDefined"  	
						message="The module '#result.moduleName#' for event '#result.eventName#' is not defined." />
				<cfelse>
					<cfset appManager = appManager.getModuleManager().getModule(result.moduleName).getModuleAppManager() />
				</cfif>
			</cfif>
			
			
			<cfif NOT appManager.getEventManager().isEventDefined(result.eventName, false)>
				<cfthrow type="MachII.framework.EventHandlerNotDefined" 
					message="Event-handler for event '#result.eventName#', module '#result.moduleName#' is not defined." />
			<cfelseif NOT appManager.getEventManager().isEventPublic(result.eventName, false)>
				<cfthrow type="MachII.framework.EventHandlerNotAccessible" 
					message="Event-handler for event '#result.eventName#', module '#result.moduleName#' is not accessible." />
			</cfif>
			
			
			<cfset nextEvent = appManager.getEventManager().createEvent(result.moduleName, result.eventName, eventArgs, result.eventName, result.moduleName) />
			<cfset getEventQueue().put(nextEvent) />
			<cfset setupEventContext(appManager, nextEvent) />
			
			
			<cfcatch type="any">
				
				<cfset setupEventContext(appManager) />
				<cfset exception = wrapException(cfcatch) />
				<cfset getEventContext().handleException(exception, true) />
			</cfcatch>
		</cftry>
		
		
		<cfset processEvents() />
	</cffunction> 

hasMoreEvents

private boolean hasMoreEvents( )

Checks if there are more events in the queue.

Parameters:

Code:

	<cffunction name="hasMoreEvents" access="private" returntype="boolean" output="false"
		hint="Checks if there are more events in the queue.">
		<cfreturn NOT getEventQueue().isEmpty() />
	</cffunction> 

incrementEventCount

private void incrementEventCount( )

Increments the current event count by 1.

Parameters:

Code:

	<cffunction name="incrementEventCount" access="private" returntype="void" output="false"
		hint="Increments the current event count by 1.">
		<cfset variables.eventCount = variables.eventCount + 1 />
	</cffunction> 

init

public RequestHandler init( AppManager appManager, string eventParameter, string parameterPrecedence, string moduleDelimiter, numeric maxEvents )

Initializes the RequestHandler.

Parameters:
AppManager appManager
string eventParameter
string parameterPrecedence
string moduleDelimiter
numeric maxEvents

Code:

	<cffunction name="init" access="public" returntype="RequestHandler" output="false"
		hint="Initializes the RequestHandler.">
		<cfargument name="appManager" type="MachII.framework.AppManager" required="true" />
		<cfargument name="eventParameter" type="string" required="true" />
		<cfargument name="parameterPrecedence" type="string" required="true" />
		<cfargument name="moduleDelimiter" type="string" required="true" />
		<cfargument name="maxEvents" type="numeric" required="true" />
		
		<cfset setAppManager(arguments.appManager) />
		<cfset setEventParameter(arguments.eventParameter) />
		<cfset setModuleDelimiter(arguments.moduleDelimiter) />
		<cfset setMaxEvents(arguments.maxEvents) />
		
		
		<cfset setEventQueue(CreateObject("component", "MachII.util.SizedQueue").init(getMaxEvents())) />
				
		
		<cfset setEventContext(CreateObject("component", "MachII.framework.EventContext").init(this, getEventQueue())) />
		
		
		<cfset request.eventContext = getEventContext() />
		
		<cfreturn this />
	</cffunction> 

parseEventParameter

private struct parseEventParameter( struct eventArgs )

Gets the module and event name from the incoming event arg struct.

Parameters:
struct eventArgs

Code:

	<cffunction name="parseEventParameter" access="private" returntype="struct" output="false"
		hint="Gets the module and event name from the incoming event arg struct.">
		<cfargument name="eventArgs" type="struct" required="true" />
		
		<cfset var rawEvent = "" />
		<cfset var eventParameter = getEventParameter() />
		<cfset var moduleDelimiter = getModuleDelimiter() />
		<cfset var result = StructNew() />
		
		
		<cfif StructKeyExists(arguments.eventArgs, eventParameter) AND Len(arguments.eventArgs[eventParameter])>
		
			<cfset rawEvent = arguments.eventArgs[eventParameter] />
		
			
			<cfif listLen(rawEvent, moduleDelimiter) eq 2>
				<cfset result.moduleName = listGetAt(rawEvent, 1, moduleDelimiter) />
				<cfset result.eventName = listGetAt(rawEvent, 2, moduleDelimiter) />
			
			<cfelseif listLen(rawEvent, moduleDelimiter) eq 1 AND Right(rawEvent, 1) eq moduleDelimiter>
				<cfset result.moduleName = listGetAt(rawEvent, 1, moduleDelimiter) />
				<cfset result.eventName = getAppManager().getModuleManager().getModule(result.moduleName).getModuleAppManager().getPropertyManager().getProperty("defaultEvent") />			
			
			<cfelse>
				<cfset result.moduleName = "" />
				<cfset result.eventName = rawEvent />
			</cfif>
		
		<cfelse>
			<cfset result.moduleName = "" />
			<cfset result.eventName = getAppManager().getPropertyManager().getProperty("defaultEvent") />
		</cfif>
		
		<cfreturn result />
	</cffunction> 

processEvents

private void processEvents( )

Begins processing of queued events. Can only be called once.

Parameters:

Code:

	<cffunction name="processEvents" access="private" returntype="void" output="true"
		hint="Begins processing of queued events. Can only be called once.">
	
		<cfset var pluginManager = "" />
		<cfset var exception = "" />
		
		<cfif getIsProcessing()>
			<cfthrow message="The RequestHandler is already processing the events in the queue. The processEvents() method can only be called once." />
		</cfif>
		<cfset setIsProcessing(true) />
		
		<cfset pluginManager = getEventContext().getAppManager().getPluginManager() />
	
		
		<cfset pluginManager.preProcess(getEventContext()) />
		
		<cfloop condition="hasMoreEvents() AND getEventCount() LT getMaxEvents()">
			<cfset handleNextEvent() />
		</cfloop>
		
		
		<cfif NOT getIsException() AND hasMoreEvents()>
			<cfset exception = createException("MachII.framework.MaxEventsExceeded", "The maximum number of events (#getMaxEvents()#) the framework will process for a single request has been exceeded.") />
			<cfset getEventContext().handleException(exception, true) />
			
			
			<cfset resetEventCount() />
			
			<cfloop condition="hasMoreEvents() AND getEventCount() LT getMaxEvents()">
				<cfset handleNextEvent() />
			</cfloop>
			
			<cfif hasMoreEvents()>
				<cfthrow
					type="MachII.framework.MaxEventsExceededDuringException"
					message="The maximum number of events (#getMaxEvents()#) has been exceeded. An exception was generated, but the maximum number of events was exceeded again during the handling of the exception."
					detail="Please check your exception handling since it initiated an infinite loop." />
			</cfif>
		
		<cfelseif getIsException() AND hasMoreEvents()>
			<cfset exception = getEventContext().getCurrentEvent().getArg("exception").getCaughtException() />
			<cfthrow
				type="MachII.framework.MaxEventsExceededDuringException"
				message="The maximum number of events (#getMaxEvents()#) has been exceeded. An exception was generated, but the maximum number of events was exceeded again during the handling of the exception."
				detail="The last exception was '#exception.detail#' which occurred on line #exception.tagContext[1].line# in '#exception.tagContext[1].template#'." />
		</cfif>
		
		
		<cfset pluginManager = getEventContext().getAppManager().getPluginManager() />
		<cfset pluginManager.postProcess(getEventContext()) />
		
		<cfset setIsProcessing(false) />
	</cffunction> 

resetEventCount

private void resetEventCount( )

Reset the current event count.

Parameters:

Code:

	<cffunction name="resetEventCount" access="private" returntype="void" output="false"
		hint="Reset the current event count.">
		<cfset variables.eventCount = 0 />
	</cffunction> 

setAppManager

private void setAppManager( AppManager appManager )

Parameters:
AppManager appManager

Code:

	<cffunction name="setAppManager" access="private" returntype="void" output="false">
		<cfargument name="appManager" type="MachII.framework.AppManager" required="true" />
		<cfset variables.appManager = arguments.appManager />
	</cffunction> 

setEventContext

private void setEventContext( EventContext eventContext )

Parameters:
EventContext eventContext

Code:

	<cffunction name="setEventContext" access="private" returntype="void" output="false">
		<cfargument name="eventContext" type="MachII.framework.EventContext" required="true" />
		<cfset variables.eventContext = arguments.eventContext />
	</cffunction> 

setEventParameter

private void setEventParameter( string eventParameter )

Parameters:
string eventParameter

Code:

	<cffunction name="setEventParameter" access="private" returntype="void" output="false">
		<cfargument name="eventParameter" type="string" required="true" />
		<cfset variables.eventParameter = arguments.eventParameter />
	</cffunction> 

setEventQueue

private void setEventQueue( SizedQueue eventQueue )

Parameters:
SizedQueue eventQueue

Code:

	<cffunction name="setEventQueue" access="private" returntype="void" output="false">
		<cfargument name="eventQueue" type="MachII.util.SizedQueue" required="true" />
		<cfset variables.eventQueue = arguments.eventQueue />
	</cffunction> 

setIsException

private void setIsException( boolean isException )

Parameters:
boolean isException

Code:

	<cffunction name="setIsException" access="private" returntype="void" output="false">
		<cfargument name="isException" type="boolean" required="true" />
		<cfset variables.isException = arguments.isException />
	</cffunction> 

setIsProcessing

private void setIsProcessing( boolean isProcessing )

Parameters:
boolean isProcessing

Code:

	<cffunction name="setIsProcessing" access="private" returntype="void" output="false">
		<cfargument name="isProcessing" type="boolean" required="true" />
		<cfset variables.isProcessing = arguments.isProcessing />
	</cffunction> 

setMaxEvents

private void setMaxEvents( numeric maxEvents )

Parameters:
numeric maxEvents

Code:

	<cffunction name="setMaxEvents" access="private" returntype="void" output="false">
		<cfargument name="maxEvents" required="true" type="numeric" />
		<cfset variables.maxEvents = arguments.maxEvents />
	</cffunction> 

setModuleDelimiter

private void setModuleDelimiter( string moduleDelimiter )

Parameters:
string moduleDelimiter

Code:

	<cffunction name="setModuleDelimiter" access="private" returntype="void" output="false">
		<cfargument name="moduleDelimiter" type="string" required="true" />
		<cfset variables.moduleDelimiter = arguments.moduleDelimiter />
	</cffunction> 

setParameterPrecedence

private void setParameterPrecedence( string parameterPrecedence )

Parameters:
string parameterPrecedence

Code:

	<cffunction name="setParameterPrecedence" access="private" returntype="void" output="false">
		<cfargument name="parameterPrecedence" type="string" required="true" />
		<cfset variables.parameterPrecedence = arguments.parameterPrecedencerameter />
	</cffunction> 

setRequestEventName

private void setRequestEventName( string requestEventName )

Parameters:
string requestEventName

Code:

	<cffunction name="setRequestEventName" access="private" returntype="void" output="false">
		<cfargument name="requestEventName" type="string" required="true" />
		<cfset variables.requestEventName = arguments.requestEventName />
	</cffunction> 

setRequestModuleName

private void setRequestModuleName( string requestModuleName )

Parameters:
string requestModuleName

Code:

	<cffunction name="setRequestModuleName" access="private" returntype="void" output="false">
		<cfargument name="requestModuleName" type="string" required="true" />
		<cfset variables.requestModuleName = arguments.requestModuleName />
	</cffunction> 

setupEventContext

private void setupEventContext( AppManager appManager, [any currentEvent=""] )

Setup an EventContext instance.

Parameters:
AppManager appManager
[any currentEvent=""]

Code:

	<cffunction name="setupEventContext" access="private" returntype="void" output="false"
		hint="Setup an EventContext instance.">
		<cfargument name="appManager" type="MachII.framework.AppManager" required="true" />
		<cfargument name="currentEvent" type="any" required="false" default="" />
		<cfset getEventContext().setup(arguments.appManager, arguments.currentEvent) />
	</cffunction> 

wrapException

public Exception wrapException( any caughtException )

Creates an exception object (with cfcatch).

Parameters:
any caughtException

Code:

	<cffunction name="wrapException" access="public" returntype="MachII.util.Exception" output="false"
		hint="Creates an exception object (with cfcatch).">
		<cfargument name="caughtException" type="any" required="true" />
		
		<cfset var exception = CreateObject("component", "MachII.util.Exception").wrapException(arguments.caughtException) />
		<cfif NOT getIsException()>
			<cfset resetEventCount() />
		</cfif>
		<cfset setIsException(true) />
		
		<cfreturn exception />
	</cffunction>