I was talking with Brian Kotek recently about a particular design issue when he suggested I make use of yUML. This is an online service that allows you to dynamically generate UML documents. UML is not something that I'm really into. I can see the benefits of it, but I just haven't felt the need yet to make it part of my development process. That being said, I thought it was pretty cool how yUML allowed you to generate a UML picture straight from a URL. If you look at their samples page, you can see how they go from a simple URL "api" to a generate graphic.
Based on that, I decided to see if I could whip up some code to examine a CFC and generate the URL. While this isn't completely useful (it only works with one CFC and doesn't handle relationships), it was fun and I thought someone may be able to play with it more. Here is the script I came up with:
<cfset meta = getComponentMetadata("test")> <cfdump var="#meta#" expand="false">
<cfset modifiers = {public="+",protected="##",private="-",package="~",remote="+"}>
<cfset rooturl = "http://yuml.me/diagram/scrufy/class/">
<!--- Name ---> <cfset rooturl &= "[" & urlEncodedFormat(meta.name) & "|">
<!--- Properties ---> <cfloop index="x" from="1" to="#arrayLen(meta.properties)#"> <cfset p = meta.properties[x]> <!--- all properties are public ---> <cfset rooturl &= "#urlEncodedFormat(modifiers.public)##p.name#;"> </cfloop>
<!--- Methods---> <cfif arrayLen(meta.functions)> <cfset rooturl &= "|"> </cfif>
<cfloop index="x" from="1" to="#arrayLen(meta.functions)#"> <cfset f = meta.functions[x]> <cfif not structKeyExists(f, "access")> <cfset f.access = "public"> </cfif> <cfset rooturl &= "#urlEncodedFormat(modifiers[f.access])##f.name#();"> </cfloop>
<cfset rooturl &= "]">
<cfoutput> #rooturl#<br/> <img src="#rooturl#"> </cfoutput>
Going from top to bottom, you can see I get the metadata for a CFC called test. If this code were converted into a UDF you would want to simply make that portion dynamic. I create a structure that maps ColdFusion's access modifiers into the symbols that yUML will use to generate the UML graphic. Since remote doesn't make sense in this context, I mapped it to public.
After that, it's simply then a matter of looping over the metadata. I start off with the properties and then handle the methods. Given this input:
<cfcomponent persistent="true"><cfproperty name="foo" ormtype="string"> <cfproperty name="goo" ormtype="string"> <cfproperty name="aaa" ormtype="string">
<cffunction name="privatetest" access="private"> </cffunction>
<cffunction name="publictest" access="public"> </cffunction>
<cffunction name="packagetest" access="package"> </cffunction>
<cffunction name="remotetest" access="remote"> </cffunction>
</cfcomponent>
The output is:
It would probably be nice to sort the values (one thing I wish cfdump would do for CFCs). Handling relationships should - in theory - be possible. You just want to ensure you don't get into an infinite recursion loop with bidirectional relationships.