Change discovery servic to get APIs from invoker service
[nonrtric/plt/sme.git] / capifcore / internal / discoverservice / discoverservice.go
1 // -
2 //   ========================LICENSE_START=================================
3 //   O-RAN-SC
4 //   %%
5 //   Copyright (C) 2022: Nordix Foundation
6 //   %%
7 //   Licensed under the Apache License, Version 2.0 (the "License");
8 //   you may not use this file except in compliance with the License.
9 //   You may obtain a copy of the License at
10 //
11 //        http://www.apache.org/licenses/LICENSE-2.0
12 //
13 //   Unless required by applicable law or agreed to in writing, software
14 //   distributed under the License is distributed on an "AS IS" BASIS,
15 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 //   See the License for the specific language governing permissions and
17 //   limitations under the License.
18 //   ========================LICENSE_END===================================
19 //
20
21 package discoverservice
22
23 import (
24         "net/http"
25
26         "oransc.org/nonrtric/capifcore/internal/common29122"
27         discoverapi "oransc.org/nonrtric/capifcore/internal/discoverserviceapi"
28         "oransc.org/nonrtric/capifcore/internal/invokermanagement"
29
30         "github.com/labstack/echo/v4"
31
32         publishapi "oransc.org/nonrtric/capifcore/internal/publishserviceapi"
33 )
34
35 type DiscoverService struct {
36         invokerRegister invokermanagement.InvokerRegister
37 }
38
39 func NewDiscoverService(invokerRegister invokermanagement.InvokerRegister) *DiscoverService {
40         return &DiscoverService{
41                 invokerRegister: invokerRegister,
42         }
43 }
44
45 func (ds *DiscoverService) GetAllServiceAPIs(ctx echo.Context, params discoverapi.GetAllServiceAPIsParams) error {
46         allApis := ds.invokerRegister.GetInvokerApiList(params.ApiInvokerId)
47         if allApis == nil {
48                 return sendCoreError(ctx, http.StatusNotFound, "Invoker not registered")
49         }
50         filteredApis := []publishapi.ServiceAPIDescription{}
51         gatewayDomain := "r1-expo-func-aef"
52         for _, api := range *allApis {
53                 if !matchesFilter(api, params) {
54                         continue
55                 }
56                 profiles := *api.AefProfiles
57                 for i, profile := range profiles {
58                         profile.DomainName = &gatewayDomain // Hardcoded for now. Should be provided through some other mechanism.
59                         profiles[i] = profile
60                 }
61                 filteredApis = append(filteredApis, api)
62         }
63         discoveredApis := discoverapi.DiscoveredAPIs{
64                 ServiceAPIDescriptions: &filteredApis,
65         }
66         err := ctx.JSON(http.StatusOK, discoveredApis)
67         if err != nil {
68                 // Something really bad happened, tell Echo that our handler failed
69                 return err
70         }
71
72         return nil
73 }
74
75 func matchesFilter(api publishapi.ServiceAPIDescription, filter discoverapi.GetAllServiceAPIsParams) bool {
76         if filter.ApiName != nil && *filter.ApiName != api.ApiName {
77                 return false
78         }
79         if filter.ApiCat != nil && (api.ServiceAPICategory == nil || *filter.ApiCat != *api.ServiceAPICategory) {
80                 return false
81         }
82         profiles := *api.AefProfiles
83         for _, profile := range profiles {
84                 if checkAefId(filter, profile) && checkVersionAndCommType(profile, filter) && checkProtocol(filter, profile) && checkDataFormat(filter, profile) {
85                         return true
86                 }
87         }
88         return false
89 }
90
91 func checkAefId(filter discoverapi.GetAllServiceAPIsParams, profile publishapi.AefProfile) bool {
92         if filter.AefId != nil {
93                 return *filter.AefId == profile.AefId
94         }
95         return true
96 }
97
98 func checkVersionAndCommType(profile publishapi.AefProfile, filter discoverapi.GetAllServiceAPIsParams) bool {
99         match := false
100         if filter.ApiVersion != nil {
101                 for _, version := range profile.Versions {
102                         match = checkVersion(version, filter.ApiVersion, filter.CommType)
103                         if match {
104                                 break
105                         }
106                 }
107         } else if filter.CommType != nil {
108                 for _, version := range profile.Versions {
109                         match = checkCommType(version.Resources, filter.CommType)
110                 }
111         } else {
112                 match = true
113         }
114         return match
115 }
116
117 func checkProtocol(filter discoverapi.GetAllServiceAPIsParams, profile publishapi.AefProfile) bool {
118         if filter.Protocol != nil {
119                 return profile.Protocol != nil && *filter.Protocol == *profile.Protocol
120         }
121         return true
122 }
123
124 func checkDataFormat(filter discoverapi.GetAllServiceAPIsParams, profile publishapi.AefProfile) bool {
125         if filter.DataFormat != nil {
126                 return profile.DataFormat != nil && *filter.DataFormat == *profile.DataFormat
127         }
128         return true
129 }
130
131 func checkVersion(version publishapi.Version, wantedVersion *string, commType *publishapi.CommunicationType) bool {
132         match := false
133         if *wantedVersion == version.ApiVersion {
134                 if commType != nil {
135                         match = checkCommType(version.Resources, commType)
136                 } else {
137                         match = true
138                 }
139         }
140         return match
141 }
142
143 func checkCommType(resources *[]publishapi.Resource, commType *publishapi.CommunicationType) bool {
144         match := false
145         if commType != nil {
146                 for _, resource := range *resources {
147                         if resource.CommType == *commType {
148                                 match = true
149                                 break
150                         }
151                 }
152         } else {
153                 match = true
154         }
155         return match
156 }
157
158 // This function wraps sending of an error in the Error format, and
159 // handling the failure to marshal that.
160 func sendCoreError(ctx echo.Context, code int, message string) error {
161         pd := common29122.ProblemDetails{
162                 Cause:  &message,
163                 Status: &code,
164         }
165         err := ctx.JSON(code, pd)
166         return err
167 }