More actor clean-up 95/102095/1
authorJim Hahn <jrh3@att.com>
Thu, 20 Feb 2020 14:40:14 +0000 (09:40 -0500)
committerJim Hahn <jrh3@att.com>
Thu, 20 Feb 2020 21:29:08 +0000 (16:29 -0500)
Currently, Operator classes refer to Operation classes, and
vice versa, creating a dependency cycle.  In addition, there is
a slight problem in that if an operator is reconfigured, any
running operation may get inconsistent configuration data.
Modified the code to create Config objects that are passed to
the operation, instead of passing the Operator to the operations.
This solved both issues.

Replaceed makeOperator() with constructors.
Added parameter type to HttpActors.

Modified guard to get "ONAP" properties from its configuration,
as a default.

Changed setUp() to setUpBasic(), so "throws Exception" could be
removed, thus resolving a sonar issue.

Issue-ID: POLICY-1625
Signed-off-by: Jim Hahn <jrh3@att.com>
Change-Id: I21eb8798acfbc636ff1bd8741b21c7278365b6e4

68 files changed:
models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiActorServiceProvider.java
models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiCustomQueryOperation.java
models-interactions/model-actors/actor.aai/src/main/java/org/onap/policy/controlloop/actor/aai/AaiGetOperation.java
models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiCustomQueryOperationTest.java
models-interactions/model-actors/actor.aai/src/test/java/org/onap/policy/controlloop/actor/aai/AaiGetOperationTest.java
models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcActorServiceProvider.java
models-interactions/model-actors/actor.appc/src/main/java/org/onap/policy/controlloop/actor/appc/AppcOperation.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/AppcOperationTest.java
models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/BasicAppcOperation.java
models-interactions/model-actors/actor.appc/src/test/java/org/onap/policy/controlloop/actor/appc/ModifyConfigOperationTest.java
models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorParams.java [new file with mode: 0644]
models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProvider.java
models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardConfig.java [new file with mode: 0644]
models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardOperation.java
models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardOperator.java [new file with mode: 0644]
models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardParams.java [new file with mode: 0644]
models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorParamsTest.java [new file with mode: 0644]
models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardConfigTest.java [new file with mode: 0644]
models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardOperationTest.java
models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardOperatorTest.java [new file with mode: 0644]
models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardParamsTest.java [new file with mode: 0644]
models-interactions/model-actors/actor.guard/src/test/resources/makeReqStd.json
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/SdncActorServiceProvider.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/BasicSdncOperation.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.so/src/main/java/org/onap/policy/controlloop/actor/so/SoActorServiceProvider.java
models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoConfig.java [new file with mode: 0644]
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/SoOperator.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/test/java/org/onap/policy/controlloop/actor/so/BasicSoOperation.java
models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoConfigTest.java [new file with mode: 0644]
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/SoOperatorTest.java
models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java
models-interactions/model-actors/actor.test/src/main/java/org/onap/policy/controlloop/actor/test/BasicBidirectionalTopicOperation.java
models-interactions/model-actors/actor.test/src/main/java/org/onap/policy/controlloop/actor/test/BasicHttpOperation.java
models-interactions/model-actors/actor.test/src/main/java/org/onap/policy/controlloop/actor/test/BasicOperation.java
models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/BasicBidirectionalTopicOperationTest.java
models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/BasicHttpOperationTest.java
models-interactions/model-actors/actor.test/src/test/java/org/onap/policy/controlloop/actor/test/BasicOperationTest.java
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/BidirectionalTopicActor.java
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/BidirectionalTopicOperation.java
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/BidirectionalTopicOperator.java
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/HttpActor.java
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/HttpOperation.java
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/HttpOperator.java
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationMaker.java [new file with mode: 0644]
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationPartial.java
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperatorPartial.java
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/BidirectionalTopicConfig.java [new file with mode: 0644]
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/HttpConfig.java [new file with mode: 0644]
models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/OperatorConfig.java [new file with mode: 0644]
models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/BidirectionalTopicActorTest.java
models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/BidirectionalTopicOperationTest.java
models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/BidirectionalTopicOperatorTest.java
models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/HttpActorTest.java
models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/HttpOperationTest.java
models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/HttpOperatorTest.java
models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationPartialTest.java
models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/BidirectionalTopicConfigTest.java [new file with mode: 0644]
models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/HttpConfigTest.java [new file with mode: 0644]

index df427c3..a65a000 100644 (file)
@@ -23,25 +23,25 @@ package org.onap.policy.controlloop.actor.aai;
 import org.onap.policy.aai.AaiConstants;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpActorParams;
 
 /**
  * A&AI Actor.
  */
