2 * ========================LICENSE_START=================================
5 * Copyright (C) 2019 Nordix Foundation
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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===================================
20 package org.oransc.ric.portal.dashboard.config;
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.Mockito.doAnswer;
24 import static org.mockito.Mockito.mock;
25 import static org.mockito.Mockito.when;
26 import com.fasterxml.jackson.core.JsonProcessingException;
27 import java.lang.invoke.MethodHandles;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.Iterator;
32 import java.util.List;
34 import java.util.Optional;
36 import org.oransc.ric.a1controller.client.api.A1ControllerApi;
37 import org.oransc.ric.a1controller.client.invoker.ApiClient;
38 import org.oransc.ric.a1controller.client.model.InputNRRidPTidPIidPISchema;
39 import org.oransc.ric.a1controller.client.model.InputNRRidPTidPIidSchema;
40 import org.oransc.ric.a1controller.client.model.InputNRRidPTidSchema;
41 import org.oransc.ric.a1controller.client.model.InputNRRidSchema;
42 import org.oransc.ric.a1controller.client.model.OutputCodeSchema;
43 import org.oransc.ric.a1controller.client.model.OutputCodeSchemaOutput;
44 import org.oransc.ric.a1controller.client.model.OutputDescNamePTCodeSchema;
45 import org.oransc.ric.a1controller.client.model.OutputDescNamePTCodeSchemaOutput;
46 import org.oransc.ric.a1controller.client.model.OutputPICodeSchema;
47 import org.oransc.ric.a1controller.client.model.OutputPICodeSchemaOutput;
48 import org.oransc.ric.a1controller.client.model.OutputPIidsListCodeSchema;
49 import org.oransc.ric.a1controller.client.model.OutputPIidsListCodeSchemaOutput;
50 import org.oransc.ric.a1controller.client.model.OutputPTidsListCodeSchema;
51 import org.oransc.ric.a1controller.client.model.OutputPTidsListCodeSchemaOutput;
52 import org.oransc.ric.portal.dashboard.model.PolicyType;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55 import org.springframework.beans.factory.annotation.Value;
56 import org.springframework.context.annotation.Bean;
57 import org.springframework.context.annotation.Configuration;
58 import org.springframework.context.annotation.Profile;
59 import org.springframework.http.HttpStatus;
62 * Creates a mock implementation of the A1 controller client API.
66 public class A1ControllerMockConfiguration {
68 private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
70 // A "control" is an element in the XApp descriptor
71 public static final String AC_CONTROL_NAME = "admission_control_policy";
73 // Simulate remote method delay for UI testing
74 @Value("${mock.config.delay:0}")
77 public A1ControllerMockConfiguration() {
78 logger.info("Configuring mock A1 Mediator");
81 private ApiClient apiClient() {
82 ApiClient mockClient = mock(ApiClient.class);
83 when(mockClient.getStatusCode()).thenReturn(HttpStatus.OK);
88 // Use the same name as regular configuration
89 public A1ControllerApi a1ControllerApi() {
90 ApiClient apiClient = apiClient();
91 A1ControllerApi mockApi = mock(A1ControllerApi.class);
93 when(mockApi.getApiClient()).thenReturn(apiClient);
97 logger.debug("a1ControllerGetHandler sleeping {}", delayMs);
98 Thread.sleep(delayMs);
100 List<Integer> types = database.getTypes();
101 OutputPTidsListCodeSchemaOutput output = new OutputPTidsListCodeSchemaOutput();
102 output.setPolicyTypeIdList(types);
103 output.setCode(String.valueOf(HttpStatus.OK.value()));
104 OutputPTidsListCodeSchema outputSchema = new OutputPTidsListCodeSchema();
105 outputSchema.setOutput(output);
107 }).when(mockApi).a1ControllerGetAllPolicyTypes(any(InputNRRidSchema.class));
111 logger.debug("a1ControllerGetPolicyType sleeping {}", delayMs);
112 Thread.sleep(delayMs);
114 InputNRRidPTidSchema input = inv.<InputNRRidPTidSchema>getArgument(0);
115 PolicyType policyType = database.getPolicyType(input.getInput().getPolicyTypeId());
116 OutputDescNamePTCodeSchemaOutput type = new OutputDescNamePTCodeSchemaOutput();
117 type.setName(policyType.getName());
118 type.setDescription(policyType.getDescription());
119 type.setPolicyType(database.normalize(policyType.getCreateSchema()));
120 type.setCode(String.valueOf(HttpStatus.OK.value()));
121 OutputDescNamePTCodeSchema outputSchema = new OutputDescNamePTCodeSchema();
122 outputSchema.setOutput(type);
124 }).when(mockApi).a1ControllerGetPolicyType(any(InputNRRidPTidSchema.class));
128 logger.debug("a1ControllerGetHandler sleeping {}", delayMs);
129 Thread.sleep(delayMs);
131 InputNRRidPTidSchema input = inv.<InputNRRidPTidSchema>getArgument(0);
132 List<String> instances = database.getInstances(Optional.of(input.getInput().getPolicyTypeId()));
133 OutputPIidsListCodeSchemaOutput instancesOutput = new OutputPIidsListCodeSchemaOutput();
134 instancesOutput.setPolicyInstanceIdList(instances);
135 instancesOutput.setCode(String.valueOf(HttpStatus.OK.value()));
136 OutputPIidsListCodeSchema outputSchema = new OutputPIidsListCodeSchema();
137 outputSchema.setOutput(instancesOutput);
139 }).when(mockApi).a1ControllerGetAllInstancesForType(any(InputNRRidPTidSchema.class));
143 logger.debug("a1ControllerGetHandler sleeping {}", delayMs);
144 Thread.sleep(delayMs);
146 InputNRRidPTidPIidSchema input = inv.<InputNRRidPTidPIidSchema>getArgument(0);
147 Integer polcyTypeId = input.getInput().getPolicyTypeId();
148 String instanceId = input.getInput().getPolicyInstanceId();
149 String instance = database.normalize(database.getInstance(polcyTypeId, instanceId));
150 OutputPICodeSchemaOutput instanceOutput = new OutputPICodeSchemaOutput();
151 instanceOutput.setPolicyInstance(instance);
152 instanceOutput.setCode(String.valueOf(HttpStatus.OK.value()));
153 OutputPICodeSchema outputSchema = new OutputPICodeSchema();
154 outputSchema.setOutput(instanceOutput);
156 }).when(mockApi).a1ControllerGetPolicyInstance(any(InputNRRidPTidPIidSchema.class));
160 logger.debug("a1ControllerGetHandler sleeping {}", delayMs);
161 Thread.sleep(delayMs);
163 InputNRRidPTidPIidPISchema input = inv.<InputNRRidPTidPIidPISchema>getArgument(0);
164 Integer polcyTypeId = input.getInput().getPolicyTypeId();
165 String instanceId = input.getInput().getPolicyInstanceId();
166 String instance = input.getInput().getPolicyInstance();
167 database.putInstance(polcyTypeId, instanceId, instance);
168 OutputCodeSchemaOutput outputCodeSchemaOutput = new OutputCodeSchemaOutput();
169 outputCodeSchemaOutput.setCode(String.valueOf(HttpStatus.CREATED.value()));
170 OutputCodeSchema outputCodeSchema = new OutputCodeSchema();
171 outputCodeSchema.setOutput(outputCodeSchemaOutput);
172 return outputCodeSchema;
173 }).when(mockApi).a1ControllerCreatePolicyInstance(any(InputNRRidPTidPIidPISchema.class));
177 logger.debug("a1ControllerGetHandler sleeping {}", delayMs);
178 Thread.sleep(delayMs);
180 InputNRRidPTidPIidSchema input = inv.<InputNRRidPTidPIidSchema>getArgument(0);
181 Integer polcyTypeId = input.getInput().getPolicyTypeId();
182 String instanceId = input.getInput().getPolicyInstanceId();
183 database.deleteInstance(polcyTypeId, instanceId);
184 OutputCodeSchemaOutput outputCodeSchemaOutput = new OutputCodeSchemaOutput();
185 outputCodeSchemaOutput.setCode(String.valueOf(HttpStatus.NO_CONTENT.value()));
186 OutputCodeSchema outputCodeSchema = new OutputCodeSchema();
187 outputCodeSchema.setOutput(outputCodeSchemaOutput);
188 return outputCodeSchema;
189 }).when(mockApi).a1ControllerDeletePolicyInstance(any(InputNRRidPTidPIidSchema.class));
196 private String schema1 = "{\"$schema\": " //
197 + "\"http://json-schema.org/draft-07/schema#\"," //
198 + "\"title\": \"ANR\"," //
199 + "\"description\": \"ANR Neighbour Cell Relation Policy\"," //
200 + "\"type\": \"object\"," //
201 + "\"properties\": " //
202 + "{ \"servingCellNrcgi\": {" //
203 + "\"type\": \"string\"," //
204 + "\"description\" : \"Serving Cell Identifier (NR CGI)\"}," //
205 + "\"neighborCellNrpci\": {" //
206 + "\"type\": \"string\"," //
207 + "\"description\": \"Neighbor Cell Identifier (NR PCI)\"}," //
208 + "\"neighborCellNrcgi\": {" //
209 + "\"type\": \"string\"," //
210 + "\"description\": \"Neighbor Cell Identifier (NR CGI)\"}," //
211 + "\"flagNoHo\": {" //
212 + "\"type\": \"boolean\"," //
213 + "\"description\": \"Flag for HANDOVER NOT ALLOWED\"}," //
214 + "\"flagNoXn\": {" //
215 + "\"type\": \"boolean\"," //
216 + "\"description\": \"Flag for Xn CONNECTION NOT ALLOWED\"}," //
217 + "\"flagNoRemove\": {" //
218 + "\"type\": \"boolean\"," //
219 + "\"description\": \"Flag for DELETION NOT ALLOWED\"}}, " //
220 + "\"required\": [ \"servingCellNrcgi\",\"neighborCellNrpci\",\"neighborCellNrcgi\",\"flagNoHo\",\"flagNoXn\",\"flagNoRemove\" ]}";
221 private PolicyType policy1 = new PolicyType(1, "ANR", "ANR Neighbour Cell Relation Policy", schema1);
223 private String policyInstance1 = "{\"servingCellNrcgi\": \"Cell1\",\r\n" + //
224 "\"neighborCellNrpci\": \"NCell1\",\r\n" + //
225 "\"neighborCellNrcgi\": \"Ncell1\",\r\n" + //
226 "\"flagNoHo\": true,\r\n" + //
227 "\"flagNoXn\": true,\r\n" + //
228 "\"flagNoRemove\": true}";
230 private String schema2 = "{\n" + " \"type\": \"object\",\n" + //
231 " \"title\": \"Car\",\n" + //
232 " \"properties\": {\n" + //
233 " \"make\": {\n" + //
234 " \"type\": \"string\",\n" + //
235 " \"enum\": [\n" + //
236 " \"Toyota\",\n" + //
244 " \"model\": {\n" + //
245 " \"type\": \"string\"\n" + //
247 " \"year\": {\n" + //
248 " \"type\": \"integer\",\n" + //
249 " \"enum\": [\n" + //
250 " 1995,1996,1997,1998,1999,\n" + //
251 " 2000,2001,2002,2003,2004,\n" + //
252 " 2005,2006,2007,2008,2009,\n" + //
253 " 2010,2011,2012,2013,2014\n" + //
255 " \"default\": 2008\n" + //
257 " \"safety\": {\n" + //
258 " \"type\": \"integer\",\n" + //
259 " \"format\": \"rating\",\n" + //
260 " \"maximum\": 5,\n" + //
261 " \"exclusiveMaximum\": false,\n" + //
262 " \"readonly\": false\n" + //
266 private PolicyType policy2 = new PolicyType(2, "type2", "Type2 description", schema2);
268 private String schema3 = "{\n" + //
269 " \"$id\": \"https://example.com/person.schema.json\",\n" + //
270 " \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n" + //
271 " \"title\": \"Person\",\n" + //
272 " \"type\": \"object\",\n" + //
273 " \"properties\": {\n" + //
274 " \"firstName\": {\n" + //
275 " \"type\": \"string\",\n" + //
276 " \"description\": \"The person's first name.\"\n" + //
278 " \"lastName\": {\n" + //
279 " \"type\": \"string\",\n" + //
280 " \"description\": \"The person's last name.\"\n" + //
283 " \"description\": \"Age in years which must be equal to or greater than zero.\",\n" + //
284 " \"type\": \"integer\",\n" + //
285 " \"minimum\": 0\n" + //
289 private PolicyType policy3 = new PolicyType(3, "type3", "Type3 description", schema3);
291 private String schema4 = "{" + //
292 " \"$id\": \"https://example.com/arrays.schema.json\"," + //
293 " \"$schema\": \"http://json-schema.org/draft-07/schema#\"," + //
294 " \"description\": \"A representation of a person, company, organization, or place\"," + //
295 " \"type\": \"object\"," + //
296 " \"properties\": {" + //
297 " \"fruits\": {" + //
298 " \"type\": \"array\"," + //
300 " \"type\": \"string\"" + //
303 " \"vegetables\": {" + //
304 " \"type\": \"array\"," + //
305 " \"items\": { \"$ref\": \"#/definitions/veggie\" }" + //
308 " \"definitions\": {" + //
309 " \"veggie\": {" + //
310 " \"type\": \"object\"," + //
311 " \"required\": [ \"veggieName\", \"veggieLike\" ]," + //
312 " \"properties\": {" + //
313 " \"veggieName\": {" + //
314 " \"type\": \"string\"," + //
315 " \"description\": \"The name of the vegetable.\"" + //
317 " \"veggieLike\": {" + //
318 " \"type\": \"boolean\"," + //
319 " \"description\": \"Do I like this vegetable?\"" + //
325 private PolicyType policy4 = new PolicyType(4, "type4", "Type4 description", schema4);
327 public class PolicyException extends Exception {
329 private static final long serialVersionUID = 1L;
331 public PolicyException(String message) {
333 System.out.println("**** Exception " + message);
337 private class PolicyTypeHolder {
338 PolicyTypeHolder(PolicyType pt) {
339 this.policyType = pt;
342 String getInstance(String instanceId) throws PolicyException {
343 String instance = instances.get(instanceId);
344 if (instance == null) {
345 throw new PolicyException("Instance not found: " + instanceId);
350 PolicyType getPolicyType() {
354 void putInstance(String id, String data) {
355 instances.put(id, data);
358 void deleteInstance(String id) {
359 instances.remove(id);
362 List<String> getInstances() {
363 return new ArrayList<>(instances.keySet());
366 private final PolicyType policyType;
367 private Map<String, String> instances = new HashMap<>();
371 types.put(1, new PolicyTypeHolder(policy1));
372 types.put(2, new PolicyTypeHolder(policy2));
373 types.put(3, new PolicyTypeHolder(policy3));
374 types.put(4, new PolicyTypeHolder(policy4));
376 putInstance(1, "ANR-1", policyInstance1);
377 } catch (JsonProcessingException | PolicyException e) {
382 String normalize(String str) {
383 return str.replace('\n', ' ');
386 void putInstance(Integer typeId, String instanceId, String instanceData)
387 throws JsonProcessingException, PolicyException {
388 PolicyTypeHolder type = getTypeHolder(typeId);
389 type.putInstance(instanceId, instanceData);
392 void deleteInstance(Integer typeId, String instanceId) throws JsonProcessingException, PolicyException {
393 PolicyTypeHolder type = getTypeHolder(typeId);
394 type.deleteInstance(instanceId);
397 String getInstance(Integer typeId, String instanceId) throws JsonProcessingException, PolicyException {
398 return getTypeHolder(typeId).getInstance(instanceId);
401 List<Integer> getTypes() {
402 return new ArrayList<>(types.keySet());
405 List<String> getInstances(Optional<Integer> typeId) throws PolicyException {
406 if (typeId.isPresent()) {
407 return getTypeHolder(typeId.get()).getInstances();
409 Set<String> res = new HashSet<String>();
410 for (Iterator<PolicyTypeHolder> i = types.values().iterator(); i.hasNext();) {
411 res.addAll(i.next().getInstances());
413 return new ArrayList<>(res);
417 private PolicyTypeHolder getTypeHolder(Integer typeId) throws PolicyException {
418 PolicyTypeHolder typeHolder = types.get(typeId);
419 if (typeHolder == null) {
420 throw new PolicyException("Type not found: " + typeId);
425 private PolicyType getPolicyType(Integer typeId) throws PolicyException {
426 PolicyTypeHolder typeHolder = getTypeHolder(typeId);
427 return typeHolder.getPolicyType();
430 private Map<Integer, PolicyTypeHolder> types = new HashMap<>();
434 private final Database database = new Database();