github.com/TIBCOSoftware/flogo-lib@v0.5.9/core/mapper/exprmapper/json/set.go (about)

     1  package json
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/json/field"
     7  )
     8  
     9  type JSONData struct {
    10  	container *Container
    11  	rw        sync.RWMutex
    12  }
    13  
    14  func SetStringValue(data interface{}, jsonData string, mappingField *field.MappingField) (interface{}, error) {
    15  	jsonParsed, err := ParseJSON([]byte(jsonData))
    16  	if err != nil {
    17  		return nil, err
    18  
    19  	}
    20  	container := &JSONData{container: jsonParsed, rw: sync.RWMutex{}}
    21  	err = handleSetValue(data, container, mappingField.Getfields())
    22  	return container.container.object, err
    23  }
    24  
    25  func SetFieldValue(data interface{}, jsonData interface{}, mappingField *field.MappingField) (interface{}, error) {
    26  	switch t := jsonData.(type) {
    27  	case string:
    28  		return SetStringValue(data, t, mappingField)
    29  	default:
    30  		jsonParsed, err := Consume(jsonData)
    31  		if err != nil {
    32  			return nil, err
    33  		}
    34  		container := &JSONData{container: jsonParsed, rw: sync.RWMutex{}}
    35  		err = handleSetValue(data, container, mappingField.Getfields())
    36  		if err != nil {
    37  			return nil, err
    38  		}
    39  		return container.container.object, nil
    40  	}
    41  
    42  }
    43  
    44  func handleSetValue(value interface{}, jsonData *JSONData, fields []string) error {
    45  
    46  	jsonData.rw.Lock()
    47  	defer jsonData.rw.Unlock()
    48  
    49  	container := jsonData.container
    50  	if hasArrayFieldInArray(fields) {
    51  		arrayFields, fieldNameindex, arrayIndex := getArrayFieldName(fields)
    52  		//No array field found
    53  		if fieldNameindex == -1 {
    54  			if arrayIndex == -2 {
    55  				//Append
    56  				err := container.ArrayAppend(value, arrayFields...)
    57  				if err != nil {
    58  					return err
    59  				}
    60  			} else {
    61  				//set to exist index array
    62  				size, err := container.ArrayCount(arrayFields...)
    63  				if err != nil {
    64  					return err
    65  				}
    66  				if arrayIndex > size-1 {
    67  					err := container.ArrayAppend(value, arrayFields...)
    68  					if err != nil {
    69  						return err
    70  					}
    71  				} else {
    72  					array := container.S(arrayFields...)
    73  					_, err := array.SetIndex(value, arrayIndex)
    74  					if err != nil {
    75  						return err
    76  					}
    77  				}
    78  			}
    79  		} else {
    80  			restFields := fields[fieldNameindex+1:]
    81  			//Has field before [0]
    82  			if arrayFields != nil {
    83  				//check if array field exist
    84  				if container.Exists(arrayFields...) {
    85  					if restFields == nil || len(restFields) <= 0 {
    86  						array, ok := container.Search(arrayFields...).Data().([]interface{})
    87  						if ok {
    88  							if arrayIndex > len(array)-1 {
    89  								array = append(array, value)
    90  							} else {
    91  								array[arrayIndex] = value
    92  							}
    93  						}
    94  						_, err := container.Set(array, arrayFields...)
    95  						return err
    96  					} else {
    97  						var element *Container
    98  						var err error
    99  						count, err := container.ArrayCount(arrayFields...)
   100  						if err != nil {
   101  							return err
   102  						}
   103  						if arrayIndex > count-1 {
   104  							maps := make(map[string]interface{})
   105  							newObject, _ := Consume(maps)
   106  							_, err = newObject.Set(value, restFields...)
   107  							log.Debugf("new object %s", newObject.String())
   108  							if err != nil {
   109  								return err
   110  							}
   111  
   112  							err = container.ArrayAppend(maps, arrayFields...)
   113  							if err != nil {
   114  								return err
   115  							}
   116  							if !hasArrayFieldInArray(restFields) {
   117  								return nil
   118  							}
   119  
   120  						}
   121  
   122  						element, err = container.ArrayElement(arrayIndex, arrayFields...)
   123  						if err != nil {
   124  							return err
   125  						}
   126  						return handleSetValue(value, &JSONData{container: element, rw: sync.RWMutex{}}, restFields)
   127  					}
   128  				}
   129  
   130  			} else if fieldNameindex == 0 && getFieldName(fields[fieldNameindex]) == "" {
   131  				//Root only [0]
   132  				array, ok := container.Data().([]interface{})
   133  				if !ok {
   134  					var err error
   135  					array, err = ToArray(container.Data())
   136  					if err != nil {
   137  						array = make([]interface{}, arrayIndex+1)
   138  					}
   139  
   140  				}
   141  				container.object = array
   142  
   143  				if restFields == nil || len(restFields) <= 0 {
   144  					_, err := container.SetIndex(value, arrayIndex)
   145  					return err
   146  				} else {
   147  					if hasArrayFieldInArray(restFields) {
   148  						//We need make sure the array element is not empty
   149  						count, err := container.ArrayCount(arrayFields...)
   150  						if err != nil {
   151  							return err
   152  						}
   153  						if arrayIndex > count-1 {
   154  							err = container.ArrayAppend(map[string]interface{}{})
   155  							if err != nil {
   156  								return err
   157  							}
   158  						}
   159  
   160  						arrayElement, err := container.ArrayElement(arrayIndex)
   161  						if err != nil {
   162  							return err
   163  						}
   164  						if arrayElement.object == nil {
   165  							arrayElement.object = map[string]interface{}{}
   166  						}
   167  						err = handleSetValue(value, &JSONData{container: arrayElement, rw: sync.RWMutex{}}, restFields)
   168  						if err != nil {
   169  							return err
   170  						}
   171  						//Set value back to array
   172  						_, err = container.SetIndex(arrayElement.object, arrayIndex)
   173  						return err
   174  					}
   175  
   176  					arrayElement, err := getArrayElementValue(container, arrayFields, restFields, arrayIndex, value)
   177  					if err != nil {
   178  						return err
   179  					}
   180  
   181  					_, err = container.SetIndex(arrayElement.object, arrayIndex)
   182  					return err
   183  				}
   184  			}
   185  
   186  			//Not exist in the exist container, create new one
   187  			array, err := container.ArrayOfSize(arrayIndex+1, arrayFields...)
   188  			if err != nil {
   189  				return err
   190  			}
   191  
   192  			if hasArrayFieldInArray(restFields) {
   193  				//We need make sure the array element is not empty
   194  				arrayElement, err := array.ArrayElement(arrayIndex)
   195  				if err != nil {
   196  					return err
   197  				}
   198  				if arrayElement.object == nil {
   199  					arrayElement.object = map[string]interface{}{}
   200  				}
   201  
   202  				err = handleSetValue(value, &JSONData{container: arrayElement, rw: sync.RWMutex{}}, restFields)
   203  				if err != nil {
   204  					return err
   205  				}
   206  				//Set value back to array
   207  				_, err = container.S(arrayFields...).SetIndex(arrayElement.object, arrayIndex)
   208  				return err
   209  			}
   210  
   211  			maps := make(map[string]interface{})
   212  			newObject, _ := Consume(maps)
   213  			_, err = newObject.Set(value, restFields...)
   214  			log.Debugf("new object %s", newObject.String())
   215  			if err != nil {
   216  				return err
   217  			}
   218  			_, err = array.SetIndex(newObject.object, arrayIndex)
   219  		}
   220  	} else {
   221  		_, err := jsonData.container.Set(value, fields...)
   222  		if err != nil {
   223  			return err
   224  		}
   225  	}
   226  	return nil
   227  }
   228  
   229  func getArrayElementValue(container *Container, arrayFields []string, restFields []string, arrayIndex int, value interface{}) (*Container, error) {
   230  	count, err := container.ArrayCount(arrayFields...)
   231  	if err != nil {
   232  		return nil, err
   233  	}
   234  
   235  	if arrayIndex > count-1 {
   236  		maps := make(map[string]interface{})
   237  		newObject, _ := Consume(maps)
   238  		_, err := newObject.Set(value, restFields...)
   239  		log.Debugf("new object %s", newObject.String())
   240  		if err != nil {
   241  			return nil, err
   242  		}
   243  		value = newObject.object
   244  	}
   245  
   246  	arrayElement, err := container.ArrayElement(arrayIndex)
   247  	if err != nil {
   248  		return nil, err
   249  	}
   250  	if arrayElement.object == nil {
   251  		arrayElement.object = map[string]interface{}{}
   252  	}
   253  	_, err = arrayElement.Set(value, restFields...)
   254  	return arrayElement, err
   255  }