// RecursiveChecker produces Go code that runs the validation checks recursively over the given // attribute. func RecursiveChecker(att *design.AttributeDefinition, nonzero, required, hasDefault bool, target, context string, depth int, private bool) string { var checks []string if o := att.Type.ToObject(); o != nil { if mt, ok := att.Type.(*design.MediaTypeDefinition); ok { att = mt.AttributeDefinition } else if ut, ok := att.Type.(*design.UserTypeDefinition); ok { att = ut.AttributeDefinition } validation := ValidationChecker(att, nonzero, required, hasDefault, target, context, depth, private) if validation != "" { checks = append(checks, validation) } o.IterateAttributes(func(n string, catt *design.AttributeDefinition) error { actualDepth := depth if catt.Type.IsObject() { actualDepth = depth + 1 } validation := RecursiveChecker( catt, att.IsNonZero(n), att.IsRequired(n), att.HasDefaultValue(n), fmt.Sprintf("%s.%s", target, Goify(n, true)), fmt.Sprintf("%s.%s", context, n), actualDepth, private, ) if validation != "" { if catt.Type.IsObject() { validation = fmt.Sprintf("%sif %s.%s != nil {\n%s\n%s}", Tabs(depth), target, Goify(n, true), validation, Tabs(depth)) } checks = append(checks, validation) } return nil }) } else if a := att.Type.ToArray(); a != nil { data := map[string]interface{}{ "elemType": a.ElemType, "context": context, "target": target, "depth": 1, "private": private, } validation := RunTemplate(arrayValT, data) if validation != "" { checks = append(checks, validation) } } else { validation := ValidationChecker(att, nonzero, required, hasDefault, target, context, depth, private) if validation != "" { checks = append(checks, validation) } } return strings.Join(checks, "\n") }
// RecursiveChecker produces Go code that runs the validation checks recursively over the given // attribute. func RecursiveChecker(att *design.AttributeDefinition, nonzero, required bool, target, context string, depth int) string { var checks []string validation := ValidationChecker(att, nonzero, required, target, context, depth) if validation != "" { checks = append(checks, validation) } if o := att.Type.ToObject(); o != nil { if mt, ok := att.Type.(*design.MediaTypeDefinition); ok { att = mt.AttributeDefinition } else if ut, ok := att.Type.(*design.UserTypeDefinition); ok { att = ut.AttributeDefinition } o.IterateAttributes(func(n string, catt *design.AttributeDefinition) error { validation := RecursiveChecker( catt, att.IsNonZero(n), att.IsRequired(n), fmt.Sprintf("%s.%s", target, Goify(n, true)), fmt.Sprintf("%s.%s", context, n), depth+1, ) if validation != "" { checks = append(checks, validation) } return nil }) } else if a := att.Type.ToArray(); a != nil { data := map[string]interface{}{ "elemType": a.ElemType, "context": context, "target": target, "depth": 1, } validation := RunTemplate(arrayValT, data) if validation != "" { checks = append(checks, validation) } } return strings.Join(checks, "\n") }
func (v *Validator) recurseAttribute(att, catt *design.AttributeDefinition, n, target, context string, depth int, private bool) string { var validation string if ds, ok := catt.Type.(design.DataStructure); ok { // We need to check empirically whether there are validations to be // generated, we can't just generate and check whether something was // generated to avoid infinite recursions. hasValidations := false done := errors.New("done") ds.Walk(func(a *design.AttributeDefinition) error { if a.Validation != nil { if private { hasValidations = true return done } // For public data structures there is a case where // there is validation but no actual validation // code: if the validation is a required validation // that applies to attributes that cannot be nil or // empty string i.e. primitive types other than // string. if !a.Validation.HasRequiredOnly() { hasValidations = true return done } for _, name := range a.Validation.Required { att := a.Type.ToObject()[name] if att != nil && (!att.Type.IsPrimitive() || att.Type.Kind() == design.StringKind) { hasValidations = true return done } } } return nil }) if hasValidations { validation = RunTemplate(v.userValT, map[string]interface{}{ "depth": depth, "target": fmt.Sprintf("%s.%s", target, GoifyAtt(catt, n, true)), }) } } else { dp := depth if catt.Type.IsObject() { dp++ } validation = v.recurse( catt, att.IsNonZero(n), att.IsRequired(n), att.HasDefaultValue(n), fmt.Sprintf("%s.%s", target, GoifyAtt(catt, n, true)), fmt.Sprintf("%s.%s", context, n), dp, private, ).String() } if validation != "" { if catt.Type.IsObject() { validation = fmt.Sprintf("%sif %s.%s != nil {\n%s\n%s}", Tabs(depth), target, GoifyAtt(catt, n, true), validation, Tabs(depth)) } } return validation }
// RecursiveChecker produces Go code that runs the validation checks recursively over the given // attribute. func RecursiveChecker(att *design.AttributeDefinition, nonzero, required, hasDefault bool, target, context string, depth int, private bool) string { var checks []string if o := att.Type.ToObject(); o != nil { if ds, ok := att.Type.(design.DataStructure); ok { att = ds.Definition() } validation := ValidationChecker(att, nonzero, required, hasDefault, target, context, depth, private) if validation != "" { checks = append(checks, validation) } o.IterateAttributes(func(n string, catt *design.AttributeDefinition) error { var validation string if ds, ok := catt.Type.(design.DataStructure); ok { // We need to check empirically whether there are validations to be // generated, we can't just generate and check whether something was // generated to avoid infinite recursions. hasValidations := false done := errors.New("done") ds.Walk(func(a *design.AttributeDefinition) error { if a.Validation != nil { if private { hasValidations = true return done } // For public data structures there is a case where // there is validation but no actual validation // code: if the validation is a required validation // that applies to attributes that cannot be nil or // empty string i.e. primitive types other than // string. if !a.Validation.HasRequiredOnly() { hasValidations = true return done } for _, name := range a.Validation.Required { att := a.Type.ToObject()[name] if att != nil && (!att.Type.IsPrimitive() || att.Type.Kind() == design.StringKind) { hasValidations = true return done } } } return nil }) if hasValidations { validation = RunTemplate( userValT, map[string]interface{}{ "depth": depth, "target": fmt.Sprintf("%s.%s", target, GoifyAtt(catt, n, true)), }, ) } } else { dp := depth if catt.Type.IsObject() { dp++ } validation = RecursiveChecker( catt, att.IsNonZero(n), att.IsRequired(n), att.HasDefaultValue(n), fmt.Sprintf("%s.%s", target, GoifyAtt(catt, n, true)), fmt.Sprintf("%s.%s", context, n), dp, private, ) } if validation != "" { if catt.Type.IsObject() { validation = fmt.Sprintf("%sif %s.%s != nil {\n%s\n%s}", Tabs(depth), target, GoifyAtt(catt, n, true), validation, Tabs(depth)) } checks = append(checks, validation) } return nil }) } else if a := att.Type.ToArray(); a != nil { // Perform any validation on the array type such as MinLength, MaxLength, etc. validation := ValidationChecker(att, nonzero, required, hasDefault, target, context, depth, private) if validation != "" { checks = append(checks, validation) } data := map[string]interface{}{ "elemType": a.ElemType, "context": context, "target": target, "depth": 1, "private": private, } validation = RunTemplate(arrayValT, data) if validation != "" { checks = append(checks, validation) } } else { validation := ValidationChecker(att, nonzero, required, hasDefault, target, context, depth, private) if validation != "" { checks = append(checks, validation) } } return strings.Join(checks, "\n") }