Objects Integration Point

This integration point provides the ability to download the meta model of the OHI objects that are used in the dynamic logic. This enables the customers to develop groovy on a standalone basis and write tests for it. Each object is a Groovy Class.

Download Objects

This integration point exposes a GET call on the following url.

http://<host>:<port>/<contextRoot>/objects/generate?includeDynamicData=true&withSerialization=false

The response is a zip file that gets downloaded. This IP is protected by access restriction 'objects IP'.

There are a few options to provide while generating the objects. These options are provided as query parameters to the above endpoint.

  • includeDynamicData: Allowed values are true or false, with default being true. If the option’s value is false, then dynamic fields and dynamic records are not generated as properties of the object. Irrespective of the value of this option, objects that are dynamic data aware, are generated with a dynamicData map. This helps in storing any dynamic field or record without first configuring them and then generating the objects. The snippet on how the generation of dynamicData looks like is here:

 Map<String, Object> dynamicData = [:]

 Map getDynamicData() {
   dynamicData
 }

 Object propertyMissing(String name) {
   if(dynamicData.containsKey(name)) {
     return dynamicData.get(name)
   }
   throw new PropertyMissingException(this, name)
 }

 void propertyMissing(String name, Object value) {
   dynamicData[name]=value
 }

The property missing methods are groovy methods to fall-back when a property is not found in the generated object. The implementation makes sure to find the property in the dynamicData Map first before throwing the PropertyMissingException. Same is the case for setting a property that is not a fixed property on the generated object.

  • withSerialization: Allowed values are true or false, with default being false. If this option’s value is true, then the objects are generated with Jackson specific annotations to assist in serialisation and deserialisation of these objects. This comes in handy when these objects are used standalone by customers to test the dynamic logic scripts and send them as json to the application. The annotations are specifically to ignore certain fields for serialisation and to customize behaviour of serializing dynamicData map.

    • JsonIgnore on stubs and dynamicData ensures that these maps are not serialized.

    • JsonAnyGetter on getDynamicData ensures that the contents of the map are serialized as if they were present on the main object itself.

    • JsonAnySetter on dynamicData ensures that on deserialization, any property that is not resolved directly on the object is set on the map.

For example, Lets take an Object Claim, that has fixed fields for code and claimedAmount.

Claim claim = new Claim(code: 'Test', claimedAmount: 100, key1: 'value1', key2: 'value2')

The above will set value of code and claimedAmount on claim directly and fill up dynamicData for key1 and key2. When above claim gets serialized(using Jackson) without any annotation for JsonAnyGetter, the result would be:

{
    "code": "Test",
    "claimedAmount": 100,
    "dynamicData": {
        "key1": "value1",
        "key2": "value2"
    }
}

With annotation, it will serialize like:

{
    "code": "Test",
    "claimedAmount": 100,
    "key1": "value1",
    "key2": "value2"
}

The above is accepted in the end application, but not the first one, as dynamicData field is not recognized.

Inversly if above is de-serialized without annotation JsonAnySetter, it will ignore key1 and key2, however, with annotation, key1 and key2 will be populated in dynamicData Map.

The snippet of the generated object structure is as follows:

 @JsonIgnore
 Map<String, Closure> stubs = [:]

 @JsonIgnore
 @JsonAnySetter
 Map<String, Object> dynamicData = [:]

 @JsonAnyGetter
 Map getDynamicData() {
   dynamicData
 }

 Object propertyMissing(String name) {
   if(dynamicData.containsKey(name)) {
     return dynamicData.get(name)
   }
   throw new PropertyMissingException(this, name)
 }

 void propertyMissing(String name, Object value) {
   dynamicData[name]=value
 }

Contents of the downloaded zip

The downloaded zip generates artifacts in directory: com/oracle/healthinsurance/mock.

Objects

All entities in the application, where this operation is performed are generated in groovy structure These objects contain the following:

Properties:

  • Fixed attributes

  • Dynamic attributes (dynamic field usages, dynamic record usages)

  • Extra properties created especially for use in dynamic logic, like for example Enrollment for ClaimLine

For each property, the type is generated with following rules:

  • for fixed fields the Java class of the object attribute

  • for time valid dynamic field usages for subtype free fields : List<DynamicFieldPeriodString>

  • for time-valid and multi-value dynamic field usages of sub-type free fields: List<DynamicFieldPeriodString>

  • for multi value dynamic field usages for subtype free fields : List<String>

  • for time-valid and multi-value dynamic field usages of sub-type flex code: List< DynamicFieldPeriod[FlexCode/Procedure/Diagnosis/Provider]<FlexCodeSystem.code> >

  • for multi-value dynamic field usages of sub-type flex code: List< [FlexCode/Procedure/Diagnosis/Provider]<FlexCodeSystem.code> >

  • for non-time-valid dynamic field usages of subtype Free Field: String, BigDecimal or Date, and in case of multi-value dynamic field usages the type is a List of that.

  • for non-time-valid dynamic field usages of subtype Flex Code that are not time valid: Procedure, Diagnosis, Provider, or FlexCode<FlexCodeSystem.code>, and in case of multi-value dynamic field usages the type is a List of that.

  • for time-valid or multi-value dynamic record usages: List<DynamicRecordPeriod<FlexCodeSystem.code>>

  • for non-time-valid dynamic record usages DynamicRecord<FlexCodeSystem.code>, and in case of multi-value dynamic record usages the type is a List of that.

_For TimeValid DynamicFields/Records : The type will always start with DynamicFieldPeriod/DynamicRecordPeriod _ For each property, the name of the attribute is:

  • for dynamic field/record usages: the field usage name,

  • for OhiMoney objects: the name of the corresponding amount attribute

Fields

For DynamicFieldPeriod[FlexCode/Procedure/Diagnosis/Provider]<FlexCodeSystem.code>, DynamicRecordPeriod<FlexCodeSystem.code> and DynamicRecord<FlexCodeSystem.code> properties, the type is also generated as a separated groovy class.

DynamicFieldPeriod properties are:

  • endDate as Date

  • startDate as Date

  • value as <Type of the dynamic field usage if it was not time-valid>

Insurable Entity

If an object has a reference to insurable entity then all the configured insurable entity types are generated as separate properties.

Along with insurableEntity as a standard attribute, additional attributes are shown based on the usage name of the configured insurable entity types. The name of the property is the 'Usage Name' and the type is the singular display name.

Methods

  • standard methods: "search", and for entities that can have dynamic records, several methods that support the manipulation of dynamic records: getDynamicRecord, updateDynamicRecord, addDynamicRecord and deleteDynamicRecord.

  • entity-specific methods like for example (for Claim) "hasFatalMessage". For each method, the following information is generated:

  • Return type ("Void" if it doesn’t return anything)

  • Name

  • Arguments

Extra Properties and Methods

The extra properties and methods for specific entities implemented using Groovy callable functions are also generated as part of these objects.

Signatures

The signatures refer to the dynamic logic signatures that are available as hooks for a customer to add their implementation in. These signatures are defined with a set of input parameters. As part of this integration point, signatures are also generated as groovy files with expected parameters for each of the signature. The signature files are generated in the subfolder to the main directory 'signatures'. Each signature has its own groovy file that exposes a set of input parameters expected for that signature.

Example:

package com.oracle.healthinsurance.mock.signatures

import com.oracle.healthinsurance.mock.Address

class CountryFormat {
    def Address address

    def getInputParameters() {

        return [  "address" : address
        ]
    }
}