2  * ============LICENSE_START=======================================================
 
   3  *  Copyright (C) 2020 Nordix Foundation.
 
   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.ccsdk.features.a1.adapter;
 
  23 import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
 
  24 import static org.apache.http.HttpStatus.SC_SERVICE_UNAVAILABLE;
 
  26 import com.google.common.util.concurrent.Futures;
 
  27 import com.google.common.util.concurrent.ListenableFuture;
 
  28 import java.lang.reflect.Method;
 
  29 import java.util.Properties;
 
  30 import java.util.concurrent.ExecutorService;
 
  31 import java.util.concurrent.Executors;
 
  32 import org.onap.ccsdk.sli.core.sli.provider.MdsalHelper;
 
  33 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
 
  34 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 
  35 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 
  36 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.A1ADAPTERAPIService;
 
  37 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.DeleteA1PolicyInput;
 
  38 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.DeleteA1PolicyInputBuilder;
 
  39 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.DeleteA1PolicyOutput;
 
  40 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.DeleteA1PolicyOutputBuilder;
 
  41 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyInput;
 
  42 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyInputBuilder;
 
  43 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyOutput;
 
  44 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyOutputBuilder;
 
  45 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyStatusInput;
 
  46 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyStatusInputBuilder;
 
  47 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyStatusOutput;
 
  48 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyStatusOutputBuilder;
 
  49 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyTypeInput;
 
  50 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyTypeInputBuilder;
 
  51 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyTypeOutput;
 
  52 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.GetA1PolicyTypeOutputBuilder;
 
  53 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.PutA1PolicyInput;
 
  54 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.PutA1PolicyInputBuilder;
 
  55 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.PutA1PolicyOutput;
 
  56 import org.opendaylight.yang.gen.v1.org.onap.a1.adapter.rev200122.PutA1PolicyOutputBuilder;
 
  57 import org.opendaylight.yangtools.concepts.Builder;
 
  58 import org.opendaylight.yangtools.yang.common.RpcResult;
 
  59 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
  60 import org.slf4j.Logger;
 
  61 import org.slf4j.LoggerFactory;
 
  64  * This class implements the generated interface from the YANG model and implements the request model for the A1
 
  65  * interface. This class identifies the Near-RT RIC throughout the IP passed over the payload and calls the
 
  66  * corresponding Near-RT RIC over Rest API.
 
  68 @SuppressWarnings("squid:S1874") // "@Deprecated" code should not be used
 
  69 public class A1AdapterProvider implements AutoCloseable, A1ADAPTERAPIService {
 
  71     private static final String START_OPERATION_MESSAGE = "Start of {}";
 
  72     private static final String END_OPERATION_MESSAGE = "End of {}";
 
  74     private static final String A1_ADAPTER_API = "A1-ADAPTER-API";
 
  75     private static final String RESPONSE_BODY = "responseBody";
 
  76     private static final String RESPONSE_CODE = "response-code";
 
  77     private static final String SYNC = "sync";
 
  79     private static final Logger log = LoggerFactory.getLogger(A1AdapterProvider.class);
 
  81     private static final String APPLICATION_NAME = "a1Adapter-api";
 
  83     private final ExecutorService executor;
 
  84     protected NotificationPublishService notificationService;
 
  85     protected RpcProviderRegistry rpcRegistry;
 
  86     protected BindingAwareBroker.RpcRegistration<A1ADAPTERAPIService> rpcRegistration;
 
  87     private final A1AdapterClient a1AdapterClient;
 
  89     public A1AdapterProvider(final NotificationPublishService notificationPublishService,
 
  90         final RpcProviderRegistry rpcProviderRegistry, final A1AdapterClient a1AdapterClient) {
 
  92         log.info("Creating provider for {}", APPLICATION_NAME);
 
  93         executor = Executors.newFixedThreadPool(1);
 
  94         this.notificationService = notificationPublishService;
 
  95         this.rpcRegistry = rpcProviderRegistry;
 
  96         this.a1AdapterClient = a1AdapterClient;
 
 100     public void initialize() {
 
 101         log.info("Initializing provider for {}", APPLICATION_NAME);
 
 102         rpcRegistration = rpcRegistry.addRpcImplementation(A1ADAPTERAPIService.class, this);
 
 103         log.info("Initialization complete for {}", APPLICATION_NAME);
 
 107     public void close() throws Exception {
 
 108         log.info("Closing provider for {}", APPLICATION_NAME);
 
 110         rpcRegistration.close();
 
 111         log.info("Successfully closed provider for {}", APPLICATION_NAME);
 
 115     public ListenableFuture<RpcResult<DeleteA1PolicyOutput>> deleteA1Policy(DeleteA1PolicyInput deletePolicyInput) {
 
 116         final String svcOperation = "deleteA1Policy";
 
 117         log.info(START_OPERATION_MESSAGE, svcOperation);
 
 118         DeleteA1PolicyOutputBuilder deletePolicyResponse = new DeleteA1PolicyOutputBuilder();
 
 119         setUpAndExecuteOperation(svcOperation, new DeleteA1PolicyInputBuilder(deletePolicyInput), deletePolicyResponse);
 
 121         RpcResult<DeleteA1PolicyOutput> deletePolicyResult =
 
 122             RpcResultBuilder.<DeleteA1PolicyOutput>status(true).withResult(deletePolicyResponse.build()).build();
 
 123         log.info(END_OPERATION_MESSAGE, svcOperation);
 
 124         return Futures.immediateFuture(deletePolicyResult);
 
 128     public ListenableFuture<RpcResult<GetA1PolicyOutput>> getA1Policy(GetA1PolicyInput getPolicyInput) {
 
 129         final String svcOperation = "getA1Policy";
 
 130         log.info(START_OPERATION_MESSAGE, svcOperation);
 
 131         GetA1PolicyOutputBuilder getPolicyResponse = new GetA1PolicyOutputBuilder();
 
 132         setUpAndExecuteOperation(svcOperation, new GetA1PolicyInputBuilder(getPolicyInput), getPolicyResponse);
 
 134         RpcResult<GetA1PolicyOutput> getPolicyResult =
 
 135             RpcResultBuilder.<GetA1PolicyOutput>status(true).withResult(getPolicyResponse.build()).build();
 
 136         log.info(END_OPERATION_MESSAGE, svcOperation);
 
 137         return Futures.immediateFuture(getPolicyResult);
 
 141     public ListenableFuture<RpcResult<GetA1PolicyStatusOutput>> getA1PolicyStatus(
 
 142         GetA1PolicyStatusInput getPolicyStatusInput) {
 
 143         final String svcOperation = "getA1PolicyStatus";
 
 144         log.info(START_OPERATION_MESSAGE, svcOperation);
 
 145         GetA1PolicyStatusOutputBuilder getPolicyStatusResponse = new GetA1PolicyStatusOutputBuilder();
 
 146         setUpAndExecuteOperation(svcOperation, new GetA1PolicyStatusInputBuilder(getPolicyStatusInput),
 
 147             getPolicyStatusResponse);
 
 149         RpcResult<GetA1PolicyStatusOutput> getPolicyStatusResult =
 
 150             RpcResultBuilder.<GetA1PolicyStatusOutput>status(true).withResult(getPolicyStatusResponse.build()).build();
 
 151         log.info(END_OPERATION_MESSAGE, svcOperation);
 
 152         return Futures.immediateFuture(getPolicyStatusResult);
 
 156     public ListenableFuture<RpcResult<GetA1PolicyTypeOutput>> getA1PolicyType(GetA1PolicyTypeInput getPolicyTypeInput) {
 
 157         final String svcOperation = "getA1PolicyType";
 
 158         log.info(START_OPERATION_MESSAGE, svcOperation);
 
 159         GetA1PolicyTypeOutputBuilder getPolicyTypeResponse = new GetA1PolicyTypeOutputBuilder();
 
 160         setUpAndExecuteOperation(svcOperation, new GetA1PolicyTypeInputBuilder(getPolicyTypeInput),
 
 161             getPolicyTypeResponse);
 
 163         RpcResult<GetA1PolicyTypeOutput> getPolicyTypeResult =
 
 164             RpcResultBuilder.<GetA1PolicyTypeOutput>status(true).withResult(getPolicyTypeResponse.build()).build();
 
 165         log.info(END_OPERATION_MESSAGE, svcOperation);
 
 166         return Futures.immediateFuture(getPolicyTypeResult);
 
 170     public ListenableFuture<RpcResult<PutA1PolicyOutput>> putA1Policy(PutA1PolicyInput putPolicyInput) {
 
 171         final String svcOperation = "putA1Policy";
 
 172         log.info(START_OPERATION_MESSAGE, svcOperation);
 
 173         PutA1PolicyOutputBuilder putPolicyResponse = new PutA1PolicyOutputBuilder();
 
 174         setUpAndExecuteOperation(svcOperation, new PutA1PolicyInputBuilder(putPolicyInput), putPolicyResponse);
 
 176         RpcResult<PutA1PolicyOutput> putPolicyResult =
 
 177             RpcResultBuilder.<PutA1PolicyOutput>status(true).withResult(putPolicyResponse.build()).build();
 
 178         log.info(END_OPERATION_MESSAGE, svcOperation);
 
 179         return Futures.immediateFuture(putPolicyResult);
 
 182     private <T> boolean hasGraph(final String svcOperation, Builder<T> response) {
 
 184             return a1AdapterClient.hasGraph(A1_ADAPTER_API, svcOperation, null, SYNC);
 
 185         } catch (Exception e) {
 
 186             log.error("Caught exception looking for service logic, {}", e.getMessage());
 
 187             setHttpResponse(response, SC_INTERNAL_SERVER_ERROR);
 
 192     private <U, T> void setUpAndExecuteOperation(final String svcOperation, Builder<U> inputBuilder,
 
 193         Builder<T> responseBuilder) {
 
 194         log.info("Adding INPUT data for {} input: {}", svcOperation, inputBuilder);
 
 195         // add input to parms
 
 196         Properties parms = new Properties();
 
 197         MdsalHelper.toProperties(parms, inputBuilder.build());
 
 198         logSliParameters(parms);
 
 199         // Call SLI sync method
 
 200         if (hasGraph(svcOperation, responseBuilder)) {
 
 201             log.info("A1AdapterClient has a Directed Graph for '{}'", svcOperation);
 
 202             executeOperation(svcOperation, parms, responseBuilder);
 
 204             log.error("No service logic active for A1Adapter: '{}'", svcOperation);
 
 205             setHttpResponse(responseBuilder, Integer.valueOf(SC_SERVICE_UNAVAILABLE));
 
 209     private <T> void executeOperation(final String svcOperation, Properties parms, Builder<T> response) {
 
 211             Properties responseParms =
 
 212                 a1AdapterClient.execute(A1_ADAPTER_API, svcOperation, null, SYNC, response, parms);
 
 213             logResponse(responseParms);
 
 214             setBody(response, responseParms.getProperty(RESPONSE_BODY));
 
 215             setHttpResponse(response, Integer.valueOf(responseParms.getProperty(RESPONSE_CODE)));
 
 216         } catch (Exception e) {
 
 217             log.error("Caught exception executing service logic for {}, {}", svcOperation, e.getMessage());
 
 218             setHttpResponse(response, Integer.valueOf(SC_INTERNAL_SERVER_ERROR));
 
 222     private <T> void setBody(Builder<T> responseBuilder, String body) {
 
 224             Method method = responseBuilder.getClass().getMethod("setBody", String.class);
 
 225             method.invoke(responseBuilder, body);
 
 226         } catch (Exception reflectionException) {
 
 227             throw new MissingResponseMethodRuntimeException(reflectionException);
 
 231     private <T> void setHttpResponse(Builder<T> responseBuilder, Integer response) {
 
 233             Method method = responseBuilder.getClass().getMethod("setHttpStatus", Integer.class);
 
 234             method.invoke(responseBuilder, response);
 
 235         } catch (Exception reflectionException) {
 
 236             throw new MissingResponseMethodRuntimeException(reflectionException);
 
 240     private void logSliParameters(Properties parms) {
 
 241         log.info("Printing SLI parameters to be passed");
 
 242         // iterate properties file to get key-value pairs
 
 243         for (String key : parms.stringPropertyNames()) {
 
 244             String value = parms.getProperty(key);
 
 245             log.info("The SLI parameter in {} is: {}", key, value);
 
 249     private void logResponse(Properties responseParms) {
 
 250         log.info("responseBody::{}", responseParms.getProperty(RESPONSE_BODY));
 
 251         log.info("responseCode::{}", responseParms.getProperty(RESPONSE_CODE));
 
 252         log.info("responseMessage::{}", responseParms.getProperty("response-message"));
 
 255     public class MissingResponseMethodRuntimeException extends RuntimeException {
 
 256         private static final long serialVersionUID = -6803869291161765099L;
 
 258         MissingResponseMethodRuntimeException(Exception e) {