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  }