-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtype.go
127 lines (107 loc) · 3.81 KB
/
type.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package def
import (
"fmt"
)
// Type defines structure for data.
type Type struct {
// The name of the role this type has in its context.
// Can make use of properties.
Name string `json:"name" yaml:"name"`
// Type is either "stream", "map", "generic", "reference" or a type the target system understands.
// Normally, the following types should be available: "string", "number", "boolean", "trigger".
// Cannot (!) make use of properties.
Type string `json:"type" yaml:"type"`
/* === REFERENCE + SPECIFICATION (only in case Type == "reference") === */
// Reference is the name of a referenced type.
// Cannot (!) make use of properties.
Reference string `json:"reference,omitempty" yaml:"reference,omitempty"`
// Generics is a specification of the generics inside a referenced type.
Generics Generics `json:"generics,omitempty" yaml:"generics,omitempty"`
// Values is a specification of the properties inside a referenced type.
Values Values `json:"values,omitempty" yaml:"values,omitempty"`
/* === DEFINITION === */
// Properties of this type and its subtypes.
// Cannot (!) make use of properties.
Properties Properties `json:"properties" yaml:"properties"`
// Description of this type in natural language (English).
// Can make use of properties.
Description string `json:"description" yaml:"description"`
// Stream is the underlying type for the stream.
// It is ignored in case Type is not "stream".
Stream *Type `json:"stream,omitempty" yaml:"stream,omitempty"`
// Map is a map of underlying types.
// It is ignored in case Type is not "map".
Map []*Type `json:"map,omitempty" yaml:"map,omitempty"`
// MapTemplate specifies a map being built from a property.
// It is ignored in case Type is not "map".
MapTemplate MapTemplate `json:"mapTemplate,omitempty" yaml:"mapTemplate,omitempty"`
// Generic is a placeholder for an arbitrary type.
// It is ignored in case Type is not "generic".
// Can make use of properties.
Generic string `json:"generic,omitempty" yaml:"generic,omitempty"`
}
// MapTemplate
type MapTemplate struct {
// Property, must be a stream
Property string `json:"property" yaml:"property"`
Index string `json:"index" yaml:"index"`
Value string `json:"value" yaml:"value"`
Expand *Type `json:"expand" yaml:"expand"`
Entry *Type `json:"entry" yaml:"entry"`
}
// Generics is a specification of generics.
type Generics map[string]*Type
// Resolves the type using the given provider.
func (t Type) Resolve(typeProvider TypeProvider, generics Generics, values Values) (Type, error) {
resolved := Type{
Description: t.Description,
Type: t.Type,
}
if t.Type == "stream" {
resolvedStream, err := t.Stream.Resolve(typeProvider, generics, values)
if err != nil {
return Type{}, err
}
resolved.Stream = &resolvedStream
} else if t.Type == "map" {
resolvedMap := []*Type{}
for _, subtype := range t.Map {
resolvedSubtype, err := subtype.Resolve(typeProvider, generics, values)
if err != nil {
return Type{}, err
}
resolvedMap = append(resolvedMap, &resolvedSubtype)
}
resolved.Map = resolvedMap
} else if t.Type == "generic" {
gen, ok := generics[t.Generic]
if !ok {
return Type{}, fmt.Errorf("generic '%s' not specified", t.Generic)
}
resolved = *gen
} else if t.Type == "reference" {
ref, err := typeProvider.dereferenceType(t.Reference)
if err != nil {
return Type{}, err
}
refGens := make(Generics)
for gen, genType := range t.Generics {
resolvedGen, err := genType.Resolve(typeProvider, generics, values)
if err != nil {
return Type{}, err
}
refGens[gen] = &resolvedGen
}
resolved, err = ref.Resolve(typeProvider, refGens, values)
if err != nil {
return Type{}, err
}
} else {
var err error
resolved, err = typeProvider.buildType(t.Type)
if err != nil {
return Type{}, err
}
}
return resolved, nil
}