func EvaluateValueSource()

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,
	})
}