in wstl1/mapping_engine/mapping/engine.go [98:203]
func EvaluateValueSource(vs *mappb.ValueSource, args []jsonutil.JSONMetaNode, output jsonutil.JSONToken, pctx *types.Context, a jsonutil.JSONTokenAccessor) (jsonutil.JSONMetaNode, error) {
if vs == nil {
return nil, errors.New("nil value source pointer")
}
nextArgs := make([]jsonutil.JSONMetaNode, 0, 1)
var iterableIndicies []bool
var anyArgsToIterate bool
if vs.GetSource() != nil {
arg, err := evaluateValueSourceSource(vs, args, output, pctx, a)
if err != nil {
return nil, err
}
nextArgs = append(nextArgs, arg)
iterableIndicies = append(iterableIndicies, isArray(vs))
anyArgsToIterate = isArray(vs)
for _, s := range vs.AdditionalArg {
arg, err := EvaluateValueSource(s, args, output, pctx, a)
if err != nil {
return nil, errs.Wrap(errs.NewProtoLocation(s, vs), err)
}
nextArgs = append(nextArgs, arg)
// Check if we need to enumerate each additional arg (based on whether it/it's projector is enumerated)
shouldIterate := (isArray(s) && s.GetProjector() == "") || isSelectorArray(s.GetProjector())
iterableIndicies = append(iterableIndicies, shouldIterate)
anyArgsToIterate = anyArgsToIterate || shouldIterate
}
}
projName := strings.TrimSuffix(vs.Projector, "[]")
proj, err := pctx.Registry.FindProjector(projName)
if err != nil {
return nil, fmt.Errorf("error finding projector: %v", err)
}
if anyArgsToIterate {
if len(nextArgs) == 0 {
return nil, errors.New("source was enumerated (ended with []) but source itself did not exist (?)")
}
// Zip the arguments together - enumerate any additional args that need it.
zippedArgs, err := zip(nextArgs, iterableIndicies)
if err != nil {
return nil, fmt.Errorf("error zipping args: %v", err)
}
projVals := make([]jsonutil.JSONMetaNode, 0)
for _, args := range zippedArgs {
sources := []string{}
for _, s := range args {
if s != nil {
sources = append(sources, s.ProvenanceString())
} else {
sources = append(sources, "null")
}
}
pv, err := proj(args, pctx)
if err != nil {
return nil, errs.Wrap(errs.Locationf("Iterated arguments %q", strings.Join(sources, ", ")), err)
}
pv = postProcessValue(pv)
if isNil(pv) {
continue
}
pvm, err := jsonutil.TokenToNodeWithProvenance(pv, "", jsonutil.Provenance{
Sources: args,
Function: projName,
})
if err != nil {
return nil, err
}
projVals = append(projVals, pvm)
}
return jsonutil.JSONMetaArrayNode{
Items: projVals,
JSONMeta: jsonutil.NewJSONMeta("", jsonutil.Provenance{
Sources: nextArgs,
Function: projName,
}),
}, nil
}
pv, err := proj(nextArgs, pctx)
if err != nil {
return nil, err
}
if projName == "" && len(nextArgs) == 1 && nextArgs[0] != nil {
return jsonutil.TokenToNodeWithProvenance(pv, nextArgs[0].Key(), nextArgs[0].Provenance())
}
return jsonutil.TokenToNodeWithProvenance(pv, "", jsonutil.Provenance{
Sources: nextArgs,
Function: projName,
})
}