forked from fabric8-services/fabric8-wit
/
work_item_link_type.go
221 lines (196 loc) · 7.91 KB
/
work_item_link_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
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
package controller
import (
"fmt"
"net/http"
"github.com/fabric8-services/fabric8-wit/app"
"github.com/fabric8-services/fabric8-wit/application"
"github.com/fabric8-services/fabric8-wit/errors"
"github.com/fabric8-services/fabric8-wit/jsonapi"
"github.com/fabric8-services/fabric8-wit/rest"
"github.com/fabric8-services/fabric8-wit/space"
"github.com/fabric8-services/fabric8-wit/workitem/link"
"github.com/goadesign/goa"
)
// WorkItemLinkTypeController implements the work-item-link-type resource.
type WorkItemLinkTypeController struct {
*goa.Controller
db application.DB
config WorkItemLinkTypeControllerConfiguration
}
// WorkItemLinkTypeControllerConfiguration the configuration for the WorkItemLinkTypeController
type WorkItemLinkTypeControllerConfiguration interface {
GetCacheControlWorkItemLinkTypes() string
GetCacheControlWorkItemLinkType() string
}
// NewWorkItemLinkTypeController creates a work-item-link-type controller.
func NewWorkItemLinkTypeController(service *goa.Service, db application.DB, config WorkItemLinkTypeControllerConfiguration) *WorkItemLinkTypeController {
return &WorkItemLinkTypeController{
Controller: service.NewController("WorkItemLinkTypeController"),
db: db,
config: config,
}
}
// enrichLinkTypeSingle includes related resources in the single's "included" array
// TODO(kwk): Adding of links in this function can be done during conversion.
func enrichLinkTypeSingle(ctx *workItemLinkContext, single *app.WorkItemLinkTypeSingle) error {
// Add "links" element
relatedURL := rest.AbsoluteURL(ctx.Request, ctx.LinkFunc(*single.Data.ID))
single.Data.Links = &app.GenericLinks{
Self: &relatedURL,
Related: &relatedURL,
}
return nil
}
// enrichLinkTypeList includes related resources in the list's "included" array
// TODO(kwk): Adding of links in this function can be done during conversion.
func enrichLinkTypeList(ctx *workItemLinkContext, list *app.WorkItemLinkTypeList) error {
// Add "links" element
for _, data := range list.Data {
relatedURL := rest.AbsoluteURL(ctx.Request, ctx.LinkFunc(*data.ID))
data.Links = &app.GenericLinks{
Self: &relatedURL,
Related: &relatedURL,
}
}
return nil
}
// Show runs the show action.
func (c *WorkItemLinkTypeController) Show(ctx *app.ShowWorkItemLinkTypeContext) error {
err := application.Transactional(c.db, func(appl application.Application) error {
modelLinkType, err := appl.WorkItemLinkTypes().Load(ctx.Context, ctx.WiltID)
if err != nil {
return jsonapi.JSONErrorResponse(ctx, err)
}
return ctx.ConditionalRequest(*modelLinkType, c.config.GetCacheControlWorkItemLinkType, func() error {
// Convert the created link type entry into a rest representation
appLinkType := ConvertWorkItemLinkTypeFromModel(ctx.Request, *modelLinkType)
// Enrich
HrefFunc := func(obj interface{}) string {
return fmt.Sprintf(app.WorkItemLinkTypeHref("%s"), obj)
}
linkCtx := newWorkItemLinkContext(ctx.Context, ctx.Service, appl, c.db, ctx.Request, ctx.ResponseWriter, HrefFunc, nil)
err = enrichLinkTypeSingle(linkCtx, &appLinkType)
if err != nil {
return goa.ErrInternal("Failed to enrich link type: %s", err.Error())
}
return ctx.OK(&appLinkType)
})
})
if err != nil {
return jsonapi.JSONErrorResponse(ctx, err)
}
return nil
}
// ConvertWorkItemLinkTypeFromModel converts a work item link type from model to REST representation
func ConvertWorkItemLinkTypeFromModel(request *http.Request, modelLinkType link.WorkItemLinkType) app.WorkItemLinkTypeSingle {
linkCategoryRelatedURL := rest.AbsoluteURL(request, app.WorkItemLinkCategoryHref(modelLinkType.LinkCategoryID.String()))
spaceTemplateRelatedURL := rest.AbsoluteURL(request, app.SpaceTemplateHref(modelLinkType.SpaceTemplateID.String()))
spaceRelatedURL := rest.AbsoluteURL(request, app.SpaceHref(space.SystemSpace.String()))
topologyStr := modelLinkType.Topology.String()
var converted = app.WorkItemLinkTypeSingle{
Data: &app.WorkItemLinkTypeData{
Type: link.EndpointWorkItemLinkTypes,
ID: &modelLinkType.ID,
Attributes: &app.WorkItemLinkTypeAttributes{
Name: &modelLinkType.Name,
Description: modelLinkType.Description,
Version: &modelLinkType.Version,
CreatedAt: &modelLinkType.CreatedAt,
UpdatedAt: &modelLinkType.UpdatedAt,
ForwardName: &modelLinkType.ForwardName,
ReverseName: &modelLinkType.ReverseName,
Topology: &topologyStr,
},
Relationships: &app.WorkItemLinkTypeRelationships{
LinkCategory: &app.RelationWorkItemLinkCategory{
Data: &app.RelationWorkItemLinkCategoryData{
Type: link.EndpointWorkItemLinkCategories,
ID: modelLinkType.LinkCategoryID,
},
Links: &app.GenericLinks{
Self: &linkCategoryRelatedURL,
Related: &linkCategoryRelatedURL,
},
},
Space: app.NewSpaceRelation(space.SystemSpace, spaceRelatedURL),
SpaceTemplate: app.NewSpaceTemplateRelation(modelLinkType.SpaceTemplateID, spaceTemplateRelatedURL),
},
},
}
return converted
}
// ConvertWorkItemLinkTypeToModel converts the incoming app representation of a work item link type to the model layout.
// Values are only overwrriten if they are set in "in", otherwise the values in "out" remain.
func ConvertWorkItemLinkTypeToModel(appLinkType app.WorkItemLinkTypeSingle) (*link.WorkItemLinkType, error) {
modelLinkType := link.WorkItemLinkType{}
if appLinkType.Data == nil {
return nil, errors.NewBadParameterError("data", nil).Expected("not <nil>")
}
if appLinkType.Data.Attributes == nil {
return nil, errors.NewBadParameterError("data.attributes", nil).Expected("not <nil>")
}
if appLinkType.Data.Relationships == nil {
return nil, errors.NewBadParameterError("data.relationships", nil).Expected("not <nil>")
}
attrs := appLinkType.Data.Attributes
rel := appLinkType.Data.Relationships
if appLinkType.Data.ID != nil {
modelLinkType.ID = *appLinkType.Data.ID
}
if attrs != nil {
// If the name is not nil, it MUST NOT be empty
if attrs.Name != nil {
if *attrs.Name == "" {
return nil, errors.NewBadParameterError("data.attributes.name", *attrs.Name)
}
modelLinkType.Name = *attrs.Name
}
if attrs.Description != nil {
modelLinkType.Description = attrs.Description
}
if attrs.Version != nil {
modelLinkType.Version = *attrs.Version
}
// If the forwardName is not nil, it MUST NOT be empty
if attrs.ForwardName != nil {
if *attrs.ForwardName == "" {
return nil, errors.NewBadParameterError("data.attributes.forward_name", *attrs.ForwardName)
}
modelLinkType.ForwardName = *attrs.ForwardName
}
// If the ReverseName is not nil, it MUST NOT be empty
if attrs.ReverseName != nil {
if *attrs.ReverseName == "" {
return nil, errors.NewBadParameterError("data.attributes.reverse_name", *attrs.ReverseName)
}
modelLinkType.ReverseName = *attrs.ReverseName
}
if attrs.Topology != nil {
modelLinkType.Topology = link.Topology(*attrs.Topology)
if err := modelLinkType.Topology.CheckValid(); err != nil {
return nil, err
}
}
}
if rel != nil && rel.LinkCategory != nil && rel.LinkCategory.Data != nil {
modelLinkType.LinkCategoryID = rel.LinkCategory.Data.ID
}
if rel != nil && rel.SpaceTemplate != nil && rel.SpaceTemplate.Data != nil {
modelLinkType.SpaceTemplateID = rel.SpaceTemplate.Data.ID
}
return &modelLinkType, nil
}
func ConvertLinkTypesFromModels(request *http.Request, modelLinkTypes []link.WorkItemLinkType) (*app.WorkItemLinkTypeList, error) {
appLinkTypes := app.WorkItemLinkTypeList{}
appLinkTypes.Data = make([]*app.WorkItemLinkTypeData, len(modelLinkTypes))
for index, modelLinkType := range modelLinkTypes {
appLinkType := ConvertWorkItemLinkTypeFromModel(request, modelLinkType)
appLinkTypes.Data[index] = appLinkType.Data
}
// TODO: When adding pagination, this must not be len(rows) but
// the overall total number of elements from all pages.
appLinkTypes.Meta = &app.WorkItemLinkTypeListMeta{
TotalCount: len(modelLinkTypes),
}
return &appLinkTypes, nil
}