Modify Actors to use properties when provided 00/110900/5
authorJim Hahn <jrh3@att.com>
Tue, 4 Aug 2020 20:27:18 +0000 (16:27 -0400)
committerJim Hahn <jrh3@att.com>
Thu, 6 Aug 2020 23:19:46 +0000 (19:19 -0400)
Modified the Actors to use properties when the application provides them
instead of going to the event context for the data.  This sometimes entailed
moving code out of the Operation subclass constructor that used or validated
the context data.
Combined some property names and renamed others.
Changed VF Count from AtomicInteger to Integer.

Issue-ID: POLICY-2746
Change-Id: Ib8730538309bb77d2f4f6161e9a20a49362d8972
Signed-off-by: Jim Hahn <jrh3@att.com>
26 files changed:
models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiCustomQueryOperation.java
models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiCustomQueryOperationTest.java
models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/ModifyConfigOperation.java
models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/ModifyConfigOperationTest.java
models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/GrpcOperation.java
models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/GrpcOperationTest.java
models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperation.java
models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperation.java
models-interactions/model-actors/actor.sdnc/src/main/java/org/onap/policy/controlloop/actor/sdnc/SdncOperation.java
models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/BandwidthOnDemandOperationTest.java
models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/RerouteOperationTest.java
models-interactions/model-actors/actor.sdnc/src/test/java/org/onap/policy/controlloop/actor/sdnc/SdncOperationTest.java
models-interactions/model-actors/actor.sdnc/src/test/resources/bod.json
models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrOperation.java
models-interactions/model-actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrOperationTest.java
models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoOperation.java
models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleCreate.java
models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/VfModuleDelete.java
models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperationTest.java
models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java
models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleDeleteTest.java
models-interactions/model-actors/actor.vfc/src/main/java/org/onap/policy/controlloop/actor/vfc/VfcOperation.java
models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/RestartTest.java
models-interactions/model-actors/actor.vfc/src/test/java/org/onap/policy/controlloop/actor/vfc/VfcOperationTest.java
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/OperationProperties.java
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationPartial.java

index 151f7a2..c8e0870 100644 (file)
@@ -29,7 +29,6 @@ import javax.ws.rs.client.Invocation.Builder;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-import lombok.Getter;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.aai.AaiConstants;
 import org.onap.policy.aai.AaiCqResponse;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.aai.AaiConstants;
 import org.onap.policy.aai.AaiCqResponse;
@@ -64,9 +63,6 @@ public class AaiCustomQueryOperation extends HttpOperation<String> {
     // TODO make this configurable
     private static final String PREFIX = "/aai/v16";
 
     // TODO make this configurable
     private static final String PREFIX = "/aai/v16";
 
-    @Getter
-    private final String vserver;
-
     /**
      * Constructs the object.
      *
     /**
      * Constructs the object.
      *
@@ -75,11 +71,20 @@ public class AaiCustomQueryOperation extends HttpOperation<String> {
      */
     public AaiCustomQueryOperation(ControlLoopOperationParams params, HttpConfig config) {
         super(params, config, String.class, PROPERTY_NAMES);
      */
     public AaiCustomQueryOperation(ControlLoopOperationParams params, HttpConfig config) {
         super(params, config, String.class, PROPERTY_NAMES);
+    }
 
 
-        this.vserver = params.getContext().getEnrichment().get(VSERVER_VSERVER_NAME);
-        if (StringUtils.isBlank(this.vserver)) {
+    /**
+     * Gets the vserver name from the enrichment data.
+     *
+     * @return the vserver name
+     */
+    protected String getVserver() {
+        String vserver = this.params.getContext().getEnrichment().get(VSERVER_VSERVER_NAME);
+        if (StringUtils.isBlank(vserver)) {
             throw new IllegalArgumentException("missing " + VSERVER_VSERVER_NAME + " in enrichment data");
         }
             throw new IllegalArgumentException("missing " + VSERVER_VSERVER_NAME + " in enrichment data");
         }
+
+        return vserver;
     }
 
     /**
     }
 
     /**
@@ -91,6 +96,7 @@ public class AaiCustomQueryOperation extends HttpOperation<String> {
             return null;
         }
 
             return null;
         }
 
+        String vserver = getVserver();
         ControlLoopOperationParams tenantParams =
                         params.toBuilder().actor(AaiConstants.ACTOR_NAME).operation(AaiGetTenantOperation.NAME)
                                         .targetEntity(vserver).payload(null).retry(null).timeoutSec(null).build();
         ControlLoopOperationParams tenantParams =
                         params.toBuilder().actor(AaiConstants.ACTOR_NAME).operation(AaiGetTenantOperation.NAME)
                                         .targetEntity(vserver).payload(null).retry(null).timeoutSec(null).build();
@@ -146,16 +152,33 @@ public class AaiCustomQueryOperation extends HttpOperation<String> {
      * Constructs the custom query using the previously retrieved tenant data.
      */
     private Map<String, String> makeRequest() {
      * Constructs the custom query using the previously retrieved tenant data.
      */
     private Map<String, String> makeRequest() {
+        return Map.of("start", getVserverLink(), "query", "query/closed-loop");
+    }
+
+    /**
+     * Gets the vserver link, first checking the properties, and then the tenant data.
+     *
+     * @return the vserver link
+     */
+    protected String getVserverLink() {
+        String resourceLink = getProperty(OperationProperties.AAI_VSERVER_LINK);
+        if (resourceLink != null) {
+            return resourceLink;
+        }
+
+        String vserver = getVserver();
         StandardCoderObject tenant = params.getContext().getProperty(AaiGetTenantOperation.getKey(vserver));
         StandardCoderObject tenant = params.getContext().getProperty(AaiGetTenantOperation.getKey(vserver));
+        if (tenant == null) {
+            throw new IllegalStateException("cannot perform custom query - cannot determine resource-link");
+        }
 
 
-        String resourceLink = tenant.getString(RESULT_DATA, 0, RESOURCE_LINK);
+        resourceLink = tenant.getString(RESULT_DATA, 0, RESOURCE_LINK);
         if (resourceLink == null) {
             throw new IllegalArgumentException("cannot perform custom query - no resource-link");
         }
 
         resourceLink = resourceLink.replace(PREFIX, "");
         if (resourceLink == null) {
             throw new IllegalArgumentException("cannot perform custom query - no resource-link");
         }
 
         resourceLink = resourceLink.replace(PREFIX, "");
-
-        return Map.of("start", resourceLink, "query", "query/closed-loop");
+        return resourceLink;
     }
 
     @Override
     }
 
     @Override
index 476e643..f122537 100644 (file)
@@ -23,6 +23,7 @@ package org.onap.policy.controlloop.actor.aai;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -113,11 +114,12 @@ public class AaiCustomQueryOperationTest extends BasicAaiOperation {
         HttpParams opParams = HttpParams.builder().clientName(MY_CLIENT).path("v16/query").build();
         config = new HttpConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory());
 
         HttpParams opParams = HttpParams.builder().clientName(MY_CLIENT).path("v16/query").build();
         config = new HttpConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory());
 
-        preloadTenantData();
-
-        params = params.toBuilder().targetEntity(SIM_VSERVER).retry(0).timeoutSec(5).executor(blockingExecutor).build();
+        params = params.toBuilder().targetEntity(SIM_VSERVER).retry(0).timeoutSec(5).executor(blockingExecutor)
+                        .preprocessed(true).build();
         oper = new AaiCustomQueryOperation(params, config);
 
         oper = new AaiCustomQueryOperation(params, config);
 
+        oper.setProperty(OperationProperties.AAI_VSERVER_LINK, MY_LINK);
+
         outcome = oper.start().get();
         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
 
         outcome = oper.start().get();
         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
 
@@ -129,15 +131,19 @@ public class AaiCustomQueryOperationTest extends BasicAaiOperation {
     public void testConstructor() {
         assertEquals(AaiConstants.ACTOR_NAME, oper.getActorName());
         assertEquals(AaiCustomQueryOperation.NAME, oper.getName());
     public void testConstructor() {
         assertEquals(AaiConstants.ACTOR_NAME, oper.getActorName());
         assertEquals(AaiCustomQueryOperation.NAME, oper.getName());
-        assertEquals(MY_VSERVER, oper.getVserver());
 
         // verify that it works with an empty target entity
         params = params.toBuilder().targetEntity("").build();
         assertThatCode(() -> new AaiCustomQueryOperation(params, config)).doesNotThrowAnyException();
 
         // verify that it works with an empty target entity
         params = params.toBuilder().targetEntity("").build();
         assertThatCode(() -> new AaiCustomQueryOperation(params, config)).doesNotThrowAnyException();
+    }
+
+    @Test
+    public void testGetVserver() {
+        assertEquals(MY_VSERVER, oper.getVserver());
 
         // try without enrichment data
         params.getContext().getEnrichment().remove(AaiCustomQueryOperation.VSERVER_VSERVER_NAME);
 
         // try without enrichment data
         params.getContext().getEnrichment().remove(AaiCustomQueryOperation.VSERVER_VSERVER_NAME);
-        assertThatIllegalArgumentException().isThrownBy(() -> new AaiCustomQueryOperation(params, config))
+        assertThatIllegalArgumentException().isThrownBy(() -> oper.getVserver())
                         .withMessage("missing " + AaiCustomQueryOperation.VSERVER_VSERVER_NAME + " in enrichment data");
     }
 
                         .withMessage("missing " + AaiCustomQueryOperation.VSERVER_VSERVER_NAME + " in enrichment data");
     }
 
@@ -215,7 +221,7 @@ public class AaiCustomQueryOperationTest extends BasicAaiOperation {
 
     @Test
     @SuppressWarnings("unchecked")
 
     @Test
     @SuppressWarnings("unchecked")
-    public void testMakeRequest() throws Exception {
+    public void testMakeRequest_testGetVserverLink() throws Exception {
         // preload
         preloadTenantData();
 
         // preload
         preloadTenantData();
 
@@ -237,17 +243,24 @@ public class AaiCustomQueryOperationTest extends BasicAaiOperation {
     }
 
     @Test
     }
 
     @Test
-    @SuppressWarnings("unchecked")
-    public void testMakeRequestNoResourceLink() throws Exception {
-        // pre-load EMPTY tenant data
-        preloadTenantData(new StandardCoderObject());
+    public void testGetVserverLinkViaProperty() throws Exception {
+        oper.setProperty(OperationProperties.AAI_VSERVER_LINK, MY_LINK);
+        assertEquals(MY_LINK, oper.getVserverLink());
+    }
 
 
-        when(rawResponse.readEntity(String.class)).thenReturn(makeCqReply());
-        when(webAsync.put(any(), any(InvocationCallback.class))).thenAnswer(provideResponse(rawResponse, 1));
+    @Test
+    public void testGetVserverLinkNoTenantData() throws Exception {
+        assertThatIllegalStateException().isThrownBy(() -> oper.getVserverLink())
+                        .withMessage("cannot perform custom query - cannot determine resource-link");
+    }
 
 
-        CompletableFuture<OperationOutcome> future2 = oper.start();
+    @Test
+    public void testGetVserverLinkNoResourceLink() throws Exception {
+        // pre-load EMPTY tenant data
+        preloadTenantData(new StandardCoderObject());
 
 
-        assertEquals(PolicyResult.FAILURE_EXCEPTION, getResult(future2));
+        assertThatIllegalArgumentException().isThrownBy(() -> oper.getVserverLink())
+                        .withMessage("cannot perform custom query - no resource-link");
     }
 
     private String makeTenantReply() throws Exception {
     }
 
     private String makeTenantReply() throws Exception {
index 680bd9c..13ddaf4 100644 (file)
@@ -69,7 +69,19 @@ public class ModifyConfigOperation extends AppcOperation {
 
     @Override
     protected Request makeRequest(int attempt) {
 
     @Override
     protected Request makeRequest(int attempt) {
+        return makeRequest(attempt, getVnfId());
+    }
+
+    protected String getVnfId() {
+        GenericVnf vnf = this.getProperty(OperationProperties.AAI_RESOURCE_VNF);
+        if (vnf != null) {
+            return vnf.getVnfId();
+        }
+
         AaiCqResponse cq = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY);
         AaiCqResponse cq = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY);
+        if (cq == null) {
+            throw new IllegalStateException("target vnf-id could not be determined");
+        }
 
         GenericVnf genvnf = cq.getGenericVnfByModelInvariantId(params.getTarget().getResourceID());
         if (genvnf == null) {
 
         GenericVnf genvnf = cq.getGenericVnfByModelInvariantId(params.getTarget().getResourceID());
         if (genvnf == null) {
@@ -77,6 +89,6 @@ public class ModifyConfigOperation extends AppcOperation {
             throw new IllegalArgumentException("target vnf-id could not be found");
         }
 
             throw new IllegalArgumentException("target vnf-id could not be found");
         }
 
-        return makeRequest(attempt, genvnf.getVnfId());
+        return genvnf.getVnfId();
     }
 }
     }
 }
index 9c602f5..3b63514 100644 (file)
@@ -22,6 +22,7 @@ package org.onap.policy.controlloop.actor.appc;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -42,6 +43,7 @@ import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.mockito.Mock;
 import org.onap.aai.domain.yang.GenericVnf;
 import org.onap.policy.aai.AaiCqResponse;
 import org.onap.policy.appc.Request;
 import org.onap.aai.domain.yang.GenericVnf;
 import org.onap.policy.aai.AaiCqResponse;
 import org.onap.policy.appc.Request;
@@ -56,8 +58,14 @@ import org.onap.policy.controlloop.policy.PolicyResult;
 
 public class ModifyConfigOperationTest extends BasicAppcOperation {
 
 
 public class ModifyConfigOperationTest extends BasicAppcOperation {
 
+    @Mock
+    private GenericVnf genvnf;
+    @Mock
+    private AaiCqResponse cq;
+
     private ModifyConfigOperation oper;
 
     private ModifyConfigOperation oper;
 
+
     public ModifyConfigOperationTest() {
         super(DEFAULT_ACTOR, ModifyConfigOperation.NAME);
     }
     public ModifyConfigOperationTest() {
         super(DEFAULT_ACTOR, ModifyConfigOperation.NAME);
     }
@@ -77,6 +85,9 @@ public class ModifyConfigOperationTest extends BasicAppcOperation {
     @Override
     public void setUp() throws Exception {
         super.setUp();
     @Override
     public void setUp() throws Exception {
         super.setUp();
+        when(genvnf.getVnfId()).thenReturn(MY_VNF);
+        when(cq.getGenericVnfByModelInvariantId(any())).thenReturn(genvnf);
+
         oper = new ModifyConfigOperation(params, config);
     }
 
         oper = new ModifyConfigOperation(params, config);
     }
 
@@ -95,14 +106,9 @@ public class ModifyConfigOperationTest extends BasicAppcOperation {
                         BidirectionalTopicParams.builder().sinkTopic(MY_SINK).sourceTopic(MY_SINK).build();
         config = new BidirectionalTopicConfig(blockingExecutor, opParams, topicMgr, AppcOperation.SELECTOR_KEYS);
 
                         BidirectionalTopicParams.builder().sinkTopic(MY_SINK).sourceTopic(MY_SINK).build();
         config = new BidirectionalTopicConfig(blockingExecutor, opParams, topicMgr, AppcOperation.SELECTOR_KEYS);
 
-        AaiCqResponse cq = mock(AaiCqResponse.class);
-        GenericVnf genvnf = mock(GenericVnf.class);
-        when(genvnf.getVnfId()).thenReturn(MY_VNF);
-        when(cq.getGenericVnfByModelInvariantId(any())).thenReturn(genvnf);
-
         params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq);
 
         params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq);
 
-        params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).build();
+        params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).preprocessed(true).build();
 
         oper = new ModifyConfigOperation(params, config) {
             @Override
 
         oper = new ModifyConfigOperation(params, config) {
             @Override
@@ -111,6 +117,8 @@ public class ModifyConfigOperationTest extends BasicAppcOperation {
             }
         };
 
             }
         };
 
+        oper.setProperty(OperationProperties.AAI_RESOURCE_VNF, genvnf);
+
         outcome = oper.start().get();
         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
         assertTrue(outcome.getResponse() instanceof Response);
         outcome = oper.start().get();
         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
         assertTrue(outcome.getResponse() instanceof Response);
@@ -168,23 +176,41 @@ public class ModifyConfigOperationTest extends BasicAppcOperation {
 
     @Test
     public void testMakeRequest() throws CoderException {
 
     @Test
     public void testMakeRequest() throws CoderException {
-        AaiCqResponse cq = new AaiCqResponse("{}");
+        oper.setProperty(OperationProperties.AAI_RESOURCE_VNF, genvnf);
+
+        oper.generateSubRequestId(2);
+        Request request = oper.makeRequest(2);
+        assertNotNull(request);
+        assertEquals(MY_VNF, request.getPayload().get(ModifyConfigOperation.VNF_ID_KEY));
+
+        verifyRequest("modifyConfig.json", request, IGNORE_FIELDS);
+    }
+
+    @Test
+    public void testGetVnfIdViaProperty() throws CoderException {
+        oper.setProperty(OperationProperties.AAI_RESOURCE_VNF, genvnf);
+        assertEquals(MY_VNF, oper.getVnfId());
+    }
+
+    @Test
+    public void testGetVnfId() throws CoderException {
+        // no CQ data
+        assertThatIllegalStateException().isThrownBy(() -> oper.getVnfId())
+                        .withMessage("target vnf-id could not be determined");
+
+        cq = new AaiCqResponse("{}");
 
         // missing vnf-id
         params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq);
 
         // missing vnf-id
         params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq);
-        assertThatIllegalArgumentException().isThrownBy(() -> oper.makeRequest(1));
+        assertThatIllegalArgumentException().isThrownBy(() -> oper.getVnfId())
+                        .withMessage("target vnf-id could not be found");
 
         // populate the CQ data with a vnf-id
 
         // populate the CQ data with a vnf-id
-        GenericVnf genvnf = new GenericVnf();
+        genvnf = new GenericVnf();
         genvnf.setVnfId(MY_VNF);
         genvnf.setModelInvariantId(RESOURCE_ID);
         cq.setInventoryResponseItems(Arrays.asList(genvnf));
 
         genvnf.setVnfId(MY_VNF);
         genvnf.setModelInvariantId(RESOURCE_ID);
         cq.setInventoryResponseItems(Arrays.asList(genvnf));
 
-        oper.generateSubRequestId(2);
-        Request request = oper.makeRequest(2);
-        assertNotNull(request);
-        assertEquals(MY_VNF, request.getPayload().get(ModifyConfigOperation.VNF_ID_KEY));
-
-        verifyRequest("modifyConfig.json", request, IGNORE_FIELDS);
+        assertEquals(MY_VNF, oper.getVnfId());
     }
 }
     }
 }
