Sexy command objects in Grails
Sometimes a bit of new information comes along that makes wrangling code a bit more fun. This is one such story.
/**
* @param pid Medical record number. Default unspecified
* @param age
* @param race
* @param sex
* @param totalCholesterol
* @param hdlCholesterol
* @param systolicBloodPressure
* @param currentSmoker
* @param diabetesStatus
* @param hyperDrug Was hypertension drug administered or not? Default is false
* @param precision What is the number of significant digits needed in the risk score result? Default is 3
*/
class RecalculationParamsCommand {
String pid
Integer age
Integer race
Integer sex
Integer totalCholesterol
Integer hdlCholesterol
Integer systolicBloodPressure
Integer currentSmoker
Integer diabetesStatus
Boolean hyperDrug
Integer precision
static constraints = {
pid(nullable: false, blank: false, validator: { value, obj ->
if (!value) {
return 'recalculationParamsCommand.invalid.pid.message'
}
})
age(nullable: false, blank: false, min: 40, max: 79, validator: { value, obj ->
if (value && !(value instanceof Integer)) {
return 'recalculationParamsCommand.invalid.age.message'
}
})
race(nullable: false, blank: false, range: 1..20, validator: { value, obj ->
if (value && !(value instanceof Integer)) {
return 'recalculationParamsCommand.invalid.race.message'
}
})
sex(nullable: false, blank: false, validator: { value, obj ->
if (value && !(value instanceof Integer)) {
return 'recalculationParamsCommand.invalid.sex.message'
}
})
totalCholesterol(nullable: false, blank: false, min: 130, max: 320, validator: { value, obj ->
if (value && !(value instanceof Integer)) {
return 'recalculationParamsCommand.invalid.totalCholesterol.message'
}
})
hdlCholesterol(nullable: false, blank: false, min: 20, max: 100, validator: { value, obj ->
if (value && !(value instanceof Integer)) {
return 'recalculationParamsCommand.invalid.hdlCholesterol.message'
}
})
systolicBloodPressure(nullable: false, blank: false, min: 90, max: 200, validator: { value, obj ->
if (value && !(value instanceof Integer)) {
return 'recalculationParamsCommand.invalid.systolicBloodPressure.message'
}
})
currentSmoker(nullable: false, blank: false, validator: { value, obj ->
if (value && !(value instanceof Integer)) {
return 'recalculationParamsCommand.invalid.currentSmoker.message'
}
})
diabetesStatus(nullable: false, blank: false, validator: { value, obj ->
if (value && !(value instanceof Integer)) {
return 'recalculationParamsCommand.invalid.diabetesStatus.message'
}
})
hyperDrug(nullable: true, blank: false, validator: { value, obj ->
if (value && !(value instanceof Boolean)) {
return 'recalculationParamsCommand.invalid.hyperDrug.message'
}
})
precision(nullable: true, blank: false, validator: { value, obj ->
if (value && !(value instanceof Integer) || !(1 <= value)) {
return 'recalculationParamsCommand.invalid.precision.message'
}
})
}
def beforeValidate() {
hyperDrug = hyperDrug ?: false
precision = precision ?: 3
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("pid", pid)
.append("age", age)
.append("race", race)
.append("sex", sex)
.append("totalCholesterol", totalCholesterol)
.append("hdlCholesterol", hdlCholesterol)
.append("systolicBloodPressure", systolicBloodPressure)
.append("currentSmoker", currentSmoker)
.append("diabetesStatus", diabetesStatus)
.append("hyperDrug", hyperDrug)
.append("precision", precision)
.toString();
}
}
/**
* Expecting the following params from EHR post call:
* encdte = encounter date in internal epic format
* PATID = patient identifier in internal epic format ZiD
* ENCBPS = Systolic blood pressure
* ENCBPD = Diastolic blood pressure
* ENCWT = Encounter weight
* ENCHT = Encounter Height
*
* @param pid Patient id in internal Epic format
* @param encDate Encounter date in internal Epic format
* @param sbp Systolic blood pressure
* @param dbp Diastolic blood pressure
* @param weight Patient weight
* @param height Patient height
* @param hyperDrug Was hypertension drug administered or not? Default is false
* @param precision What is the number of significant digits needed in the risk score result? Default is 3
*/
class InitialParamsCommand {
String pid
String encDate
Integer sbp
Integer dbp
Double weight
String height
Boolean hyperDrug
Integer precision
static constraints = {
pid(nullable: true, blank: false, validator: { value, obj ->
if (value && !(value.charAt(0) == 'Z')) {
return 'initialParamsCommand.invalid.pid.message'
}
})
encDate(nullable: true, blank: false)
sbp(nullable: true, blank: false, min: 90, max: 200, validator: { value, obj ->
if (value && !(value instanceof Integer)) {
return 'initialParamsCommand.invalid.sbp.message'
}
})
dbp(nullable: true, blank: false, validator: { value, obj ->
if (value && !(value instanceof Integer)) {
return 'initialParamsCommand.invalid.dbp.message'
}
})
weight(nullable: true, blank: false, min:Double.valueOf(0))
height(nullable: true, blank: false, validator: { value, obj ->
if (value && !(value instanceof String)) {
return 'initialParamsCommand.invalid.height.message'
}
})
hyperDrug(nullable: true, blank: false, validator: { value, obj ->
if (value && !(value instanceof Boolean)) {
return 'initialParamsCommand.invalid.hyperDrug.message'
}
})
precision(nullable: true, blank: false, validator: { value, obj ->
if (value && !(value instanceof Integer) || !(1 <= value)) {
return 'initialParamsCommand.invalid.precision.message'
}
})
}
def beforeValidate() {
hyperDrug = hyperDrug ?: false
precision = precision ?: 3
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("pid", pid)
.append("encDate", encDate)
.append("sbp", sbp)
.append("dbp", dbp)
.append("weight", weight)
.append("height", height)
.append("hyperDrug", hyperDrug)
.append("precision", precision)
.toString();
}
}