Using Structures For Similar Types

In OO parlance we are very used to inheritance, polymorphism and subtypes.  These let us create objects which share common properties and methods that we can override within the different classes.  Since these objects come from the same base object, they can further be cast from one type to another, as long as the parent type is the same.

In classic OO, if we have a Submission, which inherits from Job, we have a JobNumber.  If instead we refer to a Renewal, we still have JobNumber because it also inherits from Job.  This is common, every day, OO and we are very used to this.

Problem

We have an entity within Guidewire which shares common properties to another entity but they don’t share a common parent.  How can we treat them as equals if we need to pass them as an argument to a method?

We can simply write an overload to achieve this.  But doing this often results in duplicated code.

OK, OK, quit talking and show me an example.

Glad you asked.

One that continually gets me in Guidewire PolicyCenter is a PolicyLocation.  It has properties of an Address but isn’t an Address.  What if I want to operate on the Address portions of the PolicyLocation the same as I do on a real address?

Solution

Enter Structures.

A Structure is a native type which allows disparate types to behave the same way, as long as they share common properties.

Let’s define an address structure.  We have to use a more typical Java approach because Guidewire Gosu as type properties are not supported by structures.

structure AddressStructure {
  public property get AddressLine1() : String
  public property set AddressLine1(value : String)
  public property get AddressLine2() : String
  public property set AddressLine2(value : String)
  public property get AddressLine3() : String
  public property set AddressLine3(value : String)
  public property get AddressType() : AddressType
  public property set AddressType(value : AddressType)
  public property get City() : String
  public property set City(value : String)
  public property get State() : State
  public property set State(value : State)
  public property get PostalCode() : String
  public property set PostalCode(value : String)
  public property get Country() : Country
  public property set Country(value : Country)

  public static function copy(from : AddressStructure, to : AddressStructure) {
    if (from == to) return // same object reference = nothing to do
    to.AddressLine1 = from.AddressLine1
    to.AddressLine2 = from.AddressLine2
    to.AddressLine3 = from.AddressLine3
    to.City = from.City
    to.State = from.State
    to.PostalCode = from.PostalCode
    to.Country = from.Country
    to.AddressType = from.AddressType
  }

  property get toString() : String {
    var formatter =  new gw.api.address.AddressFormatter() {
     :AddressLine1 = AddressLine1,
     :State = State,
     :City = City,
     :PostalCode = PostalCode,
     :Country = Country
    }
    return formatter.format(formatter, ", ")
  }
}

Now if we want to access the Address portion of an entity which supports these properties, we just cast it and voila, we can treat it the same.  Let’s use a simple query to retrieve a Policy and get both an Account Location and the Account Holder’s primary address.

uses gw.address.AddressStructure
uses gw.api.database.Query

var policy = Query.make(Policy).select().FirstResult
var accountLocation = policy.Account.AccountLocations[0]
var primaryAddress = policy.Account.AccountHolder.AccountContact.Contact.PrimaryAddress

// we can print either using the structure’s toString method
print((accountLocation as AddressStructure).toString)
print((primaryAddress as AddressStructure).toString)

// we can also copy from one type to another just by casting
var newAddress = new Address()
AddressStructure.copy(accountLocation as AddressStructure, newAddress as AddressStructure)
print((newAddress as AddressStructure).toString)

Though accountLocation and primaryAddress are different types of entities, as long as each entity shares those common properties, you can cast from one to another.

This allows polymorphism on disparate types and provides an easy way to handle issues where you need common routines.

A structural type can act like an interface in that a class can implement a structure.  From that regard, there is no difference between an interface and a structure.  The real difference comes when you can simply cast one type to another without needing to implement anything, which interfaces cannot do.

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