github.com/shogo82148/goa-v1@v1.6.2/design/dup.go (about) 1 package design 2 3 import "github.com/shogo82148/goa-v1/dslengine" 4 5 // Dup creates a copy the given data type. 6 func Dup(d DataType) DataType { 7 return newDupper().DupType(d) 8 } 9 10 // DupAtt creates a copy of the given attribute. 11 func DupAtt(att *AttributeDefinition) *AttributeDefinition { 12 return newDupper().DupAttribute(att) 13 } 14 15 // dupper implements recursive and cycle safe copy of data types. 16 type dupper struct { 17 dts map[string]*UserTypeDefinition 18 dmts map[string]*MediaTypeDefinition 19 } 20 21 // newDupper returns a new initialized dupper. 22 func newDupper() *dupper { 23 return &dupper{ 24 dts: make(map[string]*UserTypeDefinition), 25 dmts: make(map[string]*MediaTypeDefinition), 26 } 27 } 28 29 // DupUserType creates a copy of the given user type. 30 func (d *dupper) DupUserType(ut *UserTypeDefinition) *UserTypeDefinition { 31 return &UserTypeDefinition{ 32 AttributeDefinition: d.DupAttribute(ut.AttributeDefinition), 33 TypeName: ut.TypeName, 34 } 35 } 36 37 // DupAttribute creates a copy of the given attribute. 38 func (d *dupper) DupAttribute(att *AttributeDefinition) *AttributeDefinition { 39 var valDup *dslengine.ValidationDefinition 40 if att.Validation != nil { 41 valDup = att.Validation.Dup() 42 } 43 dup := AttributeDefinition{ 44 Type: att.Type, 45 Description: att.Description, 46 Validation: valDup, 47 Metadata: att.Metadata, 48 DefaultValue: att.DefaultValue, 49 NonZeroAttributes: att.NonZeroAttributes, 50 View: att.View, 51 DSLFunc: att.DSLFunc, 52 Example: att.Example, 53 } 54 return &dup 55 } 56 57 // DupType creates a copy of the given data type. 58 func (d *dupper) DupType(t DataType) DataType { 59 switch actual := t.(type) { 60 case Primitive: 61 return t 62 case *Array: 63 return &Array{ElemType: d.DupAttribute(actual.ElemType)} 64 case Object: 65 res := make(Object, len(actual)) 66 for n, att := range actual { 67 res[n] = d.DupAttribute(att) 68 } 69 return res 70 case *Hash: 71 return &Hash{ 72 KeyType: d.DupAttribute(actual.KeyType), 73 ElemType: d.DupAttribute(actual.ElemType), 74 } 75 case *UserTypeDefinition: 76 if u, ok := d.dts[actual.TypeName]; ok { 77 return u 78 } 79 u := &UserTypeDefinition{ 80 TypeName: actual.TypeName, 81 } 82 d.dts[u.TypeName] = u 83 u.AttributeDefinition = d.DupAttribute(actual.AttributeDefinition) 84 return u 85 case *MediaTypeDefinition: 86 if m, ok := d.dmts[actual.Identifier]; ok { 87 return m 88 } 89 m := &MediaTypeDefinition{ 90 Identifier: actual.Identifier, 91 Links: actual.Links, 92 Views: actual.Views, 93 Resource: actual.Resource, 94 } 95 d.dmts[actual.Identifier] = m 96 m.UserTypeDefinition = d.DupUserType(actual.UserTypeDefinition) 97 return m 98 } 99 panic("unknown type " + t.Name()) 100 }