-
Notifications
You must be signed in to change notification settings - Fork 33
/
registry.go
123 lines (108 loc) · 2.98 KB
/
registry.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
package shared
import (
"fmt"
"github.com/viant/toolbox"
"strings"
)
var registry = make(map[string]ContractAdapter, 0)
var typeMetaRegistry byAPI = make(map[string]byKind)
//Register register an adapter
func Register(adapter ContractAdapter) {
id := adapter.GetId()
registry[id] = adapter
meta := NewKindMethodMeta(id)
typeMetaRegistry.Put(meta, adapter)
}
//Get returns contract adapter
func Get(id string) (ContractAdapter, bool) {
result, ok := registry[id]
return result, ok
}
//Lookup returns KindOperations with all defined operations or error
func Lookup(apiVersion, kind string) (*KindOperations, error) {
if kind == "" {
return nil, fmt.Errorf("kind was empty")
}
if strings.Contains(kind, ".") && apiVersion == "" {
pair := strings.SplitN(kind, ".", 2)
apiVersion = pair[0]
kind = pair[1]
}
if apiVersion == "" {
apiVersion, _ = LookupAPIVersion(kind)
}
if apiVersion == "" {
return nil, fmt.Errorf("apiVersion was empty")
}
byKind, ok := typeMetaRegistry[apiVersion]
if !ok {
available := toolbox.MapKeysToStringSlice(typeMetaRegistry)
return nil, fmt.Errorf("failed to lookup api %v, avaiale: %v", apiVersion, available)
}
result, ok := byKind[strings.Title(kind)]
if !ok {
return nil, fmt.Errorf("failed to lookup kind %v in api: %v", kind, apiVersion)
}
return result, nil
}
type byKind map[string]*KindOperations
type byAPI map[string]byKind
func (by *byAPI) Put(meta *KindMethodMeta, adapter ContractAdapter) {
if _, has := (*by)[meta.APIVersion]; !has {
(*by)[meta.APIVersion] = make(map[string]*KindOperations)
}
byKind := (*by)[meta.APIVersion]
byKind.Put(meta, adapter)
_, has := defaultKindAPIVersion[meta.Kind]
if !has {
defaultKindAPIVersion[meta.Kind] = []string{meta.APIVersion}
} else {
for _, api := range defaultKindAPIVersion[meta.Kind] {
if api == meta.APIVersion {
return
}
}
defaultKindAPIVersion[meta.Kind] = append(defaultKindAPIVersion[meta.Kind], meta.APIVersion)
}
}
func (by *byKind) Put(meta *KindMethodMeta, adapter ContractAdapter) {
if _, has := (*by)[meta.Kind]; !has {
(*by)[meta.Kind] = &KindOperations{
TypeMeta: meta.TypeMeta,
Methods: make(map[string]ContractAdapter),
}
}
(*by)[meta.Kind].Methods[meta.Method] = adapter
}
//MetaTypes returns meta types
func MetaTypes() []string {
var index = make(map[string]bool)
var result = make([]string, 0)
for _, api := range typeMetaRegistry {
for _, kind := range api {
if _, has := index[kind.Kind]; has {
continue
}
index[kind.Kind] = true
result = append(result, kind.APIVersion+"."+kind.Kind)
}
}
return result
}
//MatchedMetaTypes returns matched kinds
func MatchedMetaTypes(kinds ...string) []string {
var index = make(map[string]bool)
for _, kind := range kinds {
index[kind] = true
}
var result = make([]string, 0)
for _, api := range typeMetaRegistry {
for _, kind := range api {
if _, has := index[kind.Kind]; !has {
continue
}
result = append(result, kind.APIVersion+"."+kind.Kind)
}
}
return result
}