25fb51c46002bc72014cfa595fc0c20103a5875d
[cps/ncmp-dmi-plugin.git] /
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2025 OpenInfra Foundation Europe
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *  SPDX-License-Identifier: Apache-2.0
18  *  ============LICENSE_END=========================================================
19  */
20
21 package org.onap.cps.ncmp.dmi.rest.stub.controller;
22
23 import jakarta.servlet.http.HttpServletRequest;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Optional;
27 import java.util.regex.Matcher;
28 import java.util.regex.Pattern;
29 import lombok.RequiredArgsConstructor;
30 import lombok.extern.slf4j.Slf4j;
31 import org.onap.cps.ncmp.dmi.provmns.api.ProvMnS;
32 import org.onap.cps.ncmp.dmi.provmns.model.ClassNameIdGetDataNodeSelectorParameter;
33 import org.onap.cps.ncmp.dmi.provmns.model.ErrorResponseDefault;
34 import org.onap.cps.ncmp.dmi.provmns.model.Resource;
35 import org.onap.cps.ncmp.dmi.provmns.model.ResourceOneOf;
36 import org.onap.cps.ncmp.dmi.provmns.model.Scope;
37 import org.onap.cps.ncmp.dmi.rest.stub.utils.Sleeper;
38 import org.springframework.http.HttpStatus;
39 import org.springframework.http.ResponseEntity;
40 import org.springframework.web.bind.annotation.RequestMapping;
41 import org.springframework.web.bind.annotation.RestController;
42
43 @RestController
44 @RequestMapping("${rest.api.provmns-base-path}")
45 @RequiredArgsConstructor
46 @Slf4j
47 public class ProvMnsStubController implements ProvMnS {
48
49     static final ResourceOneOf dummyResource = new ResourceOneOf("some id");
50
51     static final Pattern PATTERN_SIMULATION = Pattern.compile("dmiSimulation=(\\w+_\\d{1,3})");
52     static final Pattern PATTERN_HTTP_ERROR = Pattern.compile("httpError_(\\d{3})");
53     static final Pattern PATTERN_SLOW_RESPONSE = Pattern.compile("slowResponse_(\\d{1,3})");
54
55     private final Sleeper sleeper;
56
57     static {
58         dummyResource.setObjectClass("dummyClass");
59         dummyResource.setObjectInstance("dummyInstance");
60         dummyResource.setAttributes(Collections.singletonMap("dummyAttribute", "dummy value"));
61     }
62
63     /**
64      * Replaces a complete single resource or creates it if it does not exist.
65      *
66      * @param httpServletRequest      URI request including path
67      * @param resource                Resource representation of the resource to be created or replaced
68      * @return {@code Object}         The representation of the updated resource is returned in the response
69      *                                message body.
70      */
71     @Override
72     public ResponseEntity<Object> putMoi(final HttpServletRequest httpServletRequest, final Resource resource) {
73         log.info("putMoi: {}", resource);
74         final Optional<ResponseEntity<Object>> optionalResponseEntity = simulate(httpServletRequest);
75         return optionalResponseEntity.orElseGet(() -> new ResponseEntity<>(resource, HttpStatus.OK));
76     }
77
78     /**
79      * Reads one or multiple resources.
80      *
81      * @param httpServletRequest      URI request including path
82      * @param scope                   Extends the set of targeted resources beyond the base
83      *                                resource identified with the authority and path component of
84      *                                the URI.
85      * @param filter                  Reduces the targeted set of resources by applying a filter to
86      *                                the scoped set of resource representations. Only resources
87      *                                representations for which the filter construct evaluates to
88      *                                "true" are targeted.
89      * @param attributes              Attributes of the scoped resources to be returned. The
90      *                                value is a comma-separated list of attribute names.
91      * @param fields                  Attribute fields of the scoped resources to be returned. The
92      *                                value is a comma-separated list of JSON pointers to the
93      *                                attribute fields.
94      * @param dataNodeSelector        dataNodeSelector object
95      * @return {@code ResponseEntity} The resources identified in the request for retrieval are returned
96      *                                in the response message body.
97      */
98     @Override
99     public ResponseEntity<Object> getMoi(final HttpServletRequest httpServletRequest, final Scope scope,
100                                            final String filter, final List<String> attributes,
101                                            final List<String> fields,
102                                            final ClassNameIdGetDataNodeSelectorParameter dataNodeSelector) {
103         log.info("getMoi: scope: {}, filter: {}, attributes: {}, fields: {}, dataNodeSelector: {}",
104                 scope, filter, attributes, fields, dataNodeSelector);
105         final Optional<ResponseEntity<Object>> optionalResponseEntity = simulate(httpServletRequest);
106         return optionalResponseEntity.orElseGet(() -> new ResponseEntity<>(dummyResource, HttpStatus.OK));
107     }
108
109     /**
110      * Patches (Create, Update or Delete) one or multiple resources.
111      *
112      * @param httpServletRequest      URI request including path
113      * @param resource                Resource representation of the resource to be created or replaced
114      * @return {@code ResponseEntity} The updated resource representations are returned in the response message body.
115      */
116     @Override
117     public ResponseEntity<Object> patchMoi(final HttpServletRequest httpServletRequest, final Resource resource) {
118         log.info("patchMoi: {}", resource);
119         final Optional<ResponseEntity<Object>> optionalResponseEntity = simulate(httpServletRequest);
120         return optionalResponseEntity.orElseGet(() -> new ResponseEntity<>(resource, HttpStatus.OK));
121     }
122
123     /**
124      * Delete one or multiple resources.
125      *
126      * @param httpServletRequest      URI request including path
127      * @return {@code ResponseEntity} The response body is empty, HTTP status returned.
128      */
129     @Override
130     public ResponseEntity<Object> deleteMoi(final HttpServletRequest httpServletRequest) {
131         log.info("deleteMoi:");
132         final Optional<ResponseEntity<Object>> optionalResponseEntity = simulate(httpServletRequest);
133         return optionalResponseEntity.orElseGet(() -> new ResponseEntity<>(HttpStatus.OK));
134     }
135
136     private Optional<ResponseEntity<Object>> simulate(final HttpServletRequest httpServletRequest) {
137         Matcher matcher = PATTERN_SIMULATION.matcher(httpServletRequest.getRequestURI());
138         if (matcher.find()) {
139             final String simulation = matcher.group(1);
140             matcher = PATTERN_SLOW_RESPONSE.matcher(simulation);
141             if (matcher.matches()) {
142                 haveALittleRest(Integer.parseInt(matcher.group(1)));
143             }
144             matcher = PATTERN_HTTP_ERROR.matcher(simulation);
145             if (matcher.matches()) {
146                 return Optional.of(createErrorRsponseEntity(Integer.parseInt(matcher.group(1))));
147             }
148         }
149         return Optional.empty();
150     }
151
152     private void haveALittleRest(final int durationInSeconds) {
153         log.warn("Stub is mocking slow response; delay {} seconds", durationInSeconds);
154         try {
155             sleeper.haveALittleRest(durationInSeconds);
156         } catch (final InterruptedException e) {
157             log.trace("Sleep interrupted, re-interrupting the thread");
158             Thread.currentThread().interrupt();
159         }
160     }
161
162     private static ResponseEntity<Object> createErrorRsponseEntity(final int errorCode) {
163         log.warn("Stub is mocking an error response, code: {}", errorCode);
164         final ErrorResponseDefault errorResponseDefault = new ErrorResponseDefault("ERROR_FROM_STUB");
165         errorResponseDefault.setTitle("Title set by Stub");
166         errorResponseDefault.setStatus(String.valueOf(errorCode));
167         return new ResponseEntity<>(errorResponseDefault, HttpStatus.valueOf(errorCode));
168     }
169
170 }