PageRenderTime 15ms CodeModel.GetById 10ms app.highlight 2ms RepoModel.GetById 1ms app.codeStats 0ms

/core/factory.cfc

http://github.com/atuttle/Taffy
ColdFusion CFScript | 202 lines | 194 code | 5 blank | 3 comment | 8 complexity | 8c44ed69fd11aca845948cb42a0009f0 MD5 | raw file
  1<cfcomponent output="false">
  2	<cfscript>
  3		//bean cache
  4		this.beans = structNew();
  5		this.transients = structNew();
  6		//functionality
  7	</cfscript>
  8
  9	<cffunction name="init" output="false">
 10		<cfargument name="externalBeanFactory">
 11	<cfscript>
 12			if (structKeyExists(arguments, "externalBeanFactory")) {
 13				this.externalBeanFactory = arguments.externalBeanFactory;
 14			}
 15			return this;
 16	</cfscript>
 17	</cffunction>
 18
 19	<cfscript>
 20		// Proxy to beanExists to provide similar interface to ColdSpring
 21		function containsBean(beanName){
 22			return beanExists(arguments.beanName);
 23		}
 24		function transientExists(beanName){
 25			return structKeyExists(this.transients, arguments.beanName);
 26		}
 27		function getBean(beanName){
 28			var b = 0;
 29			var meta = 0;
 30			if (beanExists(arguments.beanName, false, false)){
 31				return this.beans[arguments.beanName];
 32			}else if (transientExists(arguments.beanName)){
 33				b = createObject('component', this.transients[arguments.beanName]);
 34				meta = getMetadata(b);
 35				_recurse_ResolveDependencies(b, meta);
 36				return b;
 37			}else if (externalBeanExists(arguments.beanName)){
 38				return this.externalBeanFactory.getBean(arguments.beanName);
 39			}else{
 40				throwError(message="Bean name '#arguments.beanName#' not found.", type="Taffy.Factory.BeanNotFound");
 41			}
 42		}
 43		function getBeanList(){
 44			var combined = structKeyList(this.beans);
 45			var trans = structKeyList(this.transients);
 46			if (len(combined) and len(trans)){
 47				combined = combined & ",";
 48			}
 49			combined = combined & trans;
 50			return combined;
 51		}
 52	</cfscript>
 53	<cffunction name="beanExists" output="false">
 54		<cfargument required="true" name="beanName">
 55		<cfargument name="includeTransients" default="true">
 56		<cfargument name="includeExternal" default="false">
 57		<cfscript>
 58			return structKeyExists(this.beans, arguments.beanName) or (arguments.includeTransients and transientExists(arguments.beanName)) or
 59				(arguments.includeExternal and externalBeanExists(arguments.beanName));
 60		</cfscript>
 61	</cffunction>
 62	<cffunction name="externalBeanExists" access="private" output="false" returnType="boolean">
 63		<cfargument required="true" name="beanName">
 64		<cfscript>
 65			return structKeyExists(this, "externalBeanFactory") and this.externalBeanFactory.containsBean(arguments.beanName);
 66		</cfscript>
 67	</cffunction>
 68	<cffunction name="loadBeansFromPath" access="public" output="false" returnType="void">
 69		<cfargument name="beanPath" type="string" required="true" hint="Absolute path to folder containing beans" />
 70		<cfargument name="resourcesPath" type="string" default="resources" />
 71		<cfargument name="resourcesBasePath" type="string" default="" />
 72		<cfargument name="isFullReload" type="boolean" default="false" />
 73		<cfargument name="taffyRef" type="any" required="false" default="#structNew()#" />
 74		<cfset var local = StructNew() />
 75		<!--- cache all of the beans --->
 76		<cfif isFullReload>
 77			<cfset this.beans = structNew() />
 78			<cfset arguments.taffyRef.status.skippedResources = arrayNew(1) /> <!--- empty out the array on factory reloads --->
 79			<cfset arguments.taffyRef.beanList = "" />
 80		</cfif>
 81		<!--- if the folder doesn't exist, do nothing --->
 82		<cfif not directoryExists(arguments.beanPath)>
 83			<cfreturn />
 84		</cfif>
 85		<!--- get list of beans to load --->
 86		<cfdirectory action="list" directory="#arguments.beanPath#" filter="*.cfc" name="local.beanQuery" recurse="true" />
 87		<cfloop query="local.beanQuery">
 88			<cfset local.beanName = filePathToBeanName(local.beanQuery.directory, local.beanquery.name, arguments.resourcesBasePath) />
 89			<cfset local.beanPath = filePathToBeanPath(local.beanQuery.directory, local.beanquery.name, arguments.resourcesPath, arguments.resourcesBasePath) />
 90			<cftry>
 91				<cfset local.objBean = createObject("component", local.beanPath) />
 92				<cfif isInstanceOf(local.objBean, "taffy.core.baseSerializer")>
 93					<cfset this.transients[local.beanName] = local.beanPath />
 94				<cfelse>
 95					<cfset this.beans[local.beanName] = local.objBean />
 96				</cfif>
 97				<cfcatch>
 98					<!--- skip cfc's with errors, but save info about them for display in the dashboard --->
 99					<cfset local.err = structNew() />
