buildConstructorCode builds the transformation code to create a projected type from a service type and vice versa. source and target contains the projected/service contextual attributes sourceVar and targetVar contains the variable name that holds the source and target data structures in the trans
(src, tgt *expr.AttributeExpr, sourceVar, targetVar string, sourceCtx, targetCtx *codegen.AttributeContext, view string)
| 2337 | // |
| 2338 | // view is used to generate the constructor function name. |
| 2339 | func buildConstructorCode(src, tgt *expr.AttributeExpr, sourceVar, targetVar string, sourceCtx, targetCtx *codegen.AttributeContext, view string) (string, []*codegen.TransformFunctionData) { |
| 2340 | var ( |
| 2341 | helpers []*codegen.TransformFunctionData |
| 2342 | buf bytes.Buffer |
| 2343 | ) |
| 2344 | rt := src.Type.(*expr.ResultTypeExpr) |
| 2345 | arr := expr.AsArray(tgt.Type) |
| 2346 | |
| 2347 | data := map[string]any{ |
| 2348 | "ArgVar": sourceVar, |
| 2349 | "ReturnVar": targetVar, |
| 2350 | "IsCollection": arr != nil, |
| 2351 | "TargetType": targetCtx.Scope.Name(tgt, targetCtx.Pkg(tgt), targetCtx.Pointer, targetCtx.UseDefault), |
| 2352 | } |
| 2353 | |
| 2354 | if arr != nil { |
| 2355 | // result type collection |
| 2356 | init := "new" + targetCtx.Scope.Name(arr.ElemType, "", targetCtx.Pointer, targetCtx.UseDefault) |
| 2357 | if view != "" && view != expr.DefaultView { |
| 2358 | init += codegen.Goify(view, true) |
| 2359 | } |
| 2360 | data["InitName"] = init |
| 2361 | if err := initTypeCodeTmpl.Execute(&buf, data); err != nil { |
| 2362 | panic(err) // bug |
| 2363 | } |
| 2364 | return buf.String(), helpers |
| 2365 | } |
| 2366 | |
| 2367 | // service type to projected type (or vice versa) |
| 2368 | targetRTs := &expr.Object{} |
| 2369 | tatt := expr.DupAtt(tgt) |
| 2370 | tobj := expr.AsObject(tatt.Type) |
| 2371 | for _, nat := range *tobj { |
| 2372 | if _, ok := nat.Attribute.Type.(*expr.ResultTypeExpr); ok { |
| 2373 | targetRTs.Set(nat.Name, nat.Attribute) |
| 2374 | tobj.Delete(nat.Name) |
| 2375 | } |
| 2376 | } |
| 2377 | data["Source"] = sourceVar |
| 2378 | data["Target"] = targetVar |
| 2379 | |
| 2380 | // build code for target with no result types |
| 2381 | code, helpers, err := codegen.GoTransform(src, tatt, sourceVar, targetVar, sourceCtx, targetCtx, "transform", true) |
| 2382 | if err != nil { |
| 2383 | panic(err) // bug |
| 2384 | } |
| 2385 | data["Code"] = code |
| 2386 | |
| 2387 | if view != "" { |
| 2388 | data["InitName"] = targetCtx.Scope.Name(src, "", targetCtx.Pointer, targetCtx.UseDefault) |
| 2389 | } |
| 2390 | fields := make([]map[string]any, 0, len(*targetRTs)) |
| 2391 | // iterate through the result types found in the target and add the |
| 2392 | // code to initialize them |
| 2393 | for _, nat := range *targetRTs { |
| 2394 | finit := "new" + targetCtx.Scope.Name(nat.Attribute, "", targetCtx.Pointer, targetCtx.UseDefault) |
| 2395 | if view != "" { |
| 2396 | v := "" |