index ec8f2ac..d384244 100644 (file)
@@ -44,7 +44,6 @@ import org.onap.policy.aai.AaiConstants;
 import org.onap.policy.aai.AaiCqResponse;
 import org.onap.policy.cds.client.CdsProcessorGrpcClient;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.aai.AaiCqResponse;
 import org.onap.policy.cds.client.CdsProcessorGrpcClient;
 import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.common.utils.coder.StandardCoderObject;
 import org.onap.policy.controlloop.actor.aai.AaiCustomQueryOperation;
 import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation;
 import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants;
 import org.onap.policy.controlloop.actor.aai.AaiCustomQueryOperation;
 import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation;
 import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants;
@@ -91,13 +90,15 @@ public class GrpcOperation extends OperationPartial {
     // @formatter:off
     private static final List<String> PNF_PROPERTY_NAMES = List.of(
                             OperationProperties.AAI_PNF,
     // @formatter:off
     private static final List<String> PNF_PROPERTY_NAMES = List.of(
                             OperationProperties.AAI_PNF,
-                            OperationProperties.EVENT_ADDITIONAL_PARAMS);
+                            OperationProperties.EVENT_ADDITIONAL_PARAMS,
+                            OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES);
 
 
     private static final List<String> VNF_PROPERTY_NAMES = List.of(
 
 
     private static final List<String> VNF_PROPERTY_NAMES = List.of(
-                            OperationProperties.AAI_MODEL_INVARIANT_GENERIC_VNF,
-                            OperationProperties.AAI_RESOURCE_SERVICE_INSTANCE,
-                            OperationProperties.EVENT_ADDITIONAL_PARAMS);
+                            OperationProperties.AAI_RESOURCE_VNF,
+                            OperationProperties.AAI_SERVICE,
+                            OperationProperties.EVENT_ADDITIONAL_PARAMS,
+                            OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES);
     // @formatter:on
 
     /**
     // @formatter:on
 
     /**
@@ -177,11 +178,15 @@ public class GrpcOperation extends OperationPartial {
      * @return a map of the PNF data
      */
     private Map<String, String> convertPnfToAaiProperties() {
      * @return a map of the PNF data
      */
     private Map<String, String> convertPnfToAaiProperties() {
+        Map<String, String> result = this.getProperty(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES);
+        if (result != null) {
+            return result;
+        }
+
         // convert PNF data to a Map
         // convert PNF data to a Map
-        StandardCoderObject pnf = params.getContext().getProperty(AaiGetPnfOperation.getKey(params.getTargetEntity()));
-        Map<String, Object> source = Util.translateToMap(getFullName(), pnf);
+        Map<String, Object> source = Util.translateToMap(getFullName(), getPnfData());
 
 
-        Map<String, String> result = new LinkedHashMap<>();
+        result = new LinkedHashMap<>();
 
         for (Entry<String, Object> ent : source.entrySet()) {
             result.put(AAI_PNF_PREFIX + ent.getKey(), ent.getValue().toString());
 
         for (Entry<String, Object> ent : source.entrySet()) {
             result.put(AAI_PNF_PREFIX + ent.getKey(), ent.getValue().toString());
@@ -190,6 +195,26 @@ public class GrpcOperation extends OperationPartial {
         return result;
     }
 
         return result;
     }
 
+    /**
+     * Gets the PNF from the operation properties, if it exists, or from the context
+     * properties otherwise.
+     *
+     * @return the PNF item
+     */
+    protected Object getPnfData() {
+        Object pnf = getProperty(OperationProperties.AAI_PNF);
+        if (pnf != null) {
+            return pnf;
+        }
+
+        pnf = params.getContext().getProperty(AaiGetPnfOperation.getKey(params.getTargetEntity()));
+        if (pnf == null) {
+            throw new IllegalArgumentException("missing PNF data");
+        }
+
+        return pnf;
+    }
+
     /**
      * Converts the A&AI Custom Query data to a map suitable for passing via the
      * "aaiProperties" field in the CDS request.
     /**
      * Converts the A&AI Custom Query data to a map suitable for passing via the
      * "aaiProperties" field in the CDS request.
@@ -197,24 +222,49 @@ public class GrpcOperation extends OperationPartial {
      * @return a map of the custom query data
      */
     private Map<String, String> convertCqToAaiProperties() {
      * @return a map of the custom query data
      */
     private Map<String, String> convertCqToAaiProperties() {
-        AaiCqResponse aaicq = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY);
+        Map<String, String> result = this.getProperty(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES);
+        if (result != null) {
+            return result;
+        }
 
 
-        Map<String, String> result = new LinkedHashMap<>();
+        result = new LinkedHashMap<>();
+
+        result.put(AAI_SERVICE_INSTANCE_ID_KEY, getServiceInstanceId());
+        result.put(AAI_VNF_ID_KEY, getVnfId());
+
+        return result;
+    }
 
 
-        ServiceInstance serviceInstance = aaicq.getServiceInstance();
+    protected String getServiceInstanceId() {
+        ServiceInstance serviceInstance = getProperty(OperationProperties.AAI_SERVICE);
+        if (serviceInstance != null) {
+            return serviceInstance.getServiceInstanceId();
+        }
+
+        AaiCqResponse aaicq = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY);
+
+        serviceInstance = aaicq.getServiceInstance();
         if (serviceInstance == null) {
             throw new IllegalArgumentException("Target service instance could not be found");
         }
 
         if (serviceInstance == null) {
             throw new IllegalArgumentException("Target service instance could not be found");
         }
 
-        GenericVnf genericVnf = aaicq.getGenericVnfByModelInvariantId(params.getTarget().getResourceID());
+        return serviceInstance.getServiceInstanceId();
+    }
+
+    protected String getVnfId() {
+        GenericVnf genericVnf = getProperty(OperationProperties.AAI_RESOURCE_VNF);
+        if (genericVnf != null) {
+            return genericVnf.getVnfId();
+        }
+
+        AaiCqResponse aaicq = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY);
+
+        genericVnf = aaicq.getGenericVnfByModelInvariantId(params.getTarget().getResourceID());
         if (genericVnf == null) {
             throw new IllegalArgumentException("Target generic vnf could not be found");
         }
 
         if (genericVnf == null) {
             throw new IllegalArgumentException("Target generic vnf could not be found");
         }
 
-        result.put(AAI_SERVICE_INSTANCE_ID_KEY, serviceInstance.getServiceInstanceId());
-        result.put(AAI_VNF_ID_KEY, genericVnf.getVnfId());
-
-        return result;
+        return genericVnf.getVnfId();
     }
 
     @Override
     }
 
     @Override
@@ -232,7 +282,7 @@ public class GrpcOperation extends OperationPartial {
          * construct the request first so that we don't have to clean up the "client" if
          * an exception is thrown
          */
          * construct the request first so that we don't have to clean up the "client" if
          * an exception is thrown
          */
-        ExecutionServiceInput request = constructRequest(params);
+        ExecutionServiceInput request = constructRequest();
 
         CompletableFuture<OperationOutcome> future = new CompletableFuture<>();
 
 
         CompletableFuture<OperationOutcome> future = new CompletableFuture<>();
 
@@ -255,10 +305,9 @@ public class GrpcOperation extends OperationPartial {
      * enriched parameters. TO-DO: Avoid leaking Exceptions to the Kie Session thread. TBD
      * item for Frankfurt release.
      *
      * enriched parameters. TO-DO: Avoid leaking Exceptions to the Kie Session thread. TBD
      * item for Frankfurt release.
      *
-     * @param params the control loop parameters specifying the onset, payload, etc.
      * @return an ExecutionServiceInput instance.
      */
      * @return an ExecutionServiceInput instance.
      */
-    public ExecutionServiceInput constructRequest(ControlLoopOperationParams params) {
+    public ExecutionServiceInput constructRequest() {
 
         // For the current operational TOSCA policy model (yaml) CBA name and version are
         // embedded in the payload
 
         // For the current operational TOSCA policy model (yaml) CBA name and version are
         // embedded in the payload
@@ -295,8 +344,9 @@ public class GrpcOperation extends OperationPartial {
         request.setAaiProperties(aaiConverter.get());
 
         // Inject any additional event parameters that may be present in the onset event
         request.setAaiProperties(aaiConverter.get());
 
         // Inject any additional event parameters that may be present in the onset event
-        if (params.getContext().getEvent().getAdditionalEventParams() != null) {
-            request.setAdditionalEventParams(params.getContext().getEvent().getAdditionalEventParams());
+        Map<String, String> additionalParams = getAdditionalEventParams();
+        if (additionalParams != null) {
+            request.setAdditionalEventParams(additionalParams);
         }
 
         Builder struct = Struct.newBuilder();
         }
 
         Builder struct = Struct.newBuilder();
@@ -324,6 +374,14 @@ public class GrpcOperation extends OperationPartial {
                         .setPayload(struct.build()).build();
     }
 
                         .setPayload(struct.build()).build();
     }
 
+    protected Map<String, String> getAdditionalEventParams() {
+        if (containsProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS)) {
+            return getProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS);
+        }
+
+        return params.getContext().getEvent().getAdditionalEventParams();
+    }
+
     private Map<String, String> convertPayloadMap(Map<String, Object> payload) {
         Map<String, String> convertedPayload = new HashMap<>();
         for (Entry<String, Object> entry : payload.entrySet()) {
     private Map<String, String> convertPayloadMap(Map<String, Object> payload) {
         Map<String, String> convertedPayload = new HashMap<>();
         for (Entry<String, Object> entry : payload.entrySet()) {
index 06f239b..2e9935f 100644 (file)
@@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
@@ -31,6 +32,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -49,6 +51,7 @@ import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.onap.aai.domain.yang.GenericVnf;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.Pnf;
 import org.onap.aai.domain.yang.ServiceInstance;
 import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput;
 import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput;
 import org.onap.aai.domain.yang.ServiceInstance;
 import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput;
 import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput;
@@ -187,6 +190,37 @@ public class GrpcOperationTest {
         assertTrue(outcome.getResponse() instanceof ExecutionServiceOutput);
     }
 
         assertTrue(outcome.getResponse() instanceof ExecutionServiceOutput);
     }
 
+    /**
+     * Tests "success" case with simulator using properties.
+     */
+    @Test
+    public void testSuccessViaProperties() throws Exception {
+        ControlLoopEventContext context = new ControlLoopEventContext(onset);
+        loadCqData(context);
+
+        Map<String, Object> payload = Map.of("artifact_name", "my_artifact", "artifact_version", "1.0");
+
+        params = ControlLoopOperationParams.builder()
+                        .actor(CdsActorConstants.CDS_ACTOR).operation("subscribe").context(context)
+                        .actorService(new ActorService()).targetEntity(TARGET_ENTITY).target(target).retry(0)
+                        .timeoutSec(5).executor(blockingExecutor).payload(payload).preprocessed(true).build();
+
+        cdsProps.setHost("localhost");
+        cdsProps.setPort(sim.getPort());
+        cdsProps.setTimeout(3);
+
+        GrpcConfig config = new GrpcConfig(blockingExecutor, cdsProps);
+
+        operation = new GrpcOperation(params, config);
+
+        // set the properties
+        operation.setProperty(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES, Collections.emptyMap());
+
+        OperationOutcome outcome = operation.start().get();
+        assertEquals(PolicyResult.SUCCESS, outcome.getResult());
+        assertTrue(outcome.getResponse() instanceof ExecutionServiceOutput);
+    }
+
     @Test
     public void testGetPropertyNames() {
 
     @Test
     public void testGetPropertyNames() {
 
@@ -198,9 +232,10 @@ public class GrpcOperationTest {
         // @formatter:off
         assertThat(operation.getPropertyNames()).isEqualTo(
                         List.of(
         // @formatter:off
         assertThat(operation.getPropertyNames()).isEqualTo(
                         List.of(
-                            OperationProperties.AAI_MODEL_INVARIANT_GENERIC_VNF,
-                            OperationProperties.AAI_RESOURCE_SERVICE_INSTANCE,
-                            OperationProperties.EVENT_ADDITIONAL_PARAMS));
+                            OperationProperties.AAI_RESOURCE_VNF,
+                            OperationProperties.AAI_SERVICE,
+                            OperationProperties.EVENT_ADDITIONAL_PARAMS,
+                            OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES));
         // @formatter:on
 
         /*
         // @formatter:on
 
         /*
@@ -213,10 +248,76 @@ public class GrpcOperationTest {
         assertThat(operation.getPropertyNames()).isEqualTo(
                         List.of(
                             OperationProperties.AAI_PNF,
         assertThat(operation.getPropertyNames()).isEqualTo(
                         List.of(
                             OperationProperties.AAI_PNF,
-                            OperationProperties.EVENT_ADDITIONAL_PARAMS));
+                            OperationProperties.EVENT_ADDITIONAL_PARAMS,
+                            OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES));
         // @formatter:on
     }
 
         // @formatter:on
     }
 
+    @Test
+    public void testGetPnf() {
+        ControlLoopEventContext context = new ControlLoopEventContext(onset);
+        params = params.toBuilder().context(context).build();
+        operation = new GrpcOperation(params, config);
+
+        // in neither property nor context
+        assertThatIllegalArgumentException().isThrownBy(() -> operation.getPnfData())
+                        .withMessage("missing PNF data");
+
+        // only in context
+        Pnf pnf = new Pnf();
+        params.getContext().setProperty(AaiGetPnfOperation.getKey(params.getTargetEntity()), pnf);
+        assertSame(pnf, operation.getPnfData());
+
+        // both - should choose the property
+        Pnf pnf2 = new Pnf();
+        operation.setProperty(OperationProperties.AAI_PNF, pnf2);
+        assertSame(pnf2, operation.getPnfData());
+    }
+
+    @Test
+    public void testGetServiceInstanceId() {
+        ControlLoopEventContext context = new ControlLoopEventContext(onset);
+        params = params.toBuilder().context(context).build();
+        operation = new GrpcOperation(params, config);
+
+        // in neither property nor custom query
+        context.setProperty(AaiCqResponse.CONTEXT_KEY, mock(AaiCqResponse.class));
+        assertThatIllegalArgumentException().isThrownBy(() -> operation.getServiceInstanceId())
+                        .withMessage("Target service instance could not be found");
+
+        // only in custom query
+        loadCqData(params.getContext());
+        assertEquals(MY_SVC_ID, operation.getServiceInstanceId());
+
+        // both - should choose the property
+        ServiceInstance serviceInstance = new ServiceInstance();
+        serviceInstance.setServiceInstanceId("another-service-id");
+        operation.setProperty(OperationProperties.AAI_SERVICE, serviceInstance);
+        assertEquals("another-service-id", operation.getServiceInstanceId());
+    }
+
+    @Test
+    public void testGetVnfId() {
+        ControlLoopEventContext context = new ControlLoopEventContext(onset);
+        params = params.toBuilder().context(context).build();
+        operation = new GrpcOperation(params, config);
+
+        // in neither property nor custom query
+        context.setProperty(AaiCqResponse.CONTEXT_KEY, mock(AaiCqResponse.class));
+        assertThatIllegalArgumentException().isThrownBy(() -> operation.getVnfId())
+                        .withMessage("Target generic vnf could not be found");
+
+        // only in custom query
+        loadCqData(params.getContext());
+        assertEquals(MY_VNF, operation.getVnfId());
+
+        // both - should choose the property
+        GenericVnf vnf = new GenericVnf();
+        vnf.setVnfId("another-vnf-id");
+        operation.setProperty(OperationProperties.AAI_RESOURCE_VNF, vnf);
+        assertEquals("another-vnf-id", operation.getVnfId());
+    }
+
     @Test
     public void testStartPreprocessorAsync() throws InterruptedException, ExecutionException, TimeoutException {
         AtomicBoolean guardStarted = new AtomicBoolean();
     @Test
     public void testStartPreprocessorAsync() throws InterruptedException, ExecutionException, TimeoutException {
         AtomicBoolean guardStarted = new AtomicBoolean();
@@ -317,6 +418,29 @@ public class GrpcOperationTest {
         assertThatIllegalArgumentException().isThrownBy(() -> operation.startOperationAsync(1, params.makeOutcome()));
     }
 
         assertThatIllegalArgumentException().isThrownBy(() -> operation.startOperationAsync(1, params.makeOutcome()));
     }
 
+    @Test
+    public void testGetAdditionalEventParams() {
+        operation = new GrpcOperation(params, config);
+
+        // in neither property nor context
+        assertNull(operation.getAdditionalEventParams());
+
+        final Map<String, String> eventParams = Collections.emptyMap();
+
+        // only in context
+        onset.setAdditionalEventParams(eventParams);
+        assertSame(eventParams, operation.getAdditionalEventParams());
+
+        // both - should choose the property, even if it's null
+        operation.setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, null);
+        assertNull(operation.getAdditionalEventParams());
+
+        // both - should choose the property
+        final Map<String, String> propParams = Collections.emptyMap();
+        operation.setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, propParams);
+        assertSame(propParams, operation.getAdditionalEventParams());
+    }
+
     private void verifyOperation(ControlLoopEventContext context) {
 
         Map<String, Object> payloadMap = Map.of(CdsActorConstants.KEY_CBA_NAME, CDS_BLUEPRINT_NAME,
     private void verifyOperation(ControlLoopEventContext context) {
 
         Map<String, Object> payloadMap = Map.of(CdsActorConstants.KEY_CBA_NAME, CDS_BLUEPRINT_NAME,
index 434b3b9..d2a1536 100644 (file)
@@ -23,7 +23,6 @@ package org.onap.policy.controlloop.actor.sdnc;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
-import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.sdnc.SdncHealRequest;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.sdnc.SdncHealRequest;
@@ -38,15 +37,18 @@ import org.onap.policy.sdnc.SdncHealVnfInfo;
 import org.onap.policy.sdnc.SdncRequest;
 
 public class BandwidthOnDemandOperation extends SdncOperation {
 import org.onap.policy.sdnc.SdncRequest;
 
 public class BandwidthOnDemandOperation extends SdncOperation {
+
     public static final String NAME = "BandwidthOnDemand";
 
     // fields in the enrichment data
     public static final String SERVICE_ID_KEY = "service-instance.service-instance-id";
     public static final String NAME = "BandwidthOnDemand";
 
     // fields in the enrichment data
     public static final String SERVICE_ID_KEY = "service-instance.service-instance-id";
+    public static final String BANDWIDTH = "bandwidth";
+    public static final String BANDWIDTH_CHANGE_TIME = "bandwidth-change-time";
     public static final String VNF_ID = "vnfId";
 
     // @formatter:off
     private static final List<String> PROPERTY_NAMES = List.of(
     public static final String VNF_ID = "vnfId";
 
     // @formatter:off
     private static final List<String> PROPERTY_NAMES = List.of(
-                            OperationProperties.ENRICHMENT_SERVICE_INSTANCE_ID,
+                            OperationProperties.ENRICHMENT_SERVICE_ID,
                             OperationProperties.ENRICHMENT_BANDWIDTH,
                             OperationProperties.ENRICHMENT_BANDWIDTH_CHANGE_TIME,
                             OperationProperties.ENRICHMENT_VNF_ID);
                             OperationProperties.ENRICHMENT_BANDWIDTH,
                             OperationProperties.ENRICHMENT_BANDWIDTH_CHANGE_TIME,
                             OperationProperties.ENRICHMENT_VNF_ID);
@@ -64,20 +66,18 @@ public class BandwidthOnDemandOperation extends SdncOperation {
 
     @Override
     protected SdncRequest makeRequest(int attempt) {
 
     @Override
     protected SdncRequest makeRequest(int attempt) {
-        ControlLoopEventContext context = params.getContext();
-
-        String serviceInstance = context.getEnrichment().get(SERVICE_ID_KEY);
+        String serviceInstance = getOptProperty(OperationProperties.ENRICHMENT_SERVICE_ID, SERVICE_ID_KEY);
         if (StringUtils.isBlank(serviceInstance)) {
             throw new IllegalArgumentException("missing enrichment data, " + SERVICE_ID_KEY);
         }
 
         SdncHealVfModuleParameter bandwidth = new SdncHealVfModuleParameter();
         if (StringUtils.isBlank(serviceInstance)) {
             throw new IllegalArgumentException("missing enrichment data, " + SERVICE_ID_KEY);
         }
 
         SdncHealVfModuleParameter bandwidth = new SdncHealVfModuleParameter();
-        bandwidth.setName("bandwidth");
-        bandwidth.setValue(context.getEnrichment().get("bandwidth"));
+        bandwidth.setName(BANDWIDTH);
+        bandwidth.setValue(getOptProperty(OperationProperties.ENRICHMENT_BANDWIDTH, BANDWIDTH));
 
         SdncHealVfModuleParameter timeStamp = new SdncHealVfModuleParameter();
 
         SdncHealVfModuleParameter timeStamp = new SdncHealVfModuleParameter();
-        timeStamp.setName("bandwidth-change-time");
-        timeStamp.setValue(context.getEnrichment().get("bandwidth-change-time"));
+        timeStamp.setName(BANDWIDTH_CHANGE_TIME);
+        timeStamp.setValue(getOptProperty(OperationProperties.ENRICHMENT_BANDWIDTH_CHANGE_TIME, BANDWIDTH_CHANGE_TIME));
 
         SdncHealVfModuleParametersInfo vfParametersInfo = new SdncHealVfModuleParametersInfo();
         vfParametersInfo.addParameters(bandwidth);
 
         SdncHealVfModuleParametersInfo vfParametersInfo = new SdncHealVfModuleParametersInfo();
         vfParametersInfo.addParameters(bandwidth);
@@ -102,7 +102,7 @@ public class BandwidthOnDemandOperation extends SdncOperation {
         request.setUrl("/" + getPath());
 
         SdncHealVnfInfo vnfInfo = new SdncHealVnfInfo();
         request.setUrl("/" + getPath());
 
         SdncHealVnfInfo vnfInfo = new SdncHealVnfInfo();
-        vnfInfo.setVnfId(context.getEnrichment().get(VNF_ID));
+        vnfInfo.setVnfId(getOptProperty(OperationProperties.ENRICHMENT_VNF_ID, VNF_ID));
 
         SdncHealVfModuleInfo vfModuleInfo = new SdncHealVfModuleInfo();
         vfModuleInfo.setVfModuleId("");
 
         SdncHealVfModuleInfo vfModuleInfo = new SdncHealVfModuleInfo();
         vfModuleInfo.setVfModuleId("");
index d26fad8..105a276 100644 (file)
@@ -23,7 +23,6 @@ package org.onap.policy.controlloop.actor.sdnc;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
-import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.sdnc.SdncHealNetworkInfo;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.sdnc.SdncHealNetworkInfo;
@@ -58,16 +57,14 @@ public class RerouteOperation extends SdncOperation {
 
     @Override
     protected SdncRequest makeRequest(int attempt) {
 
     @Override
     protected SdncRequest makeRequest(int attempt) {
-        ControlLoopEventContext context = params.getContext();
-
-        String serviceInstance = context.getEnrichment().get(SERVICE_ID_KEY);
+        String serviceInstance = getOptProperty(OperationProperties.ENRICHMENT_SERVICE_ID, SERVICE_ID_KEY);
         if (StringUtils.isBlank(serviceInstance)) {
             throw new IllegalArgumentException("missing enrichment data, " + SERVICE_ID_KEY);
         }
         SdncHealServiceInfo serviceInfo = new SdncHealServiceInfo();
         serviceInfo.setServiceInstanceId(serviceInstance);
 
         if (StringUtils.isBlank(serviceInstance)) {
             throw new IllegalArgumentException("missing enrichment data, " + SERVICE_ID_KEY);
         }
         SdncHealServiceInfo serviceInfo = new SdncHealServiceInfo();
         serviceInfo.setServiceInstanceId(serviceInstance);
 
-        String networkId = context.getEnrichment().get(NETWORK_ID_KEY);
+        String networkId = getOptProperty(OperationProperties.ENRICHMENT_NETWORK_ID, NETWORK_ID_KEY);
         if (StringUtils.isBlank(networkId)) {
             throw new IllegalArgumentException("missing enrichment data, " + NETWORK_ID_KEY);
         }
         if (StringUtils.isBlank(networkId)) {
             throw new IllegalArgumentException("missing enrichment data, " + NETWORK_ID_KEY);
         }
index 4d8e35e..defbcfb 100644 (file)
@@ -96,4 +96,21 @@ public abstract class SdncOperation extends HttpOperation<SdncResponse> {
     protected boolean isSuccess(Response rawResponse, SdncResponse response) {
         return response.getResponseOutput() != null && "200".equals(response.getResponseOutput().getResponseCode());
     }
     protected boolean isSuccess(Response rawResponse, SdncResponse response) {
         return response.getResponseOutput() != null && "200".equals(response.getResponseOutput().getResponseCode());
     }
+
+    /**
+     * Gets an optional property, first checking the properties, then checking the
+     * enrichment data.
+     *
+     * @param propName property name
+     * @param enrichmentName property name within the enrichment data
+     * @return the property's value, or {@code null} if it is not found
+     */
+    protected String getOptProperty(String propName, String enrichmentName) {
+        if (containsProperty(propName)) {
+            // return the value, even if it's null
+            return getProperty(propName);
+        }
+
+        return params.getContext().getEnrichment().get(enrichmentName);
+    }
 }
 }
index 56b64e4..f80299f 100644 (file)
@@ -32,6 +32,7 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
 import org.junit.Test;
 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
+import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
 import org.onap.policy.controlloop.policy.PolicyResult;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
 import org.onap.policy.controlloop.policy.PolicyResult;
@@ -39,6 +40,10 @@ import org.onap.policy.sdnc.SdncRequest;
 import org.onap.policy.sdnc.SdncResponse;
 
 public class BandwidthOnDemandOperationTest extends BasicSdncOperation {
 import org.onap.policy.sdnc.SdncResponse;
 
 public class BandwidthOnDemandOperationTest extends BasicSdncOperation {
+    private static final String MY_SERVICE = "my-service";
+    private static final String MY_VNF = "my-vnf";
+    private static final String MY_BANDWIDTH = "my-bandwidth";
+    private static final String MY_CHANGE_TIME = "my-change-time";
 
     private BandwidthOnDemandOperation oper;
 
 
     private BandwidthOnDemandOperation oper;
 
@@ -76,7 +81,7 @@ public class BandwidthOnDemandOperationTest extends BasicSdncOperation {
         // @formatter:off
         assertThat(oper.getPropertyNames()).isEqualTo(
                         List.of(
         // @formatter:off
         assertThat(oper.getPropertyNames()).isEqualTo(
                         List.of(
-                            OperationProperties.ENRICHMENT_SERVICE_INSTANCE_ID,
+                            OperationProperties.ENRICHMENT_SERVICE_ID,
                             OperationProperties.ENRICHMENT_BANDWIDTH,
                             OperationProperties.ENRICHMENT_BANDWIDTH_CHANGE_TIME,
                             OperationProperties.ENRICHMENT_VNF_ID));
                             OperationProperties.ENRICHMENT_BANDWIDTH,
                             OperationProperties.ENRICHMENT_BANDWIDTH_CHANGE_TIME,
                             OperationProperties.ENRICHMENT_VNF_ID));
@@ -93,9 +98,14 @@ public class BandwidthOnDemandOperationTest extends BasicSdncOperation {
                         .path("GENERIC-RESOURCE-API:vf-module-topology-operation").build();
         config = new HttpConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory());
 
                         .path("GENERIC-RESOURCE-API:vf-module-topology-operation").build();
         config = new HttpConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory());
 
-        params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).build();
+        params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).preprocessed(true).build();
         oper = new BandwidthOnDemandOperation(params, config);
 
         oper = new BandwidthOnDemandOperation(params, config);
 
+        oper.setProperty(OperationProperties.ENRICHMENT_SERVICE_ID, MY_SERVICE);
+        oper.setProperty(OperationProperties.ENRICHMENT_BANDWIDTH, MY_BANDWIDTH);
+        oper.setProperty(OperationProperties.ENRICHMENT_BANDWIDTH_CHANGE_TIME, MY_CHANGE_TIME);
+        oper.setProperty(OperationProperties.ENRICHMENT_VNF_ID, MY_VNF);
+
         outcome = oper.start().get();
         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
         assertTrue(outcome.getResponse() instanceof SdncResponse);
         outcome = oper.start().get();
         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
         assertTrue(outcome.getResponse() instanceof SdncResponse);
@@ -105,7 +115,7 @@ public class BandwidthOnDemandOperationTest extends BasicSdncOperation {
     public void testMakeRequest() throws Exception {
         oper.generateSubRequestId(1);
         SdncRequest request = oper.makeRequest(1);
     public void testMakeRequest() throws Exception {
         oper.generateSubRequestId(1);
         SdncRequest request = oper.makeRequest(1);
-        assertEquals("my-service", request.getNsInstanceId());
+        assertEquals(MY_SERVICE, request.getNsInstanceId());
         assertEquals(REQ_ID, request.getRequestId());
         assertEquals("/my-path/", request.getUrl());
         assertEquals(oper.getSubRequestId(), request.getHealRequest().getRequestHeaderInfo().getSvcRequestId());
         assertEquals(REQ_ID, request.getRequestId());
         assertEquals("/my-path/", request.getUrl());
         assertEquals(oper.getSubRequestId(), request.getHealRequest().getRequestHeaderInfo().getSvcRequestId());
@@ -119,9 +129,26 @@ public class BandwidthOnDemandOperationTest extends BasicSdncOperation {
         verifyRequest("bod.json", verifyOperation(oper), IGNORE_FIELDS);
     }
 
         verifyRequest("bod.json", verifyOperation(oper), IGNORE_FIELDS);
     }
 
+    @Test
+    public void testMakeRequestViaProperties() throws Exception {
+        // clear the enrichment data and remake the operation
+        event.setAai(null);
+        context = new ControlLoopEventContext(event);
+        params = params.toBuilder().context(context).build();
+        oper = new BandwidthOnDemandOperation(params, config);
+
+        oper.setProperty(OperationProperties.ENRICHMENT_SERVICE_ID, MY_SERVICE);
+        oper.setProperty(OperationProperties.ENRICHMENT_BANDWIDTH, MY_BANDWIDTH);
+        oper.setProperty(OperationProperties.ENRICHMENT_BANDWIDTH_CHANGE_TIME, MY_CHANGE_TIME);
+        oper.setProperty(OperationProperties.ENRICHMENT_VNF_ID, MY_VNF);
+
+        verifyRequest("bod.json", verifyOperation(oper), IGNORE_FIELDS);
+    }
+
     @Override
     protected Map<String, String> makeEnrichment() {
     @Override
     protected Map<String, String> makeEnrichment() {
-        return Map.of(BandwidthOnDemandOperation.SERVICE_ID_KEY, "my-service", BandwidthOnDemandOperation.VNF_ID,
-                        "my-vnf");
+        return Map.of(BandwidthOnDemandOperation.SERVICE_ID_KEY, MY_SERVICE, BandwidthOnDemandOperation.BANDWIDTH,
+                        MY_BANDWIDTH, BandwidthOnDemandOperation.BANDWIDTH_CHANGE_TIME, MY_CHANGE_TIME,
+                        BandwidthOnDemandOperation.VNF_ID, MY_VNF);
     }
 }
     }
 }
index 9f06805..b71e567 100644 (file)
@@ -32,6 +32,7 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
 import org.junit.Test;
 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
+import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
 import org.onap.policy.controlloop.policy.PolicyResult;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
 import org.onap.policy.controlloop.policy.PolicyResult;
@@ -39,6 +40,8 @@ import org.onap.policy.sdnc.SdncRequest;
 import org.onap.policy.sdnc.SdncResponse;
 
 public class RerouteOperationTest extends BasicSdncOperation {
 import org.onap.policy.sdnc.SdncResponse;
 
 public class RerouteOperationTest extends BasicSdncOperation {
+    private static final String MY_SERVICE = "my-service";
+    private static final String MY_NETWORK = "my-network";
 
     private RerouteOperation oper;
 
 
     private RerouteOperation oper;
 
@@ -74,9 +77,12 @@ public class RerouteOperationTest extends BasicSdncOperation {
                         .path("GENERIC-RESOURCE-API:network-topology-operation").build();
         config = new HttpConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory());
 
                         .path("GENERIC-RESOURCE-API:network-topology-operation").build();
         config = new HttpConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory());
 
-        params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).build();
+        params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).preprocessed(true).build();
         oper = new RerouteOperation(params, config);
 
         oper = new RerouteOperation(params, config);
 
+        oper.setProperty(OperationProperties.ENRICHMENT_SERVICE_ID, MY_SERVICE);
+        oper.setProperty(OperationProperties.ENRICHMENT_NETWORK_ID, MY_NETWORK);
+
         outcome = oper.start().get();
         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
         assertTrue(outcome.getResponse() instanceof SdncResponse);
         outcome = oper.start().get();
         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
         assertTrue(outcome.getResponse() instanceof SdncResponse);
@@ -102,7 +108,7 @@ public class RerouteOperationTest extends BasicSdncOperation {
     public void testMakeRequest() throws Exception {
         oper.generateSubRequestId(1);
         SdncRequest request = oper.makeRequest(1);
     public void testMakeRequest() throws Exception {
         oper.generateSubRequestId(1);
         SdncRequest request = oper.makeRequest(1);
-        assertEquals("my-service", request.getNsInstanceId());
+        assertEquals(MY_SERVICE, request.getNsInstanceId());
         assertEquals(REQ_ID, request.getRequestId());
         assertEquals("/my-path/", request.getUrl());
         assertEquals(oper.getSubRequestId(), request.getHealRequest().getRequestHeaderInfo().getSvcRequestId());
         assertEquals(REQ_ID, request.getRequestId());
         assertEquals("/my-path/", request.getUrl());
         assertEquals(oper.getSubRequestId(), request.getHealRequest().getRequestHeaderInfo().getSvcRequestId());
@@ -117,8 +123,22 @@ public class RerouteOperationTest extends BasicSdncOperation {
         verifyRequest("reroute.json", verifyOperation(oper), IGNORE_FIELDS);
     }
 
         verifyRequest("reroute.json", verifyOperation(oper), IGNORE_FIELDS);
     }
 
+    @Test
+    public void testMakeRequestViaProperties() throws Exception {
+        // clear the enrichment data and remake the operation
+        event.setAai(null);
+        context = new ControlLoopEventContext(event);
+        params = params.toBuilder().context(context).build();
+        oper = new RerouteOperation(params, config);
+
+        oper.setProperty(OperationProperties.ENRICHMENT_SERVICE_ID, MY_SERVICE);
+        oper.setProperty(OperationProperties.ENRICHMENT_NETWORK_ID, MY_NETWORK);
+
+        verifyRequest("reroute.json", verifyOperation(oper), IGNORE_FIELDS);
+    }
+
     @Override
     protected Map<String, String> makeEnrichment() {
     @Override
     protected Map<String, String> makeEnrichment() {
-        return Map.of(RerouteOperation.SERVICE_ID_KEY, "my-service", RerouteOperation.NETWORK_ID_KEY, "my-network");
+        return Map.of(RerouteOperation.SERVICE_ID_KEY, MY_SERVICE, RerouteOperation.NETWORK_ID_KEY, MY_NETWORK);
     }
 }
     }
 }
index fb9f71b..4ba12c6 100644 (file)
@@ -23,6 +23,7 @@ package org.onap.policy.controlloop.actor.sdnc;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.util.Collections;
 import static org.junit.Assert.assertTrue;
 
 import java.util.Collections;
@@ -30,6 +31,7 @@ import java.util.Map;
 import java.util.TreeMap;
 import org.junit.Before;
 import org.junit.Test;
 import java.util.TreeMap;
 import org.junit.Before;
 import org.junit.Test;
+import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
 import org.onap.policy.sdnc.SdncHealRequest;
 import org.onap.policy.sdnc.SdncHealRequestHeaderInfo;
 import org.onap.policy.sdnc.SdncRequest;
 import org.onap.policy.sdnc.SdncHealRequest;
 import org.onap.policy.sdnc.SdncHealRequestHeaderInfo;
 import org.onap.policy.sdnc.SdncRequest;
@@ -101,6 +103,44 @@ public class SdncOperationTest extends BasicSdncOperation {
         assertFalse(oper.isSuccess(null, response));
     }
 
         assertFalse(oper.isSuccess(null, response));
     }
 
+    @Test
+    public void testGetOptProperty() {
+        // in neither property nor enrichment
+        assertNull(oper.getOptProperty("propA", "propA2"));
+
+        // both - should choose the property
+        remakeOper(Map.of("propB2", "valueB2"));
+        oper.setProperty("propB", "valueB");
+        assertEquals("valueB", oper.getOptProperty("propB", "propB2"));
+
+        // both - should choose the property, even if it's null
+        remakeOper(Map.of("propC2", "valueC2"));
+        oper.setProperty("propC", null);
+        assertNull(oper.getOptProperty("propC", "propC2"));
+
+        // only in enrichment data
+        remakeOper(Map.of("propD2", "valueD2"));
+        assertEquals("valueD2", oper.getOptProperty("propD", "propD2"));
+    }
+
+    /**
+     * Remakes the operation, with the specified A&AI enrichment data.
+     *
+     * @param aai A&AI enrichment data
+     */
+    private void remakeOper(Map<String, String> aai) {
+        event.setAai(aai);
+        context = new ControlLoopEventContext(event);
+        params = params.toBuilder().context(context).build();
+
+        oper = new SdncOperation(params, config, Collections.emptyList()) {
+            @Override
+            protected SdncRequest makeRequest(int attempt) {
+                return request;
+            }
+        };
+    }
+
     @Override
     protected Map<String, String> makeEnrichment() {
         return new TreeMap<>();
     @Override
     protected Map<String, String> makeEnrichment() {
         return new TreeMap<>();
index 8c60bbd..8d3545e 100644 (file)
       "vf-module-input-parameters": {
         "param": [
           {
       "vf-module-input-parameters": {
         "param": [
           {
-            "name": "bandwidth"
+            "name": "bandwidth",
+            "value": "my-bandwidth"
           },
           {
           },
           {
-            "name": "bandwidth-change-time"
+            "name": "bandwidth-change-time",
+            "value": "my-change-time"
           }
         ]
       }
           }
         ]
       }
index f88f3c3..4511cc3 100644 (file)
@@ -46,7 +46,7 @@ public class SdnrOperation extends BidirectionalTopicOperation<PciMessage, PciMe
      */
     public static final String NAME = "any";
 
      */
     public static final String NAME = "any";
 
-    private static final List<String> PROPERTY_NAMES = List.of(OperationProperties.AAI_VSERVER_LINK);
+    private static final List<String> PROPERTY_NAMES = List.of(OperationProperties.EVENT_PAYLOAD);
 
     /**
      * Keys used to match the response with the request listener. The sub request ID is a
 
     /**
      * Keys used to match the response with the request listener. The sub request ID is a
@@ -156,7 +156,7 @@ public class SdnrOperation extends BidirectionalTopicOperation<PciMessage, PciMe
         requestCommonHeader.setSubRequestId(subRequestId);
 
         sdnrRequest.setCommonHeader(requestCommonHeader);
         requestCommonHeader.setSubRequestId(subRequestId);
 
         sdnrRequest.setCommonHeader(requestCommonHeader);
-        sdnrRequest.setPayload(params.getContext().getEvent().getPayload());
+        sdnrRequest.setPayload(getEventPayload());
         sdnrRequest.setAction(params.getOperation());
 
         /*
         sdnrRequest.setAction(params.getOperation());
 
         /*
@@ -169,4 +169,18 @@ public class SdnrOperation extends BidirectionalTopicOperation<PciMessage, PciMe
         /* Return the request to be sent through dmaap. */
         return dmaapRequest;
     }
         /* Return the request to be sent through dmaap. */
         return dmaapRequest;
     }
+
+    /**
+     * Gets the event payload, first checking for it in the properties and then in the
+     * event.
+     *
+     * @return the event payload
+     */
+    protected String getEventPayload() {
+        if (containsProperty(OperationProperties.EVENT_PAYLOAD)) {
+            return getProperty(OperationProperties.EVENT_PAYLOAD);
+        }
+
+        return params.getContext().getEvent().getPayload();
+    }
 }
 }
index 8ec1e4a..abce210 100644 (file)
@@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
@@ -90,7 +91,7 @@ public class SdnrOperationTest extends BasicSdnrOperation {
 
     @Test
     public void testGetPropertyNames() {
 
     @Test
     public void testGetPropertyNames() {
-        assertThat(operation.getPropertyNames()).isEqualTo(List.of(OperationProperties.AAI_VSERVER_LINK));
+        assertThat(operation.getPropertyNames()).isEqualTo(List.of(OperationProperties.EVENT_PAYLOAD));
     }
 
     @Test
     }
 
     @Test
@@ -235,6 +236,24 @@ public class SdnrOperationTest extends BasicSdnrOperation {
         checkOutcome();
     }
 
         checkOutcome();
     }
 
+    @Test
+    public void testGetEventPayload() {
+        // in neither property nor event
+        assertNull(operation.getEventPayload());
+
+        // only in event
+        event.setPayload("valueA2");
+        assertEquals("valueA2", operation.getEventPayload());
+
+        // both - should choose the property
+        operation.setProperty(OperationProperties.EVENT_PAYLOAD, "valueB");
+        assertEquals("valueB", operation.getEventPayload());
+
+        // both - should choose the property, even if it's null
+        operation.setProperty(OperationProperties.EVENT_PAYLOAD, null);
+        assertNull(operation.getEventPayload());
+    }
+
     protected void checkOutcome() {
         assertSame(outcome, operation.setOutcome(outcome, PolicyResult.SUCCESS, response));
         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
     protected void checkOutcome() {
         assertSame(outcome, operation.setOutcome(outcome, PolicyResult.SUCCESS, response));
         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
index f269ea0..8f0dda3 100644 (file)
@@ -29,10 +29,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
+import java.util.function.Function;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.onap.aai.domain.yang.CloudRegion;
 import org.onap.aai.domain.yang.GenericVnf;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.onap.aai.domain.yang.CloudRegion;
 import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.ModelVer;
 import org.onap.aai.domain.yang.ServiceInstance;
 import org.onap.aai.domain.yang.Tenant;
 import org.onap.policy.aai.AaiConstants;
 import org.onap.aai.domain.yang.ServiceInstance;
 import org.onap.aai.domain.yang.Tenant;
 import org.onap.policy.aai.AaiConstants;
@@ -43,6 +45,7 @@ import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.coder.StandardCoder;
 import org.onap.policy.common.utils.coder.StandardCoderObject;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.common.utils.coder.StandardCoder;
 import org.onap.policy.common.utils.coder.StandardCoderObject;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
+import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpPollingConfig;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpPollingConfig;
@@ -170,10 +173,19 @@ public abstract class SoOperation extends HttpOperation<SoResponse> {
     }
 
     protected int getVfCount() {
     }
 
     protected int getVfCount() {
+        if (containsProperty(OperationProperties.DATA_VF_COUNT)) {
+            return getProperty(OperationProperties.DATA_VF_COUNT);
+        }
+
         return params.getContext().getProperty(vfCountKey);
     }
 
     protected void setVfCount(int vfCount) {
         return params.getContext().getProperty(vfCountKey);
     }
 
     protected void setVfCount(int vfCount) {
+        if (containsProperty(OperationProperties.DATA_VF_COUNT)) {
+            setProperty(OperationProperties.DATA_VF_COUNT, vfCount);
+            return;
+        }
+
         params.getContext().setProperty(vfCountKey, vfCount);
     }
 
         params.getContext().setProperty(vfCountKey, vfCount);
     }
 
@@ -370,45 +382,77 @@ public abstract class SoOperation extends HttpOperation<SoResponse> {
         return headers;
     }
 
         return headers;
     }
 
-    /*
-     * These methods extract data from the Custom Query and throw an
-     * IllegalArgumentException if the desired data item is not found.
+    /**
+     * Gets an item from a property. If the property is not found, then it invokes the
+     * given function to retrieve it from the custom query data. If that fails as well,
+     * then an exception is thrown.
+     *
+     * @param propName property name
+     * @param getter method to extract the value from the custom query data
+     * @param errmsg error message to include in any exception
+     * @return the retrieved item
      */
      */
+    protected <T> T getItem(String propName, Function<AaiCqResponse, T> getter, String errmsg) {
+        if (containsProperty(propName)) {
+            return getProperty(propName);
+        }
 
 
-    protected GenericVnf getVnfItem(AaiCqResponse aaiCqResponse, SoModelInfo soModelInfo) {
-        GenericVnf vnf = aaiCqResponse.getGenericVnfByVfModuleModelInvariantId(soModelInfo.getModelInvariantId());
-        if (vnf == null) {
-            throw new IllegalArgumentException("missing generic VNF");
+        final AaiCqResponse aaiCqResponse = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY);
+        T item = getter.apply(aaiCqResponse);
+        if (item == null) {
+            throw new IllegalArgumentException(errmsg);
         }
 
         }
 
-        return vnf;
+        return item;
     }
 
     }
 
-    protected ServiceInstance getServiceInstance(AaiCqResponse aaiCqResponse) {
-        ServiceInstance vnfService = aaiCqResponse.getServiceInstance();
-        if (vnfService == null) {
-            throw new IllegalArgumentException("missing VNF Service Item");
-        }
+    /*
+     * These methods extract data from the Custom Query and throw an
+     * IllegalArgumentException if the desired data item is not found.
+     */
 
 
-        return vnfService;
+    protected GenericVnf getVnfItem(SoModelInfo soModelInfo) {
+        // @formatter:off
+        return getItem(OperationProperties.AAI_VNF,
+            cq -> cq.getGenericVnfByVfModuleModelInvariantId(soModelInfo.getModelInvariantId()),
+            "missing generic VNF");
+        // @formatter:on
     }
 
     }
 
-    protected Tenant getDefaultTenant(AaiCqResponse aaiCqResponse) {
-        Tenant tenant = aaiCqResponse.getDefaultTenant();
-        if (tenant == null) {
-            throw new IllegalArgumentException("missing Tenant Item");
-        }
+    protected ServiceInstance getServiceInstance() {
+        return getItem(OperationProperties.AAI_SERVICE, AaiCqResponse::getServiceInstance, "missing VNF Service Item");
+    }
 
 
-        return tenant;
+    protected Tenant getDefaultTenant() {
+        // @formatter:off
+        return getItem(OperationProperties.AAI_DEFAULT_TENANT,
+            AaiCqResponse::getDefaultTenant,
+            "missing Default Tenant Item");
+        // @formatter:on
     }
 
     }
 
-    protected CloudRegion getDefaultCloudRegion(AaiCqResponse aaiCqResponse) {
-        CloudRegion cloudRegion = aaiCqResponse.getDefaultCloudRegion();
-        if (cloudRegion == null) {
-            throw new IllegalArgumentException("missing Cloud Region");
-        }
+    protected CloudRegion getDefaultCloudRegion() {
+        // @formatter:off
+        return getItem(OperationProperties.AAI_DEFAULT_CLOUD_REGION,
+            AaiCqResponse::getDefaultCloudRegion,
+            "missing Default Cloud Region");
+        // @formatter:on
+    }
+
+    protected ModelVer getVnfModel(GenericVnf vnfItem) {
+        // @formatter:off
+        return getItem(OperationProperties.AAI_VNF_MODEL,
+            cq -> cq.getModelVerByVersionId(vnfItem.getModelVersionId()),
+            "missing generic VNF Model");
+        // @formatter:on
+    }
 
 
-        return cloudRegion;
+    protected ModelVer getServiceModel(ServiceInstance vnfServiceItem) {
+        // @formatter:off
+        return getItem(OperationProperties.AAI_SERVICE_MODEL,
+            cq -> cq.getModelVerByVersionId(vnfServiceItem.getModelVersionId()),
+            "missing Service Model");
+        // @formatter:on
     }
 
     // these may be overridden by junit tests
     }
 
     // these may be overridden by junit tests
index 4bae1e8..7e95bda 100644 (file)
@@ -29,6 +29,7 @@ import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.tuple.Pair;
 import org.onap.aai.domain.yang.CloudRegion;
 import org.onap.aai.domain.yang.GenericVnf;
 import org.apache.commons.lang3.tuple.Pair;
 import org.onap.aai.domain.yang.CloudRegion;
 import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.ModelVer;
 import org.onap.aai.domain.yang.ServiceInstance;
 import org.onap.aai.domain.yang.Tenant;
 import org.onap.policy.aai.AaiConstants;
 import org.onap.aai.domain.yang.ServiceInstance;
 import org.onap.aai.domain.yang.Tenant;
 import org.onap.policy.aai.AaiConstants;
@@ -61,10 +62,12 @@ public class VfModuleCreate extends SoOperation {
 
     // @formatter:off
     private static final List<String> PROPERTY_NAMES = List.of(
 
     // @formatter:off
     private static final List<String> PROPERTY_NAMES = List.of(
-                            OperationProperties.AAI_MODEL_SERVICE,
-                            OperationProperties.AAI_MODEL_VNF,
-                            OperationProperties.AAI_MODEL_CLOUD_REGION,
-                            OperationProperties.AAI_MODEL_TENANT,
+                            OperationProperties.AAI_SERVICE,
+                            OperationProperties.AAI_SERVICE_MODEL,
+                            OperationProperties.AAI_VNF,
+                            OperationProperties.AAI_VNF_MODEL,
+                            OperationProperties.AAI_DEFAULT_CLOUD_REGION,
+                            OperationProperties.AAI_DEFAULT_TENANT,
                             OperationProperties.DATA_VF_COUNT);
     // @formatter:off
 
                             OperationProperties.DATA_VF_COUNT);
     // @formatter:off
 
@@ -156,12 +159,13 @@ public class VfModuleCreate extends SoOperation {
      * @return a pair containing the request URL and the new request
      */
     protected Pair<String, SoRequest> makeRequest() {
      * @return a pair containing the request URL and the new request
      */
     protected Pair<String, SoRequest> makeRequest() {
-        final AaiCqResponse aaiCqResponse = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY);
         final SoModelInfo soModelInfo = prepareSoModelInfo();
         final SoModelInfo soModelInfo = prepareSoModelInfo();
-        final GenericVnf vnfItem = getVnfItem(aaiCqResponse, soModelInfo);
-        final ServiceInstance vnfServiceItem = getServiceInstance(aaiCqResponse);
-        final Tenant tenantItem = getDefaultTenant(aaiCqResponse);
-        final CloudRegion cloudRegionItem = getDefaultCloudRegion(aaiCqResponse);
+        final GenericVnf vnfItem = getVnfItem(soModelInfo);
+        final ServiceInstance vnfServiceItem = getServiceInstance();
+        final Tenant tenantItem = getDefaultTenant();
+        final CloudRegion cloudRegionItem = getDefaultCloudRegion();
+        final ModelVer vnfModel = getVnfModel(vnfItem);
+        final ModelVer vnfServiceModel = getServiceModel(vnfServiceItem);
 
         SoRequest request = new SoRequest();
         request.setOperationType(SoOperationType.SCALE_OUT);
 
         SoRequest request = new SoRequest();
         request.setOperationType(SoOperationType.SCALE_OUT);
@@ -198,10 +202,8 @@ public class VfModuleCreate extends SoOperation {
                         .setModelInvariantId(vnfServiceItem.getModelInvariantId());
         relatedInstanceListElement1.getRelatedInstance().getModelInfo()
                         .setModelVersionId(vnfServiceItem.getModelVersionId());
                         .setModelInvariantId(vnfServiceItem.getModelInvariantId());
         relatedInstanceListElement1.getRelatedInstance().getModelInfo()
                         .setModelVersionId(vnfServiceItem.getModelVersionId());
-        relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelName(
-                        aaiCqResponse.getModelVerByVersionId(vnfServiceItem.getModelVersionId()).getModelName());
-        relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelVersion(
-                        aaiCqResponse.getModelVerByVersionId(vnfServiceItem.getModelVersionId()).getModelVersion());
+        relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelName(vnfModel.getModelName());
+        relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelVersion(vnfModel.getModelVersion());
 
         // VNF Item
         relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getVnfId());
 
         // VNF Item
         relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getVnfId());
@@ -211,10 +213,9 @@ public class VfModuleCreate extends SoOperation {
                         .setModelInvariantId(vnfItem.getModelInvariantId());
         relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersionId(vnfItem.getModelVersionId());
 
                         .setModelInvariantId(vnfItem.getModelInvariantId());
         relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersionId(vnfItem.getModelVersionId());
 
+        relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelName(vnfServiceModel.getModelName());
         relatedInstanceListElement2.getRelatedInstance().getModelInfo()
         relatedInstanceListElement2.getRelatedInstance().getModelInfo()
-                        .setModelName(aaiCqResponse.getModelVerByVersionId(vnfItem.getModelVersionId()).getModelName());
-        relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersion(
-                        aaiCqResponse.getModelVerByVersionId(vnfItem.getModelVersionId()).getModelVersion());
+                        .setModelVersion(vnfServiceModel.getModelVersion());
 
         relatedInstanceListElement2.getRelatedInstance().getModelInfo()
                         .setModelCustomizationId(vnfItem.getModelCustomizationId());
 
         relatedInstanceListElement2.getRelatedInstance().getModelInfo()
                         .setModelCustomizationId(vnfItem.getModelCustomizationId());
index 7db76d2..0ff833c 100644 (file)
@@ -70,10 +70,10 @@ public class VfModuleDelete extends SoOperation {
 
     // @formatter:off
     private static final List<String> PROPERTY_NAMES = List.of(
 
     // @formatter:off
     private static final List<String> PROPERTY_NAMES = List.of(
-                            OperationProperties.AAI_MODEL_SERVICE,
-                            OperationProperties.AAI_MODEL_VNF,
-                            OperationProperties.AAI_MODEL_CLOUD_REGION,
-                            OperationProperties.AAI_MODEL_TENANT,
+                            OperationProperties.AAI_SERVICE,
+                            OperationProperties.AAI_VNF,
+                            OperationProperties.AAI_DEFAULT_CLOUD_REGION,
+                            OperationProperties.AAI_DEFAULT_TENANT,
                             OperationProperties.DATA_VF_COUNT);
     // @formatter:on
 
                             OperationProperties.DATA_VF_COUNT);
     // @formatter:on
 
@@ -239,12 +239,11 @@ public class VfModuleDelete extends SoOperation {
      * @return a pair containing the request URL and the new request
      */
     protected Pair<String, SoRequest> makeRequest() {
      * @return a pair containing the request URL and the new request
      */
     protected Pair<String, SoRequest> makeRequest() {
-        final AaiCqResponse aaiCqResponse = params.getContext().getProperty(AaiCqResponse.CONTEXT_KEY);
         final SoModelInfo soModelInfo = prepareSoModelInfo();
         final SoModelInfo soModelInfo = prepareSoModelInfo();
-        final GenericVnf vnfItem = getVnfItem(aaiCqResponse, soModelInfo);
-        final ServiceInstance vnfServiceItem = getServiceInstance(aaiCqResponse);
-        final Tenant tenantItem = getDefaultTenant(aaiCqResponse);
-        final CloudRegion cloudRegionItem = getDefaultCloudRegion(aaiCqResponse);
+        final GenericVnf vnfItem = getVnfItem(soModelInfo);
+        final ServiceInstance vnfServiceItem = getServiceInstance();
+        final Tenant tenantItem = getDefaultTenant();
+        final CloudRegion cloudRegionItem = getDefaultCloudRegion();
 
         SoRequest request = new SoRequest();
         request.setOperationType(SoOperationType.DELETE_VF_MODULE);
 
         SoRequest request = new SoRequest();
         request.setOperationType(SoOperationType.DELETE_VF_MODULE);
index 7314c59..e364246 100644 (file)
@@ -36,12 +36,14 @@ import java.time.Month;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
+import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 import org.junit.Before;
 import org.junit.Test;
 import org.onap.aai.domain.yang.CloudRegion;
 import org.onap.aai.domain.yang.GenericVnf;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 import org.junit.Before;
 import org.junit.Test;
 import org.onap.aai.domain.yang.CloudRegion;
 import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.ModelVer;
 import org.onap.aai.domain.yang.ServiceInstance;
 import org.onap.aai.domain.yang.Tenant;
 import org.onap.policy.aai.AaiCqResponse;
 import org.onap.aai.domain.yang.ServiceInstance;
 import org.onap.aai.domain.yang.Tenant;
 import org.onap.policy.aai.AaiCqResponse;
@@ -49,6 +51,7 @@ import org.onap.policy.common.utils.coder.Coder;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.controlloop.ControlLoopOperation;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.controlloop.ControlLoopOperation;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
+import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
 import org.onap.policy.controlloop.policy.PolicyResult;
 import org.onap.policy.so.SoModelInfo;
 import org.onap.policy.so.SoRequest;
 import org.onap.policy.controlloop.policy.PolicyResult;
 import org.onap.policy.so.SoModelInfo;
 import org.onap.policy.so.SoRequest;
@@ -63,6 +66,8 @@ public class SoOperationTest extends BasicSoOperation {
 
     private static final List<String> PROP_NAMES = Collections.emptyList();
 
 
     private static final List<String> PROP_NAMES = Collections.emptyList();
 
+    private static final String VERSION_ID = "1.2.3";
+
     private SoOperation oper;
 
     /**
     private SoOperation oper;
 
     /**
@@ -139,6 +144,24 @@ public class SoOperationTest extends BasicSoOperation {
         assertEquals(VF_COUNT + 1, oper.getVfCount());
     }
 
         assertEquals(VF_COUNT + 1, oper.getVfCount());
     }
 
+    /**
+     * Tests the VF Count methods when properties are being used.
+     * @throws Exception if an error occurs
+     */
+    @Test
+    public void testGetVfCount_testSetVfCount_ViaProperties() throws Exception {
+        oper.setProperty(OperationProperties.DATA_VF_COUNT, VF_COUNT);
+
+        // verify that the count was stored
+        assertEquals(VF_COUNT.intValue(), oper.getVfCount());
+
+        oper.setVfCount(VF_COUNT + 1);
+
+        int count = oper.getProperty(OperationProperties.DATA_VF_COUNT);
+        assertEquals(VF_COUNT + 1, count);
+        assertEquals(VF_COUNT + 1, oper.getVfCount());
+    }
+
     /**
      * Tests obtainVfCount() when it actually has to query.
      */
     /**
      * Tests obtainVfCount() when it actually has to query.
      */
@@ -286,55 +309,114 @@ public class SoOperationTest extends BasicSoOperation {
     }
 
     @Test
     }
 
     @Test
-    public void testGetVnfItem() {
-        // missing data
+    public void testGetItem() {
         AaiCqResponse cq = mock(AaiCqResponse.class);
         AaiCqResponse cq = mock(AaiCqResponse.class);
-        assertThatIllegalArgumentException().isThrownBy(() -> oper.getVnfItem(cq, oper.prepareSoModelInfo()))
-                        .withMessage("missing generic VNF");
+        params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq);
 
 
-        // valid data
-        GenericVnf vnf = new GenericVnf();
-        when(cq.getGenericVnfByVfModuleModelInvariantId(MODEL_INVAR_ID)).thenReturn(vnf);
-        assertSame(vnf, oper.getVnfItem(cq, oper.prepareSoModelInfo()));
+        // in neither property nor custom query
+        assertThatIllegalArgumentException().isThrownBy(() -> oper.getItem("propA", cq2 -> null, "not found"))
+                        .withMessage("not found");
+
+        // only in custom query
+        assertEquals("valueB", oper.getItem("propB", cq2 -> "valueB", "failureB"));
+
+        // both - should choose the property
+        oper.setProperty("propC", "valueC");
+        assertEquals("valueC", oper.getItem("propC", cq2 -> "valueC2", "failureC"));
+
+        // both - should choose the property, even if it's null
+        oper.setProperty("propD", null);
+        assertNull(oper.getItem("propD", cq2 -> "valueD2", "failureD"));
     }
 
     @Test
     }
 
     @Test
-    public void testGetServiceInstance() {
-        // missing data
-        AaiCqResponse cq = mock(AaiCqResponse.class);
-        assertThatIllegalArgumentException().isThrownBy(() -> oper.getServiceInstance(cq))
-                        .withMessage("missing VNF Service Item");
+    public void testGetVnfItem() {
+        // @formatter:off
+        verifyItems(OperationProperties.AAI_VNF, GenericVnf::new,
+            (cq, instance) -> when(cq.getGenericVnfByVfModuleModelInvariantId(MODEL_INVAR_ID)).thenReturn(instance),
+            () -> oper.getVnfItem(oper.prepareSoModelInfo()),
+            "missing generic VNF");
+        // @formatter:on
+    }
 
 
-        // valid data
-        ServiceInstance instance = new ServiceInstance();
-        when(cq.getServiceInstance()).thenReturn(instance);
-        assertSame(instance, oper.getServiceInstance(cq));
+    @Test
+    public void testGetServiceInstance() {
+        // @formatter:off
+        verifyItems(OperationProperties.AAI_SERVICE, ServiceInstance::new,
+            (cq, instance) -> when(cq.getServiceInstance()).thenReturn(instance),
+            () -> oper.getServiceInstance(),
+            "missing VNF Service Item");
+        // @formatter:on
     }
 
     @Test
     public void testGetDefaultTenant() {
     }
 
     @Test
     public void testGetDefaultTenant() {
-        // missing data
-        AaiCqResponse cq = mock(AaiCqResponse.class);
-        assertThatIllegalArgumentException().isThrownBy(() -> oper.getDefaultTenant(cq))
-                        .withMessage("missing Tenant Item");
+        // @formatter:off
+        verifyItems(OperationProperties.AAI_DEFAULT_TENANT, Tenant::new,
+            (cq, tenant) -> when(cq.getDefaultTenant()).thenReturn(tenant),
+            () -> oper.getDefaultTenant(),
+            "missing Default Tenant Item");
+        // @formatter:on
+    }
 
 
-        // valid data
-        Tenant tenant = new Tenant();
-        when(cq.getDefaultTenant()).thenReturn(tenant);
-        assertSame(tenant, oper.getDefaultTenant(cq));
+    @Test
+    public void testGetVnfModel() {
+        GenericVnf vnf = new GenericVnf();
+        vnf.setModelVersionId(VERSION_ID);
+
+        // @formatter:off
+        verifyItems(OperationProperties.AAI_VNF_MODEL, ModelVer::new,
+            (cq, model) -> when(cq.getModelVerByVersionId(VERSION_ID)).thenReturn(model),
+            () -> oper.getVnfModel(vnf),
+            "missing generic VNF Model");
+        // @formatter:on
+    }
+
+    @Test
+    public void testGetServiceModel() {
+        ServiceInstance service = new ServiceInstance();
+        service.setModelVersionId(VERSION_ID);
+
+        // @formatter:off
+        verifyItems(OperationProperties.AAI_SERVICE_MODEL, ModelVer::new,
+            (cq, model) -> when(cq.getModelVerByVersionId(VERSION_ID)).thenReturn(model),
+            () -> oper.getServiceModel(service),
+            "missing Service Model");
+        // @formatter:on
     }
 
     @Test
     public void testGetDefaultCloudRegion() {
     }
 
     @Test
     public void testGetDefaultCloudRegion() {
-        // missing data
+        // @formatter:off
+        verifyItems(OperationProperties.AAI_DEFAULT_CLOUD_REGION, CloudRegion::new,
+            (cq, region) -> when(cq.getDefaultCloudRegion()).thenReturn(region),
+            () -> oper.getDefaultCloudRegion(),
+            "missing Default Cloud Region");
+        // @formatter:on
+    }
+
+    private <T> void verifyItems(String propName, Supplier<T> maker, BiConsumer<AaiCqResponse, T> setter,
+                    Supplier<T> getter, String errmsg) {
+
         AaiCqResponse cq = mock(AaiCqResponse.class);
         AaiCqResponse cq = mock(AaiCqResponse.class);
-        assertThatIllegalArgumentException().isThrownBy(() -> oper.getDefaultCloudRegion(cq))
-                        .withMessage("missing Cloud Region");
+        params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq);
 
 
-        // valid data
-        CloudRegion region = new CloudRegion();
-        when(cq.getDefaultCloudRegion()).thenReturn(region);
-        assertSame(region, oper.getDefaultCloudRegion(cq));
+        // in neither property nor custom query
+        assertThatIllegalArgumentException().isThrownBy(getter::get).withMessage(errmsg);
+
+        // only in custom query
+        final T item1 = maker.get();
+        setter.accept(cq, item1);
+        assertSame(item1, getter.get());
+
+        // both - should choose the property
+        final T item2 = maker.get();
+        oper.setProperty(propName, item2);
+        assertSame(item2, getter.get());
+
+        // both - should choose the property, even if it's null
+        oper.setProperty(propName, null);
+        assertNull(getter.get());
     }
 
     @Test
     }
 
     @Test
index 012f8de..9d80343 100644 (file)
@@ -108,6 +108,51 @@ public class VfModuleCreateTest extends BasicSoOperation {
         assertTrue(outcome.getResponse() instanceof SoResponse);
     }
 
         assertTrue(outcome.getResponse() instanceof SoResponse);
     }
 
+    /**
+     * Tests "success" case with simulator, using properties instead of custom query data.
+     */
+    @Test
+    public void testSuccessViaProperties() throws Exception {
+        HttpPollingParams opParams = HttpPollingParams.builder().clientName(MY_CLIENT)
+                        .path("serviceInstantiation/v7/serviceInstances").pollPath("orchestrationRequests/v5/")
+                        .maxPolls(2).build();
+        config = new HttpPollingConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory());
+
+        params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).preprocessed(true).build();
+        params.getContext().removeProperty(AaiCqResponse.CONTEXT_KEY);
+
+        oper = new VfModuleCreate(params, config);
+
+        // set the properties
+        ServiceInstance instance = new ServiceInstance();
+        instance.setServiceInstanceId(SVC_INSTANCE_ID);
+        oper.setProperty(OperationProperties.AAI_SERVICE, instance);
+
+        ModelVer modelVers = new ModelVer();
+        modelVers.setModelName(MODEL_NAME2);
+        modelVers.setModelVersion(MODEL_VERS2);
+
+        oper.setProperty(OperationProperties.AAI_SERVICE_MODEL, modelVers);
+        oper.setProperty(OperationProperties.AAI_VNF_MODEL, modelVers);
+
+        GenericVnf vnf = new GenericVnf();
+        vnf.setVnfId(VNF_ID);
+        oper.setProperty(OperationProperties.AAI_VNF, vnf);
+
+        oper.setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, new CloudRegion());
+        oper.setProperty(OperationProperties.AAI_DEFAULT_TENANT, new Tenant());
+
+        oper.setProperty(OperationProperties.DATA_VF_COUNT, VF_COUNT);
+
+        // run the operation
+        outcome = oper.start().get();
+        assertEquals(PolicyResult.SUCCESS, outcome.getResult());
+        assertTrue(outcome.getResponse() instanceof SoResponse);
+
+        int count = oper.getProperty(OperationProperties.DATA_VF_COUNT);
+        assertEquals(VF_COUNT + 1, count);
+    }
+
     @Test
     public void testConstructor() {
         assertEquals(DEFAULT_ACTOR, oper.getActorName());
     @Test
     public void testConstructor() {
         assertEquals(DEFAULT_ACTOR, oper.getActorName());
@@ -124,10 +169,12 @@ public class VfModuleCreateTest extends BasicSoOperation {
         // @formatter:off
         assertThat(oper.getPropertyNames()).isEqualTo(
                         List.of(
         // @formatter:off
         assertThat(oper.getPropertyNames()).isEqualTo(
                         List.of(
-                            OperationProperties.AAI_MODEL_SERVICE,
-                            OperationProperties.AAI_MODEL_VNF,
-                            OperationProperties.AAI_MODEL_CLOUD_REGION,
-                            OperationProperties.AAI_MODEL_TENANT,
+                            OperationProperties.AAI_SERVICE,
+                            OperationProperties.AAI_SERVICE_MODEL,
+                            OperationProperties.AAI_VNF,
+                            OperationProperties.AAI_VNF_MODEL,
+                            OperationProperties.AAI_DEFAULT_CLOUD_REGION,
+                            OperationProperties.AAI_DEFAULT_TENANT,
                             OperationProperties.DATA_VF_COUNT));
         // @formatter:on
     }
                             OperationProperties.DATA_VF_COUNT));
         // @formatter:on
     }
index cc2aafa..9335f01 100644 (file)
@@ -137,6 +137,43 @@ public class VfModuleDeleteTest extends BasicSoOperation {
         assertTrue(outcome.getResponse() instanceof SoResponse);
     }
 
         assertTrue(outcome.getResponse() instanceof SoResponse);
     }
 
+    /**
+     * Tests "success" case with simulator, using properties instead of custom query data.
+     */
+    @Test
+    public void testSuccessViaProperties() throws Exception {
+        HttpPollingParams opParams = HttpPollingParams.builder().clientName(MY_CLIENT).path("serviceInstances/v7")
+                        .pollPath("orchestrationRequests/v5/").maxPolls(2).build();
+        config = new HttpPollingConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory());
+
+        params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).preprocessed(true).build();
+        params.getContext().removeProperty(AaiCqResponse.CONTEXT_KEY);
+
+        oper = new VfModuleDelete(params, config);
+
+        // set the properties
+        ServiceInstance instance = new ServiceInstance();
+        instance.setServiceInstanceId(SVC_INSTANCE_ID);
+        oper.setProperty(OperationProperties.AAI_SERVICE, instance);
+
+        GenericVnf vnf = new GenericVnf();
+        vnf.setVnfId(VNF_ID);
+        oper.setProperty(OperationProperties.AAI_VNF, vnf);
+
+        oper.setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, new CloudRegion());
+        oper.setProperty(OperationProperties.AAI_DEFAULT_TENANT, new Tenant());
+
+        oper.setProperty(OperationProperties.DATA_VF_COUNT, VF_COUNT);
+
+        // run the operation
+        outcome = oper.start().get();
+        assertEquals(PolicyResult.SUCCESS, outcome.getResult());
+        assertTrue(outcome.getResponse() instanceof SoResponse);
+
+        int count = oper.getProperty(OperationProperties.DATA_VF_COUNT);
+        assertEquals(VF_COUNT - 1, count);
+    }
+
     @Test
     public void testConstructor() {
         assertEquals(DEFAULT_ACTOR, oper.getActorName());
     @Test
     public void testConstructor() {
         assertEquals(DEFAULT_ACTOR, oper.getActorName());
@@ -153,10 +190,10 @@ public class VfModuleDeleteTest extends BasicSoOperation {
         // @formatter:off
         assertThat(oper.getPropertyNames()).isEqualTo(
                         List.of(
         // @formatter:off
         assertThat(oper.getPropertyNames()).isEqualTo(
                         List.of(
-                            OperationProperties.AAI_MODEL_SERVICE,
-                            OperationProperties.AAI_MODEL_VNF,
-                            OperationProperties.AAI_MODEL_CLOUD_REGION,
-                            OperationProperties.AAI_MODEL_TENANT,
+                            OperationProperties.AAI_SERVICE,
+                            OperationProperties.AAI_VNF,
+                            OperationProperties.AAI_DEFAULT_CLOUD_REGION,
+                            OperationProperties.AAI_DEFAULT_TENANT,
                             OperationProperties.DATA_VF_COUNT));
         // @formatter:on
     }
                             OperationProperties.DATA_VF_COUNT));
         // @formatter:on
     }
index 8bd4630..bb23fdc 100644 (file)
@@ -26,7 +26,6 @@ import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
-import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
@@ -48,7 +47,7 @@ public abstract class VfcOperation extends HttpOperation<VfcResponse> {
 
     // @formatter:off
     private static final List<String> PROPERTY_NAMES = List.of(
 
     // @formatter:off
     private static final List<String> PROPERTY_NAMES = List.of(
-                            OperationProperties.ENRICHMENT_SERVICE_INSTANCE_ID,
+                            OperationProperties.ENRICHMENT_SERVICE_ID,
                             OperationProperties.ENRICHMENT_VSERVER_ID,
                             OperationProperties.ENRICHMENT_VSERVER_NAME,
                             OperationProperties.ENRICHMENT_GENERIC_VNF_ID);
                             OperationProperties.ENRICHMENT_VSERVER_ID,
                             OperationProperties.ENRICHMENT_VSERVER_NAME,
                             OperationProperties.ENRICHMENT_GENERIC_VNF_ID);
@@ -133,7 +132,7 @@ public abstract class VfcOperation extends HttpOperation<VfcResponse> {
      */
     protected String getRequestState(VfcResponse response) {
         if (response == null || response.getResponseDescriptor() == null
      */
     protected String getRequestState(VfcResponse response) {
         if (response == null || response.getResponseDescriptor() == null
-                || StringUtils.isBlank(response.getResponseDescriptor().getStatus())) {
+                        || StringUtils.isBlank(response.getResponseDescriptor().getStatus())) {
             return null;
         }
         return response.getResponseDescriptor().getStatus();
             return null;
         }
         return response.getResponseDescriptor().getStatus();
@@ -153,7 +152,7 @@ public abstract class VfcOperation extends HttpOperation<VfcResponse> {
      */
     @Override
     public OperationOutcome setOutcome(OperationOutcome outcome, PolicyResult result, Response rawResponse,
      */
     @Override
     public OperationOutcome setOutcome(OperationOutcome outcome, PolicyResult result, Response rawResponse,
-            VfcResponse response) {
+                    VfcResponse response) {
 
         // set default result and message
         setOutcome(outcome, result);
 
         // set default result and message
         setOutcome(outcome, result);
@@ -171,14 +170,16 @@ public abstract class VfcOperation extends HttpOperation<VfcResponse> {
      * @return request
      */
     protected VfcRequest constructVfcRequest() {
      * @return request
      */
     protected VfcRequest constructVfcRequest() {
-        ControlLoopEventContext context = params.getContext();
-        String serviceInstance = context.getEnrichment().get("service-instance.service-instance-id");
-        String vmId = context.getEnrichment().get("vserver.vserver-id");
-        String vmName = context.getEnrichment().get("vserver.vserver-name");
+        final String serviceInstance = getOptProperty(OperationProperties.ENRICHMENT_SERVICE_ID,
+                        "service-instance.service-instance-id");
+        final String vmId = getOptProperty(OperationProperties.ENRICHMENT_VSERVER_ID, "vserver.vserver-id");
+        final String vmName = getOptProperty(OperationProperties.ENRICHMENT_VSERVER_NAME, "vserver.vserver-name");
+        final String vnfId = getOptProperty(OperationProperties.ENRICHMENT_GENERIC_VNF_ID, GENERIC_VNF_ID);
 
         if (StringUtils.isBlank(serviceInstance) || StringUtils.isBlank(vmId) || StringUtils.isBlank(vmName)) {
 
         if (StringUtils.isBlank(serviceInstance) || StringUtils.isBlank(vmId) || StringUtils.isBlank(vmName)) {
+            // original code did not check the VNF id, so we won't check it either
             throw new IllegalArgumentException(
             throw new IllegalArgumentException(
-                    "Cannot extract enrichment data for service instance, server id, or server name.");
+                            "Cannot extract enrichment data for service instance, server id, or server name.");
         }
 
         VfcHealActionVmInfo vmActionInfo = new VfcHealActionVmInfo();
         }
 
         VfcHealActionVmInfo vmActionInfo = new VfcHealActionVmInfo();
@@ -190,7 +191,7 @@ public abstract class VfcOperation extends HttpOperation<VfcResponse> {
         additionalParams.setActionInfo(vmActionInfo);
 
         VfcHealRequest healRequest = new VfcHealRequest();
         additionalParams.setActionInfo(vmActionInfo);
 
         VfcHealRequest healRequest = new VfcHealRequest();
-        healRequest.setVnfInstanceId(params.getContext().getEnrichment().get(GENERIC_VNF_ID));
+        healRequest.setVnfInstanceId(vnfId);
         healRequest.setCause(getName());
         healRequest.setAdditionalParams(additionalParams);
 
         healRequest.setCause(getName());
         healRequest.setAdditionalParams(additionalParams);
 
@@ -201,4 +202,21 @@ public abstract class VfcOperation extends HttpOperation<VfcResponse> {
 
         return request;
     }
 
         return request;
     }
+
+    /**
+     * Gets an optional property, first checking the properties, then checking the
+     * enrichment data.
+     *
+     * @param propName property name
+     * @param enrichmentName property name within the enrichment data
+     * @return the property's value, or {@code null} if it is not found
+     */
+    protected String getOptProperty(String propName, String enrichmentName) {
+        if (containsProperty(propName)) {
+            // return the value, even if it's null
+            return getProperty(propName);
+        }
+
+        return params.getContext().getEnrichment().get(enrichmentName);
+    }
 }
 }
index 4666645..068ffda 100644 (file)
@@ -32,6 +32,7 @@ import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.onap.policy.aai.AaiCqResponse;
 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
@@ -42,8 +43,14 @@ import org.onap.policy.vfc.VfcRequest;
 import org.onap.policy.vfc.VfcResponse;
 
 public class RestartTest extends BasicVfcOperation {
 import org.onap.policy.vfc.VfcResponse;
 
 public class RestartTest extends BasicVfcOperation {
+    private static final String TEST_SERVICE_INSTANCE_ID = "test-service-instance-id";
+    private static final String TEST_VSERVER_ID = "test-vserver-id";
+    private static final String TEST_VSERVER_NAME = "test-vserver-name";
+    private static final String TEST_GENERIC_VNF_ID = "test-generic-vnf-id";
+
     private Restart restartOper;
 
     private Restart restartOper;
 
+
     @BeforeClass
     public static void setUpBeforeClass() throws Exception {
         initBeforeClass();
     @BeforeClass
     public static void setUpBeforeClass() throws Exception {
         initBeforeClass();
@@ -60,9 +67,9 @@ public class RestartTest extends BasicVfcOperation {
     @Before
     public void setup() throws Exception {
         super.setUp();
     @Before
     public void setup() throws Exception {
         super.setUp();
-        params.getContext().getEnrichment().put("service-instance.service-instance-id", "test-service-instance-id");
-        params.getContext().getEnrichment().put("vserver.vserver-id", "test-vserver-id");
-        params.getContext().getEnrichment().put("vserver.vserver-name", "test-vserver-name");
+        params.getContext().getEnrichment().put("service-instance.service-instance-id", TEST_SERVICE_INSTANCE_ID);
+        params.getContext().getEnrichment().put("vserver.vserver-id", TEST_VSERVER_ID);
+        params.getContext().getEnrichment().put("vserver.vserver-name", TEST_VSERVER_NAME);
         restartOper = new Restart(params, config);
     }
 
         restartOper = new Restart(params, config);
     }
 
@@ -84,6 +91,32 @@ public class RestartTest extends BasicVfcOperation {
         assertTrue(outcome.getResponse() instanceof VfcResponse);
     }
 
         assertTrue(outcome.getResponse() instanceof VfcResponse);
     }
 
+    /**
+     * Tests "success" case with simulator, using properties instead of custom query data.
+     */
+    @Test
+    public void testSuccessViaProperties() throws Exception {
+        HttpPollingParams opParams = HttpPollingParams.builder().clientName(MY_CLIENT).path("ns").pollPath("jobs")
+                        .maxPolls(1).build();
+        config = new HttpPollingConfig(blockingExecutor, opParams, HttpClientFactoryInstance.getClientFactory());
+
+        params = params.toBuilder().retry(0).timeoutSec(5).executor(blockingExecutor).preprocessed(true).build();
+        params.getContext().removeProperty(AaiCqResponse.CONTEXT_KEY);
+
+        restartOper = new Restart(params, config);
+
+        // set the properties
+        restartOper.setProperty(OperationProperties.ENRICHMENT_SERVICE_ID, TEST_SERVICE_INSTANCE_ID);
+        restartOper.setProperty(OperationProperties.ENRICHMENT_VSERVER_ID, TEST_VSERVER_ID);
+        restartOper.setProperty(OperationProperties.ENRICHMENT_VSERVER_NAME, TEST_VSERVER_NAME);
+        restartOper.setProperty(OperationProperties.ENRICHMENT_GENERIC_VNF_ID, TEST_GENERIC_VNF_ID);
+
+        // run the operation
+        outcome = restartOper.start().get();
+        assertEquals(PolicyResult.SUCCESS, outcome.getResult());
+        assertTrue(outcome.getResponse() instanceof VfcResponse);
+    }
+
     @Test
     public void testConstructor() {
         CompletableFuture<OperationOutcome> futureRes = restartOper.startOperationAsync(1, outcome);
     @Test
     public void testConstructor() {
         CompletableFuture<OperationOutcome> futureRes = restartOper.startOperationAsync(1, outcome);
@@ -96,7 +129,7 @@ public class RestartTest extends BasicVfcOperation {
         // @formatter:off
         assertThat(restartOper.getPropertyNames()).isEqualTo(
                         List.of(
         // @formatter:off
         assertThat(restartOper.getPropertyNames()).isEqualTo(
                         List.of(
-                            OperationProperties.ENRICHMENT_SERVICE_INSTANCE_ID,
+                            OperationProperties.ENRICHMENT_SERVICE_ID,
                             OperationProperties.ENRICHMENT_VSERVER_ID,
                             OperationProperties.ENRICHMENT_VSERVER_NAME,
                             OperationProperties.ENRICHMENT_GENERIC_VNF_ID));
                             OperationProperties.ENRICHMENT_VSERVER_ID,
                             OperationProperties.ENRICHMENT_VSERVER_NAME,
                             OperationProperties.ENRICHMENT_GENERIC_VNF_ID));
index 425ff91..6f8956f 100644 (file)
@@ -26,9 +26,11 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import java.util.Map;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
+import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
 import org.onap.policy.vfc.VfcResponse;
 import org.onap.policy.vfc.VfcResponseDescriptor;
 
 import org.onap.policy.vfc.VfcResponse;
 import org.onap.policy.vfc.VfcResponseDescriptor;
 
@@ -87,4 +89,36 @@ public class VfcOperationTest extends BasicVfcOperation {
         assertTrue(oper.isSuccess(rawResponse, response));
     }
 
         assertTrue(oper.isSuccess(rawResponse, response));
     }
 
+    @Test
+    public void testGetOptProperty() {
+        // in neither property nor enrichment
+        assertNull(oper.getOptProperty("propA", "propA2"));
+
+        // both - should choose the property
+        remakeOper(Map.of("propB2", "valueB2"));
+        oper.setProperty("propB", "valueB");
+        assertEquals("valueB", oper.getOptProperty("propB", "propB2"));
+
+        // both - should choose the property, even if it's null
+        remakeOper(Map.of("propC2", "valueC2"));
+        oper.setProperty("propC", null);
+        assertNull(oper.getOptProperty("propC", "propC2"));
+
+        // only in enrichment data
+        remakeOper(Map.of("propD2", "valueD2"));
+        assertEquals("valueD2", oper.getOptProperty("propD", "propD2"));
+    }
+
+    /**
+     * Remakes the operation, with the specified A&AI enrichment data.
+     *
+     * @param aai A&AI enrichment data
+     */
+    private void remakeOper(Map<String, String> aai) {
+        event.setAai(aai);
+        context = new ControlLoopEventContext(event);
+        params = params.toBuilder().context(context).build();
+
+        oper = new VfcOperation(params, config) {};
+    }
 }
 }
index 4284646..c36b61e 100644 (file)
@@ -25,28 +25,112 @@ package org.onap.policy.controlloop.actorserviceprovider;
  * exhaustive, as additional property names may be returned by company-defined Actors.
  */
 public class OperationProperties {
  * exhaustive, as additional property names may be returned by company-defined Actors.
  */
 public class OperationProperties {
-    public static final String AAI_MODEL_CLOUD_REGION = "AAI/modelInvariantId/cloudRegion";
-    public static final String AAI_MODEL_INVARIANT_GENERIC_VNF = "AAI/modelInvariantId/genericVnf";
-    public static final String AAI_MODEL_SERVICE = "AAI/modelInvariantId/service";
-    public static final String AAI_MODEL_TENANT = "AAI/modelInvariantId/tenant";
-    public static final String AAI_MODEL_VNF = "AAI/modelInvariantId/vnf";
-    public static final String AAI_RESOURCE_SERVICE_INSTANCE = "AAI/resourceId/serviceInstanceId";
-    public static final String AAI_RESOURCE_VNF = "AAI/resourceId/modelInvariantId/vnf";
+
+    /**
+     * A&AI Default Cloud Region. Obtained as follows:
+     * <ol>
+     * <li>invoke the custom query getDefaultCloudRegion() method</li>
+     * </ol>
+     */
+    public static final String AAI_DEFAULT_CLOUD_REGION = "AAI/defaultCloudRegion";
+
+    /**
+     * A&AI Default Tenant. Obtained as follows:
+     * <ol>
+     * <li>invoke the custom query getDefaultTenant() method</li>
+     * </ol>
+     */
+    public static final String AAI_DEFAULT_TENANT = "AAI/defaultTenant";
+
+    /**
+     * A&AI Service instance. Obtained as follows:
+     * <ol>
+     * <li>invoke the custom query getServiceInstance() method</li>
+     * </ol>
+     */
+    public static final String AAI_SERVICE = "AAI/service";
+
+    /**
+     * A&AI Service model. Obtained as follows:
+     * <ol>
+     * <li>invoke the custom query getServiceInstance() method</li>
+     * <li>using the service instance, invoke the getModelVersionId() method</li>
+     * </ol>
+     */
+    public static final String AAI_SERVICE_MODEL = "AAI/service/model";
+
+    /**
+     * A&AI VNF. Obtained as follows:
+     * <ol>
+     * <li>using the target model invariant ID, invoke the custom query
+     * getGenericVnfByModelInvariantId() method to get the VNF</li>
+     * <li>using the VNF item, invoke the getModelVersionId() method to get the
+     * version</li>
+     * </ol>
+     */
+    public static final String AAI_VNF = "AAI/vnf";
+
+    /**
+     * A&AI VNF Model. Obtained as follows:
+     * <ol>
+     * <li>using the target model invariant ID, invoke the custom query
+     * getGenericVnfByModelInvariantId() method to get the VNF</li>
+     * <li>using the VNF item, invoke the getModelVersionId() method to get the
+     * version</li>
+     * <li>using the version, invoke the custom query getModelVerByVersionId() method</li>
+     * </ol>
+     */
+    public static final String AAI_VNF_MODEL = "AAI/vnf/model";
+
+    /**
+     * A&AI VNF id for the target resource ID. Obtained as follows:
+     * <ol>
+     * <li>using the target resource ID, invoke the custom query
+     * getGenericVnfByModelInvariantId() method to get the generic VNF</li>
+     * </ol>
+     */
+    public static final String AAI_RESOURCE_VNF = "AAI/resourceId/vnf";
+
+    /**
+     * A&AI PNF. Obtained as follows:
+     * <ol>
+     * <li>using the target entity, invoke AaiGetPnfOperation</li>
+     * </ol>
+     */
     public static final String AAI_PNF = "AAI/pnf";
     public static final String AAI_PNF = "AAI/pnf";
+
+    /**
+     * A&AI link to the vserver. Obtained as follows:
+     * <ol>
+     * <li>using the vserver name from the enrichment data, perform an A&AI tenant
+     * query</li>
+     * <li>get the "result-data" field from the tenant output</li>
+     * <li>get the "resource-link" field from that</li>
+     * <li>strip off the "/aai/v16" prefix</li>
+     * </ol>
+     */
     public static final String AAI_VSERVER_LINK = "AAI/vserver/link";
 
     public static final String AAI_VSERVER_LINK = "AAI/vserver/link";
 
+    /**
+     * Optional A&AI properties (Map-String-String) for CDS GRPC. If an application
+     * provides this, it will be used instead of constructing the map from the other
+     * properties.
+     */
+    public static final String OPT_CDS_GRPC_AAI_PROPERTIES = "cds/grpc/aai/properties";
+
     /*
      * These are typically extracted from the event or from the event's enrichment data.
     /*
      * These are typically extracted from the event or from the event's enrichment data.
+     *
+     * NOTE: all of the values must be of the form "enrichment/{enrichment-field-name}".
      */
     public static final String ENRICHMENT_BANDWIDTH = "enrichment/bandwidth";
      */
     public static final String ENRICHMENT_BANDWIDTH = "enrichment/bandwidth";
-    public static final String ENRICHMENT_BANDWIDTH_CHANGE_TIME = "enrichment/bandwidth/changeTime";
-    public static final String ENRICHMENT_GENERIC_VNF_ID = "enrichment/genericVnf/id";
-    public static final String ENRICHMENT_NETWORK_ID = "enrichment/network/id";
-    public static final String ENRICHMENT_SERVICE_ID = "enrichment/service/id";
-    public static final String ENRICHMENT_SERVICE_INSTANCE_ID = "enrichment/serviceInstance/id";
-    public static final String ENRICHMENT_VNF_ID = "enrichment/vnf/id";
-    public static final String ENRICHMENT_VSERVER_ID = "enrichment/vserver/id";
-    public static final String ENRICHMENT_VSERVER_NAME = "enrichment/vserver/name";
+    public static final String ENRICHMENT_BANDWIDTH_CHANGE_TIME = "enrichment/bandwidth-change-time";
+    public static final String ENRICHMENT_GENERIC_VNF_ID = "enrichment/generic-vnf.vnf-id";
+    public static final String ENRICHMENT_NETWORK_ID = "enrichment/network-information.network-id";
+    public static final String ENRICHMENT_SERVICE_ID = "enrichment/service-instance.service-instance-id";
+    public static final String ENRICHMENT_VNF_ID = "enrichment/vnfId";
+    public static final String ENRICHMENT_VSERVER_ID = "enrichment/vserver.vserver-id";
+    public static final String ENRICHMENT_VSERVER_NAME = "enrichment/vserver.vserver-name";
 
     public static final String EVENT_ADDITIONAL_PARAMS = "event/additionalParams";
     public static final String EVENT_PAYLOAD = "event/payload";
 
     public static final String EVENT_ADDITIONAL_PARAMS = "event/additionalParams";
     public static final String EVENT_PAYLOAD = "event/payload";
@@ -54,6 +138,10 @@ public class OperationProperties {
     /*
      * These are data computed and/or tracked by the invoker.
      */
     /*
      * These are data computed and/or tracked by the invoker.
      */
+
+    /**
+     * An Integer containing the count.
+     */
     public static final String DATA_VF_COUNT = "data/vfCount";
 
 
     public static final String DATA_VF_COUNT = "data/vfCount";
 
 
index 9ce53aa..0aa1122 100644 (file)
@@ -139,6 +139,17 @@ public abstract class OperationPartial implements Operation {
         return params.getOperation();
     }
 
         return params.getOperation();
     }
 
+    /**
+     * Determines if a property has been assigned for the operation.
+     *
+     * @param name property name
+     * @return {@code true} if the given property has been assigned for the operation,
+     *         {@code false} otherwise
+     */
+    public boolean containsProperty(String name) {
+        return properties.containsKey(name);
+    }
+
     /**
      * Sets a property.
      *
     /**
      * Sets a property.
      *
@@ -326,6 +337,7 @@ public abstract class OperationPartial implements Operation {
 
     /**
      * Generates and sets {@link #subRequestId} to a new subrequest ID.
 
     /**
      * Generates and sets {@link #subRequestId} to a new subrequest ID.
+     *
      * @param attempt attempt number, typically starting with 1
      */
     public void generateSubRequestId(int attempt) {
      * @param attempt attempt number, typically starting with 1
      */
     public void generateSubRequestId(int attempt) {