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