Groovy, ColdFusion, Java, PHP, C#... I enjoy programming. Father, software engineer, programming language nerd, and entrepreneur, I'm bringing nerdy back. Adam has posted 9 posts at DZone. View Full User Profile

Groovy Script to Generate JSON from CFSCRIPT

04.29.2011
| 12686 views |
  • submit to reddit
Today I was working on a bit of code that had a big SWITCH statement in CFSCRIPT in ColdFusion that for each case would go through the motions of registering some input parameters, then getting a reference to a controller, or handler, for the specified input request. That code looked a little something like this.
switch (arguments.action)
{
   case "action":
      result.controller = __controller("test.actionHandler");
      __registerParameters("param1,param2");
      break;
}

In an effort to change how this portion of code works I wanted to take all of these CASE statements and turn them into a JSON structure that looks like so.

{
   "action": {
      "controller": "test.actionHandler",
      "parameters": "param1,param2"
   }
}
This would allow me to read the file, deserialize the JSON, then instantiate and execute the correct handler without having them defined in code.

I didn't want to hand-type all of these, however, so I opened up the GroovyConsole and created a little script to automate this task. Here's the code.
def results = []
def currentAction = ""
def currentController = ""
def currentParams = ""
 
def foundCase = false
def foundParams = false
def matcher = null
 
new File("C:/code/app/ControllerFactory.cfc").eachLine { line ->
   if (!foundCase) {
      if (line.contains("case \"")) {
         foundCase = true
         matcher = (line =~ /(?i)case "(.*?)"/)
         currentAction = matcher[0][1]
 
         println "Action: ${currentAction}"
      }
   }
   else if (foundParams) {
      if (line.contains(")")) {
         foundParams = false
      }
      else {
         matcher = line =~ /(?i)"(.*?)"/
         if (matcher.size() > 0) {
            currentParams += matcher[0][1]
         }
      }
   }
   else {
      if (line.contains("break")) {
         foundCase = false
         results << [ action: currentAction, controller: currentController, params: currentParams ]
      }
      else {
         matcher = line =~ /(?i)__controller\("(.*?)"\)/
         if (matcher.size() > 0) {
            currentController = matcher[0][1]
         }
 
         // single line registration
         matcher = line =~ /(?i)__registerParameters\("(.*?)"\)/
         if (matcher.size() > 0) {
            currentParams = matcher[0][1]
         }
 
         // Multi-line registration
         matcher = line =~ /(?i)__registerParameters\(/
         if (matcher.size() > 0) {
            foundParams = true
            currentParams = ""
         }
      }
   }
}
 
 
/*
 * Write the results out to a definition file.
 */
def out = new File("C:/definitions.json")
if (out.exists()) out.delete()
 
out.createNewFile()
 
out << "{\n"
 
results.eachWithIndex { actionItem, index ->
   out << "\t\"${actionItem.action}\": {\n"
   out << "\t\t\"controller\": \"${actionItem.controller}\",\n"
   out << "\t\t\"parameters\": \"${actionItem.params}\"\n"
   if (index < results.size() - 1)
      out << "\t},\n"
   else
      out << "\t}\n"
}
 
out << "}"

With this script I read the CFC in one line at a time and when I find a CASE statement I start looking for the controller definition and the parameters, if any. It's mostly a lot of regexs, but overall a simple script.
References
Published at DZone with permission of its author, Adam Presley. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)