255 lines
5.9 KiB
Go
255 lines
5.9 KiB
Go
// params — слияние, фильтрация, анализ параметров и ForceNew.
|
||
package main
|
||
|
||
import (
|
||
"sort"
|
||
"strings"
|
||
)
|
||
|
||
func mergeParams(sets ...[]Param) []Param {
|
||
seen := map[string]Param{}
|
||
for _, s := range sets {
|
||
for _, p := range s {
|
||
key := strings.ToLower(strings.TrimSpace(p.Code))
|
||
if key == "" {
|
||
continue
|
||
}
|
||
if _, ok := seen[key]; !ok {
|
||
seen[key] = p
|
||
}
|
||
}
|
||
}
|
||
out := make([]Param, 0, len(seen))
|
||
for _, p := range seen {
|
||
out = append(out, p)
|
||
}
|
||
sort.Slice(out, func(i, j int) bool { return out[i].Code < out[j].Code })
|
||
return out
|
||
}
|
||
|
||
func alignParamTypes(params []Param, schema []Param) []Param {
|
||
if len(params) == 0 || len(schema) == 0 {
|
||
return params
|
||
}
|
||
codeType := make(map[string]string, len(schema))
|
||
for _, p := range schema {
|
||
key := strings.ToLower(strings.TrimSpace(p.Code))
|
||
if key == "" {
|
||
continue
|
||
}
|
||
if strings.TrimSpace(p.Type) != "" {
|
||
codeType[key] = p.Type
|
||
}
|
||
}
|
||
if len(codeType) == 0 {
|
||
return params
|
||
}
|
||
|
||
for i, p := range params {
|
||
key := strings.ToLower(strings.TrimSpace(p.Code))
|
||
if key == "" {
|
||
continue
|
||
}
|
||
if t, ok := codeType[key]; ok && strings.TrimSpace(t) != "" {
|
||
params[i].Type = t
|
||
}
|
||
}
|
||
|
||
return params
|
||
}
|
||
|
||
func computeCreateOnly(createParams []Param, modifyParams []Param) map[string]struct{} {
|
||
modifyCodes := make(map[string]struct{}, len(modifyParams))
|
||
for _, p := range modifyParams {
|
||
key := strings.ToLower(strings.TrimSpace(p.Code))
|
||
if key == "" {
|
||
continue
|
||
}
|
||
modifyCodes[key] = struct{}{}
|
||
}
|
||
|
||
createOnly := make(map[string]struct{})
|
||
for _, p := range createParams {
|
||
key := strings.ToLower(strings.TrimSpace(p.Code))
|
||
if key == "" {
|
||
continue
|
||
}
|
||
if _, ok := modifyCodes[key]; !ok {
|
||
createOnly[key] = struct{}{}
|
||
}
|
||
}
|
||
|
||
return createOnly
|
||
}
|
||
|
||
func markCreateOnly(schema []Param, createOnly map[string]struct{}) []Param {
|
||
if len(schema) == 0 || len(createOnly) == 0 {
|
||
return schema
|
||
}
|
||
|
||
for i, p := range schema {
|
||
key := strings.ToLower(strings.TrimSpace(p.Code))
|
||
if key == "" {
|
||
continue
|
||
}
|
||
if _, ok := createOnly[key]; ok {
|
||
schema[i].CreateOnly = true
|
||
}
|
||
}
|
||
|
||
return schema
|
||
}
|
||
|
||
func filterCreateOnly(schema []Param) []Param {
|
||
if len(schema) == 0 {
|
||
return []Param{}
|
||
}
|
||
|
||
result := make([]Param, 0, len(schema))
|
||
for _, p := range schema {
|
||
if p.CreateOnly {
|
||
result = append(result, p)
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
func filterCreateOnlyRequired(schema []Param) []Param {
|
||
if len(schema) == 0 {
|
||
return []Param{}
|
||
}
|
||
|
||
result := make([]Param, 0, len(schema))
|
||
for _, p := range schema {
|
||
if p.CreateOnly && p.Required {
|
||
result = append(result, p)
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
func analyzeParams(usesBool *bool, usesInt64 *bool, usesString *bool, hasDefaults *bool, needsBoolDefault *bool, needsInt64Default *bool, needsStringDefault *bool, params []Param) {
|
||
for _, p := range params {
|
||
switch strings.ToLower(p.Type) {
|
||
case "bool":
|
||
*usesBool = true
|
||
if p.Default != "" {
|
||
*needsBoolDefault = true
|
||
*hasDefaults = true
|
||
}
|
||
case "int", "int64", "number":
|
||
*usesInt64 = true
|
||
if p.Default != "" {
|
||
*needsInt64Default = true
|
||
*hasDefaults = true
|
||
}
|
||
default:
|
||
*usesString = true
|
||
if p.Default != "" {
|
||
*needsStringDefault = true
|
||
*hasDefaults = true
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
func buildSubresourceForceNewCodes(sr *GenSubresource, createOnly map[string]struct{}) map[string]struct{} {
|
||
forceNew := map[string]struct{}{}
|
||
if sr.ModifyOpName == "" {
|
||
for _, p := range sr.SchemaParams {
|
||
key := strings.ToLower(strings.TrimSpace(p.Code))
|
||
if key != "" {
|
||
forceNew[key] = struct{}{}
|
||
}
|
||
}
|
||
return forceNew
|
||
}
|
||
for key := range createOnly {
|
||
forceNew[key] = struct{}{}
|
||
}
|
||
for _, p := range sr.DeleteParams {
|
||
key := strings.ToLower(strings.TrimSpace(p.Code))
|
||
if key != "" {
|
||
forceNew[key] = struct{}{}
|
||
}
|
||
}
|
||
return forceNew
|
||
}
|
||
|
||
func markForceNew(params []Param, forceNew map[string]struct{}) []Param {
|
||
if len(params) == 0 || len(forceNew) == 0 {
|
||
return params
|
||
}
|
||
for i, p := range params {
|
||
key := strings.ToLower(strings.TrimSpace(p.Code))
|
||
if key == "" {
|
||
continue
|
||
}
|
||
if _, ok := forceNew[key]; ok {
|
||
params[i].ForceNew = true
|
||
}
|
||
}
|
||
return params
|
||
}
|
||
|
||
func filterForceNew(params []Param) []Param {
|
||
result := []Param{}
|
||
for _, p := range params {
|
||
if p.ForceNew {
|
||
result = append(result, p)
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
// analyzeJsonPlanMod возвращает true, если хотя бы один параметр является JSON-строкой.
|
||
// Используется для условного добавления импорта planmodifier в сгенерированные файлы.
|
||
func analyzeJsonPlanMod(params []Param) bool {
|
||
for _, p := range params {
|
||
if p.IsJson {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// hasRestoreCasingParams возвращает true, если есть ref_svc params с RefSvcId > 0 && != 12
|
||
// (restore-casing блок в Create/Read/Update использует strings.EqualFold для них).
|
||
func hasRestoreCasingParams(params []Param) bool {
|
||
for _, p := range params {
|
||
if p.RefSvcId > 0 && p.RefSvcId != 12 && strings.EqualFold(strings.TrimSpace(p.Type), "string") {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// analyzeNeedsStrings возвращает true, если среди params есть хотя бы один строковый параметр.
|
||
// Используется для условного добавления импорта "strings" (EqualFold в Update).
|
||
func analyzeNeedsStrings(params []Param) bool {
|
||
for _, p := range params {
|
||
t := strings.ToLower(strings.TrimSpace(p.Type))
|
||
if t != "bool" && t != "int" && t != "int64" && t != "number" {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
func analyzePlanModifiers(needsBool *bool, needsInt64 *bool, needsString *bool, params []Param) {
|
||
for _, p := range params {
|
||
if !p.ForceNew {
|
||
continue
|
||
}
|
||
switch strings.ToLower(strings.TrimSpace(p.Type)) {
|
||
case "bool":
|
||
*needsBool = true
|
||
case "int", "int64", "number":
|
||
*needsInt64 = true
|
||
default:
|
||
*needsString = true
|
||
}
|
||
}
|
||
}
|