-public class AaiActorServiceProvider extends HttpActor {
+public class AaiActorServiceProvider extends HttpActor<HttpActorParams> {
     public static final String NAME = AaiConstants.ACTOR_NAME;
 
     /**
      * Constructs the object.
      */
     public AaiActorServiceProvider() {
-        super(NAME);
+        super(NAME, HttpActorParams.class);
 
-        addOperator(HttpOperator.makeOperator(NAME, AaiCustomQueryOperation.NAME,
-                        AaiCustomQueryOperation::new));
+        addOperator(new HttpOperator(NAME, AaiCustomQueryOperation.NAME, AaiCustomQueryOperation::new));
 
         // add all "get" operators
         for (String operation : AaiGetOperation.OPERATIONS) {
-            addOperator(HttpOperator.makeOperator(NAME, operation, AaiGetOperation::new));
+            addOperator(new HttpOperator(NAME, operation, AaiGetOperation::new));
         }
     }
 }
index 4277015..6b02871 100644 (file)
@@ -32,8 +32,8 @@ import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
 import org.onap.policy.common.utils.coder.StandardCoderObject;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation;
-import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -56,10 +56,10 @@ public class AaiCustomQueryOperation extends HttpOperation<String> {
      * Constructs the object.
      *
      * @param params operation parameters
-     * @param operator operator that created this operation
+     * @param config configuration for this operation
      */
-    public AaiCustomQueryOperation(ControlLoopOperationParams params, HttpOperator operator) {
-        super(params, operator, String.class);
+    public AaiCustomQueryOperation(ControlLoopOperationParams params, HttpConfig config) {
+        super(params, config, String.class);
     }
 
     /**
@@ -91,7 +91,7 @@ public class AaiCustomQueryOperation extends HttpOperation<String> {
 
         // @formatter:off
         return handleResponse(outcome, url,
-            callback -> getOperator().getClient().put(callback, makePath(), entity, headers));
+            callback -> getClient().put(callback, makePath(), entity, headers));
         // @formatter:on
     }
 
index dd3a4d6..408c1a0 100644 (file)
@@ -31,8 +31,8 @@ import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
 import org.onap.policy.common.utils.coder.StandardCoderObject;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation;
-import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -68,11 +68,11 @@ public class AaiGetOperation extends HttpOperation<StandardCoderObject> {
      * Constructs the object.
      *
      * @param params operation parameters
-     * @param operator operator that created this operation
+     * @param config configuration for this operation
      */
-    public AaiGetOperation(ControlLoopOperationParams params, HttpOperator operator) {
-        super(params, operator, StandardCoderObject.class);
-        this.propertyPrefix = operator.getFullName() + ".";
+    public AaiGetOperation(ControlLoopOperationParams params, HttpConfig config) {
+        super(params, config, StandardCoderObject.class);
+        this.propertyPrefix = getFullName() + ".";
     }
 
     /**
@@ -98,7 +98,7 @@ public class AaiGetOperation extends HttpOperation<StandardCoderObject> {
 
         // @formatter:off
         return handleResponse(outcome, url,
-            callback -> getOperator().getClient().get(callback, makePath(), headers));
+            callback -> getClient().get(callback, makePath(), headers));
         // @formatter:on
     }
 
@@ -109,7 +109,7 @@ public class AaiGetOperation extends HttpOperation<StandardCoderObject> {
 
     @Override
     public String makePath() {
-        return (getOperator().getPath() + "/" + params.getTargetEntity());
+        return (getPath() + "/" + params.getTargetEntity());
     }
 
     /**
index 05b07fb..1ec7bea 100644 (file)
@@ -77,14 +77,14 @@ public class AaiCustomQueryOperationTest extends BasicAaiOperation<Map<String, S
      */
     @Before
     public void setUp() throws Exception {
-        super.setUp();
+        super.setUpBasic();
 
         MyTenantOperator tenantOperator = new MyTenantOperator();
 
         when(service.getActor(AaiConstants.ACTOR_NAME)).thenReturn(tenantActor);
         when(tenantActor.getOperator(AaiGetOperation.TENANT)).thenReturn(tenantOperator);
 
-        oper = new AaiCustomQueryOperation(params, operator);
+        oper = new AaiCustomQueryOperation(params, config);
     }
 
     @Test
@@ -216,7 +216,7 @@ public class AaiCustomQueryOperationTest extends BasicAaiOperation<Map<String, S
 
         @Override
         public Operation buildOperation(ControlLoopOperationParams params) {
-            return new AaiGetOperation(params, this);
+            return new AaiGetOperation(params, getCurrentConfig());
         }
 
         @Override
index 6548642..4681d9e 100644 (file)
@@ -54,8 +54,8 @@ public class AaiGetOperationTest extends BasicAaiOperation<Void> {
      */
     @Before
     public void setUp() throws Exception {
-        super.setUp();
-        oper = new AaiGetOperation(params, operator);
+        super.setUpBasic();
+        oper = new AaiGetOperation(params, config);
     }
 
     @Test
index 1ec4689..f6a2045 100644 (file)
@@ -35,12 +35,13 @@ import org.onap.policy.controlloop.ControlLoopOperation;
 import org.onap.policy.controlloop.VirtualControlLoopEvent;
 import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicActor;
 import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicActorParams;
 import org.onap.policy.controlloop.policy.Policy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
-public class AppcActorServiceProvider extends BidirectionalTopicActor {
+public class AppcActorServiceProvider extends BidirectionalTopicActor<BidirectionalTopicActorParams> {
     private static final String NAME = "APPC";
 
     private static final Logger logger = LoggerFactory.getLogger(AppcActorServiceProvider.class);
@@ -74,10 +75,10 @@ public class AppcActorServiceProvider extends BidirectionalTopicActor {
      * Constructs the object.
      */
     public AppcActorServiceProvider() {
-        super(NAME);
+        super(NAME, BidirectionalTopicActorParams.class);
 
-        addOperator(BidirectionalTopicOperator.makeOperator(NAME, ModifyConfigOperation.NAME, this,
-                        AppcOperation.SELECTOR_KEYS, ModifyConfigOperation::new));
+        addOperator(new BidirectionalTopicOperator(NAME, ModifyConfigOperation.NAME, this, AppcOperation.SELECTOR_KEYS,
+                        ModifyConfigOperation::new));
     }
 
 
index 8bc1a7f..7d4af80 100644 (file)
@@ -32,7 +32,7 @@ import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.coder.StandardCoder;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperation;
-import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.topic.SelectorKey;
 import org.onap.policy.controlloop.policy.PolicyResult;
@@ -60,10 +60,10 @@ public abstract class AppcOperation extends BidirectionalTopicOperation<Request,
      * Constructs the object.
      *
      * @param params operation parameters
-     * @param operator operator that created this operation
+     * @param config configuration for this operation
      */
-    public AppcOperation(ControlLoopOperationParams params, BidirectionalTopicOperator operator) {
-        super(params, operator, Response.class);
+    public AppcOperation(ControlLoopOperationParams params, BidirectionalTopicConfig config) {
+        super(params, config, Response.class);
     }
 
     /**
index 5839df5..b88be44 100644 (file)
@@ -27,7 +27,7 @@ import org.onap.policy.aai.AaiCqResponse;
 import org.onap.policy.appc.Request;
 import org.onap.policy.controlloop.actor.aai.AaiCustomQueryOperation;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
-import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -41,10 +41,10 @@ public class ModifyConfigOperation extends AppcOperation {
      * Constructs the object.
      *
      * @param params operation parameters
-     * @param operator operator that created this operation
+     * @param config configuration for this operation
      */
-    public ModifyConfigOperation(ControlLoopOperationParams params, BidirectionalTopicOperator operator) {
-        super(params, operator);
+    public ModifyConfigOperation(ControlLoopOperationParams params, BidirectionalTopicConfig config) {
+        super(params, config);
     }
 
     /**
index 8a86b34..218a4e5 100644 (file)
@@ -48,7 +48,7 @@ public class AppcOperationTest extends BasicAppcOperation {
     public void setUp() throws Exception {
         super.setUp();
 
-        oper = new AppcOperation(params, operator) {
+        oper = new AppcOperation(params, config) {
             @Override
             protected Request makeRequest(int attempt) {
                 return oper.makeRequest(attempt, MY_VNF);
@@ -81,7 +81,7 @@ public class AppcOperationTest extends BasicAppcOperation {
 
         // repeat using a null payload
         params = params.toBuilder().payload(null).build();
-        oper = new AppcOperation(params, operator) {
+        oper = new AppcOperation(params, config) {
             @Override
             protected Request makeRequest(int attempt) {
                 return oper.makeRequest(attempt, MY_VNF);
@@ -111,7 +111,7 @@ public class AppcOperationTest extends BasicAppcOperation {
 
         params = params.toBuilder().payload(payload).build();
 
-        oper = new AppcOperation(params, operator) {
+        oper = new AppcOperation(params, config) {
             @Override
             protected Request makeRequest(int attempt) {
                 return oper.makeRequest(attempt, MY_VNF);
index 3d4a046..ed3e7a7 100644 (file)
@@ -32,7 +32,6 @@ import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
 import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
 import org.onap.policy.appc.Response;
 import org.onap.policy.appc.ResponseCode;
 import org.onap.policy.appc.ResponseStatus;
@@ -40,8 +39,8 @@ import org.onap.policy.common.utils.coder.StandardCoderObject;
 import org.onap.policy.controlloop.actor.test.BasicBidirectionalTopicOperation;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.Util;
-import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator;
-import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.impl.OperationMaker;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicConfig;
 import org.onap.policy.controlloop.policy.PolicyResult;
 import org.onap.policy.controlloop.policy.Target;
 import org.powermock.reflect.Whitebox;
@@ -82,7 +81,7 @@ public abstract class BasicAppcOperation extends BasicBidirectionalTopicOperatio
      * Initializes mocks and sets up.
      */
     public void setUp() throws Exception {
-        super.setUp();
+        super.setUpBasic();
 
         response = new Response();
 
@@ -123,12 +122,12 @@ public abstract class BasicAppcOperation extends BasicBidirectionalTopicOperatio
      * @param expectedText text expected in the exception message
      */
     protected void verifyMissing(String fieldName, String expectedText,
-                    BiFunction<ControlLoopOperationParams, BidirectionalTopicOperator, AppcOperation> maker) {
+                    OperationMaker<BidirectionalTopicConfig, AppcOperation> maker) {
 
         makeContext();
         enrichment.remove(fieldName);
 
-        AppcOperation oper = maker.apply(params, operator);
+        AppcOperation oper = maker.apply(params, config);
 
         assertThatIllegalArgumentException().isThrownBy(() -> Whitebox.invokeMethod(oper, "makeRequest", 1))
                         .withMessageContaining("missing").withMessageContaining(expectedText);
index 34bbec3..5ff7897 100644 (file)
@@ -54,7 +54,7 @@ public class ModifyConfigOperationTest extends BasicAppcOperation {
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        oper = new ModifyConfigOperation(params, operator);
+        oper = new ModifyConfigOperation(params, config);
     }
 
     @Test
@@ -72,7 +72,7 @@ public class ModifyConfigOperationTest extends BasicAppcOperation {
 
         AtomicBoolean guardStarted = new AtomicBoolean();
 
-        oper = new ModifyConfigOperation(params, operator) {
+        oper = new ModifyConfigOperation(params, config) {
             @Override
             protected CompletableFuture<OperationOutcome> startGuardAsync() {
                 guardStarted.set(true);
diff --git a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorParams.java b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorParams.java
new file mode 100644 (file)
index 0000000..b8eb85c
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.guard;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpActorParams;
+
+@Getter
+@Setter
+@EqualsAndHashCode(callSuper = true)
+public class GuardActorParams extends HttpActorParams {
+    public static final String DEFAULT_ACTION = "guard";
+
+    /*
+     * Optional, default values that are used if missing from the operation-specific
+     * parameters.
+     */
+
+    private String onapName;
+    private String onapComponent;
+    private String onapInstance;
+    private String action = DEFAULT_ACTION;
+}
index 104c383..ea08d13 100644 (file)
@@ -25,7 +25,7 @@ package org.onap.policy.controlloop.actor.guard;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
 
-public class GuardActorServiceProvider extends HttpActor {
+public class GuardActorServiceProvider extends HttpActor<GuardActorParams> {
     // actor name
     public static final String NAME = "GUARD";
 
@@ -33,9 +33,8 @@ public class GuardActorServiceProvider extends HttpActor {
      * Constructs the object.
      */
     public GuardActorServiceProvider() {
-        super(NAME);
+        super(NAME, GuardActorParams.class);
 
-        addOperator(HttpOperator.makeOperator(NAME, GuardOperation.NAME,
-                        GuardOperation::new));
+        addOperator(new HttpOperator(NAME, GuardOperation.NAME, GuardOperation::new));
     }
 }
diff --git a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardConfig.java b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardConfig.java
new file mode 100644 (file)
index 0000000..c6bf326
--- /dev/null
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.guard;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
+
+/**
+ * Configuration for Guard Operators.
+ */
+public class GuardConfig extends HttpConfig {
+    private final Map<String, Object> defaultRequest = new LinkedHashMap<>();
+
+    /**
+     * Constructs the object.
+     *
+     * @param blockingExecutor executor to be used for tasks that may perform blocking I/O
+     * @param params operator parameters
+     * @param clientFactory factory from which to obtain the {@link HttpClient}
+     */
+    public GuardConfig(Executor blockingExecutor, GuardParams params, HttpClientFactory clientFactory) {
+        super(blockingExecutor, params, clientFactory);
+
+        addProperty("ONAPComponent", params.getOnapComponent());
+        addProperty("ONAPInstance", params.getOnapInstance());
+        addProperty("ONAPName", params.getOnapName());
+        addProperty("action", params.getAction());
+    }
+
+    /**
+     * Adds a property to the default request, if the value is not {@code null}.
+     *
+     * @param key property key
+     * @param value property value, or {@code null}
+     */
+    private void addProperty(String key, String value) {
+        if (value != null) {
+            defaultRequest.put(key, value);
+        }
+    }
+
+    /**
+     * Creates a new request, with the default values.
+     *
+     * @return a new request map
+     */
+    public Map<String, Object> makeRequest() {
+        return new LinkedHashMap<>(defaultRequest);
+    }
+}
index 941838f..453a3e3 100644 (file)
@@ -33,8 +33,8 @@ import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.Util;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation;
-import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.controlloop.policy.PolicyResult;
 import org.onap.policy.models.decisions.concepts.DecisionRequest;
 import org.onap.policy.models.decisions.concepts.DecisionResponse;
@@ -74,15 +74,18 @@ public class GuardOperation extends HttpOperation<DecisionResponse> {
      */
     public static final String RESOURCE_PREFIX = "resource.";
 
+    private final GuardConfig config;
+
 
     /**
      * Constructs the object.
      *
      * @param params operation parameters
-     * @param operator operator that created this operation
+     * @param config configuration for this operation
      */
-    public GuardOperation(ControlLoopOperationParams params, HttpOperator operator) {
-        super(params, operator, DecisionResponse.class);
+    public GuardOperation(ControlLoopOperationParams params, HttpConfig config) {
+        super(params, config, DecisionResponse.class);
+        this.config = (GuardConfig) config;
     }
 
     @Override
@@ -101,7 +104,7 @@ public class GuardOperation extends HttpOperation<DecisionResponse> {
 
         // @formatter:off
         return handleResponse(outcome, url,
-            callback -> getOperator().getClient().post(callback, makePath(), entity, headers));
+            callback -> getClient().post(callback, makePath(), entity, headers));
         // @formatter:on
     }
 
@@ -121,7 +124,7 @@ public class GuardOperation extends HttpOperation<DecisionResponse> {
          * appropriate field.
          */
 
-        Map<String, Object> req = new LinkedHashMap<>();
+        Map<String, Object> req = config.makeRequest();
         Map<String, Object> resource = new LinkedHashMap<>();
 
         for (Entry<String, String> ent : params.getPayload().entrySet()) {
@@ -141,7 +144,6 @@ public class GuardOperation extends HttpOperation<DecisionResponse> {
             }
         }
 
-        req.putIfAbsent("action", "guard");
         req.computeIfAbsent("requestId", key -> UUID.randomUUID().toString());
         req.put(RESOURCE, resource);
 
diff --git a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardOperator.java b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardOperator.java
new file mode 100644 (file)
index 0000000..b3a47fd
--- /dev/null
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.guard;
+
+import java.util.Map;
+import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.controlloop.actorserviceprovider.Util;
+import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation;
+import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
+import org.onap.policy.controlloop.actorserviceprovider.impl.OperationMaker;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.ParameterValidationRuntimeException;
+
+/**
+ * Guard Operator.
+ */
+public class GuardOperator extends HttpOperator {
+
+    public GuardOperator(String actorName, String name,
+                    @SuppressWarnings("rawtypes") OperationMaker<HttpConfig, HttpOperation> operationMaker) {
+        super(actorName, name, operationMaker);
+    }
+
+    @Override
+    protected HttpConfig makeConfiguration(Map<String, Object> parameters) {
+        GuardParams params = Util.translate(getFullName(), parameters, GuardParams.class);
+        ValidationResult result = params.validate(getFullName());
+        if (!result.isValid()) {
+            throw new ParameterValidationRuntimeException("invalid parameters", result);
+        }
+
+        return new GuardConfig(getBlockingExecutor(), params, getClientFactory());
+    }
+}
diff --git a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardParams.java b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardParams.java
new file mode 100644 (file)
index 0000000..2514825
--- /dev/null
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.guard;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.SuperBuilder;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
+
+/**
+ * Default values to be included if not specified in the payload.
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@SuperBuilder(toBuilder = true)
+public class GuardParams extends HttpParams {
+
+    /*
+     * Optional, default values that are used if missing from the payload.
+     */
+
+    private String onapName;
+    private String onapComponent;
+    private String onapInstance;
+    private String action;
+}
diff --git a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorParamsTest.java b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardActorParamsTest.java
new file mode 100644 (file)
index 0000000..cd9f4e3
--- /dev/null
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.guard;
+
+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.assertTrue;
+
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.function.Consumer;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.controlloop.actorserviceprovider.Util;
+
+public class GuardActorParamsTest {
+    private static final String CONTAINER = "my-container";
+    private static final String CLIENT = "my-client";
+    private static final int TIMEOUT = 10;
+    private static final String ONAP_NAME = "onap-nap";
+    private static final String ONAP_COMP = "onap-component";
+    private static final String ONAP_INST = "onap-instance";
+    private static final String MY_ACTION = "my-action";
+
+    private static final String PATH1 = "path #1";
+    private static final String PATH2 = "path #2";
+    private static final String URI1 = "uri #1";
+    private static final String URI2 = "uri #2";
+
+    private Map<String, Map<String, Object>> operations;
+    private GuardActorParams params;
+
+    /**
+     * Initializes {@link #operations} with two items and {@link params} with a fully
+     * populated object.
+     */
+    @Before
+    public void setUp() {
+        operations = new TreeMap<>();
+        operations.put(PATH1, Map.of("path", URI1));
+        operations.put(PATH2, Map.of("path", URI2));
+
+        params = makeGuardActorParams();
+    }
+
+    @Test
+    public void testValidate() {
+        assertTrue(params.validate(CONTAINER).isValid());
+
+        // only a few fields are required
+        GuardActorParams sparse = Util.translate(CONTAINER, Map.of("operation", operations), GuardActorParams.class);
+        assertTrue(sparse.validate(CONTAINER).isValid());
+
+        assertEquals(GuardActorParams.DEFAULT_ACTION, sparse.getAction());
+
+        // check fields from superclass
+        testValidateField("operation", "null", params2 -> params2.setOperation(null));
+        testValidateField("timeoutSec", "minimum", params2 -> params2.setTimeoutSec(-1));
+    }
+
+    private void testValidateField(String fieldName, String expected, Consumer<GuardActorParams> makeInvalid) {
+
+        // original params should be valid
+        ValidationResult result = params.validate(CONTAINER);
+        assertTrue(fieldName, result.isValid());
+
+        // make invalid params
+        GuardActorParams params2 = makeGuardActorParams();
+        makeInvalid.accept(params2);
+        result = params2.validate(CONTAINER);
+        assertFalse(fieldName, result.isValid());
+        assertThat(result.getResult()).contains(CONTAINER).contains(fieldName).contains(expected);
+    }
+
+    private GuardActorParams makeGuardActorParams() {
+        GuardActorParams params2 = new GuardActorParams();
+        params2.setClientName(CLIENT);
+        params2.setTimeoutSec(TIMEOUT);
+        params2.setOperation(operations);
+
+        params2.setOnapName(ONAP_NAME);
+        params2.setOnapComponent(ONAP_COMP);
+        params2.setOnapInstance(ONAP_INST);
+        params2.setAction(MY_ACTION);
+
+        return params2;
+    }
+}
diff --git a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardConfigTest.java b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardConfigTest.java
new file mode 100644 (file)
index 0000000..f94d122
--- /dev/null
@@ -0,0 +1,92 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.guard;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.Executor;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
+import org.onap.policy.controlloop.actorserviceprovider.Util;
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+
+public class GuardConfigTest {
+    private static final String MY_CLIENT = "my-client";
+    private static final String PATH = "my-path";
+    private static final int TIMEOUT = 10;
+    private static final String ONAP_NAME = "onap-nap";
+    private static final String ONAP_COMP = "onap-component";
+    private static final String ONAP_INST = "onap-instance";
+    private static final String MY_ACTION = "my-action";
+
+    @Mock
+    private HttpClient client;
+    @Mock
+    private HttpClientFactory factory;
+    @Mock
+    private Executor executor;
+
+    private GuardParams params;
+    private GuardConfig config;
+
+    /**
+     * Sets up.
+     */
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(factory.get(MY_CLIENT)).thenReturn(client);
+
+        params = GuardParams.builder().onapName(ONAP_NAME).onapComponent(ONAP_COMP).onapInstance(ONAP_INST)
+                        .action(MY_ACTION).clientName(MY_CLIENT).path(PATH).timeoutSec(TIMEOUT).build();
+        config = new GuardConfig(executor, params, factory);
+    }
+
+    @Test
+    public void test() {
+        DecisionRequest expected = new DecisionRequest();
+        expected.setOnapComponent(ONAP_COMP);
+        expected.setOnapInstance(ONAP_INST);
+        expected.setOnapName(ONAP_NAME);
+        expected.setAction(MY_ACTION);
+
+        DecisionRequest actual = Util.translate("", config.makeRequest(), DecisionRequest.class);
+        assertEquals(expected, actual);
+
+        // check value from superclass
+        assertSame(executor, config.getBlockingExecutor());
+        assertSame(client, config.getClient());
+
+        // repeat, with minimal parameters
+        params = GuardParams.builder().clientName(MY_CLIENT).path(PATH).timeoutSec(TIMEOUT).build();
+        config = new GuardConfig(executor, params, factory);
+
+        actual = Util.translate("", config.makeRequest(), DecisionRequest.class);
+        assertEquals(new DecisionRequest(), actual);
+    }
+}
index 5051060..406cdd0 100644 (file)
@@ -25,10 +25,10 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.concurrent.CompletableFuture;
@@ -51,9 +51,15 @@ public class GuardOperationTest extends BasicHttpOperation<DecisionRequest> {
      */
     @Before
     public void setUp() throws Exception {
-        super.setUp();
+        super.setUpBasic();
 
-        oper = new GuardOperation(params, operator);
+        GuardConfig cguard = mock(GuardConfig.class);
+        when(cguard.makeRequest()).thenAnswer(args -> new TreeMap<>(Map.of("action", "guard")));
+
+        config = cguard;
+        initConfig();
+
+        oper = new GuardOperation(params, config);
     }
 
     @Test
@@ -78,9 +84,6 @@ public class GuardOperationTest extends BasicHttpOperation<DecisionRequest> {
         executor.runAll(100);
         assertTrue(future2.isDone());
 
-        DecisionRequest request = requestCaptor.getValue().getEntity();
-        verifyRequest("makeReqStd.json", request, "requestId");
-
         assertEquals(PolicyResult.SUCCESS, future2.get().getResult());
     }
 
@@ -102,7 +105,7 @@ public class GuardOperationTest extends BasicHttpOperation<DecisionRequest> {
 
         // null payload - start with fresh parameters and operation
         params = params.toBuilder().payload(null).build();
-        oper = new GuardOperation(params, operator);
+        oper = new GuardOperation(params, config);
         assertThatIllegalArgumentException().isThrownBy(() -> oper.makeRequest());
     }
 
@@ -156,7 +159,7 @@ public class GuardOperationTest extends BasicHttpOperation<DecisionRequest> {
         req.setRequestId("my-request-id");
 
         @SuppressWarnings("unchecked")
-        Map<String, String> map = Util.translate("", req, LinkedHashMap.class);
+        Map<String, String> map = Util.translate("", req, TreeMap.class);
 
         // add resources
         map.put(GuardOperation.RESOURCE_PREFIX + "actor", "resource-actor");
diff --git a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardOperatorTest.java b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardOperatorTest.java
new file mode 100644 (file)
index 0000000..3626332
--- /dev/null
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.guard;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
+import org.onap.policy.controlloop.actorserviceprovider.Util;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.ParameterValidationRuntimeException;
+
+public class GuardOperatorTest {
+    private static final String ACTOR = "my-actor";
+    private static final String OPERATION = "my-name";
+    private static final String CLIENT = "my-client";
+    private static final String PATH = "my-path";
+    private static final int TIMEOUT = 10;
+    private static final String ONAP_NAME = "onap-nap";
+    private static final String ONAP_COMP = "onap-component";
+    private static final String ONAP_INST = "onap-instance";
+    private static final String MY_ACTION = "my-action";
+
+    @Mock
+    private HttpClient client;
+
+    @Mock
+    private HttpClientFactory factory;
+
+
+    private GuardOperator oper;
+
+    /**
+     * Initializes fields, including {@link #oper}, and resets the static fields used by
+     * the REST server.
+     */
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(factory.get(CLIENT)).thenReturn(client);
+
+        oper = new MyOperator();
+
+        GuardParams params = GuardParams.builder().onapName(ONAP_NAME).onapComponent(ONAP_COMP).onapInstance(ONAP_INST)
+                        .action(MY_ACTION).clientName(CLIENT).path(PATH).timeoutSec(TIMEOUT).build();
+        Map<String, Object> paramMap = Util.translateToMap(OPERATION, params);
+        oper.configure(paramMap);
+
+        assertTrue(oper.makeConfiguration(paramMap) instanceof GuardConfig);
+    }
+
+    @Test
+    public void testConstructor() {
+        assertEquals(ACTOR, oper.getActorName());
+        assertEquals(OPERATION, oper.getName());
+        assertEquals(ACTOR + "." + OPERATION, oper.getFullName());
+    }
+
+    @Test
+    public void testDoConfigure_testGetters() {
+        assertTrue(oper.getCurrentConfig() instanceof GuardConfig);
+
+        // test invalid parameters
+        Map<String, Object> paramMap2 = Util.translateToMap(OPERATION, GuardParams.builder().build());
+        assertThatThrownBy(() -> oper.configure(paramMap2)).isInstanceOf(ParameterValidationRuntimeException.class);
+    }
+
+
+    private class MyOperator extends GuardOperator {
+        public MyOperator() {
+            super(ACTOR, OPERATION, null);
+        }
+
+        @Override
+        protected HttpClientFactory getClientFactory() {
+            return factory;
+        }
+    }
+}
diff --git a/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardParamsTest.java b/models-interactions/model-actors/actor.guard/src/test/java/org/onap/policy/controlloop/actor/guard/GuardParamsTest.java
new file mode 100644 (file)
index 0000000..b414885
--- /dev/null
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.guard;
+
+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.assertTrue;
+
+import java.util.function.Function;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.controlloop.actor.guard.GuardParams.GuardParamsBuilder;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams.HttpParamsBuilder;
+
+public class GuardParamsTest {
+    private static final String CONTAINER = "my-container";
+    private static final String CLIENT = "my-client";
+    private static final String PATH = "my-path";
+    private static final int TIMEOUT = 10;
+    private static final String ONAP_NAME = "onap-nap";
+    private static final String ONAP_COMP = "onap-component";
+    private static final String ONAP_INST = "onap-instance";
+    private static final String MY_ACTION = "my-action";
+
+    private GuardParams params;
+
+    @Before
+    public void setUp() {
+        params = GuardParams.builder().onapName(ONAP_NAME).onapComponent(ONAP_COMP).onapInstance(ONAP_INST)
+                        .action(MY_ACTION).clientName(CLIENT).path(PATH).timeoutSec(TIMEOUT).build();
+    }
+
+    @Test
+    public void testValidate() {
+        assertTrue(params.validate(CONTAINER).isValid());
+
+        // validate one of the superclass fields
+        testValidateField("clientName", "null", bldr -> bldr.clientName(null));
+
+        // validate with mostly empty params
+        params = GuardParams.builder().clientName(CLIENT).path(PATH).timeoutSec(TIMEOUT).build();
+        assertTrue(params.validate(CONTAINER).isValid());
+    }
+
+    @Test
+    public void testBuilder_testToBuilder() {
+        assertEquals(CLIENT, params.getClientName());
+
+        assertEquals(ONAP_NAME, params.getOnapName());
+        assertEquals(ONAP_COMP, params.getOnapComponent());
+        assertEquals(ONAP_INST, params.getOnapInstance());
+        assertEquals(MY_ACTION, params.getAction());
+
+        assertEquals(params, params.toBuilder().build());
+    }
+
+    private void testValidateField(String fieldName, String expected,
+                    @SuppressWarnings("rawtypes") Function<GuardParamsBuilder, HttpParamsBuilder> makeInvalid) {
+
+        // original params should be valid
+        ValidationResult result = params.validate(CONTAINER);
+        assertTrue(fieldName, result.isValid());
+
+        // make invalid params
+        result = makeInvalid.apply(params.toBuilder()).build().validate(CONTAINER);
+        assertFalse(fieldName, result.isValid());
+        assertThat(result.getResult()).contains(fieldName).contains(expected);
+    }
+}
index 5437ae8..6ae8867 100644 (file)
@@ -1,9 +1,9 @@
 {
-  "ONAPName": "my-onap-name",
   "ONAPComponent": "my-onap-component",
   "ONAPInstance": "my-onap-instance",
-  "requestId": "abcdefghi",
+  "ONAPName": "my-onap-name",
   "action": "my-action",
+  "requestId": "abcdefghi",
   "resource": {
     "actor": "resource-actor",
     "operation": "resource-operation"
index 26cdfad..ff18813 100644 (file)
@@ -23,8 +23,8 @@ package org.onap.policy.controlloop.actor.sdnc;
 import java.util.UUID;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
-import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
 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.sdnc.SdncHealRequestHeaderInfo;
 import org.onap.policy.sdnc.SdncHealRequestInfo;
@@ -49,10 +49,10 @@ public class BandwidthOnDemandOperation extends SdncOperation {
      * Constructs the object.
      *
      * @param params operation parameters
-     * @param operator operator that created this operation
+     * @param config configuration for this operation
      */
-    public BandwidthOnDemandOperation(ControlLoopOperationParams params, HttpOperator operator) {
-        super(params, operator);
+    public BandwidthOnDemandOperation(ControlLoopOperationParams params, HttpConfig config) {
+        super(params, config);
     }
 
     @Override
index f255f3e..753da1b 100644 (file)
@@ -23,8 +23,8 @@ package org.onap.policy.controlloop.actor.sdnc;
 import java.util.UUID;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
-import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
 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.sdnc.SdncHealRequest;
 import org.onap.policy.sdnc.SdncHealRequestHeaderInfo;
@@ -45,10 +45,10 @@ public class RerouteOperation extends SdncOperation {
      * Constructs the object.
      *
      * @param params operation parameters
-     * @param operator operator that created this operation
+     * @param config configuration for this operation
      */
-    public RerouteOperation(ControlLoopOperationParams params, HttpOperator operator) {
-        super(params, operator);
+    public RerouteOperation(ControlLoopOperationParams params, HttpConfig config) {
+        super(params, config);
     }
 
     @Override
index 99a4fda..cd9ad1a 100644 (file)
@@ -31,6 +31,7 @@ import org.onap.policy.controlloop.ControlLoopOperation;
 import org.onap.policy.controlloop.VirtualControlLoopEvent;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpActorParams;
 import org.onap.policy.controlloop.policy.Policy;
 import org.onap.policy.sdnc.SdncHealNetworkInfo;
 import org.onap.policy.sdnc.SdncHealRequest;
@@ -46,7 +47,7 @@ import org.onap.policy.sdnc.SdncRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class SdncActorServiceProvider extends HttpActor {
+public class SdncActorServiceProvider extends HttpActor<HttpActorParams> {
     private static final Logger logger = LoggerFactory.getLogger(SdncActorServiceProvider.class);
 
     public static final String NAME = "SDNC";
@@ -75,13 +76,10 @@ public class SdncActorServiceProvider extends HttpActor {
      * Constructs the object.
      */
     public SdncActorServiceProvider() {
-        super(NAME);
+        super(NAME, HttpActorParams.class);
 
-        addOperator(HttpOperator.makeOperator(NAME, RerouteOperation.NAME,
-                        RerouteOperation::new));
-
-        addOperator(HttpOperator.makeOperator(NAME, BandwidthOnDemandOperation.NAME,
-                        BandwidthOnDemandOperation::new));
+        addOperator(new HttpOperator(NAME, RerouteOperation.NAME, RerouteOperation::new));
+        addOperator(new HttpOperator(NAME, BandwidthOnDemandOperation.NAME, BandwidthOnDemandOperation::new));
     }
 
 
index f6cacd9..a83faa7 100644 (file)
@@ -29,8 +29,8 @@ import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation;
-import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.sdnc.SdncRequest;
 import org.onap.policy.sdnc.SdncResponse;
 
@@ -43,10 +43,10 @@ public abstract class SdncOperation extends HttpOperation<SdncResponse> {
      * Constructs the object.
      *
      * @param params operation parameters
-     * @param operator operator that created this operation
+     * @param config configuration for this operation
      */
-    public SdncOperation(ControlLoopOperationParams params, HttpOperator operator) {
-        super(params, operator, SdncResponse.class);
+    public SdncOperation(ControlLoopOperationParams params, HttpConfig config) {
+        super(params, config, SdncResponse.class);
     }
 
     /**
@@ -73,7 +73,7 @@ public abstract class SdncOperation extends HttpOperation<SdncResponse> {
 
         // @formatter:off
         return handleResponse(outcome, url,
-            callback -> getOperator().getClient().post(callback, makePath(), entity, headers));
+            callback -> getClient().post(callback, makePath(), entity, headers));
         // @formatter:on
     }
 
index e849062..ade2513 100644 (file)
@@ -42,7 +42,7 @@ public class BandwidthOnDemandOperationTest extends BasicSdncOperation {
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        oper = new BandwidthOnDemandOperation(params, operator);
+        oper = new BandwidthOnDemandOperation(params, config);
     }
 
     @Test
index c1278f1..50e9749 100644 (file)
@@ -32,12 +32,11 @@ import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
-import java.util.function.BiFunction;
 import org.onap.policy.common.utils.coder.StandardCoder;
 import org.onap.policy.controlloop.actor.test.BasicHttpOperation;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
-import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
-import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.impl.OperationMaker;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.controlloop.policy.PolicyResult;
 import org.onap.policy.sdnc.SdncRequest;
 import org.onap.policy.sdnc.SdncResponse;
@@ -76,7 +75,7 @@ public abstract class BasicSdncOperation extends BasicHttpOperation<SdncRequest>
      * Initializes mocks and sets up.
      */
     public void setUp() throws Exception {
-        super.setUp();
+        super.setUpBasic();
 
         response = new SdncResponse();
 
@@ -119,12 +118,12 @@ public abstract class BasicSdncOperation extends BasicHttpOperation<SdncRequest>
      * @param expectedText text expected in the exception message
      */
     protected void verifyMissing(String fieldName, String expectedText,
-                    BiFunction<ControlLoopOperationParams, HttpOperator, SdncOperation> maker) {
+                    OperationMaker<HttpConfig, SdncOperation> maker) {
 
         makeContext();
         enrichment.remove(fieldName);
 
-        SdncOperation oper = maker.apply(params, operator);
+        SdncOperation oper = maker.apply(params, config);
 
         assertThatIllegalArgumentException().isThrownBy(() -> Whitebox.invokeMethod(oper, "makeRequest", 1))
                         .withMessageContaining("missing").withMessageContaining(expectedText);
index f0836b9..30ddd87 100644 (file)
@@ -42,7 +42,7 @@ public class RerouteOperationTest extends BasicSdncOperation {
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        oper = new RerouteOperation(params, operator);
+        oper = new RerouteOperation(params, config);
     }
 
     @Test
index e0825e1..b87ed2c 100644 (file)
@@ -42,7 +42,7 @@ public class SdncOperationTest extends BasicSdncOperation {
     public void setUp() throws Exception {
         super.setUp();
 
-        oper = new SdncOperation(params, operator) {
+        oper = new SdncOperation(params, config) {
             @Override
             protected SdncRequest makeRequest(int attempt) {
                 return request;
index c7c6b00..1dbad62 100644 (file)
@@ -98,7 +98,7 @@ public class SoActorServiceProvider extends ActorImpl {
     public SoActorServiceProvider() {
         super(NAME);
 
-        addOperator(SoOperator.makeSoOperator(NAME, VfModuleCreate.NAME, VfModuleCreate::new));
+        addOperator(new SoOperator(NAME, VfModuleCreate.NAME, VfModuleCreate::new));
     }
 
     // TODO old code: remove lines down to **HERE**
diff --git a/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoConfig.java b/models-interactions/model-actors/actor.so/src/main/java/org/onap/policy/controlloop/actor/so/SoConfig.java
new file mode 100644 (file)
index 0000000..959cd45
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.so;
+
+import java.util.concurrent.Executor;
+import lombok.Getter;
+import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
+
+@Getter
+public class SoConfig extends HttpConfig {
+
+    /**
+     * Path to use for the "get" request. A trailing "/" is added, if it is missing.
+     */
+    private String pathGet;
+
+    /**
+     * Maximum number of "get" requests permitted, after the initial request, to retrieve
+     * the response.
+     */
+    private int maxGets;
+
+    /**
+     * Time, in seconds, to wait between issuing "get" requests.
+     */
+    private int waitSecGet;
+
+
+    /**
+     * Constructs the object.
+     *
+     * @param blockingExecutor executor to be used for tasks that may perform blocking I/O
+     * @param params operator parameters
+     * @param clientFactory factory from which to obtain the {@link HttpClient}
+     */
+    public SoConfig(Executor blockingExecutor, SoParams params, HttpClientFactory clientFactory) {
+        super(blockingExecutor, params, clientFactory);
+
+        this.pathGet = params.getPathGet() + (params.getPathGet().endsWith("/") ? "" : "/");
+        this.maxGets = params.getMaxGets();
+        this.waitSecGet = params.getWaitSecGet();
+    }
+}
index 510a737..d8d960e 100644 (file)
@@ -41,6 +41,7 @@ import org.onap.policy.common.utils.coder.StandardCoder;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 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.policy.PolicyResult;
 import org.onap.policy.controlloop.policy.Target;
 import org.onap.policy.so.SoModelInfo;
@@ -68,8 +69,7 @@ public abstract class SoOperation extends HttpOperation<SoResponse> {
     public static final String REQ_PARAM_NM = "requestParameters";
     public static final String CONFIG_PARAM_NM = "configurationParameters";
 
-    @Getter
-    private final SoOperator operator;
+    private final SoConfig config;
 
     /**
      * Number of "get" requests issued so far, on the current operation attempt.
@@ -82,11 +82,11 @@ public abstract class SoOperation extends HttpOperation<SoResponse> {
      * Constructs the object.
      *
      * @param params operation parameters
-     * @param operator operator that created this operation
+     * @param config configuration for this operation
      */
-    public SoOperation(ControlLoopOperationParams params, SoOperator operator) {
-        super(params, operator, SoResponse.class);
-        this.operator = operator;
+    public SoOperation(ControlLoopOperationParams params, HttpConfig config) {
+        super(params, config, SoResponse.class);
+        this.config = (SoConfig) config;
     }
 
     /**
@@ -134,9 +134,8 @@ public abstract class SoOperation extends HttpOperation<SoResponse> {
         }
 
         // see if the limit for the number of "gets" has been reached
-        if (getCount++ >= operator.getMaxGets()) {
-            logger.warn("{}: execeeded 'get' limit {} for {}", getFullName(), operator.getMaxGets(),
-                            params.getRequestId());
+        if (getCount++ >= getMaxGets()) {
+            logger.warn("{}: execeeded 'get' limit {} for {}", getFullName(), getMaxGets(), params.getRequestId());
             setOutcome(outcome, PolicyResult.FAILURE_TIMEOUT);
             outcome.setMessage(SO_RESPONSE_CODE + " " + outcome.getMessage());
             return CompletableFuture.completedFuture(outcome);
@@ -155,15 +154,15 @@ public abstract class SoOperation extends HttpOperation<SoResponse> {
      * @return a future that can be used to cancel the "get" request or await its response
      */
     private CompletableFuture<OperationOutcome> issueGet(OperationOutcome outcome, SoResponse response) {
-        String path = operator.getPathGet() + response.getRequestReferences().getRequestId();
-        String url = operator.getClient().getBaseUrl() + path;
+        String path = getPathGet() + response.getRequestReferences().getRequestId();
+        String url = getClient().getBaseUrl() + path;
 
         logger.debug("{}: 'get' count {} for {}", getFullName(), getCount, params.getRequestId());
 
         logMessage(EventType.OUT, CommInfrastructure.REST, url, null);
 
         // TODO should this use "path" or the full "url"?
-        return handleResponse(outcome, url, callback -> operator.getClient().get(callback, path, null));
+        return handleResponse(outcome, url, callback -> getClient().get(callback, path, null));
     }
 
     /**
@@ -335,6 +334,18 @@ public abstract class SoOperation extends HttpOperation<SoResponse> {
      * @return the wait time, in milliseconds, between "get" requests
      */
     public long getWaitMsGet() {
-        return TimeUnit.MILLISECONDS.convert(operator.getWaitSecGet(), TimeUnit.SECONDS);
+        return TimeUnit.MILLISECONDS.convert(getWaitSecGet(), TimeUnit.SECONDS);
+    }
+
+    public int getMaxGets() {
+        return config.getMaxGets();
+    }
+
+    public String getPathGet() {
+        return config.getPathGet();
+    }
+
+    public int getWaitSecGet() {
+        return config.getWaitSecGet();
     }
 }
index 011201f..b8d0e65 100644 (file)
 package org.onap.policy.controlloop.actor.so;
 
 import java.util.Map;
-import java.util.function.BiFunction;
-import lombok.Getter;
 import org.onap.policy.common.parameters.ValidationResult;
-import org.onap.policy.controlloop.actorserviceprovider.Operation;
 import org.onap.policy.controlloop.actorserviceprovider.Util;
+import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation;
 import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
-import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.impl.OperationMaker;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ParameterValidationRuntimeException;
 
-@Getter
-public abstract class SoOperator extends HttpOperator {
-
-    /**
-     * Path to use for the "get" request. A trailing "/" is added, if it is missing.
-     */
-    private String pathGet;
-
-    /**
-     * Maximum number of "get" requests permitted, after the initial request, to retrieve
-     * the response.
-     */
-    private int maxGets;
-
-    /**
-     * Time, in seconds, to wait between issuing "get" requests.
-     */
-    private int waitSecGet;
-
+/**
+ * SO Operator.
+ */
+public class SoOperator extends HttpOperator {
 
-    public SoOperator(String actorName, String name) {
-        super(actorName, name);
+    public SoOperator(String actorName, String name,
+                    @SuppressWarnings("rawtypes") OperationMaker<HttpConfig, HttpOperation> operationMaker) {
+        super(actorName, name, operationMaker);
     }
 
     @Override
-    protected void doConfigure(Map<String, Object> parameters) {
+    protected HttpConfig makeConfiguration(Map<String, Object> parameters) {
         SoParams params = Util.translate(getFullName(), parameters, SoParams.class);
         ValidationResult result = params.validate(getFullName());
         if (!result.isValid()) {
             throw new ParameterValidationRuntimeException("invalid parameters", result);
         }
 
-        this.pathGet = params.getPathGet() + (params.getPathGet().endsWith("/") ? "" : "/");
-        this.maxGets = params.getMaxGets();
-        this.waitSecGet = params.getWaitSecGet();
-
-        super.doConfigure(params);
-    }
-
-    /**
-     * Makes an operator that will construct operations.
-     *
-     * @param actorName actor name
-     * @param operation operation name
-     * @param operationMaker function to make an operation
-     * @return a new operator
-     */
-    public static SoOperator makeSoOperator(String actorName, String operation,
-                    BiFunction<ControlLoopOperationParams, SoOperator, SoOperation> operationMaker) {
-
-        return new SoOperator(actorName, operation) {
-            @Override
-            public Operation buildOperation(ControlLoopOperationParams params) {
-                return operationMaker.apply(params, this);
-            }
-        };
+        return new SoConfig(getBlockingExecutor(), params, getClientFactory());
     }
 }
index f356dce..c17d252 100644 (file)
@@ -35,6 +35,7 @@ import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
 import org.onap.policy.controlloop.actor.aai.AaiCustomQueryOperation;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.so.SoCloudConfiguration;
 import org.onap.policy.so.SoModelInfo;
 import org.onap.policy.so.SoOperationType;
@@ -47,8 +48,8 @@ import org.onap.policy.so.SoRequestParameters;
 public class VfModuleCreate extends SoOperation {
     public static final String NAME = "VF Module Create";
 
-    public VfModuleCreate(ControlLoopOperationParams params, SoOperator operator) {
-        super(params, operator);
+    public VfModuleCreate(ControlLoopOperationParams params, HttpConfig config) {
+        super(params, config);
     }
 
     /**
@@ -75,13 +76,13 @@ public class VfModuleCreate extends SoOperation {
         SoRequest request = pair.getRight();
 
         Entity<SoRequest> entity = Entity.entity(request, MediaType.APPLICATION_JSON);
-        String url = getOperator().getClient().getBaseUrl() + path;
+        String url = getClient().getBaseUrl() + path;
 
         logMessage(EventType.OUT, CommInfrastructure.REST, url, request);
 
         // TODO should this use "path" or the full "url"?
 
-        return handleResponse(outcome, url, callback -> getOperator().getClient().post(callback, path, entity, null));
+        return handleResponse(outcome, url, callback -> getClient().post(callback, path, entity, null));
     }
 
     /**
index 0894704..3a2aaf8 100644 (file)
@@ -54,7 +54,7 @@ public abstract class BasicSoOperation extends BasicHttpOperation<SoRequest> {
     public static final int WAIT_SEC_GETS = 20;
 
     @Mock
-    protected SoOperator soOperator;
+    protected SoConfig config;
 
     protected Target target;
     protected SoResponse response;
@@ -80,7 +80,7 @@ public abstract class BasicSoOperation extends BasicHttpOperation<SoRequest> {
      * Initializes mocks and sets up.
      */
     public void setUp() throws Exception {
-        super.setUp();
+        super.setUpBasic();
 
         response = new SoResponse();
 
@@ -98,17 +98,16 @@ public abstract class BasicSoOperation extends BasicHttpOperation<SoRequest> {
         when(rawResponse.getStatus()).thenReturn(200);
         when(rawResponse.readEntity(String.class)).thenReturn(coder.encode(response));
 
-        operator = soOperator;
-
-        initOperator();
+        initConfig();
     }
 
     @Override
-    protected void initOperator() {
-        super.initOperator();
-        when(soOperator.getMaxGets()).thenReturn(MAX_GETS);
-        when(soOperator.getPathGet()).thenReturn(PATH_GET);
-        when(soOperator.getWaitSecGet()).thenReturn(WAIT_SEC_GETS);
+    protected void initConfig() {
+        super.initConfig();
+        when(config.getClient()).thenReturn(client);
+        when(config.getMaxGets()).thenReturn(MAX_GETS);
+        when(config.getPathGet()).thenReturn(PATH_GET);
+        when(config.getWaitSecGet()).thenReturn(WAIT_SEC_GETS);
     }
 
     @Override
diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoConfigTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoConfigTest.java
new file mode 100644 (file)
index 0000000..17fd9c9
--- /dev/null
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actor.so;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.Executor;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
+
+public class SoConfigTest {
+    private static final String MY_CLIENT = "my-client";
+    private static final String MY_PATH = "my-path";
+    private static final String GET_PATH = "get-path";
+    private static final int TIMEOUT_SEC = 10;
+    private static final int MAX_GETS = 20;
+    private static final int WAIT_SEC = 30;
+
+    @Mock
+    private HttpClient client;
+    @Mock
+    private HttpClientFactory factory;
+    @Mock
+    private Executor executor;
+
+    private SoParams params;
+    private SoConfig config;
+
+    /**
+     * Sets up.
+     */
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(factory.get(MY_CLIENT)).thenReturn(client);
+
+        params = SoParams.builder().maxGets(MAX_GETS).pathGet(GET_PATH).waitSecGet(WAIT_SEC).clientName(MY_CLIENT)
+                        .path(MY_PATH).timeoutSec(TIMEOUT_SEC).build();
+        config = new SoConfig(executor, params, factory);
+    }
+
+    @Test
+    public void test() {
+        assertEquals(GET_PATH + "/", config.getPathGet());
+        assertEquals(MAX_GETS, config.getMaxGets());
+        assertEquals(WAIT_SEC, config.getWaitSecGet());
+
+        // check value from superclass
+        assertSame(executor, config.getBlockingExecutor());
+        assertSame(client, config.getClient());
+
+        // path with trailing "/"
+        params = params.toBuilder().pathGet(GET_PATH + "/").build();
+        config = new SoConfig(executor, params, factory);
+        assertEquals(GET_PATH + "/", config.getPathGet());
+    }
+}
index e704138..871d370 100644 (file)
@@ -68,16 +68,16 @@ public class SoOperationTest extends BasicSoOperation {
     public void setUp() throws Exception {
         super.setUp();
 
-        initOperator();
+        initConfig();
 
-        oper = new SoOperation(params, soOperator) {};
+        oper = new SoOperation(params, config) {};
     }
 
     @Test
     public void testConstructor_testGetWaitMsGet() {
         assertEquals(DEFAULT_ACTOR, oper.getActorName());
         assertEquals(DEFAULT_OPERATION, oper.getName());
-        assertSame(soOperator, oper.getOperator());
+        assertSame(config, oper.getConfig());
         assertEquals(1000 * WAIT_SEC_GETS, oper.getWaitMsGet());
     }
 
@@ -85,7 +85,7 @@ public class SoOperationTest extends BasicSoOperation {
     public void testStartPreprocessorAsync() {
         AtomicBoolean guardStarted = new AtomicBoolean();
 
-        oper = new SoOperation(params, soOperator) {
+        oper = new SoOperation(params, config) {
             @Override
             protected CompletableFuture<OperationOutcome> startGuardAsync() {
                 guardStarted.set(true);
@@ -150,7 +150,7 @@ public class SoOperationTest extends BasicSoOperation {
         // use a real executor
         params = params.toBuilder().executor(ForkJoinPool.commonPool()).build();
 
-        oper = new SoOperation(params, soOperator) {
+        oper = new SoOperation(params, config) {
             @Override
             public long getWaitMsGet() {
                 return 1;
@@ -159,7 +159,7 @@ public class SoOperationTest extends BasicSoOperation {
 
         CompletableFuture<OperationOutcome> future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response);
 
-        assertSame(outcome, future2.get(5, TimeUnit.SECONDS));
+        assertSame(outcome, future2.get(500, TimeUnit.SECONDS));
         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
         assertEquals(2, oper.getGetCount());
 
@@ -236,7 +236,7 @@ public class SoOperationTest extends BasicSoOperation {
 
         // try with null target
         params = params.toBuilder().target(null).build();
-        oper = new SoOperation(params, soOperator) {};
+        oper = new SoOperation(params, config) {};
 
         assertThatIllegalArgumentException().isThrownBy(() -> oper.prepareSoModelInfo()).withMessage("missing Target");
     }
@@ -274,7 +274,7 @@ public class SoOperationTest extends BasicSoOperation {
 
         // null payload
         params = params.toBuilder().payload(null).build();
-        oper = new SoOperation(params, soOperator) {};
+        oper = new SoOperation(params, config) {};
         assertNull(oper.buildRequestParameters());
     }
 
@@ -295,7 +295,7 @@ public class SoOperationTest extends BasicSoOperation {
 
         // null payload
         params = params.toBuilder().payload(null).build();
-        oper = new SoOperation(params, soOperator) {};
+        oper = new SoOperation(params, config) {};
         assertNull(oper.buildConfigurationParameters());
     }
 
index 16bbdea..2040323 100644 (file)
@@ -22,9 +22,7 @@ package org.onap.policy.controlloop.actor.so;
 
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.when;
 
 import java.util.Map;
@@ -34,11 +32,7 @@ import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.onap.policy.common.endpoints.http.client.HttpClient;
 import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
-import org.onap.policy.controlloop.VirtualControlLoopEvent;
-import org.onap.policy.controlloop.actorserviceprovider.Operation;
 import org.onap.policy.controlloop.actorserviceprovider.Util;
-import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
-import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ParameterValidationRuntimeException;
 
 public class SoOperatorTest {
@@ -85,36 +79,9 @@ public class SoOperatorTest {
         assertEquals(ACTOR + "." + OPERATION, oper.getFullName());
     }
 
-    @Test
-    public void testMakeSoOperator() {
-        oper = SoOperator.makeSoOperator(ACTOR, OPERATION, MyOperation::new);
-
-        VirtualControlLoopEvent event = new VirtualControlLoopEvent();
-        ControlLoopEventContext context = new ControlLoopEventContext(event);
-        ControlLoopOperationParams params =
-                        ControlLoopOperationParams.builder().actor(ACTOR).operation(OPERATION).context(context).build();
-
-        Operation operation1 = oper.buildOperation(params);
-        assertNotNull(operation1);
-
-        Operation operation2 = oper.buildOperation(params);
-        assertNotNull(operation2);
-        assertNotSame(operation1, operation2);
-    }
-
     @Test
     public void testDoConfigure_testGetters() {
-        // should use given values
-        assertSame(client, oper.getClient());
-        assertEquals(PATH_GET, oper.getPathGet());
-        assertEquals(MAX_GETS, oper.getMaxGets());
-        assertEquals(WAIT_SEC_GETS, oper.getWaitSecGet());
-
-        SoParams params = SoParams.builder().pathGet("unslashed").maxGets(MAX_GETS).waitSecGet(WAIT_SEC_GETS)
-                        .clientName(CLIENT).path(PATH).timeoutSec(TIMEOUT).build();
-        Map<String, Object> paramMap = Util.translateToMap(OPERATION, params);
-        oper.configure(paramMap);
-        assertEquals("unslashed/", oper.getPathGet());
+        assertTrue(oper.getCurrentConfig() instanceof SoConfig);
 
         // test invalid parameters
         Map<String, Object> paramMap2 = Util.translateToMap(OPERATION, SoParams.builder().build());
@@ -124,12 +91,7 @@ public class SoOperatorTest {
 
     private class MyOperator extends SoOperator {
         public MyOperator() {
-            super(ACTOR, OPERATION);
-        }
-
-        @Override
-        public Operation buildOperation(ControlLoopOperationParams params) {
-            return null;
+            super(ACTOR, OPERATION, null);
         }
 
         @Override
@@ -137,10 +99,4 @@ public class SoOperatorTest {
             return factory;
         }
     }
-
-    private class MyOperation extends SoOperation {
-        public MyOperation(ControlLoopOperationParams params, SoOperator operator) {
-            super(params, operator);
-        }
-    }
 }
index 40efdc8..6c3cfbf 100644 (file)
@@ -64,7 +64,7 @@ public class VfModuleCreateTest extends BasicSoOperation {
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        oper = new VfModuleCreate(params, soOperator);
+        oper = new VfModuleCreate(params, config);
     }
 
     @Test
@@ -82,7 +82,7 @@ public class VfModuleCreateTest extends BasicSoOperation {
 
         AtomicBoolean guardStarted = new AtomicBoolean();
 
-        oper = new VfModuleCreate(params, soOperator) {
+        oper = new VfModuleCreate(params, config) {
             @Override
             protected CompletableFuture<OperationOutcome> startGuardAsync() {
                 guardStarted.set(true);
@@ -102,7 +102,7 @@ public class VfModuleCreateTest extends BasicSoOperation {
         // use a real executor
         params = params.toBuilder().executor(ForkJoinPool.commonPool()).build();
 
-        oper = new VfModuleCreate(params, soOperator) {
+        oper = new VfModuleCreate(params, config) {
             @Override
             public long getWaitMsGet() {
                 return 1;
@@ -128,7 +128,7 @@ public class VfModuleCreateTest extends BasicSoOperation {
         // use a real executor
         params = params.toBuilder().executor(ForkJoinPool.commonPool()).build();
 
-        oper = new VfModuleCreate(params, soOperator) {
+        oper = new VfModuleCreate(params, config) {
             @Override
             public long getWaitMsGet() {
                 return 1;
index e10e941..bba2bc1 100644 (file)
@@ -26,12 +26,9 @@ import java.util.function.BiConsumer;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.coder.StandardCoderObject;
-import org.onap.policy.common.utils.time.PseudoExecutor;
-import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperator;
-import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicConfig;
 import org.onap.policy.controlloop.actorserviceprovider.topic.BidirectionalTopicHandler;
 import org.onap.policy.controlloop.actorserviceprovider.topic.Forwarder;
 
@@ -41,7 +38,8 @@ import org.onap.policy.controlloop.actorserviceprovider.topic.Forwarder;
 public class BasicBidirectionalTopicOperation extends BasicOperation {
     protected static final String MY_SINK = "my-sink";
     protected static final String MY_SOURCE = "my-source";
-    protected static final int TIMEOUT = 10;
+    protected static final int TIMEOUT_SEC = 10;
+    protected static final long TIMEOUT_MS = 1000L * TIMEOUT_SEC;
 
     @Captor
     protected ArgumentCaptor<BiConsumer<String, StandardCoderObject>> listenerCaptor;
@@ -51,9 +49,7 @@ public class BasicBidirectionalTopicOperation extends BasicOperation {
     @Mock
     protected Forwarder forwarder;
     @Mock
-    protected BidirectionalTopicOperator operator;
-
-    protected BidirectionalTopicParams topicParams;
+    protected BidirectionalTopicConfig config;
 
     /**
      * Constructs the object using a default actor and operation name.
@@ -75,31 +71,19 @@ public class BasicBidirectionalTopicOperation extends BasicOperation {
     /**
      * Initializes mocks and sets up.
      */
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        executor = new PseudoExecutor();
-
-        makeContext();
-
-        outcome = params.makeOutcome();
-        topicParams = BidirectionalTopicParams.builder().sinkTopic(MY_SINK).sourceTopic(MY_SOURCE).timeoutSec(TIMEOUT)
-                        .build();
-
-        initOperator();
+    @Override
+    public void setUpBasic() {
+        super.setUpBasic();
+        initConfig();
     }
 
     /**
-     * Initializes an operator so that it is "alive" and has the given names.
+     * Initializes a configuration.
      */
-    protected void initOperator() {
-        when(operator.isAlive()).thenReturn(true);
-        when(operator.getFullName()).thenReturn(actorName + "." + operationName);
-        when(operator.getActorName()).thenReturn(actorName);
-        when(operator.getName()).thenReturn(operationName);
-        when(operator.getTopicHandler()).thenReturn(topicHandler);
-        when(operator.getForwarder()).thenReturn(forwarder);
-        when(operator.getParams()).thenReturn(topicParams);
+    protected void initConfig() {
+        when(config.getTopicHandler()).thenReturn(topicHandler);
+        when(config.getForwarder()).thenReturn(forwarder);
+        when(config.getTimeoutMs()).thenReturn(TIMEOUT_MS);
     }
 
     /**
index 05fa226..e803df8 100644 (file)
@@ -33,7 +33,7 @@ import org.mockito.Mock;
 import org.mockito.stubbing.Answer;
 import org.onap.policy.common.endpoints.http.client.HttpClient;
 import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
-import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 
 /**
  * Superclass for various HttpOperation tests.
@@ -47,25 +47,20 @@ public class BasicHttpOperation<Q> extends BasicOperation {
 
     @Captor
     protected ArgumentCaptor<InvocationCallback<Response>> callbackCaptor;
-
     @Captor
     protected ArgumentCaptor<Entity<Q>> requestCaptor;
-
     @Captor
     protected ArgumentCaptor<Map<String, Object>> headerCaptor;
 
+    @Mock
+    protected HttpConfig config;
     @Mock
     protected HttpClient client;
-
     @Mock
     protected HttpClientFactory factory;
-
     @Mock
     protected Response rawResponse;
 
-    @Mock
-    protected HttpOperator operator;
-
 
     /**
      * Constructs the object using a default actor and operation name.
@@ -87,8 +82,9 @@ public class BasicHttpOperation<Q> extends BasicOperation {
     /**
      * Initializes mocks and sets up.
      */
-    public void setUp() throws Exception {
-        super.setUp();
+    @Override
+    public void setUpBasic() {
+        super.setUpBasic();
 
         when(factory.get(MY_CLIENT)).thenReturn(client);
 
@@ -96,19 +92,15 @@ public class BasicHttpOperation<Q> extends BasicOperation {
 
         when(client.getBaseUrl()).thenReturn(BASE_URI);
 
-        initOperator();
+        initConfig();
     }
 
     /**
-     * Initializes an operator so that it is "alive" and has the given names.
+     * Initializes a configuration.
      */
-    protected void initOperator() {
-        when(operator.isAlive()).thenReturn(true);
-        when(operator.getFullName()).thenReturn(actorName + "." + operationName);
-        when(operator.getActorName()).thenReturn(actorName);
-        when(operator.getName()).thenReturn(operationName);
-        when(operator.getClient()).thenReturn(client);
-        when(operator.getPath()).thenReturn(PATH);
+    protected void initConfig() {
+        when(config.getClient()).thenReturn(client);
+        when(config.getPath()).thenReturn(PATH);
     }
 
     /**
index dbdd553..f027c1c 100644 (file)
@@ -86,7 +86,7 @@ public class BasicOperation {
     /**
      * Initializes mocks and sets up.
      */
-    public void setUp() throws Exception {
+    public void setUpBasic() {
         MockitoAnnotations.initMocks(this);
 
         future = new CompletableFuture<>();
index 9ec118e..101f130 100644 (file)
@@ -24,7 +24,6 @@ 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.assertSame;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
 
@@ -54,14 +53,14 @@ public class BasicBidirectionalTopicOperationTest {
         MockitoAnnotations.initMocks(this);
 
         oper = new BasicBidirectionalTopicOperation(ACTOR, OPERATION);
-        oper.setUp();
+        oper.setUpBasic();
     }
 
     @Test
     public void testBasicBidirectionalTopicOperation() {
         oper = new BasicBidirectionalTopicOperation();
-        assertEquals(BasicHttpOperation.DEFAULT_ACTOR, oper.actorName);
-        assertEquals(BasicHttpOperation.DEFAULT_OPERATION, oper.operationName);
+        assertEquals(BasicOperation.DEFAULT_ACTOR, oper.actorName);
+        assertEquals(BasicOperation.DEFAULT_OPERATION, oper.operationName);
     }
 
     @Test
@@ -72,24 +71,19 @@ public class BasicBidirectionalTopicOperationTest {
 
     @Test
     public void testSetUp() {
-        assertNotNull(oper.topicParams);
+        assertNotNull(oper.config);
         assertNotNull(oper.context);
         assertNotNull(oper.outcome);
         assertNotNull(oper.executor);
-        assertTrue(oper.operator.isAlive());
     }
 
     @Test
     public void testInitOperator() {
-        oper.initOperator();
-
-        assertTrue(oper.operator.isAlive());
-        assertEquals(ACTOR + "." + OPERATION, oper.operator.getFullName());
-        assertEquals(ACTOR, oper.operator.getActorName());
-        assertEquals(OPERATION, oper.operator.getName());
-        assertSame(oper.topicHandler, oper.operator.getTopicHandler());
-        assertSame(oper.forwarder, oper.operator.getForwarder());
-        assertSame(oper.topicParams, oper.operator.getParams());
+        oper.initConfig();
+
+        assertSame(oper.topicHandler, oper.config.getTopicHandler());
+        assertSame(oper.forwarder, oper.config.getForwarder());
+        assertEquals(BasicBidirectionalTopicOperation.TIMEOUT_MS, oper.config.getTimeoutMs());
     }
 
     @Test
index c463d6d..c19aa48 100644 (file)
@@ -23,7 +23,6 @@ package org.onap.policy.controlloop.actor.test;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.when;
 
@@ -42,14 +41,14 @@ public class BasicHttpOperationTest {
     @Before
     public void setUp() throws Exception {
         oper = new BasicHttpOperation<>(ACTOR, OPERATION);
-        oper.setUp();
+        oper.setUpBasic();
     }
 
     @Test
     public void testBasicHttpOperation() {
         oper = new BasicHttpOperation<>();
-        assertEquals(BasicHttpOperation.DEFAULT_ACTOR, oper.actorName);
-        assertEquals(BasicHttpOperation.DEFAULT_OPERATION, oper.operationName);
+        assertEquals(BasicOperation.DEFAULT_ACTOR, oper.actorName);
+        assertEquals(BasicOperation.DEFAULT_OPERATION, oper.operationName);
     }
 
     @Test
@@ -68,19 +67,14 @@ public class BasicHttpOperationTest {
         assertNotNull(oper.context);
         assertNotNull(oper.outcome);
         assertNotNull(oper.executor);
-        assertTrue(oper.operator.isAlive());
     }
 
     @Test
     public void testInitOperator() throws Exception {
-        oper.initOperator();
-
-        assertTrue(oper.operator.isAlive());
-        assertEquals(ACTOR + "." + OPERATION, oper.operator.getFullName());
-        assertEquals(ACTOR, oper.operator.getActorName());
-        assertEquals(OPERATION, oper.operator.getName());
-        assertSame(oper.client, oper.operator.getClient());
-        assertEquals(BasicHttpOperation.PATH, oper.operator.getPath());
+        oper.initConfig();
+
+        assertSame(oper.client, oper.config.getClient());
+        assertEquals(BasicHttpOperation.PATH, oper.config.getPath());
     }
 
     @Test
index ee0e5ce..60bb008 100644 (file)
@@ -43,7 +43,7 @@ public class BasicOperationTest {
     @Before
     public void setUp() throws Exception {
         oper = new BasicHttpOperation<>(ACTOR, OPERATION);
-        oper.setUp();
+        oper.setUpBasic();
     }
 
     @Test
index 1e44a17..564bbc3 100644 (file)
@@ -27,14 +27,23 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.onap.policy.common.endpoints.event.comm.client.BidirectionalTopicClientException;
 import org.onap.policy.controlloop.actorserviceprovider.Util;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicActorParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicParams;
 import org.onap.policy.controlloop.actorserviceprovider.topic.BidirectionalTopicHandler;
 import org.onap.policy.controlloop.actorserviceprovider.topic.BidirectionalTopicManager;
 
 /**
- * Actor that uses a bidirectional topic. The actor's parameters must be a
- * {@link BidirectionalTopicActorParams}.
+ * Actor that uses a bidirectional topic. The actor's operator parameters are expected to
+ * be an {@link BidirectionalTopicParams}.
+ *
+ * @param <P> type of parameters
  */
-public class BidirectionalTopicActor extends ActorImpl implements BidirectionalTopicManager {
+public class BidirectionalTopicActor<P extends BidirectionalTopicActorParams> extends ActorImpl
+                implements BidirectionalTopicManager {
+
+    /**
+     * Class of parameters.
+     */
+    private final Class<P> paramsClass;
 
     /**
      * Maps a pair of sink and source topic names to their bidirectional topic.
@@ -47,8 +56,9 @@ public class BidirectionalTopicActor extends ActorImpl implements BidirectionalT
      *
      * @param name actor's name
      */
-    public BidirectionalTopicActor(String name) {
+    public BidirectionalTopicActor(String name, Class<P> paramsClass) {
         super(name);
+        this.paramsClass = paramsClass;
     }
 
     @Override
@@ -92,7 +102,7 @@ public class BidirectionalTopicActor extends ActorImpl implements BidirectionalT
         String actorName = getName();
 
         // @formatter:off
-        return Util.translate(actorName, actorParameters, BidirectionalTopicActorParams.class)
+        return Util.translate(actorName, actorParameters, paramsClass)
                         .doValidation(actorName)
                         .makeOperationParameters(actorName);
         // @formatter:on
index d1e21f8..1ae8049 100644 (file)
@@ -23,14 +23,13 @@ package org.onap.policy.controlloop.actorserviceprovider.impl;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
 import java.util.function.BiConsumer;
 import lombok.Getter;
 import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.coder.StandardCoderObject;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
-import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.pipeline.PipelineControllerFuture;
 import org.onap.policy.controlloop.actorserviceprovider.topic.BidirectionalTopicHandler;
@@ -55,34 +54,40 @@ public abstract class BidirectionalTopicOperation<Q, S> extends OperationPartial
         SUCCESS, FAILURE, STILL_WAITING
     }
 
-    // fields extracted from the operator
-
-    private final BidirectionalTopicHandler topicHandler;
-    private final Forwarder forwarder;
-    private final BidirectionalTopicParams topicParams;
-    private final long timeoutMs;
+    /**
+     * Configuration for this operation.
+     */
+    private final BidirectionalTopicConfig config;
 
     /**
      * Response class.
      */
     private final Class<S> responseClass;
 
+    // fields extracted from "config"
+
+    private final BidirectionalTopicHandler topicHandler;
+    private final Forwarder forwarder;
+
 
     /**
      * Constructs the object.
      *
      * @param params operation parameters
-     * @param operator operator that created this operation
+     * @param config configuration for this operation
      * @param clazz response class
      */
-    public BidirectionalTopicOperation(ControlLoopOperationParams params, BidirectionalTopicOperator operator,
+    public BidirectionalTopicOperation(ControlLoopOperationParams params, BidirectionalTopicConfig config,
                     Class<S> clazz) {
-        super(params, operator);
-        this.topicHandler = operator.getTopicHandler();
-        this.forwarder = operator.getForwarder();
-        this.topicParams = operator.getParams();
+        super(params, config);
+        this.config = config;
         this.responseClass = clazz;
-        this.timeoutMs = TimeUnit.MILLISECONDS.convert(topicParams.getTimeoutSec(), TimeUnit.SECONDS);
+        this.forwarder = config.getForwarder();
+        this.topicHandler = config.getTopicHandler();
+    }
+
+    public long getTimeoutMs() {
+        return config.getTimeoutMs();
     }
 
     /**
@@ -91,7 +96,7 @@ public abstract class BidirectionalTopicOperation<Q, S> extends OperationPartial
     @Override
     protected long getTimeoutMs(Integer timeoutSec) {
         // TODO move this method to the superclass
-        return (timeoutSec == null || timeoutSec == 0 ? this.timeoutMs : super.getTimeoutMs(timeoutSec));
+        return (timeoutSec == null || timeoutSec == 0 ? getTimeoutMs() : super.getTimeoutMs(timeoutSec));
     }
 
     /**
index 51689e4..43c8b88 100644 (file)
@@ -23,24 +23,30 @@ package org.onap.policy.controlloop.actorserviceprovider.impl;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
-import java.util.function.BiFunction;
 import lombok.Getter;
 import org.onap.policy.common.parameters.ValidationResult;
 import org.onap.policy.controlloop.actorserviceprovider.Operation;
 import org.onap.policy.controlloop.actorserviceprovider.Util;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ParameterValidationRuntimeException;
 import org.onap.policy.controlloop.actorserviceprovider.topic.BidirectionalTopicHandler;
 import org.onap.policy.controlloop.actorserviceprovider.topic.BidirectionalTopicManager;
-import org.onap.policy.controlloop.actorserviceprovider.topic.Forwarder;
 import org.onap.policy.controlloop.actorserviceprovider.topic.SelectorKey;
 
 /**
  * Operator that uses a bidirectional topic. Topic operators may share a
  * {@link BidirectionalTopicHandler}.
  */
-public abstract class BidirectionalTopicOperator extends OperatorPartial {
+public class BidirectionalTopicOperator extends OperatorPartial {
+
+    /**
+     * Function to make an operation.
+     */
+    @SuppressWarnings("rawtypes")
+    private final OperationMaker<BidirectionalTopicConfig, BidirectionalTopicOperation> operationMaker;
 
     /**
      * Manager from which to get the topic handlers.
@@ -52,30 +58,26 @@ public abstract class BidirectionalTopicOperator extends OperatorPartial {
      */
     private final List<SelectorKey> selectorKeys;
 
-    /*
-     * The remaining fields are initialized when configure() is invoked, thus they may
-     * change.
-     */
-
     /**
-     * Current parameters. While {@link params} may change, the values contained within it
-     * will not, thus operations may copy it.
+     * Current configuration. This is set by {@link #doConfigure(Map)}.
      */
     @Getter
-    private BidirectionalTopicParams params;
+    private BidirectionalTopicConfig currentConfig;
 
-    /**
-     * Topic handler associated with the parameters.
-     */
-    @Getter
-    private BidirectionalTopicHandler topicHandler;
 
     /**
-     * Forwarder associated with the parameters.
+     * Constructs the object.
+     *
+     * @param actorName name of the actor with which this operator is associated
+     * @param name operation name
+     * @param topicManager manager from which to get the topic handler
+     * @param selectorKeys keys used to extract the fields used to select responses for
+     *        this operator
      */
-    @Getter
-    private Forwarder forwarder;
-
+    protected BidirectionalTopicOperator(String actorName, String name, BidirectionalTopicManager topicManager,
+                    List<SelectorKey> selectorKeys) {
+        this(actorName, name, topicManager, selectorKeys, null);
+    }
 
     /**
      * Constructs the object.
@@ -86,75 +88,70 @@ public abstract class BidirectionalTopicOperator extends OperatorPartial {
      * @param selectorKeys keys used to extract the fields used to select responses for
      *        this operator
      */
+    // @formatter:off
     public BidirectionalTopicOperator(String actorName, String name, BidirectionalTopicManager topicManager,
-                    List<SelectorKey> selectorKeys) {
+                    List<SelectorKey> selectorKeys,
+                    @SuppressWarnings("rawtypes") OperationMaker<BidirectionalTopicConfig, BidirectionalTopicOperation>
+                        operationMaker) {
+        // @formatter:on
+
         super(actorName, name);
         this.topicManager = topicManager;
         this.selectorKeys = selectorKeys;
-    }
-
-    @Override
-    protected void doConfigure(Map<String, Object> parameters) {
-        params = Util.translate(getFullName(), parameters, BidirectionalTopicParams.class);
-        ValidationResult result = params.validate(getFullName());
-        if (!result.isValid()) {
-            throw new ParameterValidationRuntimeException("invalid parameters", result);
-        }
-
-        topicHandler = topicManager.getTopicHandler(params.getSinkTopic(), params.getSourceTopic());
-        forwarder = topicHandler.addForwarder(selectorKeys);
+        this.operationMaker = operationMaker;
     }
 
     /**
-     * Makes an operator that will construct operations.
+     * Constructs the object.
      *
-     * @param <Q> request type
-     * @param <S> response type
-     * @param actorName actor name
-     * @param operation operation name
+     * @param actorName name of the actor with which this operator is associated
+     * @param name operation name
      * @param topicManager manager from which to get the topic handler
-     * @param operationMaker function to make an operation
-     * @param keys keys used to extract the fields used to select responses for this
-     *        operator
-     * @return a new operator
+     * @param selectorKeys keys used to extract the fields used to select responses for
+     *        this operator
      */
     // @formatter:off
-    public static <Q, S> BidirectionalTopicOperator makeOperator(String actorName, String operation,
-                    BidirectionalTopicManager topicManager,
-                    BiFunction<ControlLoopOperationParams, BidirectionalTopicOperator,
-                        BidirectionalTopicOperation<Q, S>> operationMaker,
-                    SelectorKey... keys) {
-        // @formatter:off
-
-        return makeOperator(actorName, operation, topicManager, Arrays.asList(keys), operationMaker);
+    public BidirectionalTopicOperator(String actorName, String name, BidirectionalTopicManager topicManager,
+                    @SuppressWarnings("rawtypes") OperationMaker<BidirectionalTopicConfig, BidirectionalTopicOperation>
+                        operationMaker,
+                    SelectorKey... selectorKeys) {
+        // @formatter:on
+        this(actorName, name, topicManager, Arrays.asList(selectorKeys), operationMaker);
+    }
+
+    /**
+     * Translates the parameters to an {@link HttpParams} and then extracts the relevant
+     * values.
+     */
+    @Override
+    protected void doConfigure(Map<String, Object> parameters) {
+        currentConfig = makeConfiguration(parameters);
     }
 
     /**
-     * Makes an operator that will construct operations.
+     * Makes a new configuration using the specified parameters.
      *
-     * @param <Q> request type
-     * @param <S> response type
-     * @param actorName actor name
-     * @param operation operation name
-     * @param topicManager manager from which to get the topic handler
-     * @param keys keys used to extract the fields used to select responses for
-     *        this operator
-     * @param operationMaker function to make an operation
-     * @return a new operator
+     * @param parameters operator parameters
+     * @return a new configuration
      */
-    // @formatter:off
-    public static <Q,S> BidirectionalTopicOperator makeOperator(String actorName, String operation,
-                    BidirectionalTopicManager topicManager,
-                    List<SelectorKey> keys,
-                    BiFunction<ControlLoopOperationParams, BidirectionalTopicOperator,
-                        BidirectionalTopicOperation<Q,S>> operationMaker) {
-        // @formatter:on
+    protected BidirectionalTopicConfig makeConfiguration(Map<String, Object> parameters) {
+        BidirectionalTopicParams params = Util.translate(getFullName(), parameters, BidirectionalTopicParams.class);
+        ValidationResult result = params.validate(getFullName());
+        if (!result.isValid()) {
+            throw new ParameterValidationRuntimeException("invalid parameters", result);
+        }
+
+        return new BidirectionalTopicConfig(getBlockingExecutor(), params, topicManager, selectorKeys);
+    }
+
+    @Override
+    public Operation buildOperation(ControlLoopOperationParams params) {
+        if (operationMaker == null) {
+            throw new UnsupportedOperationException("cannot make operation for " + getFullName());
+        }
+
+        verifyRunning();
 
-        return new BidirectionalTopicOperator(actorName, operation, topicManager, keys) {
-            @Override
-            public synchronized Operation buildOperation(ControlLoopOperationParams params) {
-                return operationMaker.apply(params, this);
-            }
-        };
+        return operationMaker.apply(params, currentConfig);
     }
 }
index 28b7b39..eb5662f 100644 (file)
@@ -27,18 +27,26 @@ import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpActorPara
 
 /**
  * Actor that uses HTTP, where the only additional property that an operator needs is a
- * URL. The actor's parameters must be an {@link HttpActorParams} and its operator
- * parameters are expected to be an {@link HttpParams}.
+ * URL. The actor's operator parameters are expected to be an {@link HttpParams}.
+ *
+ * @param <P> type of parameters
  */
-public class HttpActor extends ActorImpl {
+public class HttpActor<P extends HttpActorParams> extends ActorImpl {
+
+    /**
+     * Class of parameters.
+     */
+    private final Class<P> paramsClass;
 
     /**
      * Constructs the object.
      *
      * @param name actor's name
+     * @param paramsClass class of parameters
      */
-    public HttpActor(String name) {
+    public HttpActor(String name, Class<P> paramsClass) {
         super(name);
+        this.paramsClass = paramsClass;
     }
 
     /**
@@ -50,7 +58,7 @@ public class HttpActor extends ActorImpl {
         String actorName = getName();
 
         // @formatter:off
-        return Util.translate(actorName, actorParameters, HttpActorParams.class)
+        return Util.translate(actorName, actorParameters, paramsClass)
                         .doValidation(actorName)
                         .makeOperationParameters(actorName);
         // @formatter:on
index da4887e..4c007ea 100644 (file)
@@ -36,6 +36,7 @@ import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
 import org.onap.policy.controlloop.actorserviceprovider.pipeline.PipelineControllerFuture;
 import org.onap.policy.controlloop.policy.PolicyResult;
@@ -52,9 +53,9 @@ public abstract class HttpOperation<T> extends OperationPartial {
     private static final Logger logger = LoggerFactory.getLogger(HttpOperation.class);
 
     /**
-     * Operator that created this operation.
+     * Configuration for this operation.
      */
-    private final HttpOperator operator;
+    private final HttpConfig config;
 
     /**
      * Response class.
@@ -66,21 +67,33 @@ public abstract class HttpOperation<T> extends OperationPartial {
      * Constructs the object.
      *
      * @param params operation parameters
-     * @param operator operator that created this operation
+     * @param config configuration for this operation
      * @param clazz response class
      */
-    public HttpOperation(ControlLoopOperationParams params, HttpOperator operator, Class<T> clazz) {
-        super(params, operator);
-        this.operator = operator;
+    public HttpOperation(ControlLoopOperationParams params, HttpConfig config, Class<T> clazz) {
+        super(params, config);
+        this.config = config;
         this.responseClass = clazz;
     }
 
+    public HttpClient getClient() {
+        return config.getClient();
+    }
+
+    public String getPath() {
+        return config.getPath();
+    }
+
+    public long getTimeoutMs() {
+        return config.getTimeoutMs();
+    }
+
     /**
      * If no timeout is specified, then it returns the operator's configured timeout.
      */
     @Override
     protected long getTimeoutMs(Integer timeoutSec) {
-        return (timeoutSec == null || timeoutSec == 0 ? operator.getTimeoutMs() : super.getTimeoutMs(timeoutSec));
+        return (timeoutSec == null || timeoutSec == 0 ? getTimeoutMs() : super.getTimeoutMs(timeoutSec));
     }
 
     /**
@@ -99,7 +112,7 @@ public abstract class HttpOperation<T> extends OperationPartial {
      * @return the path URI suffix
      */
     public String makePath() {
-        return operator.getPath();
+        return getPath();
     }
 
     /**
@@ -110,7 +123,7 @@ public abstract class HttpOperation<T> extends OperationPartial {
      * @return the URL to which from which to get
      */
     public String makeUrl() {
-        return (operator.getClient().getBaseUrl() + makePath());
+        return (getClient().getBaseUrl() + makePath());
     }
 
     /**
index b4a3318..9e446a7 100644 (file)
 package org.onap.policy.controlloop.actorserviceprovider.impl;
 
 import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.function.BiFunction;
 import lombok.Getter;
-import org.onap.policy.common.endpoints.http.client.HttpClient;
 import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
 import org.onap.policy.common.parameters.ValidationResult;
 import org.onap.policy.controlloop.actorserviceprovider.Operation;
 import org.onap.policy.controlloop.actorserviceprovider.Util;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ParameterValidationRuntimeException;
 
 /**
  * Operator that uses HTTP. The operator's parameters must be an {@link HttpParams}.
  */
-@Getter
-public abstract class HttpOperator extends OperatorPartial {
-
-    private HttpClient client;
+public class HttpOperator extends OperatorPartial {
 
     /**
-     * Default timeout, in milliseconds, if none specified in the request.
+     * Function to make an operation.
      */
-    private long timeoutMs;
+    @SuppressWarnings("rawtypes")
+    private final OperationMaker<HttpConfig, HttpOperation> operationMaker;
 
     /**
-     * URI path for this particular operation. Includes a leading "/".
+     * Current configuration. This is set by {@link #doConfigure(Map)}.
      */
-    private String path;
+    @Getter
+    private HttpConfig currentConfig;
 
 
     /**
@@ -59,28 +56,21 @@ public abstract class HttpOperator extends OperatorPartial {
      * @param actorName name of the actor with which this operator is associated
      * @param name operation name
      */
-    public HttpOperator(String actorName, String name) {
-        super(actorName, name);
+    protected HttpOperator(String actorName, String name) {
+        this(actorName, name, null);
     }
 
     /**
-     * Makes an operator that will construct operations.
+     * Constructs the object.
      *
-     * @param <T> response type
-     * @param actorName actor name
-     * @param operation operation name
+     * @param actorName name of the actor with which this operator is associated
+     * @param name operation name
      * @param operationMaker function to make an operation
-     * @return a new operator
      */
-    public static <T> HttpOperator makeOperator(String actorName, String operation,
-                    BiFunction<ControlLoopOperationParams, HttpOperator, HttpOperation<T>> operationMaker) {
-
-        return new HttpOperator(actorName, operation) {
-            @Override
-            public Operation buildOperation(ControlLoopOperationParams params) {
-                return operationMaker.apply(params, this);
-            }
-        };
+    public HttpOperator(String actorName, String name,
+                    @SuppressWarnings("rawtypes") OperationMaker<HttpConfig, HttpOperation> operationMaker) {
+        super(actorName, name);
+        this.operationMaker = operationMaker;
     }
 
     /**
@@ -89,24 +79,34 @@ public abstract class HttpOperator extends OperatorPartial {
      */
     @Override
     protected void doConfigure(Map<String, Object> parameters) {
+        currentConfig = makeConfiguration(parameters);
+    }
+
+    /**
+     * Makes a new configuration using the specified parameters.
+     *
+     * @param parameters operator parameters
+     * @return a new configuration
+     */
+    protected HttpConfig makeConfiguration(Map<String, Object> parameters) {
         HttpParams params = Util.translate(getFullName(), parameters, HttpParams.class);
         ValidationResult result = params.validate(getFullName());
         if (!result.isValid()) {
             throw new ParameterValidationRuntimeException("invalid parameters", result);
         }
 
-        doConfigure(params);
+        return new HttpConfig(getBlockingExecutor(), params, getClientFactory());
     }
 
-    /**
-     * Configures the operator using the specified parameters.
-     *
-     * @param params operator parameters
-     */
-    protected void doConfigure(HttpParams params) {
-        client = getClientFactory().get(params.getClientName());
-        path = params.getPath();
-        timeoutMs = TimeUnit.MILLISECONDS.convert(params.getTimeoutSec(), TimeUnit.SECONDS);
+    @Override
+    public Operation buildOperation(ControlLoopOperationParams params) {
+        if (operationMaker == null) {
+            throw new UnsupportedOperationException("cannot make operation for " + getFullName());
+        }
+
+        verifyRunning();
+
+        return operationMaker.apply(params, currentConfig);
     }
 
     // these may be overridden by junit tests
diff --git a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationMaker.java b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/impl/OperationMaker.java
new file mode 100644 (file)
index 0000000..ae95097
--- /dev/null
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actorserviceprovider.impl;
+
+import org.onap.policy.controlloop.actorserviceprovider.Operation;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+
+/**
+ * Function to make an operation.
+ *
+ * @param <C> configuration type
+ * @param <T> type of operation it creates
+ */
+public interface OperationMaker<C, T extends Operation> {
+    T apply(ControlLoopOperationParams params, C config);
+}
index 680a56f..e636228 100644 (file)
@@ -35,6 +35,7 @@ import java.util.function.BiConsumer;
 import java.util.function.Function;
 import java.util.function.Supplier;
 import java.util.function.UnaryOperator;
+import lombok.Getter;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.utils.NetLoggerUtil;
 import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
@@ -46,6 +47,7 @@ import org.onap.policy.controlloop.actorserviceprovider.CallbackManager;
 import org.onap.policy.controlloop.actorserviceprovider.Operation;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.OperatorConfig;
 import org.onap.policy.controlloop.actorserviceprovider.pipeline.PipelineControllerFuture;
 import org.onap.policy.controlloop.policy.PolicyResult;
 import org.slf4j.Logger;
@@ -71,49 +73,43 @@ public abstract class OperationPartial implements Operation {
 
     public static final long DEFAULT_RETRY_WAIT_MS = 1000L;
 
-    // values extracted from the operator
-
-    private final OperatorPartial operator;
+    private final OperatorConfig config;
 
     /**
      * Operation parameters.
      */
     protected final ControlLoopOperationParams params;
 
+    @Getter
+    private final String fullName;
+
 
     /**
      * Constructs the object.
      *
      * @param params operation parameters
-     * @param operator operator that created this operation
+     * @param config configuration for this operation
      */
-    public OperationPartial(ControlLoopOperationParams params, OperatorPartial operator) {
+    public OperationPartial(ControlLoopOperationParams params, OperatorConfig config) {
         this.params = params;
-        this.operator = operator;
+        this.config = config;
+        this.fullName = params.getActor() + "." + params.getOperation();
     }
 
     public Executor getBlockingExecutor() {
-        return operator.getBlockingExecutor();
-    }
-
-    public String getFullName() {
-        return operator.getFullName();
+        return config.getBlockingExecutor();
     }
 
     public String getActorName() {
-        return operator.getActorName();
+        return params.getActor();
     }
 
     public String getName() {
-        return operator.getName();
+        return params.getOperation();
     }
 
     @Override
     public final CompletableFuture<OperationOutcome> start() {
-        if (!operator.isAlive()) {
-            throw new IllegalStateException("operation is not running: " + getFullName());
-        }
-
         // allocate a controller for the entire operation
         final PipelineControllerFuture<OperationOutcome> controller = new PipelineControllerFuture<>();
 
index 3e15c1b..8007c24 100644 (file)
@@ -61,6 +61,17 @@ public abstract class OperatorPartial extends StartConfigPartial<Map<String, Obj
         this.name = name;
     }
 
+    /**
+     * Verifies that the operator is running.
+     *
+     * @throws IllegalStateException if it is not running
+     */
+    public void verifyRunning() {
+        if (!isAlive()) {
+            throw new IllegalStateException("operation is not running: " + getFullName());
+        }
+    }
+
     /**
      * This method does nothing.
      */
diff --git a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/BidirectionalTopicConfig.java b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/BidirectionalTopicConfig.java
new file mode 100644 (file)
index 0000000..4583148
--- /dev/null
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actorserviceprovider.parameters;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import lombok.Getter;
+import org.onap.policy.controlloop.actorserviceprovider.topic.BidirectionalTopicHandler;
+import org.onap.policy.controlloop.actorserviceprovider.topic.BidirectionalTopicManager;
+import org.onap.policy.controlloop.actorserviceprovider.topic.Forwarder;
+import org.onap.policy.controlloop.actorserviceprovider.topic.SelectorKey;
+
+/**
+ * Configuration for Bidirectional Topic Operators.
+ */
+@Getter
+public class BidirectionalTopicConfig extends OperatorConfig {
+
+    /**
+     * Topic handler associated with the parameters.
+     */
+    private BidirectionalTopicHandler topicHandler;
+
+    /**
+     * Forwarder associated with the parameters.
+     */
+    private Forwarder forwarder;
+
+    /**
+     * Default timeout, in milliseconds, if none specified in the request.
+     */
+    private final long timeoutMs;
+
+
+    /**
+     * Constructs the object.
+     *
+     * @param blockingExecutor executor to be used for tasks that may perform blocking I/O
+     * @param params operator parameters
+     * @param topicManager manager from which to get the topic handler
+     * @param selectorKeys keys used to extract the fields used to select responses for
+     *        this operator
+     */
+    public BidirectionalTopicConfig(Executor blockingExecutor, BidirectionalTopicParams params,
+                    BidirectionalTopicManager topicManager, List<SelectorKey> selectorKeys) {
+        super(blockingExecutor);
+        topicHandler = topicManager.getTopicHandler(params.getSinkTopic(), params.getSourceTopic());
+        forwarder = topicHandler.addForwarder(selectorKeys);
+        timeoutMs = TimeUnit.MILLISECONDS.convert(params.getTimeoutSec(), TimeUnit.SECONDS);
+    }
+}
diff --git a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/HttpConfig.java b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/HttpConfig.java
new file mode 100644 (file)
index 0000000..b3e08f7
--- /dev/null
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actorserviceprovider.parameters;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import lombok.Getter;
+import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
+
+/**
+ * Configuration for HTTP Operators.
+ */
+@Getter
+public class HttpConfig extends OperatorConfig {
+
+    private final HttpClient client;
+
+    /**
+     * Default timeout, in milliseconds, if none specified in the request.
+     */
+    private final long timeoutMs;
+
+    /**
+     * URI path for this particular operation. Includes a leading "/".
+     */
+    private final String path;
+
+
+    /**
+     * Constructs the object.
+     *
+     * @param blockingExecutor executor to be used for tasks that may perform blocking I/O
+     * @param params operator parameters
+     * @param clientFactory factory from which to obtain the {@link HttpClient}
+     */
+    public HttpConfig(Executor blockingExecutor, HttpParams params, HttpClientFactory clientFactory) {
+        super(blockingExecutor);
+        client = clientFactory.get(params.getClientName());
+        path = params.getPath();
+        timeoutMs = TimeUnit.MILLISECONDS.convert(params.getTimeoutSec(), TimeUnit.SECONDS);
+    }
+}
diff --git a/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/OperatorConfig.java b/models-interactions/model-actors/actorServiceProvider/src/main/java/org/onap/policy/controlloop/actorserviceprovider/parameters/OperatorConfig.java
new file mode 100644 (file)
index 0000000..e5bd5f5
--- /dev/null
@@ -0,0 +1,35 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actorserviceprovider.parameters;
+
+import java.util.concurrent.Executor;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+public class OperatorConfig {
+
+    /**
+     * Executor to be used for tasks that may perform blocking I/O.
+     */
+    @Getter
+    private final Executor blockingExecutor;
+}
index e1606ae..4a43541 100644 (file)
@@ -61,7 +61,7 @@ public class BidirectionalTopicActorTest {
     @Mock
     private BidirectionalTopicHandler handler2;
 
-    private BidirectionalTopicActor actor;
+    private BidirectionalTopicActor<BidirectionalTopicActorParams> actor;
 
 
     /**
@@ -157,7 +157,8 @@ public class BidirectionalTopicActorTest {
     public void testMakeOperatorParameters() {
         BidirectionalTopicActorParams params = makeParams();
 
-        final BidirectionalTopicActor prov = new BidirectionalTopicActor(ACTOR);
+        final BidirectionalTopicActor<BidirectionalTopicActorParams> prov =
+                        new BidirectionalTopicActor<>(ACTOR, BidirectionalTopicActorParams.class);
         Function<String, Map<String, Object>> maker =
                         prov.makeOperatorParameters(Util.translateToMap(prov.getName(), params));
 
@@ -193,7 +194,7 @@ public class BidirectionalTopicActorTest {
     @Test
     public void testMakeTopicHandler() {
         // use a real actor
-        actor = new BidirectionalTopicActor(ACTOR);
+        actor = new BidirectionalTopicActor<>(ACTOR, BidirectionalTopicActorParams.class);
 
         handler1 = actor.getTopicHandler(MY_SINK, MY_SOURCE1);
         handler2 = actor.getTopicHandler(MY_SINK, MY_SOURCE2);
@@ -218,10 +219,10 @@ public class BidirectionalTopicActorTest {
         return params;
     }
 
-    private class MyActor extends BidirectionalTopicActor {
+    private class MyActor extends BidirectionalTopicActor<BidirectionalTopicActorParams> {
 
         public MyActor() {
-            super(ACTOR);
+            super(ACTOR, BidirectionalTopicActorParams.class);
         }
 
         @Override
index ceb63fe..5725a6d 100644 (file)
@@ -53,7 +53,7 @@ import org.onap.policy.common.utils.coder.StandardCoder;
 import org.onap.policy.common.utils.coder.StandardCoderObject;
 import org.onap.policy.common.utils.time.PseudoExecutor;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
-import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.topic.BidirectionalTopicHandler;
 import org.onap.policy.controlloop.actorserviceprovider.topic.Forwarder;
@@ -65,8 +65,6 @@ public class BidirectionalTopicOperationTest {
     private static final String ACTOR = "my-actor";
     private static final String OPERATION = "my-operation";
     private static final String REQ_ID = "my-request-id";
-    private static final String MY_SINK = "my-sink";
-    private static final String MY_SOURCE = "my-source";
     private static final String TEXT = "some text";
     private static final int TIMEOUT_SEC = 10;
     private static final long TIMEOUT_MS = 1000 * TIMEOUT_SEC;
@@ -75,7 +73,7 @@ public class BidirectionalTopicOperationTest {
     private static final StandardCoder coder = new StandardCoder();
 
     @Mock
-    private BidirectionalTopicOperator operator;
+    private BidirectionalTopicConfig config;
     @Mock
     private BidirectionalTopicHandler handler;
     @Mock
@@ -85,7 +83,6 @@ public class BidirectionalTopicOperationTest {
     private ArgumentCaptor<BiConsumer<String, StandardCoderObject>> listenerCaptor;
 
     private ControlLoopOperationParams params;
-    private BidirectionalTopicParams topicParams;
     private OperationOutcome outcome;
     private StandardCoderObject stdResponse;
     private String responseText;
@@ -100,15 +97,9 @@ public class BidirectionalTopicOperationTest {
     public void setUp() throws CoderException {
         MockitoAnnotations.initMocks(this);
 
-        topicParams = BidirectionalTopicParams.builder().sourceTopic(MY_SOURCE).sinkTopic(MY_SINK)
-                        .timeoutSec(TIMEOUT_SEC).build();
-
-        when(operator.getActorName()).thenReturn(ACTOR);
-        when(operator.getName()).thenReturn(OPERATION);
-        when(operator.getTopicHandler()).thenReturn(handler);
-        when(operator.getForwarder()).thenReturn(forwarder);
-        when(operator.getParams()).thenReturn(topicParams);
-        when(operator.isAlive()).thenReturn(true);
+        when(config.getTopicHandler()).thenReturn(handler);
+        when(config.getForwarder()).thenReturn(forwarder);
+        when(config.getTimeoutMs()).thenReturn(TIMEOUT_MS);
 
         when(handler.send(any())).thenReturn(true);
         when(handler.getSinkTopicCommInfrastructure()).thenReturn(SINK_INFRA);
@@ -132,7 +123,6 @@ public class BidirectionalTopicOperationTest {
         assertEquals(OPERATION, oper.getName());
         assertSame(handler, oper.getTopicHandler());
         assertSame(forwarder, oper.getForwarder());
-        assertSame(topicParams, oper.getTopicParams());
         assertEquals(TIMEOUT_MS, oper.getTimeoutMs());
         assertSame(MyResponse.class, oper.getResponseClass());
     }
@@ -334,7 +324,7 @@ public class BidirectionalTopicOperationTest {
 
     private class MyStringOperation extends BidirectionalTopicOperation<String, String> {
         public MyStringOperation() {
-            super(BidirectionalTopicOperationTest.this.params, operator, String.class);
+            super(BidirectionalTopicOperationTest.this.params, config, String.class);
         }
 
         @Override
@@ -356,7 +346,7 @@ public class BidirectionalTopicOperationTest {
 
     private class MyScoOperation extends BidirectionalTopicOperation<MyRequest, StandardCoderObject> {
         public MyScoOperation() {
-            super(BidirectionalTopicOperationTest.this.params, operator, StandardCoderObject.class);
+            super(BidirectionalTopicOperationTest.this.params, config, StandardCoderObject.class);
         }
 
         @Override
@@ -378,7 +368,7 @@ public class BidirectionalTopicOperationTest {
 
     private class MyOperation extends BidirectionalTopicOperation<MyRequest, MyResponse> {
         public MyOperation() {
-            super(BidirectionalTopicOperationTest.this.params, operator, MyResponse.class);
+            super(BidirectionalTopicOperationTest.this.params, config, MyResponse.class);
         }
 
         @Override
index 4fae782..ae923c0 100644 (file)
 
 package org.onap.policy.controlloop.actorserviceprovider.impl;
 
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
 import static org.mockito.Mockito.when;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.BiFunction;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.onap.policy.controlloop.actorserviceprovider.Operation;
 import org.onap.policy.controlloop.actorserviceprovider.Util;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ParameterValidationRuntimeException;
@@ -86,9 +89,7 @@ public class BidirectionalTopicOperatorTest {
     public void testConstructor_testGetParams_testGetTopicHandler_testGetForwarder() {
         assertEquals(ACTOR, oper.getActorName());
         assertEquals(OPERATION, oper.getName());
-        assertEquals(params, oper.getParams());
-        assertSame(handler, oper.getTopicHandler());
-        assertSame(forwarder, oper.getForwarder());
+        assertNotNull(oper.getCurrentConfig());
     }
 
     @Test
@@ -102,31 +103,45 @@ public class BidirectionalTopicOperatorTest {
     }
 
     @Test
-    public void testMakeOperator() {
+    public void testBuildOperator() {
         AtomicReference<ControlLoopOperationParams> paramsRef = new AtomicReference<>();
-        AtomicReference<BidirectionalTopicOperator> operRef = new AtomicReference<>();
+        AtomicReference<BidirectionalTopicConfig> configRef = new AtomicReference<>();
 
         // @formatter:off
-        BiFunction<ControlLoopOperationParams, BidirectionalTopicOperator,
-                    BidirectionalTopicOperation<String, Integer>> maker =
-                        (params, operator) -> {
-                            paramsRef.set(params);
-                            operRef.set(operator);
-                            return operation;
-                        };
+        @SuppressWarnings("rawtypes")
+        OperationMaker<BidirectionalTopicConfig, BidirectionalTopicOperation> maker =
+            (params, config) -> {
+                paramsRef.set(params);
+                configRef.set(config);
+                return operation;
+            };
         // @formatter:on
 
         BidirectionalTopicOperator oper2 =
-                        BidirectionalTopicOperator.makeOperator(ACTOR, OPERATION, mgr, maker, new SelectorKey(""));
+                        new BidirectionalTopicOperator(ACTOR, OPERATION, mgr, maker, new SelectorKey(""));
 
         assertEquals(ACTOR, oper2.getActorName());
         assertEquals(OPERATION, oper2.getName());
 
         ControlLoopOperationParams params2 = ControlLoopOperationParams.builder().build();
 
+        // not running yet
+        assertThatIllegalStateException().isThrownBy(() -> oper2.buildOperation(params2));
+
+        // configure and start it
+        params = BidirectionalTopicParams.builder().sourceTopic(MY_SOURCE).sinkTopic(MY_SINK).timeoutSec(TIMEOUT_SEC)
+                        .build();
+        oper2.configure(Util.translateToMap(OPERATION, params));
+        oper2.start();
+
         assertSame(operation, oper2.buildOperation(params2));
         assertSame(params2, paramsRef.get());
-        assertSame(oper2, operRef.get());
+        assertSame(oper2.getCurrentConfig(), configRef.get());
+
+        // with no operation-maker
+        BidirectionalTopicOperator oper3 =
+                        new BidirectionalTopicOperator(ACTOR, OPERATION, mgr, Arrays.asList(new SelectorKey("")));
+        assertThatThrownBy(() -> oper3.buildOperation(params2)).isInstanceOf(UnsupportedOperationException.class);
     }
 
 
index 80b1d42..dacd3a5 100644 (file)
@@ -40,11 +40,11 @@ public class HttpActorTest {
     private static final String CLIENT = "my-client";
     private static final int TIMEOUT = 10;
 
-    private HttpActor actor;
+    private HttpActor<HttpActorParams> actor;
 
     @Before
     public void setUp() {
-        actor = new HttpActor(ACTOR);
+        actor = new HttpActor<>(ACTOR, HttpActorParams.class);
     }
 
     @Test
@@ -59,7 +59,7 @@ public class HttpActorTest {
                         "operB", Map.of("path", "urlB")));
         // @formatter:on
 
-        final HttpActor prov = new HttpActor(ACTOR);
+        final HttpActor<HttpActorParams> prov = new HttpActor<>(ACTOR, HttpActorParams.class);
         Function<String, Map<String, Object>> maker =
                         prov.makeOperatorParameters(Util.translateToMap(prov.getName(), params));
 
index 8189c74..2e9f58c 100644 (file)
@@ -29,7 +29,7 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.spy;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.when;
 
 import java.util.Collections;
@@ -39,6 +39,7 @@ import java.util.UUID;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -67,6 +68,7 @@ import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
 import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams.TopicParamsBuilder;
 import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
 import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
 import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
@@ -76,11 +78,10 @@ import org.onap.policy.common.gson.GsonMessageBodyHandler;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.network.NetworkUtil;
 import org.onap.policy.controlloop.VirtualControlLoopEvent;
-import org.onap.policy.controlloop.actorserviceprovider.Operation;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
-import org.onap.policy.controlloop.actorserviceprovider.Util;
 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.controlloop.actorserviceprovider.parameters.HttpParams;
 import org.onap.policy.controlloop.policy.PolicyResult;
 
@@ -110,9 +111,12 @@ public class HttpOperationTest {
 
     @Mock
     private HttpClient client;
-
+    @Mock
+    private HttpClientFactory clientFactory;
     @Mock
     private Response response;
+    @Mock
+    private Executor executor;
 
     private VirtualControlLoopEvent event;
     private ControlLoopEventContext context;
@@ -120,7 +124,7 @@ public class HttpOperationTest {
     private OperationOutcome outcome;
     private AtomicReference<InvocationCallback<Response>> callback;
     private Future<Response> future;
-    private HttpOperator operator;
+    private HttpConfig config;
     private MyGetOperation<String> oper;
 
     /**
@@ -192,19 +196,9 @@ public class HttpOperationTest {
         callback = new AtomicReference<>();
         future = new CompletableFuture<>();
 
-        operator = new HttpOperator(ACTOR, OPERATION) {
-            @Override
-            public Operation buildOperation(ControlLoopOperationParams params) {
-                return null;
-            }
+        when(clientFactory.get(any())).thenReturn(client);
 
-            @Override
-            public HttpClient getClient() {
-                return client;
-            }
-        };
-
-        initOper(operator, HTTP_CLIENT);
+        initConfig(HTTP_CLIENT);
 
         oper = new MyGetOperation<>(String.class);
     }
@@ -229,7 +223,9 @@ public class HttpOperationTest {
     @Test
     public void testMakeUrl() {
         // use a real client
-        client = HttpClientFactoryInstance.getClientFactory().get(HTTP_CLIENT);
+        initRealConfig(HTTP_CLIENT);
+
+        oper = new MyGetOperation<>(String.class);
 
         assertThat(oper.makeUrl()).endsWith("/" + BASE_URI + PATH);
     }
@@ -243,19 +239,6 @@ public class HttpOperationTest {
 
         // should use given value
         assertEquals(20 * 1000L, oper.getTimeoutMs(20));
-
-        // indicate we have a timeout value
-        operator = spy(operator);
-        when(operator.getTimeoutMs()).thenReturn(30L);
-
-        oper = new MyGetOperation<String>(String.class);
-
-        // should use default
-        assertEquals(30L, oper.getTimeoutMs(null));
-        assertEquals(30L, oper.getTimeoutMs(0));
-
-        // should use given value
-        assertEquals(40 * 1000L, oper.getTimeoutMs(40));
     }
 
     /**
@@ -366,7 +349,7 @@ public class HttpOperationTest {
     @Test
     public void testGet() throws Exception {
         // use a real client
-        client = HttpClientFactoryInstance.getClientFactory().get(HTTP_CLIENT);
+        initRealConfig(HTTP_CLIENT);
 
         MyGetOperation<MyResponse> oper2 = new MyGetOperation<>(MyResponse.class);
 
@@ -382,7 +365,7 @@ public class HttpOperationTest {
     @Test
     public void testDelete() throws Exception {
         // use a real client
-        client = HttpClientFactoryInstance.getClientFactory().get(HTTP_CLIENT);
+        initRealConfig(HTTP_CLIENT);
 
         MyDeleteOperation oper2 = new MyDeleteOperation();
 
@@ -398,8 +381,7 @@ public class HttpOperationTest {
     @Test
     public void testPost() throws Exception {
         // use a real client
-        client = HttpClientFactoryInstance.getClientFactory().get(HTTP_CLIENT);
-
+        initRealConfig(HTTP_CLIENT);
         MyPostOperation oper2 = new MyPostOperation();
 
         OperationOutcome outcome = runOperation(oper2);
@@ -414,7 +396,7 @@ public class HttpOperationTest {
     @Test
     public void testPut() throws Exception {
         // use a real client
-        client = HttpClientFactoryInstance.getClientFactory().get(HTTP_CLIENT);
+        initRealConfig(HTTP_CLIENT);
 
         MyPutOperation oper2 = new MyPutOperation();
 
@@ -454,18 +436,34 @@ public class HttpOperationTest {
     }
 
     /**
-     * Initializes the given operator.
+     * Initializes the configuration.
      *
      * @param operator operator to be initialized
      * @param clientName name of the client which it should use
      */
-    private void initOper(HttpOperator operator, String clientName) {
-        operator.stop();
+    private void initConfig(String clientName) {
+        initConfig(clientName, clientFactory);
+    }
 
+    /**
+     * Initializes the configuration with a real client.
+     *
+     * @param operator operator to be initialized
+     * @param clientName name of the client which it should use
+     */
+    private void initConfig(String clientName, HttpClientFactory factory) {
         HttpParams params = HttpParams.builder().clientName(clientName).path(PATH).timeoutSec(1).build();
-        Map<String, Object> mapParams = Util.translateToMap(OPERATION, params);
-        operator.configure(mapParams);
-        operator.start();
+        config = new HttpConfig(executor, params, factory);
+    }
+
+    /**
+     * Initializes the configuration with a real client.
+     *
+     * @param operator operator to be initialized
+     * @param clientName name of the client which it should use
+     */
+    private void initRealConfig(String clientName) {
+        initConfig(clientName, HttpClientFactoryInstance.getClientFactory());
     }
 
     /**
@@ -497,7 +495,7 @@ public class HttpOperationTest {
 
     private class MyGetOperation<T> extends HttpOperation<T> {
         public MyGetOperation(Class<T> responseClass) {
-            super(HttpOperationTest.this.params, HttpOperationTest.this.operator, responseClass);
+            super(HttpOperationTest.this.params, HttpOperationTest.this.config, responseClass);
         }
 
         @Override
@@ -511,14 +509,14 @@ public class HttpOperationTest {
 
             // @formatter:off
             return handleResponse(outcome, url,
-                callback -> operator.getClient().get(callback, makePath(), headers));
+                callback -> getClient().get(callback, makePath(), headers));
             // @formatter:on
         }
     }
 
     private class MyPostOperation extends HttpOperation<MyResponse> {
         public MyPostOperation() {
-            super(HttpOperationTest.this.params, HttpOperationTest.this.operator, MyResponse.class);
+            super(HttpOperationTest.this.params, HttpOperationTest.this.config, MyResponse.class);
         }
 
         @Override
@@ -537,14 +535,14 @@ public class HttpOperationTest {
 
             // @formatter:off
             return handleResponse(outcome, url,
-                callback -> operator.getClient().post(callback, makePath(), entity, headers));
+                callback -> getClient().post(callback, makePath(), entity, headers));
             // @formatter:on
         }
     }
 
     private class MyPutOperation extends HttpOperation<MyResponse> {
         public MyPutOperation() {
-            super(HttpOperationTest.this.params, HttpOperationTest.this.operator, MyResponse.class);
+            super(HttpOperationTest.this.params, HttpOperationTest.this.config, MyResponse.class);
         }
 
         @Override
@@ -563,14 +561,14 @@ public class HttpOperationTest {
 
             // @formatter:off
             return handleResponse(outcome, url,
-                callback -> operator.getClient().put(callback, makePath(), entity, headers));
+                callback -> getClient().put(callback, makePath(), entity, headers));
             // @formatter:on
         }
     }
 
     private class MyDeleteOperation extends HttpOperation<String> {
         public MyDeleteOperation() {
-            super(HttpOperationTest.this.params, HttpOperationTest.this.operator, String.class);
+            super(HttpOperationTest.this.params, HttpOperationTest.this.config, String.class);
         }
 
         @Override
@@ -584,7 +582,7 @@ public class HttpOperationTest {
 
             // @formatter:off
             return handleResponse(outcome, url,
-                callback -> operator.getClient().delete(callback, makePath(), headers));
+                callback -> getClient().delete(callback, makePath(), headers));
             // @formatter:on
         }
     }
index 081bb34..873a306 100644 (file)
 
 package org.onap.policy.controlloop.actorserviceprovider.impl;
 
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
 import static org.mockito.Mockito.when;
 
 import java.util.Map;
@@ -42,6 +42,7 @@ import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.Util;
 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.controlloop.actorserviceprovider.parameters.HttpParams;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ParameterValidationRuntimeException;
 
@@ -86,63 +87,65 @@ public class HttpOperatorTest {
     }
 
     @Test
-    public void testGetClient() {
-        assertNotNull(oper.getClient());
+    public void testDoConfigureMapOfStringObject_testGetConfig() {
+        // start with an UNCONFIGURED operator
+        oper.shutdown();
+        oper = new MyOperator();
+
+        assertNull(oper.getCurrentConfig());
+
+        HttpParams params = HttpParams.builder().clientName(HTTP_CLIENT).path(PATH).timeoutSec(TIMEOUT).build();
+        Map<String, Object> paramMap = Util.translateToMap(OPERATION, params);
+        oper.configure(paramMap);
+
+        assertNotNull(oper.getCurrentConfig());
+
+        // test invalid parameters
+        paramMap.remove("path");
+        assertThatThrownBy(() -> oper.configure(paramMap)).isInstanceOf(ParameterValidationRuntimeException.class);
     }
 
     @Test
-    public void testMakeOperator() {
-        HttpOperator oper2 = HttpOperator.makeOperator(ACTOR, OPERATION, MyOperation::new);
+    public void testBuildOperation() {
+        HttpOperator oper2 = new MyOperator();
         assertNotNull(oper2);
+        assertNotNull(oper2.getClientFactory());
 
         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
         ControlLoopEventContext context = new ControlLoopEventContext(event);
         ControlLoopOperationParams params =
                         ControlLoopOperationParams.builder().actor(ACTOR).operation(OPERATION).context(context).build();
 
+        // not running yet
+        assertThatIllegalStateException().isThrownBy(() -> oper2.buildOperation(params));
+
+        // configure and start it
+        HttpParams params2 = HttpParams.builder().clientName(HTTP_CLIENT).path(PATH).timeoutSec(TIMEOUT).build();
+        Map<String, Object> paramMap = Util.translateToMap(OPERATION, params2);
+        oper2.configure(paramMap);
+        oper2.start();
+
         Operation operation1 = oper2.buildOperation(params);
         assertNotNull(operation1);
 
         Operation operation2 = oper2.buildOperation(params);
         assertNotNull(operation2);
         assertNotSame(operation1, operation2);
+
+        // with no operation-maker
+        HttpOperator oper3 = new HttpOperator(ACTOR, OPERATION);
+        assertThatThrownBy(() -> oper3.buildOperation(params)).isInstanceOf(UnsupportedOperationException.class);
     }
 
     @Test
-    public void testDoConfigureMapOfStringObject_testGetClient_testGetPath_testGetTimeoutMs() {
-        // start with an UNCONFIGURED operator
-        oper.shutdown();
-        oper = new MyOperator();
-
-        assertNull(oper.getClient());
-        assertNull(oper.getPath());
-
-        // no timeout yet
-        assertEquals(0L, oper.getTimeoutMs());
-
-        HttpParams params = HttpParams.builder().clientName(HTTP_CLIENT).path(PATH).timeoutSec(TIMEOUT).build();
-        Map<String, Object> paramMap = Util.translateToMap(OPERATION, params);
-        oper.configure(paramMap);
-
-        assertSame(client, oper.getClient());
-        assertEquals(PATH, oper.getPath());
-
-        // should use given value
-        assertEquals(TIMEOUT * 1000, oper.getTimeoutMs());
-
-        // test invalid parameters
-        paramMap.remove("path");
-        assertThatThrownBy(() -> oper.configure(paramMap)).isInstanceOf(ParameterValidationRuntimeException.class);
+    public void testGetClientFactory() {
+        HttpOperator oper2 = new HttpOperator(ACTOR, OPERATION);
+        assertNotNull(oper2.getClientFactory());
     }
 
     private class MyOperator extends HttpOperator {
         public MyOperator() {
-            super(ACTOR, OPERATION);
-        }
-
-        @Override
-        public Operation buildOperation(ControlLoopOperationParams params) {
-            return null;
+            super(ACTOR, OPERATION, MyOperation::new);
         }
 
         @Override
@@ -152,8 +155,8 @@ public class HttpOperatorTest {
     }
 
     private class MyOperation extends HttpOperation<String> {
-        public MyOperation(ControlLoopOperationParams params, HttpOperator operator) {
-            super(params, operator, String.class);
+        public MyOperation(ControlLoopOperationParams params, HttpConfig config) {
+            super(params, config, String.class);
         }
 
         @Override
index 67ac27c..39564a4 100644 (file)
@@ -21,7 +21,6 @@
 package org.onap.policy.controlloop.actorserviceprovider.impl;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -41,7 +40,6 @@ import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionException;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
 import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
@@ -70,6 +68,7 @@ import org.onap.policy.controlloop.actorserviceprovider.Operation;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.OperatorConfig;
 import org.onap.policy.controlloop.policy.PolicyResult;
 import org.slf4j.LoggerFactory;
 
@@ -111,7 +110,7 @@ public class OperationPartialTest {
     private OperationOutcome opstart;
     private OperationOutcome opend;
 
-    private OperatorPartial operator;
+    private OperatorConfig config;
 
     /**
      * Attaches the appender to the logger.
@@ -150,20 +149,7 @@ public class OperationPartialTest {
                         .executor(executor).actor(ACTOR).operation(OPERATION).timeoutSec(TIMEOUT)
                         .startCallback(this::starter).targetEntity(MY_SINK).build();
 
-        operator = new OperatorPartial(ACTOR, OPERATION) {
-            @Override
-            public Executor getBlockingExecutor() {
-                return executor;
-            }
-
-            @Override
-            public Operation buildOperation(ControlLoopOperationParams params) {
-                return null;
-            }
-        };
-
-        operator.configure(null);
-        operator.start();
+        config = new OperatorConfig(executor);
 
         oper = new MyOper();
 
@@ -197,34 +183,11 @@ public class OperationPartialTest {
         assertNull(future.get(5, TimeUnit.SECONDS));
     }
 
-    /**
-     * Exercises the doXxx() methods.
-     */
-    @Test
-    public void testDoXxx() {
-        assertThatCode(() -> operator.doConfigure(null)).doesNotThrowAnyException();
-        assertThatCode(() -> operator.doStart()).doesNotThrowAnyException();
-        assertThatCode(() -> operator.doStop()).doesNotThrowAnyException();
-        assertThatCode(() -> operator.doShutdown()).doesNotThrowAnyException();
-
-    }
-
     @Test
     public void testStart() {
         verifyRun("testStart", 1, 1, PolicyResult.SUCCESS);
     }
 
-    /**
-     * Tests startOperation() when the operator is not running.
-     */
-    @Test
-    public void testStartNotRunning() {
-        // stop the operator
-        operator.stop();
-
-        assertThatIllegalStateException().isThrownBy(() -> oper.start());
-    }
-
     /**
      * Tests startOperation() when the operation has a preprocessor.
      */
@@ -392,7 +355,7 @@ public class OperationPartialTest {
         /*
          * Use an operation that doesn't override doOperation().
          */
-        OperationPartial oper2 = new OperationPartial(params, operator) {};
+        OperationPartial oper2 = new OperationPartial(params, config) {};
 
         oper2.start();
         assertTrue(executor.runAll(MAX_REQUESTS));
@@ -1101,7 +1064,7 @@ public class OperationPartialTest {
     @Test
     public void testGetRetryWait() {
         // need an operator that doesn't override the retry time
-        OperationPartial oper2 = new OperationPartial(params, operator) {};
+        OperationPartial oper2 = new OperationPartial(params, config) {};
         assertEquals(OperationPartial.DEFAULT_RETRY_WAIT_MS, oper2.getRetryWaitMs());
     }
 
@@ -1257,7 +1220,7 @@ public class OperationPartialTest {
 
 
         public MyOper() {
-            super(OperationPartialTest.this.params, operator);
+            super(OperationPartialTest.this.params, config);
         }
 
         @Override
diff --git a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/BidirectionalTopicConfigTest.java b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/BidirectionalTopicConfigTest.java
new file mode 100644 (file)
index 0000000..7c6a98f
--- /dev/null
@@ -0,0 +1,79 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actorserviceprovider.parameters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Executor;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.controlloop.actorserviceprovider.topic.BidirectionalTopicHandler;
+import org.onap.policy.controlloop.actorserviceprovider.topic.BidirectionalTopicManager;
+import org.onap.policy.controlloop.actorserviceprovider.topic.Forwarder;
+import org.onap.policy.controlloop.actorserviceprovider.topic.SelectorKey;
+
+public class BidirectionalTopicConfigTest {
+    private static final String MY_SINK = "my-sink";
+    private static final String MY_SOURCE = "my-source";
+    private static final int TIMEOUT_SEC = 10;
+
+    @Mock
+    private BidirectionalTopicManager topicManager;
+    @Mock
+    private BidirectionalTopicHandler topicHandler;
+    @Mock
+    private Forwarder forwarder;
+    @Mock
+    private Executor executor;
+
+    private BidirectionalTopicConfig config;
+
+    /**
+     * Sets up.
+     */
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        List<SelectorKey> keys = Arrays.asList(new SelectorKey(""));
+
+        when(topicManager.getTopicHandler(MY_SINK, MY_SOURCE)).thenReturn(topicHandler);
+        when(topicHandler.addForwarder(keys)).thenReturn(forwarder);
+
+        BidirectionalTopicParams params = BidirectionalTopicParams.builder().sinkTopic(MY_SINK).sourceTopic(MY_SOURCE)
+                        .timeoutSec(TIMEOUT_SEC).build();
+        config = new BidirectionalTopicConfig(executor, params, topicManager, keys);
+    }
+
+    @Test
+    public void test() {
+        assertSame(executor, config.getBlockingExecutor());
+        assertSame(topicHandler, config.getTopicHandler());
+        assertSame(forwarder, config.getForwarder());
+        assertEquals(1000L * TIMEOUT_SEC, config.getTimeoutMs());
+    }
+}
diff --git a/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/HttpConfigTest.java b/models-interactions/model-actors/actorServiceProvider/src/test/java/org/onap/policy/controlloop/actorserviceprovider/parameters/HttpConfigTest.java
new file mode 100644 (file)
index 0000000..309b30f
--- /dev/null
@@ -0,0 +1,69 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.actorserviceprovider.parameters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.Executor;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
+
+public class HttpConfigTest {
+    private static final String MY_CLIENT = "my-client";
+    private static final String MY_PATH = "my-path";
+    private static final int TIMEOUT_SEC = 10;
+
+    @Mock
+    private HttpClient client;
+    @Mock
+    private HttpClientFactory factory;
+    @Mock
+    private Executor executor;
+
+    private HttpConfig config;
+
+    /**
+     * Sets up.
+     */
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(factory.get(MY_CLIENT)).thenReturn(client);
+
+        HttpParams params = HttpParams.builder().clientName(MY_CLIENT).path(MY_PATH).timeoutSec(TIMEOUT_SEC).build();
+        config = new HttpConfig(executor, params, factory);
+    }
+
+    @Test
+    public void test() {
+        assertSame(executor, config.getBlockingExecutor());
+        assertSame(client, config.getClient());
+        assertEquals(MY_PATH, config.getPath());
+        assertEquals(1000L * TIMEOUT_SEC, config.getTimeoutMs());
+    }
+}