Exemplo n.º 1
0
// 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")
}
Exemplo n.º 2
0
// 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")
}
Exemplo n.º 3
0
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
}
Exemplo n.º 4
0
// 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")
}