Beispiel #1
0
// attributeTags computes the struct field tags.
func attributeTags(parent, att *design.AttributeDefinition, name string, private bool) string {
	var elems []string
	keys := make([]string, len(att.Metadata))
	i := 0
	for k := range att.Metadata {
		keys[i] = k
		i++
	}
	sort.Strings(keys)
	for _, key := range keys {
		val := att.Metadata[key]
		if strings.HasPrefix(key, "struct:tag:") {
			name := key[11:]
			value := strings.Join(val, ",")
			elems = append(elems, fmt.Sprintf("%s:\"%s\"", name, value))
		}
	}
	if len(elems) > 0 {
		return " `" + strings.Join(elems, " ") + "`"
	}
	// Default algorithm
	var omit string
	if private || (!parent.IsRequired(name) && !parent.HasDefaultValue(name)) {
		omit = ",omitempty"
	}
	return fmt.Sprintf(" `form:\"%s%s\" json:\"%s%s\" xml:\"%s%s\"`", name, omit, name, omit, name, omit)
}
Beispiel #2
0
func paramsFromDefinition(params *design.AttributeDefinition, path string) ([]*Parameter, error) {
	if params == nil {
		return nil, nil
	}
	obj := params.Type.ToObject()
	if obj == nil {
		return nil, fmt.Errorf("invalid parameters definition, not an object")
	}
	res := make([]*Parameter, len(obj))
	i := 0
	wildcards := design.ExtractWildcards(path)
	obj.IterateAttributes(func(n string, at *design.AttributeDefinition) error {
		in := "query"
		required := params.IsRequired(n)
		for _, w := range wildcards {
			if n == w {
				in = "path"
				required = true
				break
			}
		}
		param := paramFor(at, n, in, required)
		res[i] = param
		i++
		return nil
	})
	return res, nil
}
Beispiel #3
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")
}
Beispiel #4
0
func paramsFromDefinition(params *design.AttributeDefinition, path string) ([]*Parameter, error) {
	if params == nil {
		return nil, nil
	}
	obj := params.Type.ToObject()
	if obj == nil {
		return nil, fmt.Errorf("invalid parameters definition, not an object")
	}
	res := make([]*Parameter, len(obj))
	i := 0
	wildcards := design.ExtractWildcards(path)
	obj.IterateAttributes(func(n string, at *design.AttributeDefinition) error {
		in := "query"
		required := params.IsRequired(n)
		for _, w := range wildcards {
			if n == w {
				in = "path"
				required = true
				break
			}
		}
		param := &Parameter{
			Name:        n,
			Default:     at.DefaultValue,
			Description: at.Description,
			Required:    required,
			In:          in,
			Type:        at.Type.Name(),
		}
		var items *Items
		if at.Type.IsArray() {
			items = itemsFromDefinition(at)
		}
		param.Items = items
		initValidations(at, param)
		res[i] = param
		i++
		return nil
	})
	return res, nil
}
Beispiel #5
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")
}
Beispiel #6
0
var _ = Describe("IsRequired", func() {
	var required string
	var attName string

	var attribute *design.AttributeDefinition
	var res bool

	JustBeforeEach(func() {
		integer := &design.AttributeDefinition{Type: design.Integer}
		attribute = &design.AttributeDefinition{
			Type: design.Object{required: integer},
			Validations: []dslengine.ValidationDefinition{
				&dslengine.RequiredValidationDefinition{Names: []string{required}},
			},
		}
		res = attribute.IsRequired(attName)
	})

	Context("called on a required field", func() {
		BeforeEach(func() {
			attName = "required"
			required = "required"
		})

		It("returns true", func() {
			Ω(res).Should(BeTrue())
		})
	})

	Context("called on a non-required field", func() {
		BeforeEach(func() {
Beispiel #7
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
}
Beispiel #8
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")
}