github.com/danlock/goa@v1.4.0/dslengine/definitions.go (about)

     1  package dslengine
     2  
     3  import "fmt"
     4  
     5  type (
     6  
     7  	// Definition is the common interface implemented by all definitions.
     8  	Definition interface {
     9  		// Context is used to build error messages that refer to the definition.
    10  		Context() string
    11  	}
    12  
    13  	// DefinitionSet contains DSL definitions that are executed as one unit.
    14  	// The slice elements may implement the Validate an, Source interfaces to enable the
    15  	// corresponding behaviors during DSL execution.
    16  	DefinitionSet []Definition
    17  
    18  	// Root is the interface implemented by the DSL root objects.
    19  	// These objects contains all the definition sets created by the DSL and can
    20  	// be passed to the dsl engine for execution.
    21  	Root interface {
    22  		// DSLName is displayed by the runner upon executing the DSL.
    23  		// Registered DSL roots must have unique names.
    24  		DSLName() string
    25  		// DependsOn returns the list of other DSL roots this root depends on.
    26  		// The DSL engine uses this function to order execution of the DSLs.
    27  		DependsOn() []Root
    28  		// IterateSets implements the visitor pattern: is is called by the engine so the
    29  		// DSL can control the order of execution. IterateSets calls back the engine via
    30  		// the given iterator as many times as needed providing the DSL definitions that
    31  		// must be run for each callback.
    32  		IterateSets(SetIterator)
    33  		// Reset restores the root to pre DSL execution state.
    34  		// This is mainly used by tests.
    35  		Reset()
    36  	}
    37  
    38  	// Validate is the interface implemented by definitions that can be validated.
    39  	// Validation is done by the DSL dsl post execution.
    40  	Validate interface {
    41  		Definition
    42  		// Validate returns nil if the definition contains no validation error.
    43  		// The Validate implementation may take advantage of ValidationErrors to report
    44  		// more than one errors at a time.
    45  		Validate() error
    46  	}
    47  
    48  	// Source is the interface implemented by definitions that can be initialized via DSL.
    49  	Source interface {
    50  		Definition
    51  		// DSL returns the DSL used to initialize the definition if any.
    52  		DSL() func()
    53  	}
    54  
    55  	// Finalize is the interface implemented by definitions that require an additional pass
    56  	// after the DSL has executed (e.g. to merge generated definitions or initialize default
    57  	// values)
    58  	Finalize interface {
    59  		Definition
    60  		// Finalize is run by the DSL runner once the definition DSL has executed and the
    61  		// definition has been validated.
    62  		Finalize()
    63  	}
    64  
    65  	// SetIterator is the function signature used to iterate over definition sets with
    66  	// IterateSets.
    67  	SetIterator func(s DefinitionSet) error
    68  
    69  	// MetadataDefinition is a set of key/value pairs
    70  	MetadataDefinition map[string][]string
    71  
    72  	// TraitDefinition defines a set of reusable properties.
    73  	TraitDefinition struct {
    74  		// Trait name
    75  		Name string
    76  		// Trait DSL
    77  		DSLFunc func()
    78  	}
    79  
    80  	// ValidationDefinition contains validation rules for an attribute.
    81  	ValidationDefinition struct {
    82  		// Values represents an enum validation as described at
    83  		// http://json-schema.org/latest/json-schema-validation.html#anchor76.
    84  		Values []interface{}
    85  		// Format represents a format validation as described at
    86  		// http://json-schema.org/latest/json-schema-validation.html#anchor104.
    87  		Format string
    88  		// PatternValidationDefinition represents a pattern validation as described at
    89  		// http://json-schema.org/latest/json-schema-validation.html#anchor33
    90  		Pattern string
    91  		// Minimum represents an minimum value validation as described at
    92  		// http://json-schema.org/latest/json-schema-validation.html#anchor21.
    93  		Minimum *float64
    94  		// Maximum represents a maximum value validation as described at
    95  		// http://json-schema.org/latest/json-schema-validation.html#anchor17.
    96  		Maximum *float64
    97  		// MinLength represents an minimum length validation as described at
    98  		// http://json-schema.org/latest/json-schema-validation.html#anchor29.
    99  		MinLength *int
   100  		// MaxLength represents an maximum length validation as described at
   101  		// http://json-schema.org/latest/json-schema-validation.html#anchor26.
   102  		MaxLength *int
   103  		// Required list the required fields of object attributes as described at
   104  		// http://json-schema.org/latest/json-schema-validation.html#anchor61.
   105  		Required []string
   106  	}
   107  )
   108  
   109  // Context returns the generic definition name used in error messages.
   110  func (t *TraitDefinition) Context() string {
   111  	if t.Name != "" {
   112  		return fmt.Sprintf("trait %#v", t.Name)
   113  	}
   114  	return "unnamed trait"
   115  }
   116  
   117  // DSL returns the initialization DSL.
   118  func (t *TraitDefinition) DSL() func() {
   119  	return t.DSLFunc
   120  }
   121  
   122  // Context returns the generic definition name used in error messages.
   123  func (v *ValidationDefinition) Context() string {
   124  	return "validation"
   125  }
   126  
   127  // Merge merges other into v.
   128  func (v *ValidationDefinition) Merge(other *ValidationDefinition) {
   129  	if v.Values == nil {
   130  		v.Values = other.Values
   131  	}
   132  	if v.Format == "" {
   133  		v.Format = other.Format
   134  	}
   135  	if v.Pattern == "" {
   136  		v.Pattern = other.Pattern
   137  	}
   138  	if v.Minimum == nil || (other.Minimum != nil && *v.Minimum > *other.Minimum) {
   139  		v.Minimum = other.Minimum
   140  	}
   141  	if v.Maximum == nil || (other.Maximum != nil && *v.Maximum < *other.Maximum) {
   142  		v.Maximum = other.Maximum
   143  	}
   144  	if v.MinLength == nil || (other.MinLength != nil && *v.MinLength > *other.MinLength) {
   145  		v.MinLength = other.MinLength
   146  	}
   147  	if v.MaxLength == nil || (other.MaxLength != nil && *v.MaxLength < *other.MaxLength) {
   148  		v.MaxLength = other.MaxLength
   149  	}
   150  	v.AddRequired(other.Required)
   151  }
   152  
   153  // AddRequired merges the required fields from other into v
   154  func (v *ValidationDefinition) AddRequired(required []string) {
   155  	for _, r := range required {
   156  		found := false
   157  		for _, rr := range v.Required {
   158  			if r == rr {
   159  				found = true
   160  				break
   161  			}
   162  		}
   163  		if !found {
   164  			v.Required = append(v.Required, r)
   165  		}
   166  	}
   167  }
   168  
   169  // HasRequiredOnly returns true if the validation only has the Required field with a non-zero value.
   170  func (v *ValidationDefinition) HasRequiredOnly() bool {
   171  	if len(v.Values) > 0 {
   172  		return false
   173  	}
   174  	if v.Format != "" || v.Pattern != "" {
   175  		return false
   176  	}
   177  	if (v.Minimum != nil) || (v.Maximum != nil) || (v.MaxLength != nil) {
   178  		return false
   179  	}
   180  	return true
   181  }
   182  
   183  // Dup makes a shallow dup of the validation.
   184  func (v *ValidationDefinition) Dup() *ValidationDefinition {
   185  	return &ValidationDefinition{
   186  		Values:    v.Values,
   187  		Format:    v.Format,
   188  		Pattern:   v.Pattern,
   189  		Minimum:   v.Minimum,
   190  		Maximum:   v.Maximum,
   191  		MinLength: v.MinLength,
   192  		MaxLength: v.MaxLength,
   193  		Required:  v.Required,
   194  	}
   195  }