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;
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;
37 import org.oransc.ric.a1controller.client.api.A1ControllerApi;
38 import org.oransc.ric.a1controller.client.invoker.ApiClient;
39 import org.oransc.ric.a1controller.client.model.InputNRRidPTidPIidPISchema;
40 import org.oransc.ric.a1controller.client.model.InputNRRidPTidPIidSchema;
41 import org.oransc.ric.a1controller.client.model.InputNRRidPTidSchema;
42 import org.oransc.ric.a1controller.client.model.InputNRRidSchema;
43 import org.oransc.ric.a1controller.client.model.OutputDescNamePTSchema;
44 import org.oransc.ric.a1controller.client.model.OutputDescNamePTSchemaOutput;
45 import org.oransc.ric.a1controller.client.model.OutputPISchema;
46 import org.oransc.ric.a1controller.client.model.OutputPISchemaOutput;
47 import org.oransc.ric.a1controller.client.model.OutputPIidsListSchema;
48 import org.oransc.ric.a1controller.client.model.OutputPIidsListSchemaOutput;
49 import org.oransc.ric.a1controller.client.model.OutputPTidsListSchema;
50 import org.oransc.ric.a1controller.client.model.OutputPTidsListSchemaOutput;
51 import org.oransc.ric.portal.dashboard.model.PolicyType;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54 import org.springframework.beans.factory.annotation.Value;
55 import org.springframework.context.annotation.Bean;
56 import org.springframework.context.annotation.Configuration;
57 import org.springframework.context.annotation.Profile;
58 import org.springframework.http.HttpStatus;
60 import com.fasterxml.jackson.core.JsonProcessingException;
63 * Creates a mock implementation of the A1 controller client API.
67 public class A1ControllerMockConfiguration {
69 private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
71 // A "control" is an element in the XApp descriptor
72 public static final String AC_CONTROL_NAME = "admission_control_policy";
74 // Simulate remote method delay for UI testing
75 @Value("${mock.config.delay:0}")
78 public A1ControllerMockConfiguration() {
79 logger.info("Configuring mock A1 Mediator");
82 private ApiClient apiClient() {
83 ApiClient mockClient = mock(ApiClient.class);
84 when(mockClient.getStatusCode()).thenReturn(HttpStatus.OK);
89 // Use the same name as regular configuration
90 public A1ControllerApi a1ControllerApi() {
91 ApiClient apiClient = apiClient();
92 A1ControllerApi mockApi = mock(A1ControllerApi.class);
94 when(mockApi.getApiClient()).thenReturn(apiClient);
98 logger.debug("a1ControllerGetHandler sleeping {}", delayMs);
99 Thread.sleep(delayMs);
101 List<Integer> types = database.getTypes();
102 OutputPTidsListSchemaOutput output = new OutputPTidsListSchemaOutput();
103 output.setPolicyTypeIdList(types);
104 OutputPTidsListSchema outputSchema = new OutputPTidsListSchema();
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 OutputDescNamePTSchemaOutput type = new OutputDescNamePTSchemaOutput();
117 type.setName(policyType.getName());
118 type.setDescription(policyType.getDescription());
119 type.setPolicyType(database.normalize(policyType.getCreateSchema()));
120 OutputDescNamePTSchema outputSchema = new OutputDescNamePTSchema();
121 outputSchema.setOutput(type);
123 }).when(mockApi).a1ControllerGetPolicyType(any(InputNRRidPTidSchema.class));
127 logger.debug("a1ControllerGetHandler sleeping {}", delayMs);
128 Thread.sleep(delayMs);
130 InputNRRidPTidSchema input = inv.<InputNRRidPTidSchema>getArgument(0);
131 List<String> instances = database.getInstances(Optional.of(input.getInput().getPolicyTypeId()));
132 OutputPIidsListSchemaOutput instancesOutput = new OutputPIidsListSchemaOutput();
133 instancesOutput.setPolicyInstanceIdList(instances);
134 OutputPIidsListSchema outputSchema = new OutputPIidsListSchema();
135 outputSchema.setOutput(instancesOutput);
137 }).when(mockApi).a1ControllerGetAllInstancesForType(any(InputNRRidPTidSchema.class));
141 logger.debug("a1ControllerGetHandler sleeping {}", delayMs);
142 Thread.sleep(delayMs);
144 InputNRRidPTidPIidSchema input = inv.<InputNRRidPTidPIidSchema>getArgument(0);
145 Integer polcyTypeId = input.getInput().getPolicyTypeId();
146 String instanceId = input.getInput().getPolicyInstanceId();
147 String instance = database.normalize(database.getInstance(polcyTypeId, instanceId));
148 OutputPISchemaOutput instanceOutput = new OutputPISchemaOutput();
149 instanceOutput.setPolicyInstance(instance);
150 OutputPISchema outputSchema = new OutputPISchema();
151 outputSchema.setOutput(instanceOutput);
153 }).when(mockApi).a1ControllerGetPolicyInstance(any(InputNRRidPTidPIidSchema.class));
157 logger.debug("a1ControllerGetHandler sleeping {}", delayMs);
158 Thread.sleep(delayMs);
160 InputNRRidPTidPIidPISchema input = inv.<InputNRRidPTidPIidPISchema>getArgument(0);
161 Integer polcyTypeId = input.getInput().getPolicyTypeId();
162 String instanceId = input.getInput().getPolicyInstanceId();
163 String instance = input.getInput().getPolicyInstance();
164 database.putInstance(polcyTypeId, instanceId, instance);
166 }).when(mockApi).a1ControllerCreatePolicyInstance(any(InputNRRidPTidPIidPISchema.class));
170 logger.debug("a1ControllerGetHandler sleeping {}", delayMs);
171 Thread.sleep(delayMs);
173 InputNRRidPTidPIidSchema input = inv.<InputNRRidPTidPIidSchema>getArgument(0);
174 Integer polcyTypeId = input.getInput().getPolicyTypeId();
175 String instanceId = input.getInput().getPolicyInstanceId();
176 database.deleteInstance(polcyTypeId, instanceId);
178 }).when(mockApi).a1ControllerDeletePolicyInstance(any(InputNRRidPTidPIidSchema.class));
185 private String schema1 = "{\"$schema\": " //
186 + "\"http://json-schema.org/draft-07/schema#\"," //
187 + "\"title\": \"ANR\"," //
188 + "\"description\": \"ANR Neighbour Cell Relation Policy\"," //
189 + "\"type\": \"object\"," //
190 + "\"properties\": " //
191 + "{ \"servingCellNrcgi\": {" //
192 + "\"type\": \"string\"," //
193 + "\"description\" : \"Serving Cell Identifier (NR CGI)\"}," //
194 + "\"neighborCellNrpci\": {" //
195 + "\"type\": \"string\"," //
196 + "\"description\": \"Neighbor Cell Identifier (NR PCI)\"}," //
197 + "\"neighborCellNrcgi\": {" //
198 + "\"type\": \"string\"," //
199 + "\"description\": \"Neighbor Cell Identifier (NR CGI)\"}," //
200 + "\"flagNoHo\": {" //
201 + "\"type\": \"boolean\"," //
202 + "\"description\": \"Flag for HANDOVER NOT ALLOWED\"}," //
203 + "\"flagNoXn\": {" //
204 + "\"type\": \"boolean\"," //
205 + "\"description\": \"Flag for Xn CONNECTION NOT ALLOWED\"}," //
206 + "\"flagNoRemove\": {" //
207 + "\"type\": \"boolean\"," //
208 + "\"description\": \"Flag for DELETION NOT ALLOWED\"}}, " //
209 + "\"required\": [ \"servingCellNrcgi\",\"neighborCellNrpci\",\"neighborCellNrcgi\",\"flagNoHo\",\"flagNoXn\",\"flagNoRemove\" ]}";
210 private PolicyType policy1 = new PolicyType(1, "ANR", "ANR Neighbour Cell Relation Policy", schema1);
212 private String policyInstance1 = "{\"servingCellNrcgi\": \"Cell1\",\r\n" + //
213 "\"neighborCellNrpci\": \"NCell1\",\r\n" + //
214 "\"neighborCellNrcgi\": \"Ncell1\",\r\n" + //
215 "\"flagNoHo\": true,\r\n" + //
216 "\"flagNoXn\": true,\r\n" + //
217 "\"flagNoRemove\": true}";
219 private String schema2 = "{\n" + " \"type\": \"object\",\n" + //
220 " \"title\": \"Car\",\n" + //
221 " \"properties\": {\n" + //
222 " \"make\": {\n" + //
223 " \"type\": \"string\",\n" + //
224 " \"enum\": [\n" + //
225 " \"Toyota\",\n" + //
233 " \"model\": {\n" + //
234 " \"type\": \"string\"\n" + //
236 " \"year\": {\n" + //
237 " \"type\": \"integer\",\n" + //
238 " \"enum\": [\n" + //
239 " 1995,1996,1997,1998,1999,\n" + //
240 " 2000,2001,2002,2003,2004,\n" + //
241 " 2005,2006,2007,2008,2009,\n" + //
242 " 2010,2011,2012,2013,2014\n" + //
244 " \"default\": 2008\n" + //
246 " \"safety\": {\n" + //
247 " \"type\": \"integer\",\n" + //
248 " \"format\": \"rating\",\n" + //
249 " \"maximum\": 5,\n" + //
250 " \"exclusiveMaximum\": false,\n" + //
251 " \"readonly\": false\n" + //
255 private PolicyType policy2 = new PolicyType(2, "type2", "Type2 description", schema2);
257 private String schema3 = "{\n" + //
258 " \"$id\": \"https://example.com/person.schema.json\",\n" + //
259 " \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n" + //
260 " \"title\": \"Person\",\n" + //
261 " \"type\": \"object\",\n" + //
262 " \"properties\": {\n" + //
263 " \"firstName\": {\n" + //
264 " \"type\": \"string\",\n" + //
265 " \"description\": \"The person's first name.\"\n" + //
267 " \"lastName\": {\n" + //
268 " \"type\": \"string\",\n" + //
269 " \"description\": \"The person's last name.\"\n" + //
272 " \"description\": \"Age in years which must be equal to or greater than zero.\",\n" + //
273 " \"type\": \"integer\",\n" + //
274 " \"minimum\": 0\n" + //
278 private PolicyType policy3 = new PolicyType(3, "type3", "Type3 description", schema3);
280 private String schema4 = "{" + //
281 " \"$id\": \"https://example.com/arrays.schema.json\"," + //
282 " \"$schema\": \"http://json-schema.org/draft-07/schema#\"," + //
283 " \"description\": \"A representation of a person, company, organization, or place\"," + //
284 " \"type\": \"object\"," + //
285 " \"properties\": {" + //
286 " \"fruits\": {" + //
287 " \"type\": \"array\"," + //
289 " \"type\": \"string\"" + //
292 " \"vegetables\": {" + //
293 " \"type\": \"array\"," + //
294 " \"items\": { \"$ref\": \"#/definitions/veggie\" }" + //
297 " \"definitions\": {" + //
298 " \"veggie\": {" + //
299 " \"type\": \"object\"," + //
300 " \"required\": [ \"veggieName\", \"veggieLike\" ]," + //
301 " \"properties\": {" + //
302 " \"veggieName\": {" + //
303 " \"type\": \"string\"," + //
304 " \"description\": \"The name of the vegetable.\"" + //
306 " \"veggieLike\": {" + //
307 " \"type\": \"boolean\"," + //
308 " \"description\": \"Do I like this vegetable?\"" + //
314 private PolicyType policy4 = new PolicyType(4, "type4", "Type4 description", schema4);
316 public class PolicyException extends Exception {
318 private static final long serialVersionUID = 1L;
320 public PolicyException(String message) {
322 System.out.println("**** Exception " + message);
326 private class PolicyTypeHolder {
327 PolicyTypeHolder(PolicyType pt) {
328 this.policyType = pt;
331 String getInstance(String instanceId) throws PolicyException {
332 String instance = instances.get(instanceId);
333 if (instance == null) {
334 throw new PolicyException("Instance not found: " + instanceId);
339 PolicyType getPolicyType() {
343 void putInstance(String id, String data) {
344 instances.put(id, data);
347 void deleteInstance(String id) {
348 instances.remove(id);
351 List<String> getInstances() {
352 return new ArrayList<>(instances.keySet());
355 private final PolicyType policyType;
356 private Map<String, String> instances = new HashMap<>();
360 types.put(1, new PolicyTypeHolder(policy1));
361 types.put(2, new PolicyTypeHolder(policy2));
362 types.put(3, new PolicyTypeHolder(policy3));
363 types.put(4, new PolicyTypeHolder(policy4));
365 putInstance(1, "ANR-1", policyInstance1);
366 } catch (JsonProcessingException | PolicyException e) {
371 String normalize(String str) {
372 return str.replace('\n', ' ');
375 void putInstance(Integer typeId, String instanceId, String instanceData)
376 throws JsonProcessingException, PolicyException {
377 PolicyTypeHolder type = getTypeHolder(typeId);
378 type.putInstance(instanceId, instanceData);
381 void deleteInstance(Integer typeId, String instanceId) throws JsonProcessingException, PolicyException {
382 PolicyTypeHolder type = getTypeHolder(typeId);
383 type.deleteInstance(instanceId);
386 String getInstance(Integer typeId, String instanceId) throws JsonProcessingException, PolicyException {
387 return getTypeHolder(typeId).getInstance(instanceId);
390 List<Integer> getTypes() {
391 return new ArrayList<>(types.keySet());
394 List<String> getInstances(Optional<Integer> typeId) throws PolicyException {
395 if (typeId.isPresent()) {
396 return getTypeHolder(typeId.get()).getInstances();
398 Set<String> res = new HashSet<String>();
399 for (Iterator<PolicyTypeHolder> i = types.values().iterator(); i.hasNext();) {
400 res.addAll(i.next().getInstances());
402 return new ArrayList<>(res);
406 private PolicyTypeHolder getTypeHolder(Integer typeId) throws PolicyException {
407 PolicyTypeHolder typeHolder = types.get(typeId);
408 if (typeHolder == null) {
409 throw new PolicyException("Type not found: " + typeId);
414 private PolicyType getPolicyType(Integer typeId) throws PolicyException {
415 PolicyTypeHolder typeHolder = getTypeHolder(typeId);
416 return typeHolder.getPolicyType();
419 private Map<Integer, PolicyTypeHolder> types = new HashMap<>();
423 private final Database database = new Database();