Skip to content

Instantly share code, notes, and snippets.

@ruckus
Created November 5, 2009 21:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ruckus/227407 to your computer and use it in GitHub Desktop.
Save ruckus/227407 to your computer and use it in GitHub Desktop.
<cfcomponent output="yes">
<!--- Take an object and a struct as input. Traverse through the object's meta-data and
find all methods and if the datastruct contains a key which matches that method name (with "set" prepended)
then call that method using the struct key value.
This is a convenient way to quickly populate an object/bean by calling all of its
setters.
--->
<cffunction name="populateBean" returntype="any" output="yes">
<cfargument name="object" type="any">
<cfargument name="datastruct" type="any">
<cfset var md = StructNew()>
<cfset var functionSeen = structNew()>
<cfset var functionIx = 0>
<cfset var functionName = ''>
<cfset var setterName = 0>
<cfset var function = "">
<cfset var value = "">
<cfif NOT IsObject(object)>
<cfthrow message="BeanUtil.populateBean()::NOT AN OBJECT!" />
</cfif>
<cfset md = getMetaData(object)>
<!--- This nested looping is necessary because we need to examine all methods that this object
has, including methods it has inherited. Inherited methods exist in sub-structs so we need to extract and examine
those. In addition, we need to maintain a list of visited methods and check this so as to not call a base method
that we have already seen and called (possibly seriously polluting an objects interior data).
---->
<cfloop condition="structKeyExists(md,'extends')">
<cfif structKeyExists(md,'functions')>
<!--- now we'll loop through the target's methods and search for matching methods --->
<cfloop from="1" to="#arraylen(md.functions)#" index="functionIx">
<cfset function = md.functions[functionIx]>
<cfset functionName = function.name>
<cfif not structKeyExists(functionSeen,functionName)>
<cfset functionSeen[functionName] = true>
<!--- Look for a match in our struct --->
<cfif len(functionName) gt 3 and
left(functionName,3) is "set" and
arrayLen(md.functions[functionIx].parameters) eq 1>
<cfset setterName = right(functionName,len(functionName)-3)>
<cfif StructKeyExists(datastruct, setterName)>
<!--- massage the value into the correct type that the setter method is expecting, if the type
information is set on the function definition --->
<cfset value = StructFind(datastruct, setterName)>
<cfscript>
if(StructKeyExists(function, 'parameters')) {
if(ArrayLen(function.parameters) == 1) {
if(function.parameters[1].type == 'numeric') {
value = Val(value);
}
if(function.parameters[1].type == 'string') {
value = Trim(value);
}
}
}
</cfscript>
<cfinvoke component="#object#"
method="set#setterName#">
<cfinvokeargument name="#md.functions[functionIx].parameters[1].name#"
value="#value#"/>
</cfinvoke>
</cfif>
</cfif>
</cfif>
</cfloop>
</cfif>
<cfset md = md.extends />
</cfloop>
<cfreturn object />
</cffunction>
</cfcomponent>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment