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  }