-
Notifications
You must be signed in to change notification settings - Fork 20
/
import.go
170 lines (139 loc) · 4.16 KB
/
import.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package tosca_v2_0
import (
"fmt"
"strings"
"unicode"
"github.com/tliron/kutil/ard"
urlpkg "github.com/tliron/kutil/url"
"github.com/tliron/puccini/tosca"
)
//
// Import
//
// [TOSCA-v2.0] @ ?
// [TOSCA-Simple-Profile-YAML-v1.3] @ 3.6.8
// [TOSCA-Simple-Profile-YAML-v1.2] @ 3.6.8
// [TOSCA-Simple-Profile-YAML-v1.1] @ 3.5.7
// [TOSCA-Simple-Profile-YAML-v1.0] @ 3.5.7
//
type Import struct {
*Entity `name:"import" json:"-" yaml:"-"`
URL *string `read:"url" require:""` // renamed in TOSCA 2.0
RepositoryName *string `read:"repository"`
Namespace *string `read:"namespace"` // renamed in TOSCA 2.0
NamespaceURI *string /// removed in TOSCA 2.0
Repository *Repository `lookup:"repository,RepositoryName" json:"-" yaml:"-"`
}
func NewImport(context *tosca.Context) *Import {
return &Import{Entity: NewEntity(context)}
}
// tosca.Reader signature
func ReadImport(context *tosca.Context) tosca.EntityPtr {
self := NewImport(context)
if context.Is(ard.TypeMap) {
// Long notation
context.ValidateUnsupportedFields(context.ReadFields(self))
} else if context.ValidateType(ard.TypeMap, ard.TypeString) {
// Short notation
name := "url"
if self.Context.ReadTagOverrides != nil {
if override, ok := self.Context.ReadTagOverrides["URL"]; ok {
name = override
}
}
self.URL = context.FieldChild(name, context.Data).ReadString()
}
return self
}
func (self *Import) NewImportSpec(unit *Unit) (*tosca.ImportSpec, bool) {
if self.URL == nil {
return nil, false
}
repository := self.Repository
if (repository == nil) && (self.RepositoryName != nil) {
// Namespace lookup phase may not have run yet, so we will retrieve the repository on our own
for _, r := range unit.Repositories {
if r.Name == *self.RepositoryName {
repository = r
break
}
}
}
var origins []urlpkg.URL
var urlContext *urlpkg.Context
if repository != nil {
repositoryUrl := repository.GetURL()
if repositoryUrl == nil {
self.Context.ReportRepositoryInaccessible(repository.Name)
return nil, false
}
origins = []urlpkg.URL{repositoryUrl}
urlContext = repositoryUrl.Context()
} else {
origin := self.Context.URL.Origin()
origins = []urlpkg.URL{origin}
urlContext = origin.Context()
}
url, err := urlpkg.NewValidURL(*self.URL, origins, urlContext)
if err != nil {
self.Context.ReportError(err)
return nil, false
}
appendShortcutNames := !self.Context.HasQuirk(tosca.QuirkNamespaceNormativeShortcutsDisable)
importSpec := &tosca.ImportSpec{
URL: url,
NameTransformer: newImportNameTransformer(self.Namespace, appendShortcutNames),
Implicit: false,
}
return importSpec, true
}
func newImportNameTransformer(prefix *string, appendShortCutnames bool) tosca.NameTransformer {
return func(name string, entityPtr tosca.EntityPtr) []string {
var names []string
if metadata, ok := tosca.GetMetadata(entityPtr); ok {
if normative, ok := metadata["puccini.normative"]; ok {
if normative == "true" {
// Reserved "tosca." names also get shorthand and prefixed names
names = getNormativeNames(entityPtr, names, name, "tosca", appendShortCutnames)
}
}
}
if (prefix != nil) && (*prefix != "") {
// Prefixed name
names = append(names, fmt.Sprintf("%s:%s", *prefix, name))
} else {
// Name as is
names = append(names, name)
}
return names
}
}
func getNormativeNames(entityPtr tosca.EntityPtr, names []string, name string, prefix string, appendShortcut bool) []string {
if !strings.HasPrefix(name, prefix+".") {
return names
}
s := strings.Split(name, ".")
// The short name starts at the first camel-cased segment
// (e.g. "prefix.blah.blah.Endpoint.Public")
firstShortSegment := len(s) - 1
for i, segment := range s {
if (len(segment) > 0) && unicode.IsUpper([]rune(segment)[0]) {
firstShortSegment = i
break
}
}
short := strings.Join(s[firstShortSegment:], ".")
// Prefixed
names = append(names, fmt.Sprintf("%s:%s", prefix, short))
// Override canonical name
tosca.SetMetadata(entityPtr, "canonical_name", fmt.Sprintf("%s::%s", prefix, short))
// Shortcut
if appendShortcut {
names = append(names, short)
}
return names
}
//
// Imports
//
type Imports []*Import