github.com/brycereitano/goa@v0.0.0-20170315073847-8ffa6c85e265/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 }