diff options
author | Jorge Hernandez <jorge.hernandez-herrero@att.com> | 2020-07-21 23:29:12 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@onap.org> | 2020-07-21 23:29:12 +0000 |
commit | ca8d5af8a7fa4d8120b76477f096cdc83638987a (patch) | |
tree | 5db620bf1046991ec86e549cf966838f87faacf8 /policy-management/src | |
parent | 8821c49a987de518eef2fe79b909be92b8656bc6 (diff) | |
parent | 8382101e6c43578b6c78dfc10bacbd165e413c69 (diff) |
Merge "Support multiple Policy/Controller types using 'controller.type' property"
Diffstat (limited to 'policy-management/src')
10 files changed, 308 insertions, 17 deletions
diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java b/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java index 7652a671..a355f6f7 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java +++ b/policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java @@ -1,8 +1,8 @@ /* * ============LICENSE_START======================================================= - * policy-management + * ONAP * ================================================================================ - * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-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. @@ -49,6 +49,7 @@ public interface DroolsControllerFactory { /** * Explicit construction of a Drools Controller. * + * @param properties properties containing initialization parameters * @param groupId maven group id of drools artifact * @param artifactId maven artifact id of drools artifact * @param version maven version id of drools artifact @@ -59,7 +60,7 @@ public interface DroolsControllerFactory { * @throws IllegalArgumentException with invalid parameters * @throws LinkageError Failure to link rules and models in Drools Libraries */ - DroolsController build(String groupId, String artifactId, String version, + DroolsController build(Properties properties, String groupId, String artifactId, String version, List<TopicCoderFilterConfiguration> decoderConfigurations, List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError; diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java b/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java index 6d42ba53..e8234a46 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java +++ b/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; import org.onap.policy.common.endpoints.event.comm.Topic; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; @@ -32,6 +33,8 @@ import org.onap.policy.common.endpoints.event.comm.TopicSource; import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; import org.onap.policy.drools.controller.internal.MavenDroolsController; import org.onap.policy.drools.controller.internal.NullDroolsController; +import org.onap.policy.drools.features.DroolsControllerFeatureApi; +import org.onap.policy.drools.features.DroolsControllerFeatureApiConstants; import org.onap.policy.drools.properties.DroolsPropertyConstants; import org.onap.policy.drools.protocol.coders.JsonProtocolFilter; import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration; @@ -48,12 +51,12 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { /** * logger. */ - private static Logger logger = LoggerFactory.getLogger(IndexedDroolsControllerFactory.class); + private static final Logger logger = LoggerFactory.getLogger(IndexedDroolsControllerFactory.class); /** * Policy Controller Name Index. */ - protected HashMap<String, DroolsController> droolsControllers = new HashMap<>(); + protected Map<String, DroolsController> droolsControllers = new HashMap<>(); /** * Null Drools Controller. @@ -97,11 +100,12 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { List<TopicCoderFilterConfiguration> topics2DecodedClasses2Filters = codersAndFilters(properties, eventSources); List<TopicCoderFilterConfiguration> topics2EncodedClasses2Filters = codersAndFilters(properties, eventSinks); - return this.build(groupId, artifactId, version, topics2DecodedClasses2Filters, topics2EncodedClasses2Filters); + return this.build(properties, groupId, artifactId, version, + topics2DecodedClasses2Filters, topics2EncodedClasses2Filters); } @Override - public DroolsController build(String newGroupId, String newArtifactId, String newVersion, + public DroolsController build(Properties properties, String newGroupId, String newArtifactId, String newVersion, List<TopicCoderFilterConfiguration> decoderConfigurations, List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError { @@ -148,16 +152,51 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { /* new drools controller */ - DroolsController controller = new MavenDroolsController(newGroupId, newArtifactId, newVersion, - decoderConfigurations, encoderConfigurations); + DroolsController controller = null; + for (DroolsControllerFeatureApi feature: getProviders()) { + try { + controller = feature.beforeInstance(properties, + newGroupId, newArtifactId, newVersion, + decoderConfigurations, encoderConfigurations); + if (controller != null) { + logger.info("feature {} ({}) beforeInstance() has intercepted drools controller {}:{}:{}", + feature.getName(), feature.getSequenceNumber(), + newGroupId, newArtifactId, newVersion); + break; + } + } catch (RuntimeException r) { + logger.error("feature {} ({}) beforeInstance() of drools controller {}:{}:{} failed", + feature.getName(), feature.getSequenceNumber(), + newGroupId, newArtifactId, newVersion, r); + } + } + + if (controller == null) { + controller = new MavenDroolsController(newGroupId, newArtifactId, newVersion, decoderConfigurations, + encoderConfigurations); + } synchronized (this) { droolsControllers.put(controllerId, controller); } + for (DroolsControllerFeatureApi feature: getProviders()) { + try { + feature.afterInstance(controller, properties); + } catch (RuntimeException r) { + logger.error("feature {} ({}) afterInstance() of drools controller {}:{}:{} failed", + feature.getName(), feature.getSequenceNumber(), + newGroupId, newArtifactId, newVersion, r); + } + } + return controller; } + protected List<DroolsControllerFeatureApi> getProviders() { + return DroolsControllerFeatureApiConstants.getProviders().getList(); + } + /** * find out decoder classes and filters. * diff --git a/policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureApi.java b/policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureApi.java index abf524e4..bb11bb64 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureApi.java +++ b/policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureApi.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-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. @@ -20,9 +20,12 @@ package org.onap.policy.drools.features; +import java.util.List; +import java.util.Properties; import org.onap.policy.common.endpoints.event.comm.TopicSink; import org.onap.policy.common.utils.services.OrderedService; import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration; /** * Drools Controller Feature API. Hooks into the Drools Controller operations. @@ -30,6 +33,38 @@ import org.onap.policy.drools.controller.DroolsController; public interface DroolsControllerFeatureApi extends OrderedService { /** + * intercepts the instantiation of a DroolsController. + * + * @param properties controller properties + * @param groupId group id coordinate + * @param artifactId artifact id coordinate + * @param version version coordinate + * @param decoderConfigurations decoder configurations + * @param encoderConfigurations encoder configurations + * + * @return a Drools Controller or 'null' for no intercept + */ + default DroolsController beforeInstance(Properties properties, + String groupId, String artifactId, String version, + List<TopicCoderFilterConfiguration> decoderConfigurations, + List<TopicCoderFilterConfiguration> encoderConfigurations) { + return null; + } + + /** + * called after a DroolsController is instantiated. + * + * @param droolsController drools controller + * @param properties controller properties + * + * @return True if this feature intercepts and takes ownership of the operation + * preventing the invocation of lower priority features. False, otherwise + */ + default boolean afterInstance(DroolsController droolsController, Properties properties) { + return false; + } + + /** * intercepts before the Drools Controller gives the Policy Container a fact to * insert into its Policy Sessions. * diff --git a/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java index d11863f0..f022bf1d 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java +++ b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java @@ -58,6 +58,32 @@ public interface PolicyControllerFeatureApi extends OrderedService { } /** + * called before the actual instantiation of a Policy Controller. + * + * @param name name of the controller + * @param properties configuration parameters in the form of properties + * + * @return a Policy Controller or 'null for no intercept. + */ + default PolicyController beforeInstance(String name, Properties properties) { + return null; + } + + /** + * called after the Policy Controller is instantiated. + * + * @param controller policy controller + * @param properties configuration parameters in the form of properties + * + * @return true if this feature intercepts and takes ownership + * of the operation preventing the invocation of + * lower priority features. False, otherwise. + */ + default boolean afterInstance(PolicyController controller, Properties properties) { + return false; + } + + /** * intercept before the Policy Controller is started. * * @return true if this feature intercepts and takes ownership diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/IndexedPolicyControllerFactory.java b/policy-management/src/main/java/org/onap/policy/drools/system/IndexedPolicyControllerFactory.java index 75fb600d..84247efe 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/system/IndexedPolicyControllerFactory.java +++ b/policy-management/src/main/java/org/onap/policy/drools/system/IndexedPolicyControllerFactory.java @@ -23,6 +23,7 @@ package org.onap.policy.drools.system; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; import org.onap.policy.common.gson.annotation.GsonJsonIgnore; import org.onap.policy.drools.controller.DroolsController; @@ -43,13 +44,13 @@ class IndexedPolicyControllerFactory implements PolicyControllerFactory { /** * Policy Controller Name Index. */ - private final HashMap<String, PolicyController> policyControllers = + private final Map<String, PolicyController> policyControllers = new HashMap<>(); /** * Group/Artifact Ids Index. */ - private final HashMap<String, PolicyController> coordinates2Controller = + private final Map<String, PolicyController> coordinates2Controller = new HashMap<>(); /** @@ -378,7 +379,35 @@ class IndexedPolicyControllerFactory implements PolicyControllerFactory { // these methods can be overridden by junit tests protected PolicyController newPolicyController(String name, Properties properties) { - return new AggregatedPolicyController(name, properties); + PolicyController controller = null; + for (PolicyControllerFeatureApi feature: getProviders()) { + try { + controller = feature.beforeInstance(name, properties); + if (controller != null) { + logger.info("feature {} ({}) beforeInstance() has intercepted controller {}", + feature.getName(), feature.getSequenceNumber(), name); + break; + } + } catch (RuntimeException r) { + logger.error("feature {} ({}) beforeInstance() of controller {} failed", + feature.getName(), feature.getSequenceNumber(), name, r); + } + } + + if (controller == null) { + controller = new AggregatedPolicyController(name, properties); + } + + for (PolicyControllerFeatureApi feature: getProviders()) { + try { + feature.afterInstance(controller, properties); + } catch (RuntimeException r) { + logger.error("feature {} ({}) afterInstance() of controller {} failed ", + feature.getName(), feature.getSequenceNumber(), name, r); + } + } + + return controller; } protected List<PolicyControllerFeatureApi> getProviders() { diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java b/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java index 6e883a03..3f744024 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java +++ b/policy-management/src/main/java/org/onap/policy/drools/system/internal/AggregatedPolicyController.java @@ -72,12 +72,12 @@ public class AggregatedPolicyController implements PolicyController, TopicListen /** * Abstracted Event Sources List regardless communication technology. */ - private final List<TopicSource> sources; + protected final List<TopicSource> sources; /** * Abstracted Event Sinks List regardless communication technology. */ - private final List<TopicSink> sinks; + protected final List<TopicSink> sinks; /** * Mapping topics to sinks. @@ -100,7 +100,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen /** * Policy Drools Controller. */ - private final AtomicReference<DroolsController> droolsController = new AtomicReference<>(); + protected final AtomicReference<DroolsController> droolsController = new AtomicReference<>(); /** * Properties used to initialize controller. @@ -188,7 +188,7 @@ public class AggregatedPolicyController implements PolicyController, TopicListen * * @throws IllegalArgumentException if invalid parameters are passed in */ - private void initDrools(Properties properties) { + protected void initDrools(Properties properties) { try { // Register with drools infrastructure this.droolsController.set(getDroolsFactory().build(properties, sources, sinks)); diff --git a/policy-management/src/test/java/org/onap/policy/drools/controller/DroolsControllerFactoryTest.java b/policy-management/src/test/java/org/onap/policy/drools/controller/DroolsControllerFactoryTest.java index 7733ca1f..03301470 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/controller/DroolsControllerFactoryTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/controller/DroolsControllerFactoryTest.java @@ -22,15 +22,26 @@ package org.onap.policy.drools.controller; 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.junit.Assert.fail; +import static org.onap.policy.drools.properties.DroolsPropertyConstants.PROPERTY_CONTROLLER_TYPE; import java.util.List; import java.util.Properties; import org.junit.Test; +import org.onap.policy.drools.controller.internal.NullDroolsController; +import org.onap.policy.drools.features.DroolsControllerFeatureApi; +import org.onap.policy.drools.properties.DroolsPropertyConstants; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration; public class DroolsControllerFactoryTest { + private static final String DROOLS_CONTROLLER_BUILDER_TAG = "DroolsControllerFactoryTest"; + public static final String TEST_GROUP_ID = "testGroupId"; + public static final String TEST_ARTIFACT_ID = "testArtifactId"; + public static final String TEST_VERSION = "testVersion"; + @Test public void testBuildNullController() { Properties droolsProps = new Properties(); @@ -95,6 +106,28 @@ public class DroolsControllerFactoryTest { return DroolsControllerConstants.NO_VERSION.equals(droolsController.getVersion()); } + @Test + public void testControllerType() { + DroolsControllerFactory droolsFactory = new IndexedDroolsControllerFactory(); + Properties props = new Properties(); + + // this should build a 'NullDroolsController' + DroolsController ctrl1 = droolsFactory.build(props, null, null); + assertSame(NullDroolsController.class, ctrl1.getClass()); + + props.setProperty(PROPERTY_CONTROLLER_TYPE, DROOLS_CONTROLLER_BUILDER_TAG); + props.setProperty(DroolsPropertyConstants.RULES_GROUPID, TEST_GROUP_ID); + props.setProperty(DroolsPropertyConstants.RULES_ARTIFACTID, TEST_ARTIFACT_ID); + props.setProperty(DroolsPropertyConstants.RULES_VERSION, TEST_VERSION); + + // this should build a 'TestDroolsController' + DroolsController ctrl2 = droolsFactory.build(props, null, null); + assertSame(TestDroolsController.class, ctrl2.getClass()); + + // verify that we can find the controller in the factory table + assertSame(ctrl2, droolsFactory.get(ctrl2.getGroupId(), ctrl2.getArtifactId(), null)); + } + private boolean isActualController(DroolsController droolsController) { if (droolsController == null) { return false; @@ -110,4 +143,44 @@ public class DroolsControllerFactoryTest { return droolsController.getVersion() != null && droolsController.getVersion().substring(0, 1).matches("[0-9]"); } + + /** + * This class provides an alternate DroolsController implementation, + * for the purpose of easy identification within a Junit test. + */ + public static class TestDroolsController extends NullDroolsController { + @Override + public String getGroupId() { + return TEST_GROUP_ID; + } + + @Override + public String getArtifactId() { + return TEST_ARTIFACT_ID; + } + } + + /** + * An instance of this class is created by 'IndexedDroolsControllerFactory', + * using features. It does the build operation when the value of the + * 'controller.type' property matches the value of DROOLS_CONTROLLER_BUILDER_TAG. + */ + public static class DroolsBuilder implements DroolsControllerFeatureApi { + @Override + public int getSequenceNumber() { + return 1; + } + + @Override + public DroolsController beforeInstance(Properties properties, + String groupId, String artifactId, String version, + List<TopicCoderFilterConfiguration> decoderConfigurations, + List<TopicCoderFilterConfiguration> encoderConfigurations) { + + if (DROOLS_CONTROLLER_BUILDER_TAG.equals(properties.getProperty(PROPERTY_CONTROLLER_TYPE))) { + return new TestDroolsController(); + } + return null; + } + } } diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java index 1c5eb61d..818f8fc1 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java @@ -24,12 +24,14 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.onap.policy.drools.properties.DroolsPropertyConstants.PROPERTY_CONTROLLER_TYPE; import java.util.Arrays; import java.util.Collections; @@ -39,10 +41,15 @@ import org.junit.Before; import org.junit.Test; import org.onap.policy.common.utils.gson.GsonTestUtils; import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.controller.internal.NullDroolsController; +import org.onap.policy.drools.features.DroolsControllerFeatureApi; import org.onap.policy.drools.features.PolicyControllerFeatureApi; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration; import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; +import org.onap.policy.drools.system.internal.AggregatedPolicyController; public class PolicyControllerFactoryTest { + private static final String POLICY_CONTROLLER_BUILDER_TAG = "PolicyControllerFactoryTest"; private static final String MY_NAME = "my-name-a"; private static final String MY_NAME2 = "my-name-b"; @@ -403,6 +410,30 @@ public class PolicyControllerFactoryTest { assertEquals(feature2, ipc.getFeatureProvider(FEATURE2)); } + @Test + public void testControllerType() { + PolicyControllerFactory factory = new IndexedPolicyControllerFactory(); + Properties props = new Properties(); + + // this should build an 'AggregatedPolicyController' + final String name1 = "ctrl1"; + PolicyController ctrl1 = factory.build(name1, props); + + // this should build a 'TestPolicyController' + final String name2 = "ctrl2"; + props.setProperty(PROPERTY_CONTROLLER_TYPE, POLICY_CONTROLLER_BUILDER_TAG); + PolicyController ctrl2 = factory.build(name2, props); + + // verify controller types + assertSame(AggregatedPolicyController.class, ctrl1.getClass()); + assertSame(TestPolicyController.class, ctrl2.getClass()); + assertSame(NullDroolsController.class, ctrl2.getDrools().getClass()); + + // verify controller lookups + assertSame(ctrl1, factory.get(name1)); + assertSame(ctrl2, factory.get(name2)); + } + /** * Factory with overrides. */ @@ -427,4 +458,58 @@ public class PolicyControllerFactoryTest { return providers; } } + + /** + * This class provides an alternate PolicyController implementation, + * for the purpose of easy identification within a junit test. + */ + public static class TestPolicyController extends AggregatedPolicyController { + public TestPolicyController(String name, Properties properties) { + super(name, properties); + } + } + + /** + * An instance of this class is created by 'IndexedPolicyControllerFactory', + * using features. It does the build operation when the value of the + * 'controller.type' property matches the value of POLICY_CONTROLLER_BUILDER_TAG. + */ + public static class PolicyBuilder implements PolicyControllerFeatureApi { + @Override + public int getSequenceNumber() { + return 1; + } + + @Override + public PolicyController beforeInstance(String name, Properties properties) { + if (POLICY_CONTROLLER_BUILDER_TAG.equals(properties.getProperty(PROPERTY_CONTROLLER_TYPE))) { + return new TestPolicyController(name, properties); + } + return null; + } + } + + /** + * An instance of this class is created by 'IndexedDroolsControllerFactory', + * using features. It does the build operation when the value of the + * 'controller.type' property matches the value of POLICY_CONTROLLER_BUILDER_TAG. + */ + public static class DroolsBuilder implements DroolsControllerFeatureApi { + @Override + public int getSequenceNumber() { + return 1; + } + + @Override + public DroolsController beforeInstance(Properties properties, + String groupId, String artifactId, String version, + List<TopicCoderFilterConfiguration> decoderConfigurations, + List<TopicCoderFilterConfiguration> encoderConfigurations) { + + if (POLICY_CONTROLLER_BUILDER_TAG.equals(properties.getProperty(PROPERTY_CONTROLLER_TYPE))) { + return new NullDroolsController(); + } + return null; + } + } } diff --git a/policy-management/src/test/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi b/policy-management/src/test/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi new file mode 100644 index 00000000..3c765a78 --- /dev/null +++ b/policy-management/src/test/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi @@ -0,0 +1,2 @@ +org.onap.policy.drools.controller.DroolsControllerFactoryTest$DroolsBuilder +org.onap.policy.drools.system.PolicyControllerFactoryTest$DroolsBuilder diff --git a/policy-management/src/test/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi b/policy-management/src/test/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi new file mode 100644 index 00000000..2a4408a8 --- /dev/null +++ b/policy-management/src/test/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi @@ -0,0 +1 @@ +org.onap.policy.drools.system.PolicyControllerFactoryTest$PolicyBuilder |