github.com/TIBCOSoftware/flogo-lib@v0.5.9/core/mapper/mapper.go (about) 1 package mapper 2 3 import ( 4 "fmt" 5 "github.com/TIBCOSoftware/flogo-lib/core/mapper/assign" 6 7 "encoding/json" 8 "strings" 9 10 "github.com/TIBCOSoftware/flogo-lib/core/data" 11 "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper" 12 "github.com/TIBCOSoftware/flogo-lib/logger" 13 ) 14 15 var mapplerLog = logger.GetLogger("basic-mapper") 16 17 type Factory interface { 18 // NewMapper creates a new data.Mapper from the specified data.MapperDef 19 NewMapper(mapperDef *data.MapperDef, resolver data.Resolver) data.Mapper 20 21 // NewUniqueMapper creates a unique data.Mapper from the specified data.MapperDef 22 // the ID can be used to facilitate use precompiled mappers 23 NewUniqueMapper(ID string, mapperDef *data.MapperDef, resolver data.Resolver) data.Mapper 24 } 25 26 var factory Factory 27 28 func SetFactory(factory Factory) { 29 factory = factory 30 } 31 32 func GetFactory() Factory { 33 34 if factory == nil { 35 factory = &BasicMapperFactory{} 36 } 37 38 return factory 39 } 40 41 type BasicMapperFactory struct { 42 } 43 44 func (mf *BasicMapperFactory) NewMapper(mapperDef *data.MapperDef, resolver data.Resolver) data.Mapper { 45 return NewBasicMapper(mapperDef, resolver) 46 } 47 48 func (mf *BasicMapperFactory) NewUniqueMapper(ID string, mapperDef *data.MapperDef, resolver data.Resolver) data.Mapper { 49 return NewBasicMapper(mapperDef, resolver) 50 } 51 52 // BasicMapper is a simple object holding and executing mappings 53 type BasicMapper struct { 54 mappings []*data.MappingDef 55 resolver data.Resolver 56 } 57 58 // NewBasicMapper creates a new BasicMapper with the specified mappings 59 func NewBasicMapper(mapperDef *data.MapperDef, resolver data.Resolver) data.Mapper { 60 61 var mapper BasicMapper 62 mapper.mappings = mapperDef.Mappings 63 64 if resolver == nil { 65 mapper.resolver = &data.BasicResolver{} 66 } else { 67 mapper.resolver = resolver 68 } 69 70 return &mapper 71 } 72 73 // Mappings gets the mappings of the BasicMapper 74 func (m *BasicMapper) Mappings() []*data.MappingDef { 75 return m.mappings 76 } 77 78 // Apply executes the mappings using the values from the input scope 79 // and puts the results in the output scope 80 // 81 // return error 82 func (m *BasicMapper) Apply(inputScope data.Scope, outputScope data.Scope) error { 83 84 if err := m.UpdateMapping(); err != nil { 85 return fmt.Errorf("Update mapping ref error %s", err.Error()) 86 } 87 88 //todo validate types 89 for _, mapping := range m.mappings { 90 91 switch mapping.Type { 92 case data.MtAssign: 93 err := assign.MapAssign(mapping, inputScope, outputScope, m.resolver) 94 if err != nil { 95 return fmt.Errorf("assign mapping failed, due to %s", err.Error()) 96 } 97 case data.MtLiteral: 98 err := assign.SetValueToOutputScope(mapping.MapTo, outputScope, mapping.Value) 99 if err != nil { 100 err = fmt.Errorf("set value %+v to output [%s] error - %s", mapping.Value, mapping.MapTo, err.Error()) 101 mapplerLog.Error(err) 102 return err 103 } 104 case data.MtObject: 105 106 val, err := MapObject(mapping.Value, inputScope, m.resolver) 107 if err != nil { 108 return err 109 } 110 err = assign.SetValueToOutputScope(mapping.MapTo, outputScope, val) 111 if err != nil { 112 err = fmt.Errorf("set value %+v to output [%s] error - %s", val, mapping.MapTo, err.Error()) 113 mapplerLog.Error(err) 114 return err 115 } 116 case data.MtExpression: 117 err := exprmapper.MapExpreesion(mapping, inputScope, outputScope, m.resolver) 118 if err != nil { 119 return fmt.Errorf("expression mapping failed, due to %s", err.Error()) 120 } 121 case data.MtArray: 122 //ArrayMapping 123 mapplerLog.Debugf("Array mapping value %s", mapping.Value) 124 //Array mapping value must be string 125 arrayMapping, err := exprmapper.ParseArrayMapping(mapping.Value) 126 if err != nil { 127 return fmt.Errorf("array mapping structure error - %s", err.Error()) 128 } 129 130 if err := arrayMapping.Validate(); err != nil { 131 return err 132 } 133 if err = arrayMapping.DoArrayMapping(inputScope, outputScope, m.resolver); err != nil { 134 return fmt.Errorf("array mapping error - %s", err.Error()) 135 } 136 137 } 138 139 } 140 141 return nil 142 } 143 144 func (m *BasicMapper) UpdateMapping() error { 145 var newMappingDefs []*data.MappingDef 146 for _, mapping := range m.mappings { 147 var mappingDef *data.MappingDef 148 //Remove all $INPUT for mapTo include array mapping 149 if mapping.MapTo != "" && strings.HasPrefix(mapping.MapTo, exprmapper.MAP_TO_INPUT) { 150 mappingDef = &data.MappingDef{Type: mapping.Type, Value: mapping.Value, MapTo: exprmapper.RemovePrefixInput(mapping.MapTo)} 151 } else { 152 mappingDef = mapping 153 } 154 155 switch mappingDef.Type { 156 //Array mapping 157 case data.MtArray: 158 //Update Array Mapping 159 arrayMapping, err := exprmapper.ParseArrayMapping(mapping.Value) 160 if err != nil { 161 return fmt.Errorf("Array mapping structure error - %s", err.Error()) 162 } 163 164 arrayMapping.RemovePrefixForMapTo() 165 v, err := json.Marshal(arrayMapping) 166 if err != nil { 167 return err 168 } 169 mappingDef.Value = string(v) 170 } 171 mapplerLog.Debugf("Updated mapping def %+v", mappingDef) 172 newMappingDefs = append(newMappingDefs, mappingDef) 173 } 174 m.mappings = newMappingDefs 175 return nil 176 }