Skip to content

Commit

Permalink
Allow embedded deviceEvent/status in deviceEvent/alarm; cleanup calcu…
Browse files Browse the repository at this point in the history
…lator embedded bolus
  • Loading branch information
darinkrauss committed Jul 21, 2016
1 parent 2f02162 commit e370608
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 24 deletions.
10 changes: 7 additions & 3 deletions data/types/base/bolus/calculator/calculator.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type Calculator struct {
BloodGlucoseInput *float64 `json:"bgInput,omitempty" bson:"bgInput,omitempty"`
Units *string `json:"units,omitempty" bson:"units,omitempty"`

//private field that will be used to build and normalize the embedded bolus
// Embedded bolus
bolus *data.Datum
}

Expand Down Expand Up @@ -159,8 +159,10 @@ func (c *Calculator) Normalize(normalizer data.Normalizer) error {
}

if c.bolus != nil {
(*c.bolus).Normalize(normalizer.NewChildNormalizer("bolus"))
normalizer.AppendDatum(*c.bolus)
if err := (*c.bolus).Normalize(normalizer.NewChildNormalizer("bolus")); err != nil {
return err
}

switch (*c.bolus).(type) {
case *extended.Extended:
c.BolusID = &(*c.bolus).(*extended.Extended).ID
Expand All @@ -169,6 +171,8 @@ func (c *Calculator) Normalize(normalizer data.Normalizer) error {
case *combination.Combination:
c.BolusID = &(*c.bolus).(*combination.Combination).ID
}

normalizer.AppendDatum(*c.bolus)
c.bolus = nil
}

Expand Down
20 changes: 10 additions & 10 deletions data/types/base/bolus/calculator/calculator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func NewRawObjectWithMmolL() map[string]interface{} {
rawObject["recommended"] = map[string]interface{}{"net": 50, "correction": -50, "carb": 50}
rawObject["bgTarget"] = map[string]interface{}{"target": 8.0, "range": 1.0}

rawObject["bolus"] = embeddedBolus("bolus", "normal", 52.1, 0.0, 0)
rawObject["bolus"] = NewEmbeddedBolus("bolus", "normal", 52.1, 0.0, 0)

rawObject["units"] = bloodglucose.MmolL
return rawObject
Expand All @@ -52,7 +52,7 @@ func NewRawObjectWithMgdL() map[string]interface{} {
rawObject["recommended"] = map[string]interface{}{"net": 50, "correction": -50, "carb": 50}
rawObject["bgTarget"] = map[string]interface{}{"target": 100, "range": 10.0}

rawObject["bolus"] = embeddedBolus("bolus", "normal", 52.1, 0.0, 0)
rawObject["bolus"] = NewEmbeddedBolus("bolus", "normal", 52.1, 0.0, 0)

rawObject["units"] = bloodglucose.MgdL
return rawObject
Expand All @@ -70,7 +70,7 @@ func NewMeta() interface{} {
}
}

var embeddedBolus = func(datumType interface{}, subType interface{}, normal, extended float64, duration int) map[string]interface{} {
func NewEmbeddedBolus(datumType interface{}, subType interface{}, normal, extended float64, duration int) map[string]interface{} {
var rawBolus = testing.RawBaseObject()

if datumType != nil {
Expand Down Expand Up @@ -252,19 +252,19 @@ var _ = Describe("Calculator", func() {

Context("bolus", func() {
DescribeTable("invalid when type", testing.ExpectFieldNotValid,
Entry("is missing", NewRawObjectWithMgdl(), "bolus", embeddedBolus(nil, "normal", 52.1, 0.0, 0),
Entry("is missing", NewRawObjectWithMgdl(), "bolus", NewEmbeddedBolus(nil, "normal", 52.1, 0.0, 0),
[]*service.Error{testing.ComposeError(validator.ErrorValueNotExists(), "/bolus/type", NewMeta())},
),
Entry("is not valid", NewRawObjectWithMgdl(), "bolus", embeddedBolus("invalid", "normal", 52.1, 0.0, 0),
Entry("is not valid", NewRawObjectWithMgdl(), "bolus", NewEmbeddedBolus("invalid", "normal", 52.1, 0.0, 0),
[]*service.Error{testing.ComposeError(validator.ErrorStringNotOneOf("invalid", []string{"bolus"}), "/bolus/type", NewMeta())},
),
)

DescribeTable("invalid when subType", testing.ExpectFieldNotValid,
Entry("is missing", NewRawObjectWithMgdl(), "bolus", embeddedBolus("bolus", nil, 0.0, 52.1, 0),
Entry("is missing", NewRawObjectWithMgdl(), "bolus", NewEmbeddedBolus("bolus", nil, 0.0, 52.1, 0),
[]*service.Error{testing.ComposeError(validator.ErrorValueNotExists(), "/bolus/subType", NewMeta())},
),
Entry("is not valid", NewRawObjectWithMgdl(), "bolus", embeddedBolus("bolus", "invalid", 0.0, 52.1, 0),
Entry("is not valid", NewRawObjectWithMgdl(), "bolus", NewEmbeddedBolus("bolus", "invalid", 0.0, 52.1, 0),
[]*service.Error{testing.ComposeError(validator.ErrorStringNotOneOf("invalid", []string{"dual/square", "normal", "square"}), "/bolus/subType", NewMeta())},
),
)
Expand Down Expand Up @@ -329,9 +329,9 @@ var _ = Describe("Calculator", func() {
calculatorBolus := calculatorDatum.(*calculator.Calculator)
Expect(calculatorBolus.BolusID).To(Not(BeNil()))
},
Entry("is normal", NewRawObjectWithMgdl(), "bolus", embeddedBolus("bolus", "normal", 52.1, 0.0, 0)),
Entry("is square", NewRawObjectWithMgdl(), "bolus", embeddedBolus("bolus", "square", 0.0, 52.1, 1000)),
Entry("is dual/square", NewRawObjectWithMgdl(), "bolus", embeddedBolus("bolus", "dual/square", 52.1, 52.1, 1000)),
Entry("is normal", NewRawObjectWithMgdl(), "bolus", NewEmbeddedBolus("bolus", "normal", 52.1, 0.0, 0)),
Entry("is square", NewRawObjectWithMgdl(), "bolus", NewEmbeddedBolus("bolus", "square", 0.0, 52.1, 1000)),
Entry("is dual/square", NewRawObjectWithMgdl(), "bolus", NewEmbeddedBolus("bolus", "dual/square", 52.1, 52.1, 1000)),
)
})
})
Expand Down
51 changes: 47 additions & 4 deletions data/types/base/device/alarm/alarm.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@ package alarm
import (
"github.com/tidepool-org/platform/data"
"github.com/tidepool-org/platform/data/types/base/device"
"github.com/tidepool-org/platform/data/types/base/device/status"
"github.com/tidepool-org/platform/data/validator"
)

type Alarm struct {
device.Device `bson:",inline"`

AlarmType *string `json:"alarmType,omitempty" bson:"alarmType,omitempty"`
Status *string `json:"status,omitempty" bson:"status,omitempty"`
StatusID *string `json:"status,omitempty" bson:"status,omitempty"`

// Embedded status
status *data.Datum
}

func SubType() string {
Expand All @@ -45,7 +50,9 @@ func (a *Alarm) Init() {
a.Device.SubType = SubType()

a.AlarmType = nil
a.Status = nil
a.StatusID = nil

a.status = nil
}

func (a *Alarm) Parse(parser data.ObjectParser) error {
Expand All @@ -54,7 +61,22 @@ func (a *Alarm) Parse(parser data.ObjectParser) error {
}

a.AlarmType = parser.ParseString("alarmType")
a.Status = parser.ParseString("status")

// TODO: This is a bit hacky to ensure we only parse true status data. Is there a better way?

if statusParser := parser.NewChildObjectParser("status"); statusParser.Object() != nil {
if statusType := statusParser.ParseString("type"); statusType == nil {
statusParser.AppendError("type", validator.ErrorValueNotExists())
} else if *statusType != device.Type() {
statusParser.AppendError("type", validator.ErrorStringNotOneOf(*statusType, []string{device.Type()}))
} else if statusSubType := statusParser.ParseString("subType"); statusSubType == nil {
statusParser.AppendError("subType", validator.ErrorValueNotExists())
} else if *statusSubType != status.SubType() {
statusParser.AppendError("subType", validator.ErrorStringNotOneOf(*statusSubType, []string{status.SubType()}))
} else {
a.status = parser.ParseDatum("status")
}
}

return nil
}
Expand All @@ -78,7 +100,28 @@ func (a *Alarm) Validate(validator data.Validator) error {
},
)

validator.ValidateString("status", a.Status).LengthGreaterThan(1)
if a.status != nil {
(*a.status).Validate(validator.NewChildValidator("status"))
}

return nil
}

func (a *Alarm) Normalize(normalizer data.Normalizer) error {
if err := a.Device.Normalize(normalizer); err != nil {
return err
}

if a.status != nil {
if err := (*a.status).Normalize(normalizer.NewChildNormalizer("status")); err != nil {
return err
}

a.StatusID = &(*a.status).(*status.Status).ID

normalizer.AppendDatum(*a.status)
a.status = nil
}

return nil
}
39 changes: 32 additions & 7 deletions data/types/base/device/alarm/alarm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"

"github.com/tidepool-org/platform/data/parser"
"github.com/tidepool-org/platform/data/types/base/device"
"github.com/tidepool-org/platform/data/types/base/testing"
"github.com/tidepool-org/platform/data/validator"
Expand All @@ -15,7 +16,7 @@ func NewRawObject() map[string]interface{} {
rawObject["type"] = "deviceEvent"
rawObject["subType"] = "alarm"
rawObject["alarmType"] = "other"
rawObject["status"] = "OK"
rawObject["status"] = NewEmbeddedStatus("deviceEvent", "status")
return rawObject
}

Expand All @@ -26,6 +27,22 @@ func NewMeta() interface{} {
}
}

func NewEmbeddedStatus(datumType interface{}, subType interface{}) map[string]interface{} {
var rawStatus = testing.RawBaseObject()

if datumType != nil {
rawStatus["type"] = datumType
}
if subType != nil {
rawStatus["subType"] = subType
}
rawStatus["status"] = "suspended"
rawStatus["duration"] = 360000
rawStatus["reason"] = map[string]interface{}{"suspended": "automatic", "resumed": "automatic"}

return rawStatus
}

var _ = Describe("Alarm", func() {
Context("alarmType", func() {
DescribeTable("invalid when", testing.ExpectFieldNotValid,
Expand All @@ -51,13 +68,21 @@ var _ = Describe("Alarm", func() {

Context("status", func() {
DescribeTable("invalid when", testing.ExpectFieldNotValid,
Entry("is one character", NewRawObject(), "status", "x",
[]*service.Error{testing.ComposeError(validator.ErrorLengthNotGreaterThan(1, 1), "/status", NewMeta())},
Entry("status is not an object", NewRawObject(), "status", "string",
[]*service.Error{testing.ComposeError(parser.ErrorTypeNotObject("string"), "/status", NewMeta())},
),
Entry("type is missing", NewRawObject(), "status", NewEmbeddedStatus(nil, "status"),
[]*service.Error{testing.ComposeError(validator.ErrorValueNotExists(), "/status/type", NewMeta())},
),
Entry("type is not valid", NewRawObject(), "status", NewEmbeddedStatus("invalid", "status"),
[]*service.Error{testing.ComposeError(validator.ErrorStringNotOneOf("invalid", []string{"deviceEvent"}), "/status/type", NewMeta())},
),
Entry("subType is missing", NewRawObject(), "status", NewEmbeddedStatus("deviceEvent", nil),
[]*service.Error{testing.ComposeError(validator.ErrorValueNotExists(), "/status/subType", NewMeta())},
),
Entry("subType is not valid", NewRawObject(), "status", NewEmbeddedStatus("deviceEvent", "invalid"),
[]*service.Error{testing.ComposeError(validator.ErrorStringNotOneOf("invalid", []string{"status"}), "/status/subType", NewMeta())},
),
)

DescribeTable("valid when", testing.ExpectFieldIsValid,
Entry("is more then one character", NewRawObject(), "status", "xx"),
)
})
})

0 comments on commit e370608

Please sign in to comment.