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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.cps.ncmp.dmi.rest.stub.controller;
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;
44 @RequestMapping("${rest.api.provmns-base-path}")
45 @RequiredArgsConstructor
47 public class ProvMnsStubController implements ProvMnS {
49 static final ResourceOneOf dummyResource = new ResourceOneOf("some id");
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})");
55 private final Sleeper sleeper;
58 dummyResource.setObjectClass("dummyClass");
59 dummyResource.setObjectInstance("dummyInstance");
60 dummyResource.setAttributes(Collections.singletonMap("dummyAttribute", "dummy value"));
64 * Replaces a complete single resource or creates it if it does not exist.
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
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));
79 * Reads one or multiple resources.
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
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
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.
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));
110 * Patches (Create, Update or Delete) one or multiple resources.
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.
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));
124 * Delete one or multiple resources.
126 * @param httpServletRequest URI request including path
127 * @return {@code ResponseEntity} The response body is empty, HTTP status returned.
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));
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)));
144 matcher = PATTERN_HTTP_ERROR.matcher(simulation);
145 if (matcher.matches()) {
146 return Optional.of(createErrorRsponseEntity(Integer.parseInt(matcher.group(1))));
149 return Optional.empty();
152 private void haveALittleRest(final int durationInSeconds) {
153 log.warn("Stub is mocking slow response; delay {} seconds", durationInSeconds);
155 sleeper.haveALittleRest(durationInSeconds);
156 } catch (final InterruptedException e) {
157 log.trace("Sleep interrupted, re-interrupting the thread");
158 Thread.currentThread().interrupt();
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));