// responseDefinition returns true and current context if it is a ResponseDefinition, // nil and false otherwise. func responseDefinition(failIfNotResponse bool) (*design.ResponseDefinition, bool) { r, ok := dslengine.CurrentDefinition().(*design.ResponseDefinition) if !ok && failIfNotResponse { dslengine.IncompatibleDSL(dslengine.Caller()) } return r, ok }
// attribute returns true and current context if it is an Attribute, // nil and false otherwise. func attributeDefinition(failIfNotAttribute bool) (*design.AttributeDefinition, bool) { a, ok := dslengine.CurrentDefinition().(*design.AttributeDefinition) if !ok && failIfNotAttribute { dslengine.IncompatibleDSL(dslengine.Caller()) } return a, ok }
// actionDefinition returns true and current context if it is an ActionDefinition, // nil and false otherwise. func actionDefinition(failIfNotAction bool) (*design.ActionDefinition, bool) { a, ok := dslengine.CurrentDefinition().(*design.ActionDefinition) if !ok && failIfNotAction { dslengine.IncompatibleDSL(dslengine.Caller()) } return a, ok }
// typeDefinition returns true and current context if it is a UserTypeDefinition, // nil and false otherwise. func typeDefinition(failIfNotMT bool) (*design.UserTypeDefinition, bool) { m, ok := dslengine.CurrentDefinition().(*design.UserTypeDefinition) if !ok && failIfNotMT { dslengine.IncompatibleDSL(dslengine.Caller()) } return m, ok }
// docsDefinition returns true and current context if it is a DocsDefinition, // nil and false otherwise. func docsDefinition(failIfNotDocs bool) (*design.DocsDefinition, bool) { a, ok := dslengine.CurrentDefinition().(*design.DocsDefinition) if !ok && failIfNotDocs { dslengine.IncompatibleDSL(dslengine.Caller()) } return a, ok }
// licenseDefinition returns true and current context if it is an APIDefinition, // nil and false otherwise. func licenseDefinition(failIfNotLicense bool) (*design.LicenseDefinition, bool) { l, ok := dslengine.CurrentDefinition().(*design.LicenseDefinition) if !ok && failIfNotLicense { dslengine.IncompatibleDSL(dslengine.Caller()) } return l, ok }
// contactDefinition returns true and current context if it is an ContactDefinition, // nil and false otherwise. func contactDefinition(failIfNotContact bool) (*design.ContactDefinition, bool) { a, ok := dslengine.CurrentDefinition().(*design.ContactDefinition) if !ok && failIfNotContact { dslengine.IncompatibleDSL(dslengine.Caller()) } return a, ok }
// encodingDefinition returns true and current context if it is an EncodingDefinition, // nil and false otherwise. func encodingDefinition(failIfNotEnc bool) (*design.EncodingDefinition, bool) { e, ok := dslengine.CurrentDefinition().(*design.EncodingDefinition) if !ok && failIfNotEnc { dslengine.IncompatibleDSL(dslengine.Caller()) } return e, ok }
// Attribute implements the attribute definition DSL. An attribute describes a data structure // recursively. Attributes are used for describing request headers, parameters and payloads - // response bodies and headers - media types and types. An attribute definition is recursive: // attributes may include other attributes. At the basic level an attribute has a name, // a type and optionally a default value and validation rules. The type of an attribute can be one of: // // * The primitive types Boolean, Integer, Number or String. // // * A type defined via the Type function. // // * A media type defined via the MediaType function. // // * An object described recursively with child attributes. // // * An array defined using the ArrayOf function. // // * An hashmap defined using the HashOf function. // // Attributes can be defined using the Attribute, Param, Member or Header functions depending // on where the definition appears. The syntax for all these DSL is the same. // Here are some examples: // // Attribute("name") // Defines an attribute of type String // // Attribute("name", func() { // Pattern("^foo") // Adds a validation rule to the attribute // }) // // Attribute("name", Integer) // Defines an attribute of type Integer // // Attribute("name", Integer, func() { // Default(42) // With a default value // }) // // Attribute("name", Integer, "description") // Specifies a description // // Attribute("name", Integer, "description", func() { // Enum(1, 2) // And validation rules // }) // // Nested attributes: // // Attribute("nested", func() { // Description("description") // Attribute("child") // Attribute("child2", func() { // // .... // }) // Required("child") // }) // // Here are all the valid usage of the Attribute function: // // Attribute(name string, dataType DataType, description string, dsl func()) // // Attribute(name string, dataType DataType, description string) // // Attribute(name string, dataType DataType, dsl func()) // // Attribute(name string, dataType DataType) // // Attribute(name string, dsl func()) // dataType is String or Object (if DSL defines child attributes) // // Attribute(name string) // dataType is String func Attribute(name string, args ...interface{}) { var parent *design.AttributeDefinition if at, ok := attributeDefinition(false); ok { parent = at } else if mt, ok := mediaTypeDefinition(false); ok { parent = mt.AttributeDefinition } else if c, ok := dslengine.CurrentDefinition().(design.ContainerDefinition); ok { parent = c.Attribute() } else { dslengine.IncompatibleDSL(dslengine.Caller()) } if parent != nil { if parent.Type == nil { parent.Type = design.Object{} } if _, ok := parent.Type.(design.Object); !ok { dslengine.ReportError("can't define child attributes on attribute of type %s", parent.Type.Name()) return } var baseAttr *design.AttributeDefinition if parent.Reference != nil { if att, ok := parent.Reference.ToObject()[name]; ok { baseAttr = design.DupAtt(att) } } dataType, description, dsl := parseAttributeArgs(baseAttr, args...) if baseAttr != nil { if description != "" { baseAttr.Description = description } if dataType != nil { baseAttr.Type = dataType } } else { baseAttr = &design.AttributeDefinition{ Type: dataType, Description: description, } } baseAttr.Reference = parent.Reference if dsl != nil { dslengine.Execute(dsl, baseAttr) } if baseAttr.Type == nil { // DSL did not contain an "Attribute" declaration baseAttr.Type = design.String } parent.Type.(design.Object)[name] = baseAttr } }