github.com/TIBCOSoftware/flogo-lib@v0.5.9/core/trigger/handler.go (about) 1 package trigger 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/TIBCOSoftware/flogo-lib/core/action" 8 "github.com/TIBCOSoftware/flogo-lib/core/data" 9 "github.com/TIBCOSoftware/flogo-lib/core/mapper" 10 "github.com/TIBCOSoftware/flogo-lib/logger" 11 ) 12 13 type Handler struct { 14 internal HandlerInf 15 config *HandlerConfig 16 act action.Action 17 } 18 19 type HandlerInf interface { 20 Handle(ctx context.Context, triggerData map[string]interface{}) (map[string]*data.Attribute, error) 21 22 GetSetting(setting string) (interface{}, bool) 23 24 GetOutput() (map[string]interface{}) 25 26 GetStringSetting(setting string) string 27 28 String() string 29 } 30 31 func NewHandler(config *HandlerConfig, act action.Action, outputMd map[string]*data.Attribute, replyMd map[string]*data.Attribute, runner action.Runner) *Handler { 32 helper := &handlerHelperImpl{config: config, act: act, outputMd: outputMd, replyMd: replyMd, runner: runner} 33 handler := &Handler{internal: helper, config: config, act: act} 34 35 if config != nil { 36 if config.Action.Mappings != nil { 37 if len(config.Action.Mappings.Input) > 0 { 38 helper.actionInputMapper = mapper.GetFactory().NewMapper(&data.MapperDef{Mappings: config.Action.Mappings.Input}, nil) 39 } 40 if len(config.Action.Mappings.Output) > 0 { 41 helper.actionOutputMapper = mapper.GetFactory().NewMapper(&data.MapperDef{Mappings: config.Action.Mappings.Output}, nil) 42 } 43 } else if config.ActionMappings != nil { 44 // temporary for backwards compatibility 45 if len(config.ActionMappings.Input) > 0 { 46 helper.actionInputMapper = mapper.GetFactory().NewMapper(&data.MapperDef{Mappings: config.ActionMappings.Input}, nil) 47 } 48 if len(config.ActionMappings.Output) > 0 { 49 helper.actionOutputMapper = mapper.GetFactory().NewMapper(&data.MapperDef{Mappings: config.ActionMappings.Output}, nil) 50 } 51 } 52 } 53 54 return handler 55 } 56 57 func (h *Handler) GetSetting(setting string) (interface{}, bool) { 58 return h.internal.GetSetting(setting) 59 } 60 61 func (h *Handler) GetOutput() (map[string]interface{}) { 62 return h.internal.GetOutput() 63 } 64 65 func (h *Handler) GetStringSetting(setting string) string { 66 return h.internal.GetStringSetting(setting) 67 } 68 69 func (h *Handler) Handle(ctx context.Context, triggerData map[string]interface{}) (map[string]*data.Attribute, error) { 70 71 return h.internal.Handle(ctx, triggerData) 72 } 73 74 func (h *Handler) String() string { 75 return h.internal.String() 76 } 77 78 func NewHandlerAlt(internal HandlerInf) *Handler { 79 return &Handler{internal:internal} 80 } 81 82 type handlerHelperImpl struct { 83 runner action.Runner 84 act action.Action 85 86 outputMd map[string]*data.Attribute 87 replyMd map[string]*data.Attribute 88 89 config *HandlerConfig 90 91 actionInputMapper data.Mapper 92 actionOutputMapper data.Mapper 93 } 94 95 func (h *handlerHelperImpl) GetSetting(setting string) (interface{}, bool) { 96 97 if h.config == nil { 98 return nil, false 99 } 100 101 val, exists := data.GetValueWithResolver(h.config.Settings, setting) 102 103 if !exists { 104 val, exists = data.GetValueWithResolver(h.config.parent.Settings, setting) 105 } 106 107 return val, exists 108 } 109 110 func (h *handlerHelperImpl) GetOutput() (map[string]interface{}) { 111 112 if h.config == nil { 113 return nil 114 } 115 return h.config.Output 116 } 117 118 func (h *handlerHelperImpl) GetStringSetting(setting string) string { 119 val, exists := h.GetSetting(setting) 120 121 if !exists { 122 return "" 123 } 124 125 strVal, err := data.CoerceToString(val) 126 127 if err != nil { 128 return "" 129 } 130 131 return strVal 132 } 133 134 func (h *handlerHelperImpl) Handle(ctx context.Context, triggerData map[string]interface{}) (map[string]*data.Attribute, error) { 135 inputs, err := h.generateInputs(triggerData) 136 137 if err != nil { 138 return nil, err 139 } 140 141 newCtx := NewHandlerContext(ctx, h.config) 142 results, err := h.runner.Execute(newCtx, h.act, inputs) 143 144 if err != nil { 145 return nil, err 146 } 147 148 retValue, err := h.generateOutputs(results) 149 150 return retValue, err 151 } 152 153 func (h *handlerHelperImpl) dataToAttrs(triggerData map[string]interface{}) ([]*data.Attribute, error) { 154 attrs := make([]*data.Attribute, 0, len(h.outputMd)) 155 156 for k, a := range h.outputMd { 157 v, _ := triggerData[k] 158 159 switch t := v.(type) { 160 case *data.Attribute: 161 attr, err := data.NewAttribute(t.Name(), t.Type(), t.Value()) 162 if err != nil { 163 return nil, err 164 } 165 attrs = append(attrs, attr) 166 default: 167 attr, err := data.NewAttribute(a.Name(), a.Type(), v) 168 if err != nil { 169 return nil, err 170 } 171 attrs = append(attrs, attr) 172 } 173 } 174 175 return attrs, nil 176 } 177 178 func (h *handlerHelperImpl) generateInputs(triggerData map[string]interface{}) (map[string]*data.Attribute, error) { 179 180 triggerAttrs, err := h.dataToAttrs(triggerData) 181 182 if err != nil { 183 logger.Errorf("Failed parsing attrs: %s, Error: %s", triggerData, err) 184 return nil, err 185 } 186 187 var inputs map[string]*data.Attribute 188 189 //if h.act.IOMetadata() == nil { 190 // inputs = make(map[string]*data.Attribute, len(triggerAttrs)) 191 // 192 // for _, attr := range triggerAttrs { 193 // inputs[attr.Name()] = attr 194 // } 195 // 196 // return inputs, nil 197 //} 198 //inputMetadata := h.act.IOMetadata().Input 199 200 logger.Debugf("iomd %#v", h.act.IOMetadata()) 201 202 //todo verify this behavior 203 if h.actionInputMapper != nil && h.act.IOMetadata() != nil && h.act.IOMetadata().Input != nil { 204 205 inputMetadata := h.act.IOMetadata().Input 206 207 inScope := data.NewSimpleScope(triggerAttrs, nil) 208 209 var attrs map[string]*data.Attribute 210 211 //todo clean this up 212 if h.act.Metadata() != nil && h.act.Metadata().Passthru { 213 outScope := data.NewFlexableScope(inputMetadata) 214 215 err := h.actionInputMapper.Apply(inScope, outScope) 216 if err != nil { 217 return nil, err 218 } 219 220 attrs = outScope.GetAttrs() 221 222 } else { 223 outScope := data.NewFixedScope(inputMetadata) 224 225 err := h.actionInputMapper.Apply(inScope, outScope) 226 if err != nil { 227 return nil, err 228 } 229 230 attrs = outScope.GetAttrs() 231 } 232 233 inputs = make(map[string]*data.Attribute, len(attrs)) 234 235 for _, attr := range attrs { 236 inputs[attr.Name()] = attr 237 } 238 239 } else { 240 // for backwards compatibility make trigger outputs map directly to action inputs 241 242 logger.Debug("No mapping specified, adding trigger outputs as inputs to action") 243 244 inputs = make(map[string]*data.Attribute, len(triggerAttrs)) 245 246 for _, attr := range triggerAttrs { 247 248 logger.Debugf(" Attr: %s, Type: %s, Value: %v", attr.Name(), attr.Type().String(), attr.Value()) 249 //inputs = append(inputs, data.NewAttribute( attr.Name, attr.Type, attr.Value)) 250 inputs[attr.Name()] = attr 251 252 attrName := "_T." + attr.Name() 253 inputs[attrName] = data.CloneAttribute(attrName, attr) 254 } 255 256 //Add action metadata into flow 257 if h.act.IOMetadata() != nil && h.act.IOMetadata().Input != nil { 258 //Adding action metadat into inputs 259 for _, attr := range h.act.IOMetadata().Input { 260 inputs[attr.Name()] = attr 261 } 262 } 263 } 264 265 return inputs, nil 266 } 267 268 func (h *handlerHelperImpl) generateOutputs(actionResults map[string]*data.Attribute) (map[string]*data.Attribute, error) { 269 270 if len(actionResults) == 0 { 271 return nil, nil 272 } 273 274 if h.actionOutputMapper == nil { 275 //for backwards compatibility 276 return actionResults, nil 277 } 278 279 outputMetadata := h.act.IOMetadata().Output 280 281 if outputMetadata != nil { 282 283 outScope := data.NewFixedScopeFromMap(h.replyMd) 284 inScope := data.NewSimpleScopeFromMap(actionResults, nil) 285 286 err := h.actionOutputMapper.Apply(inScope, outScope) 287 if err != nil { 288 return nil, err 289 } 290 291 return outScope.GetAttrs(), nil 292 } 293 294 return actionResults, nil 295 } 296 297 func (h *handlerHelperImpl) String() string { 298 return fmt.Sprintf("Handler[action:%s]", h.config.Action.Ref) 299 }