Dynamic Types In Gosu (objects ala JavaScript)

In version 10+, Guidewire has added a new intrinsic datatype to Gosu which allows objects to be created and used very much like javascript.  The functionality, while very nice, is not as complete as it is in javascript but may be in future releases.

This style is mostly used for integrations but can be very useful for dynamic style programming.

Problem

I need to ship a property bag from xCenter to a 3rd party, or receive a property bag from a 3rd party.

Solution

Dynamic and Expando

The datatype is Dynamic.  The magic is Expando.  When used together, you can do some really cool things.

Let’s say we get a property bag from a 3rd party and want to pass those properties to a function.  With this new type, we can create an object on the fly and use it either directly or dynamically.

uses com.guidewire.pl.system.util.DateTimeUtil
uses com.guidewire.pl.system.util.DateTimeUtil.Difference
uses gw.lang.reflect.Expando

var dynamic : Dynamic = new Expando()

//We get a property bag from a 3rd party
var propertyBag = new HashMap<String, Object>()
propertyBag.put("FirstName", "Tom")
propertyBag.put("LastName", "Cruise")
propertyBag.put("NumberOfCars", 5)
propertyBag.put("Cost", 56674.12)

//we build an object on the fly
propertyBag.eachKeyAndValue(k, val -> {
  dynamic[k] = val
})

print("**** Start ****")
var key = "Cost"
//we can access it one of 3 ways
print("FirstName: ${dynamic["FirstName"]}")
print("LastName: ${dynamic.LastName}")
print("Cost: ${dynamic[key]}")

print("n**** Additional Dynamic ****")
//we can add functions
dynamic.print = -> print(dynamic)
dynamic.Age = birthday : String -> {
  var age : Difference = DateTimeUtil.getDifference(new Date(), new Date(birthday))
  return age.Days / 365

}
dynamic.Birthdate = "12/01/1975"
//and then call that function
print("Age: ${dynamic.Age(dynamic.Birthdate)}")
//just for fun - notice, this is the same as a HashMap
dynamic.put("Address", "123 Main St")
//but I can access it like a property
print("Address: ${dynamic.Address}")

//finally I can add an object
dynamic.Me = dynamic

print("n**** Looping dynamically ****")
//If I want to access the properties, I need to know them ahead of time (shortcoming)
var array = new ArrayList(){"Birthdate", "Age", "FirstName", "LastName", "NumberOfCars", "Cost",  "printMe"}
//in javascript, I can look over the properties without knowing the names

array.each(elt -> {
try {
  //this is where javascript has an advantage by allowing us to check for a function
  //We can however, parse the type looking for block
  var myType = typeof dynamic[elt]

  if (myType.toString().startsWith("block")) {

    //try and create a dynamic string to call
    var dyna = "dynamic.${elt}('${dynamic.Birthdate}')"

    print("I want to call this: n ${dyna}nBut don't have an Eval function")
    //let's print the guts of the function at least
    print("Function ${elt} = n******* n ${dynamic[elt]} n*******")

    //another issue is that function calls cannot be called with hashmap notation
    //dynamic[elt]() -- will die at runtime so we resort to Explicit
    print("Age: ${dynamic.Age(dynamic.Birthdate)}")
   } else {
    //If the property is not defined, you will get a null
    if (dynamic[elt] == null) {
      print("${elt} not supported")
    } else {
      print("${elt}: ${dynamic[elt]}")
    }
   }
  } catch (e : Exception) {
    print(e)
  }
})

Here is the output from scratchpad

**** Start ****
FirstName: Tom
LastName: Cruise
Cost: 56674.12

**** Additional Dynamic ****
Age: 45
Address: 123 Main St

**** Looping dynamically ****
Birthdate: 12/01/1975
I want to call this: dynamic.Age('12/01/1975')
But don't have an Eval function
Function Age = ******* birthday : java.lang.String -> { var age : com.guidewire.pl.system.util.DateTimeUtil.Difference = com.guidewire.pl.system.util.DateTimeUtil.getDifference( new java.util.Date(), new java.util.Date( birthday ) ) return age.Days/365 }

*******
Age: 45
FirstName: Tom
LastName: Cruise
NumberOfCars: 5
Cost: 56674.12
printMe not supported

When I first started playing with this, I thought… Ooh I do this in javascript and it works well and gives me lots of flexibility. But with limited support in Gosu, I have yet to find a practical use for it.  

Maybe you can find it and if so, I would love to hear from you.

Troy Stauffer
Senior Software Architect


Watch or read our other posts at Kimputing Blogs. You’ll find everything from Automated testing to CenterTest, Guidewire knowledge to general interest. We’re trying to help share our knowledge from decades of experience.

Similar Posts