Ticket #345: ModelGlue.cfc

File ModelGlue.cfc, 22.4 kB (added by da_cameron, 17 years ago)

Updated ModelGlue?.cfc file

Line 
1<!---
2LICENSE INFORMATION:
3
4Copyright 2007, Joe Rinehart
5 
6Licensed under the Apache License, Version 2.0 (the "License"); you may not
7use this file except in compliance with the License.
8
9You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12       
13Unless required by applicable law or agreed to in writing, software distributed
14under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
15CONDITIONS OF ANY KIND, either express or implied. See the License for the
16specific language governing permissions and limitations under the License.
17
18VERSION INFORMATION:
19
20This file is part of Model-Glue Model-Glue: ColdFusion (2.0.304).
21
22The version number in parenthesis is in the format versionNumber.subversion.revisionNumber.
23--->
24
25
26<cfcomponent displayname="ModelGlue" output="false" hint="I am the Model-Glue framework." extends="ModelGlue.ModelGlue">
27
28<cfset variables._beanFactory = structNew() />
29<cfset variables._stateBuilder = structNew() />
30<cfset variables._iocAdapter = "" />
31<cfset variables._beanMaker = "" />
32<cfset variables._applicationKey = "" />
33<cfset variables._useSession = true />
34<cfset variables._useORMAdapter = structNew() />
35<cfset variables._useORMAdapter.status = false />
36<cfset variables._useORMAdapter.detail = "No ORM adapter has been loaded." />
37<cfset variables._ORMAdapterName = "" />
38<cfset variables._viewRenderer = createObject("component", "ModelGlue.unity.view.ViewRenderer").init() />
39<cfset variables._listeners = createObject("component", "ModelGlue.unity.listener.ListenerRegistry").init() />
40<cfset variables._eventHandlers = createObject("component", "ModelGlue.unity.eventhandler.EventHandlerRegistry").init() />
41<cfset variables._messageBroadcaster = createObject("component", "ModelGlue.unity.eventrequest.MessageBroadcaster").init(variables._listeners) />
42<cfset variables._fakeMessage = createObject("component", "ModelGlue.unity.eventhandler.Message").init() />
43
44<cffunction name="init" returntype="ModelGlue.unity.framework.ModelGlue" access="public" hint="Constructor" output="false">
45        <cfargument name="version" type="string" required="false" />
46       
47        <cfif structKeyExists(arguments, "version")>
48                <cfset variables._version = arguments.version />
49        </cfif>
50       
51        <cfset variables._listeners.init() />
52        <cfset variables._eventHandlers.init() />
53        <cfset variables._messageBroadcaster.init(variables._listeners) />
54       
55        <cfreturn this />
56</cffunction>
57
58
59<cffunction name="getVersion" returntype="string" output="false">
60        <cfreturn variables._version />
61</cffunction>
62
63<cffunction name="setConfiguration" returntype="void" output="false" access="public">
64        <cfargument name="modelGlueConfiguration" type="ModelGlue.unity.framework.ModelGlueConfiguration" required="true" />
65        <cfset variables._config = arguments.modelGlueConfiguration.getInstance() />
66</cffunction>
67
68<cffunction name="setApplicationKey" returntype="void" output="false" access="public">
69        <cfargument name="ApplicationKey" type="string" required="true" />
70        <cfset variables._applicationKey = arguments.applicationKey />
71</cffunction>
72<cffunction name="getApplicationKey" returntype="string" output="false">
73        <cfreturn variables._applicationKey />
74</cffunction>
75
76<cffunction name="setUseSession" returntype="void" output="false" access="public">
77        <cfargument name="UseSession" type="boolean" required="true" />
78        <cfset variables._useSession = arguments.UseSession />
79</cffunction>
80<cffunction name="getUseSession" returntype="boolean" output="false">
81        <cfreturn variables._useSession />
82</cffunction>
83
84<cffunction name="setUseORMAdapter" returntype="void" output="false" access="public">
85        <cfargument name="UseORMAdapter" type="boolean" required="true" />
86        <cfargument name="Message" type="string" required="true" />
87        <cfset variables._useORMAdapter.status = arguments.UseORMAdapter />
88        <cfset variables._useORMAdapter.detail = arguments.message />
89</cffunction>
90<cffunction name="getUseORMAdapter" returntype="struct" output="false">
91        <cfreturn variables._useORMAdapter />
92</cffunction>
93
94<cffunction name="setORMAdapterName" returntype="void" output="false" access="public">
95        <cfargument name="ORMAdapterName" type="string" required="true" />
96        <cfset variables._ORMAdapterNAme = arguments.ORMAdapterName />
97</cffunction>
98<cffunction name="getORMAdapterName" returntype="string" output="false">
99        <cfreturn variables._ORMAdapterNAme />
100</cffunction>
101
102<cffunction name="setBeanFactory" returntype="void" access="public" hint="I set the bean factory for Model-Glue to use." output="false">
103        <cfargument name="beanFactory" type="any" required="true" />
104        <cfset variables._beanFactory = arguments.beanFactory />
105</cffunction>
106<cffunction name="getBeanFactory" returntype="any" access="public" hint="I get the bean factory for Model-Glue to use." output="false">
107        <cfreturn variables._beanFactory />
108</cffunction>
109
110<cffunction name="getNativeBean" returntype="any" access="public" hint="I get a ColdSpring bean from the internal configuration store." output="false">
111        <cfargument name="name" type="string" required="true" />
112       
113        <cfreturn variables._beanFactory.getBean(arguments.name) />
114</cffunction>
115
116<cffunction name="setIocContainer" returntype="void" access="public" hint="I set the bean factory for Model-Glue to use." output="false">
117        <cfargument name="IocContainer" type="ModelGlue.unity.ioc.AbstractIOCAdapter" required="true" />
118        <cfset variables._IocContainer = arguments.IocContainer />
119        <cfset variables._IocContainer.setFramework(this) />
120</cffunction>
121<cffunction name="getIocContainer" returntype="any" access="public" hint="I get the bean factory for Model-Glue to use." output="false">
122        <cfreturn variables._IocContainer />
123</cffunction>
124
125<cffunction name="getConfigBean" returntype="any" access="public" hint="I am the (deprecated) way to get a config'd bean." output="false">
126        <cfargument name="name" type="string" required="true" />
127        <cfreturn getBean(arguments.name) />
128</cffunction>
129<cffunction name="getBean" returntype="any" access="public" hint="I am the way to get a config'd bean." output="false">
130        <cfargument name="name" type="string" required="true" />
131        <cfreturn variables._iocContainer.getBean(arguments.name) />
132</cffunction>
133
134<cffunction name="setBeanMaker" returntype="void" output="false" access="public">
135        <cfargument name="BeanMaker" type="any" required="true" />
136        <cfset variables._beanMaker = arguments.BeanMaker />
137</cffunction>
138
139
140<cffunction name="setStateBuilder" returntype="void" access="public" hint="I set the bean state builder for Model-Glue to use." output="false">
141        <cfargument name="stateBuilder" type="any" required="true" />
142        <cfset variables._stateBuilder = arguments.stateBuilder />
143        <cfset variables._stateBuilder.setFramework(this) />
144</cffunction>
145<cffunction name="getStateBuilder" returntype="ModelGlue.unity.statebuilder.StateBuilder" access="private" hint="I get the state builderfor Model-Glue to use." output="false">
146        <cfreturn variables._stateBuilder />
147</cffunction>
148<!---
149<cffunction name="setOrmAdapter" returntype="any" access="public" hint="I set the ORM Adapter." output="false">
150        <cfargument name="ormAdapter" type="any" required="true" />
151        <cfset variables._ormAdapter = arguments.ormAdapter />
152</cffunction>
153--->
154<cffunction name="getOrmAdapter" returntype="any" access="public" hint="I return the ORM Adapter (abstracts multiple ORM implementations)." output="false">
155        <cfreturn getNativeBean("ORMAdapter") />
156</cffunction>
157
158<!---
159<cffunction name="setOrmService" returntype="any" access="public" hint="I set the ORM service." output="false">
160        <cfargument name="ormService" type="any" required="true" />
161        <cfset variables._ormService = arguments.ormService />
162</cffunction>
163--->
164<cffunction name="getOrmService" returntype="any" access="public" hint="I return the ORM service (the concrete ORM implemenation used)." output="false">
165        <cfreturn getNativeBean("ORMService") />
166</cffunction>
167
168<cffunction name="getConfigSetting" returntype="any" access="public" hint="I return a configuration setting." output="false">
169        <cfargument name="name" type="string" required="true" />
170       
171        <!--- In MG 1.1, there were a few screwy names that we have to carry forward.... --->
172        <cfif arguments.name eq "self">
173                <cfset arguments.name = "defaultTemplate" />
174        </cfif>
175       
176        <cfif not structKeyExists(variables._config, arguments.name)>
177                <cfthrow message="Model-Glue:  Config setting ""#arguments.name#"" is not defined." />
178        </cfif>
179       
180        <cfreturn variables._config[arguments.name] />
181</cffunction>
182
183<cffunction name="setConfigSetting" returntype="void" access="public" hint="I set a configuration setting." output="false">
184        <cfargument name="name" type="string" required="true" />
185        <cfargument name="value" type="string" required="true" />
186        <cfset variables._config[arguments.name] = arguments.value />
187</cffunction>
188
189<cffunction name="getFakeMessage" output="false" access="private">
190        <cfreturn variables._fakeMessage />
191</cffunction>
192
193<cffunction name="createStateContainer" returntype="any" access="public" hint="I build and return the state collection." output="false">
194        <cfreturn getStateBuilder().createStateContainer() />
195</cffunction>
196
197<!--- Listener management --->
198<cffunction name="addListener" returntype="void" access="public" hint="I register a given Controller instance's method to listen for a given message." output="false">
199        <cfargument name="message" type="string" required="true" />
200        <cfargument name="target" type="any" required="true" />
201        <cfargument name="method" type="string" required="true" />
202        <cfargument name="async" type="boolean" required="true" />
203        <cfset variables._listeners.addListener(arguments.message, arguments.target, arguments.method, arguments.async) />
204</cffunction>
205
206<!--- Asynchronous Support --->
207<cffunction name="AddAsyncListener" returnType="void" output="false" access="public" hint="I configure session-level async request management for a given listener.">
208        <cfargument name="message" type="string" required="true">
209
210        <cfset session._modelGlue.asyncRequests[arguments.message] = createObject("component", "ModelGlue.unity.async.AsyncRequestCollection").init() />
211</cffunction>
212
213<cffunction name="AddAsyncRequest" returnType="void" output="false" access="public" hint="I configure session-level async request management for a given listener.">
214        <cfargument name="message" type="string" required="true">
215        <cfargument name="request" type="ModelGlue.unity.async.AsyncRequest" required="true">
216
217        <cfset session._modelGlue.asyncRequests[arguments.message].add(arguments.request) />
218</cffunction>
219
220<cffunction name="GetAsyncRequests" returnType="ModelGlue.unity.async.AsyncRequestCollection" output="false" access="public" hint="I return async requests by message name for the current session.">
221        <cfargument name="message" type="string" required="true" />
222        <cfreturn session._modelGlue.asyncRequests[arguments.message] />
223</cffunction>
224       
225<!--- Event-handler management --->
226<cffunction name="addEventHandler" access="public" hint="I register a given event-handler." output="false">
227        <cfargument name="eventHandler" type="ModelGlue.unity.eventhandler.EventHandler" required="true" />
228        <cfset variables._eventhandlers.addEventHandler(arguments.eventHandler.getName(), arguments.eventHandler) />
229</cffunction>
230<cffunction name="getEventHandler" access="public" hint="I get a given event-handler." output="false">
231        <cfargument name="name" />
232        <cfreturn variables._eventhandlers.getEventHandler(arguments.name) />
233</cffunction>
234<cffunction name="eventHandlerExists" returntype="boolean" access="public" hint="Does a given event-handler exist?" output="false">
235        <cfargument name="name" />
236        <cfreturn  variables._eventhandlers.exists(arguments.name) />
237</cffunction>
238
239<!--- Event Handling --->
240<cffunction name="CreateEventRequest" output="false" access="public" returntype="any">
241        <cfreturn createObject("component", "ModelGlue.unity.eventrequest.EventRequest").init(getStateBuilder()) />
242</cffunction>
243
244<cffunction name="CreateRequestLog" output="false" access="public" returntype="any">
245        <cfreturn createObject("component", "ModelGlue.unity.eventrequest.RequestLog").init() />
246</cffunction>
247
248<cffunction name="ReleaseEventRequest" output="false" access="public" returntype="void">
249        <cfargument name="eventRequest" />
250
251</cffunction>
252
253<!---
254<cffunction name="HandleEvent" output="false" access="public" returntype="ModelGlue.unity.eventrequest.EventRequest">
255        <cfargument name="eventRequest" type="ModelGlue.unity.eventrequest.EventRequest" />
256        <cfset var state = arguments.eventRequest.getStateContainer() />
257        <cfset var eventHandler = getEventHandler(state.getValue(getConfigSetting("eventValue"))) />
258        <cfset arguments.eventRequest.addEventHandler(eventHandler) />
259
260        <cfreturn handleEventRequest(arguments.eventRequest) />
261        <cfreturn arguments.eventRequest />
262</cffunction>
263--->
264
265<cffunction name="HandleEventRequest" output="false" access="public" hint="I handle an EventRequest.">
266  <cfargument name="eventRequest" />
267
268        <cfset var state = arguments.eventRequest.getStateContainer() />
269  <cfset var exceptionRequest = "" />
270  <cfset var stateContainer = "" />     
271        <cfset var eventHandler = "" />
272       
273        <!--- It's a zen thing (actually, it's needed for exception handling - the pointer may change). --->
274  <cfset var result = arguments.eventRequest />
275
276        <cftry>
277                <!--- Get the initial EventHandler to run --->
278                <cfset eventHandler = getEventHandler(state.getValue(getConfigSetting("eventValue"))) />
279               
280                <cfif eventHandler.getAccess() eq "private">
281                        <cfthrow type="ModelGlue.EventHandler.Private"
282                                                         message="#state.getValue(getConfigSetting("eventValue"))# is a private &lt;event-handler&gt;.">
283                </cfif>
284               
285                <!---
286                <cfset arguments.eventRequest.addEventHandler(eventHandler) />
287                --->
288               
289                <cfset result = runEventRequest(arguments.eventRequest, eventHandler) />
290          <cfcatch>
291            <cfif not len(getConfigSetting("defaultExceptionHandler"))>
292              <cfrethrow />
293            <cfelse>
294              <cfset stateContainer = arguments.eventRequest.getStateContainer() />
295              <cfset stateContainer.setValue("exception", cfcatch) />
296              <cfset exceptionRequest = createObject("component", "ModelGlue.unity.eventrequest.EventRequest").init(getStateBuilder(), stateContainer, arguments.eventRequest.getLog()) />
297              <cfset exceptionRequest.addEventHandler(getEventHandler(getConfigSetting("defaultExceptionHandler"))) />
298                                <cfset arguments.eventRequest.addTraceStatement("<font color=""red""><strong>Exception</strong></font>", "An exception has been thrown and is being handled by the default exception handler.") />
299              <cfset result = runEventRequest(exceptionRequest) />
300            </cfif>
301          </cfcatch>
302  </cftry>
303 
304  <cfreturn result />
305</cffunction>
306
307<cffunction name="RunEventRequest" output="false" access="private" hint="I handle an event by name.">
308  <cfargument name="eventRequest" />
309  <cfargument name="initialEventHandler" />
310
311        <!---
312                If we're running a normal event (not exception), tell the request to report the primary
313                event handler name instead of the internal "ModelGlue." event handler names.
314        --->
315        <cfif structKeyExists(arguments, "initialEventHandler")>
316                <cfset arguments.eventRequest.setInitialEventHandler(arguments.initialEventHandler) />
317        </cfif> 
318
319        <!--- "OnRequestStart" event --->
320        <cfset RunEventHandler(getEventHandler("ModelGlue.OnRequestStart"), arguments.eventRequest) />
321       
322        <!--- Run any events requested by OnRequestStart results --->
323        <cfset RunEventHandlerQueue(arguments.eventRequest) />
324
325        <!--- Add the initial event-handler --->
326        <cfif structKeyExists(arguments, "initialEventHandler")>
327                <cfset arguments.eventRequest.addEventHandler(arguments.initialEventHandler) />
328        </cfif>
329       
330  <!--- Run the event queue --->
331        <cfset RunEventHandlerQueue(arguments.eventRequest) />
332               
333        <!--- "OnQueueComplete" event --->
334        <cfset RunEventHandler(getEventHandler("ModelGlue.OnQueueComplete"), arguments.eventRequest) />
335
336        <!--- Run any events requested by OnQueueComplete results --->
337        <cfset RunEventHandlerQueue(arguments.eventRequest) />
338
339        <!--- Render the view queue --->
340        <cfset RenderViewQueue(arguments.eventRequest) />
341       
342        <!--- "OnRequestEnd" event --->
343        <cfset RunEventHandler(getEventHandler("ModelGlue.OnRequestEnd"), arguments.eventRequest) />
344       
345        <!--- Run any events requested by OnRequestEnd results --->
346        <cfset RunEventHandlerQueue(arguments.eventRequest) />
347
348        <!--- Render the view queue --->
349        <cfset RenderViewQueue(arguments.eventRequest) />
350
351  <!--- Return the eventRequest --->
352  <cfreturn arguments.eventRequest />
353</cffunction>
354
355<cffunction name="RunEventHandlerQueue" returntype="void" access="private" output="false">
356        <cfargument name="eventRequest" />
357       
358  <!--- Run the event queue --->
359  <cfloop condition="not #arguments.eventRequest.eventHandlerQueueIsEmpty()#">
360    <cfset RunEventHandler(arguments.eventRequest.getNextEventHandler(), arguments.eventRequest) />
361  </cfloop>
362</cffunction>
363
364<cffunction name="RunEventHandler" returntype="void" access="private" output="false">
365        <cfargument name="eventHandler" />
366        <cfargument name="eventRequest" />
367
368        <cfset var messageNames = arguments.eventHandler.getMessages() />
369        <cfset var messages = "" />
370        <cfset var views = arguments.eventHandler.getViews() />
371        <cfset var resultMappings = arguments.eventHandler.getResultMappings() />
372        <cfset var eventContext = "" />
373        <cfset var eventName = eventHandler.getName() />
374        <cfset var eventResults = "" />
375        <cfset var i = "" />
376        <cfset var j = "" />
377        <cfset var k = "" />
378        <cfset var l = "" />
379       
380  <cfset arguments.eventRequest.addTraceStatement("Event Handler", "Running Event Handler: ""#arguments.eventHandler.getName()#""", "&lt;event-handler name=""#arguments.eventHandler.getName()#""&gt;") />
381        <!--- Broadcast messages --->   
382        <cfloop from="1" to="#arrayLen(messageNames)#" index="i">
383                <cfset messages = arguments.eventHandler.getMessage(messageNames[i]) />
384                <cfloop from="1" to="#arrayLen(messages)#" index="j">
385            <cfset arguments.eventRequest.addTraceStatement("Message Broadcast", "Broadcasting message: #messages[j].getName()#", "&lt;message name=""#messages[j].getName()#"" /&gt;") />
386                        <cfset eventContext = arguments.eventRequest.createEventContext(messages[j], arguments.eventHandler, this, variables._beanMaker) />
387                        <cfset variables._messageBroadcaster.broadcast(eventContext) />
388                        <cfset eventResults = eventContext.getResults() />
389            <cfloop from="1" to="#arrayLen(eventResults)#" index="k">
390              <cfif structKeyExists(resultMappings, eventResults[k])>
391                <cfset mapping = resultMappings[eventResults[k]]>
392                <cfloop from="1" to="#arrayLen(mapping)#" index="l">
393                        <cfset arguments.eventRequest.addEventHandler(getEventHandler(mapping[l].event)) />
394                      <cfset arguments.eventRequest.addTraceStatement("Result", "Event ""#eventName#""'s result of ""#eventResults[k]#"" has queued the ""#mapping[l].event#"" event-handler", "&lt;result name=""#eventResults[k]#"" do=""#mapping[l].event#"" /&gt;") />
395                      </cfloop>
396                    <cfelse>
397                      <cfthrow message="Model-Glue: Result has no mapping" detail="The result ""#eventResults[k]#"" from the event ""#eventName#"" has no matching &lt;result&gt; tag." />
398                    </cfif>
399            </cfloop>
400                </cfloop>
401        </cfloop>
402       
403        <!--- If we have no messages, we need to create a "fake" event context for implicit results to use --->
404        <cfif not arrayLen(messageNames)>
405                <cfset eventContext = arguments.eventRequest.createEventContext(getFakeMessage(), arguments.eventHandler, this, variables._beanMaker) />
406        </cfif>
407       
408  <!--- Add any implicit results to the queue --->
409  <cfif structCount(resultMappings) and structKeyExists(resultMappings, "")>
410    <cfset mapping = resultMappings[""]>
411    <cfloop from="1" to="#arrayLen(mapping)#" index="j">
412                <cfif not mapping[j].redirect>
413       <cfset arguments.eventRequest.addEventHandler(getEventHandler(mapping[j].event)) />
414             <cfset arguments.eventRequest.addTraceStatement("Result", "Event ""#eventName#"" has queued the ""#mapping[j].event#"" event-handler", "&lt;result do=""#mapping[j].event#"" /&gt;") />
415            <cfelse>
416                <cfset eventContext.forward(mapping[j].event, mapping[j].append) />
417            </cfif>
418    </cfloop>
419  </cfif>
420       
421  <!--- Queue views --->
422  <cfloop to="1" from="#arrayLen(views)#" index="i" step="-1">
423    <cfset arguments.eventRequest.addTraceStatement("View Include", "Adding view ""#views[i].getName()#"" to the view queue.", "&lt;include name=""#views[i].getName()#"" template=""#views[i].getTemplate()#"" /&gt;") />
424    <cfset arguments.eventRequest.addView(views[i]) />
425  </cfloop>
426
427   <!--- Render the view queue
428  <cfset RenderViewQueue(arguments.eventRequest) />
429        --->
430</cffunction>
431
432<!--- VIEW RENDERING --->
433<cffunction name="RenderViewQueue" returnType="void" output="false" access="private" hint="I render the view queue.">
434  <cfargument name="eventRequest" default="#createObject("component", "ModelGlue.Util.GenericStack").init()#" hint="I am the event request this rendering belongs to." />
435
436  <cfset var thisView = "" />
437  <cfset var i = "" />
438  <cfset var viewMappings = listAppend(getConfigSetting("viewMappings"), getConfigSetting("generatedViewMapping")) />
439  <cfset var viewCollection = arguments.eventRequest.getViewCollection() />
440  <cfset var viewRenderer = variables._viewRenderer />
441  <cfset var templateExists = false />
442  <cfset var content = "" />
443
444  <cfloop condition="not #eventRequest.viewQueueIsEmpty()#">
445    <cfset thisView = arguments.eventRequest.getNextView() />
446    <cfset templateExists = false />
447    <cfloop list="#viewMappings#" index="i">
448      <cfif fileExists(expandPath(i) & "/" & thisView.getTemplate())>
449        <cfset arguments.eventRequest.addTraceStatement("View Queue", "Rendering view ""#thisView.getName()#"" (#i & "/" & thisView.getTemplate()#)", "&lt;include name=""#thisView.getName()#"" template=""#thisView.getTemplate()#"" /&gt;") />
450        <cfset content = viewRenderer.renderView(arguments.eventRequest.getStateContainer(), viewCollection, i & "/" & thisView.getTemplate(), thisView.getValues()) />
451        <cfset viewCollection.addRenderedView(thisView.getName(), content, thisView.getAppend()) />
452        <cfset templateExists = true />
453        <cfbreak />
454      </cfif>
455    </cfloop>
456    <cfif not templateExists>
457     <cfthrow message="Model-Glue:  &lt;include&gt; Template not found!" detail="None of the directories listed in your viewMappings setting contain a file named ""#thisView.getTemplate()#""" />
458    </cfif>
459  </cfloop>
460</cffunction>
461
462</cfcomponent>