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.