100					<cfset local.err.resource = local.beanName />
101					<cfset local.err.exception = cfcatch />
102					<cfset arrayAppend(arguments.taffyRef.status.skippedResources, local.err) />
103				</cfcatch>
104			</cftry>
105		</cfloop>
106		<!--- resolve dependencies --->
107		<cfloop list="#structKeyList(this.beans)#" index="local.b">
108			<cfset local.bean = this.beans[local.b] />
109			<cfset local.beanMeta = getMetadata(local.bean) />
110			<cfset _recurse_ResolveDependencies(local.bean, local.beanMeta) />
111		</cfloop>
112	</cffunction>
113
114	<cffunction name="filePathToBeanPath" access="private">
115		<cfargument name="path" />
116		<cfargument name="filename" />
117		<cfargument name="resourcesPath" />
118		<cfargument name="resourcesBasePath" />
119		<cfset var beanPath = "" />
120		<cfif len(resourcesBasePath) eq 0>
121			<cfset arguments.resourcesBasePath = "!@$%^&*()" />
122		</cfif>
123		<cfset beanPath =
124			resourcesPath
125			&
126			"."
127			&
128			replaceList(
129				replace(path, resourcesBasePath, ""),
130				"/,\",
131				".,."
132			)
133			&
134			"."
135			&
136			replace(
137				filename,
138				".cfc",
139				""
140			)
141		/>
142		<cfset beanPath = replace(beanPath, "..", ".", "ALL") />
143		<cfif left(beanPath, 1) eq ".">
144			<cfset beanPath = right(beanPath, len(beanPath)-1) />
145		</cfif>
146		<cfreturn beanPath />
147	</cffunction>
148
149	<cffunction name="filePathToBeanName" access="private">
150		<cfargument name="path" />
151		<cfargument name="filename" />
152		<cfargument name="basepath" />
153		<cfif len(basepath) eq 0>
154			<cfset arguments.basePath = "!@$%^&*()" />
155		</cfif>
156		<cfreturn
157			replaceList(
158				replace(path, basepath, ""),
159				"/,\",
160				","
161			)
162			& replace(
163				filename,
164				".cfc",
165				""
166			)
167		/>
168	</cffunction>
169
170	<cffunction name="_recurse_ResolveDependencies" access="private">
171		<cfargument name="bean" required="true" />
172		<cfargument name="metaData" type="struct" required="true" />
173		<cfset var local = structNew() />
174		<cfif structKeyExists(arguments.metaData, "functions") and isArray(arguments.metaData.functions)>
175			<cfloop from="1" to="#arrayLen(arguments.metaData.functions)#" index="local.f">
176				<cfset local.fname = arguments.metaData.functions[local.f].name />
177				<cfif len(local.fname) gt 3>
178					<cfset local.propName = right(local.fname, len(local.fname)-3) />
179					<cfif left(local.fname, 3) eq "set" and beanExists(local.propName, true, true)>
180						<cfset evaluate("arguments.bean.#local.fname#(getBean('#local.propName#'))") />
181					</cfif>
182				</cfif>
183			</cfloop>
184		</cfif>
185		<cfif structKeyExists(arguments.metaData, "properties") and isArray(arguments.metaData.properties)>
186			<cfloop from="1" to="#arrayLen(arguments.metaData.properties)#" index="local.p">
187				<cfset local.propName = arguments.metaData.properties[local.p].name />
188				<cfif beanExists(local.propName, true, true)>
189					<cfset arguments.bean[local.propName] = getBean(local.propName) />
190				</cfif>
191			</cfloop>
192		</cfif>
193		<cfif structKeyExists(arguments.metaData, "extends") and isStruct(arguments.metaData.extends)>
194			<cfset _recurse_ResolveDependencies(arguments.bean, arguments.metaData.extends) />
195		</cfif>
196	</cffunction>
197	<!--- proxy function for CF8 compatibility --->
198	<cffunction name="throwError">
199		<cfthrow attributecollection="#arguments#" />
200	</cffunction>
201
202</cfcomponent>