github.com/TIBCOSoftware/flogo-lib@v0.5.9/core/data/attribute.go (about) 1 package data 2 3 import ( 4 "encoding/json" 5 "errors" 6 ) 7 8 // Attribute is a simple structure used to define a data Attribute/property 9 type Attribute struct { 10 name string 11 dataType Type 12 value interface{} 13 } 14 15 // NewAttribute constructs a new attribute 16 func NewAttribute(name string, dataType Type, value interface{}) (*Attribute, error) { 17 18 var attr Attribute 19 attr.name = name 20 attr.dataType = dataType 21 attr.value = value 22 23 var err error 24 attr.value, err = CoerceToValue(value, dataType) 25 26 return &attr, err 27 } 28 29 // NewZeroAttribute constructs a new attribute 30 func NewZeroAttribute(name string, dataType Type) *Attribute { 31 32 var attr Attribute 33 attr.name = name 34 attr.dataType = dataType 35 attr.value, _ = CoerceToValue(nil, dataType) 36 37 return &attr 38 } 39 40 // CloneAttribute clones the given attribute assigning a new name 41 func CloneAttribute(name string, oldAttr *Attribute) *Attribute { 42 var attr Attribute 43 attr.name = name 44 attr.dataType = oldAttr.dataType 45 attr.value = oldAttr.value 46 47 return &attr 48 } 49 50 func (a *Attribute) Name() string { 51 return a.name 52 } 53 54 func (a *Attribute) Type() Type { 55 return a.dataType 56 } 57 58 func (a *Attribute) Value() interface{} { 59 return a.value 60 } 61 62 func (a *Attribute) SetValue(value interface{}) (err error) { 63 a.value, err = CoerceToValue(value, a.dataType) 64 return err 65 } 66 67 // MarshalJSON implements json.Marshaler.MarshalJSON 68 func (a *Attribute) MarshalJSON() ([]byte, error) { 69 70 return json.Marshal(&struct { 71 Name string `json:"name"` 72 Type string `json:"type"` 73 Value interface{} `json:"value"` 74 }{ 75 Name: a.name, 76 Type: a.dataType.String(), 77 Value: a.value, 78 }) 79 } 80 81 // UnmarshalJSON implements json.Unmarshaler.UnmarshalJSON 82 func (a *Attribute) UnmarshalJSON(data []byte) error { 83 84 ser := &struct { 85 Name string `json:"name"` 86 Type string `json:"type"` 87 Value interface{} `json:"value"` 88 }{} 89 90 if err := json.Unmarshal(data, ser); err != nil { 91 return err 92 } 93 94 a.name = ser.Name 95 dt, exists := ToTypeEnum(ser.Type) 96 97 if !exists { 98 return errors.New("unknown data type: " + ser.Type) 99 } 100 a.dataType = dt 101 102 strValue, ok := ser.Value.(string) 103 if ok { 104 if strValue != "" && strValue[0] == '$' { 105 // Let resolver resolve value 106 val, err := GetBasicResolver().Resolve(strValue, nil) 107 if err != nil { 108 return err 109 } 110 // Set resolved value 111 ser.Value = val 112 } 113 } 114 115 val, err := CoerceToValue(ser.Value, a.dataType) 116 117 if err != nil { 118 return err 119 } else { 120 a.value = val 121 } 122 123 return nil 124 } 125 126 // ComplexObject is the value that is used when using a "COMPLEX_OBJECT" type 127 type ComplexObject struct { 128 Metadata string `json:"metadata"` 129 Value interface{} `json:"value"` 130 } 131 132 type IOMetadata struct { 133 Input map[string]*Attribute 134 Output map[string]*Attribute 135 } 136 137 func (md *IOMetadata) UnmarshalJSON(b []byte) error { 138 139 ser := &struct { 140 Input []*Attribute `json:"input"` 141 Output []*Attribute `json:"output"` 142 }{} 143 144 if err := json.Unmarshal(b, ser); err != nil { 145 return err 146 } 147 148 md.Input = make(map[string]*Attribute, len(ser.Input)) 149 md.Output = make(map[string]*Attribute, len(ser.Output)) 150 151 for _, attr := range ser.Input { 152 md.Input[attr.Name()] = attr 153 } 154 155 for _, attr := range ser.Output { 156 md.Output[attr.Name()] = attr 157 } 158 159 return nil 160 } 161 162 func (md *IOMetadata) MarshalJSON() ([]byte, error) { 163 var mdInputs []*Attribute 164 var mdOutputs []*Attribute 165 166 for _, v := range md.Input { 167 mdInputs = append(mdInputs, v) 168 } 169 for _, v := range md.Output { 170 mdOutputs = append(mdOutputs, v) 171 } 172 173 return json.Marshal(&struct { 174 Input []*Attribute `json:"input"` 175 Output []*Attribute `json:"output"` 176 }{ 177 Input: mdInputs, 178 Output: mdOutputs, 179 }) 180 }