Fix checkstyle in policy-management 81/66481/2
authorPamela Dragosh <pdragosh@research.att.com>
Thu, 13 Sep 2018 23:35:18 +0000 (19:35 -0400)
committerPamela Dragosh <pdragosh@research.att.com>
Fri, 14 Sep 2018 00:00:37 +0000 (20:00 -0400)
The submodule policy-management checkstyle fixes. There may be
one or two sonar fixes in there.

Issue-ID: POLICY-882
Change-Id: I9cb43c573c6811dd058943650ba1ea5f6dc880aa
Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
22 files changed:
policy-management/src/main/java/org/onap/policy/drools/controller/DroolsController.java
policy-management/src/main/java/org/onap/policy/drools/controller/DroolsControllerFactory.java
policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java
policy-management/src/main/java/org/onap/policy/drools/controller/internal/NullDroolsController.java
policy-management/src/main/java/org/onap/policy/drools/features/DroolsControllerFeatureAPI.java
policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureAPI.java
policy-management/src/main/java/org/onap/policy/drools/features/PolicyEngineFeatureAPI.java
policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java
policy-management/src/main/java/org/onap/policy/drools/persistence/SystemPersistence.java
policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java
policy-management/src/main/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilter.java
policy-management/src/test/java/org/onap/policy/drools/controller/DroolsControllerFactoryTest.java
policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerTest.java
policy-management/src/test/java/org/onap/policy/drools/persistence/test/SystemPersistenceTest.java
policy-management/src/test/java/org/onap/policy/drools/protocol/coders/EventProtocolCoderTest.java
policy-management/src/test/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilterTest.java
policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java
policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/ControllerConfigurationTest.java
policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/DroolsConfigurationTest.java
policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/PdpdConfigurationTest.java
policy-management/src/test/java/org/onap/policy/drools/server/restful/test/RestManagerTest.java
policy-management/src/test/java/org/onap/policy/drools/system/test/PolicyEngineTest.java

index 7f68930..c582a1c 100644 (file)
@@ -30,67 +30,67 @@ import org.onap.policy.drools.core.PolicyContainer;
 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
 
 /**
- * Drools Controller is the abstractions that wraps the drools layer (policy-core)
+ * Drools Controller is the abstractions that wraps the drools layer (policy-core).
  */
 public interface DroolsController extends Startable, Lockable {
 
     /**
-     * No Group ID identifier
+     * No Group ID identifier.
      */
     public static final String NO_GROUP_ID = "NO-GROUP-ID";
 
     /**
-     * No Artifact ID identifier
+     * No Artifact ID identifier.
      */
     public static final String NO_ARTIFACT_ID = "NO-ARTIFACT-ID";
 
     /**
-     * No version identifier
+     * No version identifier.
      */
     public static final String NO_VERSION = "NO-VERSION";
 
     /**
-     * Factory to track and manage drools controllers
+     * Factory to track and manage drools controllers.
      */
     public static final DroolsControllerFactory factory = new IndexedDroolsControllerFactory();
 
     /**
-     * get group id
+     * get group id.
      * 
      * @return group id
      */
     public String getGroupId();
 
     /**
-     * get artifact id
+     * get artifact id.
      * 
      * @return artifact id
      */
     public String getArtifactId();
 
     /**
-     * get version
+     * get version.
      * 
      * @return version
      */
     public String getVersion();
 
     /**
-     * return the policy session names
+     * return the policy session names.
      * 
      * @return policy session
      */
     public List<String> getSessionNames();
 
     /**
-     * return the policy full session names
+     * return the policy full session names.
      * 
      * @return policy session
      */
     public List<String> getCanonicalSessionNames();
 
     /**
-     * offers an event to this controller for processing
+     * offers an event to this controller for processing.
      * 
      * @param topic topic associated with the event
      * @param event the event
@@ -100,10 +100,10 @@ public interface DroolsController extends Startable, Lockable {
     public boolean offer(String topic, String event);
 
     /**
-     * delivers "event" to "sink"
+     * delivers "event" to "sink".
      * 
      * @param sink destination
-     * @param event
+     * @param event event
      * @return true if successful, false if a failure has occurred.
      * @throws IllegalArgumentException when invalid or insufficient properties are provided
      * @throws IllegalStateException when the engine is in a state where this operation is not
@@ -114,32 +114,37 @@ public interface DroolsController extends Startable, Lockable {
     public boolean deliver(TopicSink sink, Object event);
 
     /**
+     * Get recent source events.
      * 
-     * @return the most recent received events
+     * @return the most recent received events.
      */
     public Object[] getRecentSourceEvents();
 
     /**
+     * Get recent sink events.
      * 
      * @return the most recent delivered events
      */
     public String[] getRecentSinkEvents();
 
     /**
+     * Get container.
+     * 
      * @return the underlying policy container
      */
     public PolicyContainer getContainer();
 
     /**
-     * Supports this encoder?
+     * Does it owns the coder.
      * 
-     * @param encodedObject
-     * @return
+     * @param coderClass the encoder object
+     * @param modelHash the hash for the model
+     * @return true it owns it
      */
     public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash);
 
     /**
-     * fetches a class from the model
+     * fetches a class from the model.
      * 
      * @param className the class to fetch
      * @return the actual class object, or null if not found
@@ -147,12 +152,12 @@ public interface DroolsController extends Startable, Lockable {
     public Class<?> fetchModelClass(String className);
 
     /**
-     * is this controller Smart?
+     * is this controller Smart.
      */
     public boolean isBrained();
 
     /**
-     * update the new version of the maven jar rules file
+     * update the new version of the maven jar rules file.
      * 
      * @param newGroupId - new group id
      * @param newArtifactId - new artifact id
@@ -162,14 +167,13 @@ public interface DroolsController extends Startable, Lockable {
      * 
      * @throws Exception from within drools libraries
      * @throws LinkageError from within drools libraries
-     * @throws ArgumentException bad parameter passed in
      */
     public void updateToVersion(String newGroupId, String newArtifactId, String newVersion,
             List<TopicCoderFilterConfiguration> decoderConfigurations,
             List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError;
 
     /**
-     * gets the classnames of facts as well as the current count
+     * gets the classnames of facts as well as the current count.
      * 
      * @param sessionName the session name
      * @return map of class to count
@@ -177,16 +181,15 @@ public interface DroolsController extends Startable, Lockable {
     public Map<String, Integer> factClassNames(String sessionName);
 
     /**
-     * gets the count of facts for a given session
+     * gets the count of facts for a given session.
      * 
      * @param sessionName the session name
      * @return the fact count
-     * @throws IllegalArgumentException
      */
     public long factCount(String sessionName);
 
     /**
-     * gets all the facts of a given class for a given session
+     * gets all the facts of a given class for a given session.
      * 
      * @param sessionName the session identifier
      * @param className the class type
@@ -196,7 +199,7 @@ public interface DroolsController extends Startable, Lockable {
     public List<Object> facts(String sessionName, String className, boolean delete);
 
     /**
-     * gets the facts associated with a query for a give session for a given queried entity
+     * gets the facts associated with a query for a give session for a given queried entity.
      * 
      * @param sessionName the session
      * @param queryName the query identifier
@@ -209,9 +212,8 @@ public interface DroolsController extends Startable, Lockable {
             Object... queryParams);
 
     /**
-     * halts and permanently releases all resources
+     * halts and permanently releases all resources.
      * 
-     * @throws IllegalStateException
      */
     public void halt();
 }
index b3aaaa7..6dcae63 100644 (file)
@@ -26,13 +26,13 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Properties;
 
-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.common.endpoints.event.comm.Topic;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.event.comm.TopicSink;
 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.properties.DroolsProperties;
 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
@@ -45,12 +45,12 @@ import org.slf4j.LoggerFactory;
 
 /**
  * Drools Controller Factory to manage controller creation, destruction, and retrieval for
- * management interfaces
+ * management interfaces.
  */
 public interface DroolsControllerFactory {
 
     /**
-     * Constructs a Drools Controller based on properties
+     * Constructs a Drools Controller based on properties.
      * 
      * @param properties properties containing initialization parameters
      * @param eventSources list of event sources
@@ -64,7 +64,7 @@ public interface DroolsControllerFactory {
             List<? extends TopicSink> eventSinks) throws LinkageError;
 
     /**
-     * Explicit construction of a Drools Controller
+     * Explicit construction of a Drools Controller.
      * 
      * @param groupId maven group id of drools artifact
      * @param artifactId maven artifact id of drools artifact
@@ -81,31 +81,31 @@ public interface DroolsControllerFactory {
             List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError;
 
     /**
-     * Releases the Drools Controller from operation
+     * Releases the Drools Controller from operation.
      * 
      * @param controller the Drools Controller to shut down
      */
     public void shutdown(DroolsController controller);
 
     /**
-     * Disables all Drools Controllers from operation
+     * Disables all Drools Controllers from operation.
      */
     public void shutdown();
 
     /**
-     * Destroys and releases resources for a Drools Controller
+     * Destroys and releases resources for a Drools Controller.
      * 
      * @param controller the Drools Controller to destroy
      */
     public void destroy(DroolsController controller);
 
     /**
-     * Destroys all Drools Controllers
+     * Destroys all Drools Controllers.
      */
     public void destroy();
 
     /**
-     * Gets the Drools Controller associated with the maven group and artifact id
+     * Gets the Drools Controller associated with the maven group and artifact id.
      * 
      * @param groupId maven group id of drools artifact
      * @param artifactId maven artifact id of drools artifact
@@ -117,7 +117,7 @@ public interface DroolsControllerFactory {
     public DroolsController get(String groupId, String artifactId, String version);
 
     /**
-     * returns the current inventory of Drools Controllers
+     * returns the current inventory of Drools Controllers.
      * 
      * @return a list of Drools Controllers
      */
@@ -128,22 +128,22 @@ public interface DroolsControllerFactory {
 /* ---------------- implementation ----------------- */
 
 /**
- * Factory of Drools Controllers indexed by the Maven coordinates
+ * Factory of Drools Controllers indexed by the Maven coordinates.
  */
 class IndexedDroolsControllerFactory implements DroolsControllerFactory {
 
     /**
-     * logger
+     * logger.
      */
     private static Logger logger = LoggerFactory.getLogger(MavenDroolsController.class);
 
     /**
-     * Policy Controller Name Index
+     * Policy Controller Name Index.
      */
     protected HashMap<String, DroolsController> droolsControllers = new HashMap<>();
 
     /**
-     * Null Drools Controller
+     * Null Drools Controller.
      */
     protected NullDroolsController nullDroolsController = new NullDroolsController();
 
@@ -186,8 +186,66 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
         return this.build(groupId, artifactId, version, topics2DecodedClasses2Filters, topics2EncodedClasses2Filters);
     }
 
+    @Override
+    public DroolsController build(String newGroupId, String newArtifactId, String newVersion,
+            List<TopicCoderFilterConfiguration> decoderConfigurations,
+            List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError {
+
+        if (newGroupId == null || newGroupId.isEmpty()) {
+            throw new IllegalArgumentException("Missing maven group-id coordinate");
+        }
+
+        if (newArtifactId == null || newArtifactId.isEmpty()) {
+            throw new IllegalArgumentException("Missing maven artifact-id coordinate");
+        }
+
+        if (newVersion == null || newVersion.isEmpty()) {
+            throw new IllegalArgumentException("Missing maven version coordinate");
+        }
+
+        String controllerId = newGroupId + ":" + newArtifactId;
+        DroolsController controllerCopy = null;
+        synchronized (this) {
+            /*
+             * The Null Drools Controller for no maven coordinates is always here so when no
+             * coordinates present, this is the return point
+             * 
+             * assert (controllerCopy instanceof NullDroolsController)
+             */
+            if (droolsControllers.containsKey(controllerId)) {
+                controllerCopy = droolsControllers.get(controllerId);
+                if (controllerCopy.getVersion().equalsIgnoreCase(newVersion)) {
+                    return controllerCopy;
+                }
+            }
+        }
+
+        if (controllerCopy != null) {
+            /*
+             * a controller keyed by group id + artifact id exists but with different version =>
+             * version upgrade/downgrade
+             */
+
+            controllerCopy.updateToVersion(newGroupId, newArtifactId, newVersion, decoderConfigurations,
+                    encoderConfigurations);
+
+            return controllerCopy;
+        }
+
+        /* new drools controller */
+
+        DroolsController controller = new MavenDroolsController(newGroupId, newArtifactId, newVersion,
+                decoderConfigurations, encoderConfigurations);
+
+        synchronized (this) {
+            droolsControllers.put(controllerId, controller);
+        }
+
+        return controller;
+    }
+
     /**
-     * find out decoder classes and filters
+     * find out decoder classes and filters.
      * 
      * @param properties properties with information about decoders
      * @param topicEntities topic sources
@@ -235,12 +293,12 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
 
             // 1. first the topic
 
-            String aTopic = topic.getTopic();
+            String firstTopic = topic.getTopic();
 
             // 2. check if there is a custom decoder for this topic that the user prefers to use
             // instead of the ones provided in the platform
 
-            String customGson = properties.getProperty(propertyTopicEntityPrefix + aTopic
+            String customGson = properties.getProperty(propertyTopicEntityPrefix + firstTopic
                     + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_GSON_SUFFIX);
 
             CustomGsonCoder customGsonCoder = null;
@@ -253,7 +311,7 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
                 }
             }
 
-            String customJackson = properties.getProperty(propertyTopicEntityPrefix + aTopic
+            String customJackson = properties.getProperty(propertyTopicEntityPrefix + firstTopic
                     + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_JACKSON_SUFFIX);
 
             CustomJacksonCoder customJacksonCoder = null;
@@ -269,25 +327,27 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
             // 3. second the list of classes associated with each topic
 
             String eventClasses = properties
-                    .getProperty(propertyTopicEntityPrefix + aTopic + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX);
+                    .getProperty(propertyTopicEntityPrefix + firstTopic 
+                            + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX);
 
             if (eventClasses == null || eventClasses.isEmpty()) {
-                // TODO warn
+                logger.warn("There are no event classes for topic {}", firstTopic);
                 continue;
             }
 
             List<PotentialCoderFilter> classes2Filters = new ArrayList<>();
 
-            List<String> aTopicClasses = new ArrayList<>(Arrays.asList(eventClasses.split("\\s*,\\s*")));
+            List<String> topicClasses = new ArrayList<>(Arrays.asList(eventClasses.split("\\s*,\\s*")));
 
-            for (String aClass : aTopicClasses) {
+            for (String theClass : topicClasses) {
 
 
                 // 4. third, for each coder class, get the list of field filters
 
                 String filter = properties
-                        .getProperty(propertyTopicEntityPrefix + aTopic + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX
-                                + "." + aClass + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_FILTER_SUFFIX);
+                        .getProperty(propertyTopicEntityPrefix + firstTopic 
+                                + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX
+                                + "." + theClass + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_FILTER_SUFFIX);
 
                 List<Pair<String, String>> filters = new ArrayList<>();
 
@@ -295,7 +355,7 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
                     // 4. topic -> class -> with no filters
 
                     JsonProtocolFilter protocolFilter = JsonProtocolFilter.fromRawFilters(filters);
-                    PotentialCoderFilter class2Filters = new PotentialCoderFilter(aClass, protocolFilter);
+                    PotentialCoderFilter class2Filters = new PotentialCoderFilter(theClass, protocolFilter);
                     classes2Filters.add(class2Filters);
                     continue;
                 }
@@ -330,76 +390,18 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
                 }
 
                 JsonProtocolFilter protocolFilter = JsonProtocolFilter.fromRawFilters(filters);
-                PotentialCoderFilter class2Filters = new PotentialCoderFilter(aClass, protocolFilter);
+                PotentialCoderFilter class2Filters = new PotentialCoderFilter(theClass, protocolFilter);
                 classes2Filters.add(class2Filters);
             }
 
             TopicCoderFilterConfiguration topic2Classes2Filters =
-                    new TopicCoderFilterConfiguration(aTopic, classes2Filters, customGsonCoder, customJacksonCoder);
+                    new TopicCoderFilterConfiguration(firstTopic, classes2Filters, customGsonCoder, customJacksonCoder);
             topics2DecodedClasses2Filters.add(topic2Classes2Filters);
         }
 
         return topics2DecodedClasses2Filters;
     }
 
-    @Override
-    public DroolsController build(String newGroupId, String newArtifactId, String newVersion,
-            List<TopicCoderFilterConfiguration> decoderConfigurations,
-            List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError {
-
-        if (newGroupId == null || newGroupId.isEmpty()) {
-            throw new IllegalArgumentException("Missing maven group-id coordinate");
-        }
-
-        if (newArtifactId == null || newArtifactId.isEmpty()) {
-            throw new IllegalArgumentException("Missing maven artifact-id coordinate");
-        }
-
-        if (newVersion == null || newVersion.isEmpty()) {
-            throw new IllegalArgumentException("Missing maven version coordinate");
-        }
-
-        String controllerId = newGroupId + ":" + newArtifactId;
-        DroolsController controllerCopy = null;
-        synchronized (this) {
-            /*
-             * The Null Drools Controller for no maven coordinates is always here so when no
-             * coordinates present, this is the return point
-             * 
-             * assert (controllerCopy instanceof NullDroolsController)
-             */
-            if (droolsControllers.containsKey(controllerId)) {
-                controllerCopy = droolsControllers.get(controllerId);
-                if (controllerCopy.getVersion().equalsIgnoreCase(newVersion)) {
-                    return controllerCopy;
-                }
-            }
-        }
-
-        if (controllerCopy != null) {
-            /*
-             * a controller keyed by group id + artifact id exists but with different version =>
-             * version upgrade/downgrade
-             */
-
-            controllerCopy.updateToVersion(newGroupId, newArtifactId, newVersion, decoderConfigurations,
-                    encoderConfigurations);
-
-            return controllerCopy;
-        }
-
-        /* new drools controller */
-
-        DroolsController controller = new MavenDroolsController(newGroupId, newArtifactId, newVersion,
-                decoderConfigurations, encoderConfigurations);
-
-        synchronized (this) {
-            droolsControllers.put(controllerId, controller);
-        }
-
-        return controller;
-    }
-
     @Override
     public void destroy(DroolsController controller) {
         unmanage(controller);
@@ -419,11 +421,9 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory {
     }
 
     /**
-     * unmanage the drools controller
+     * unmanage the drools controller.
      * 
-     * @param controller
-     * @return
-     * @throws IllegalArgumentException
+     * @param controller the controller
      */
     protected void unmanage(DroolsController controller) {
         if (controller == null) {
index 7b44817..707a8e7 100644 (file)
@@ -35,11 +35,11 @@ import org.kie.api.runtime.KieSession;
 import org.kie.api.runtime.rule.FactHandle;
 import org.kie.api.runtime.rule.QueryResults;
 import org.kie.api.runtime.rule.QueryResultsRow;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
 import org.onap.policy.drools.controller.DroolsController;
 import org.onap.policy.drools.core.PolicyContainer;
 import org.onap.policy.drools.core.PolicySession;
 import org.onap.policy.drools.core.jmx.PdpJmx;
-import org.onap.policy.common.endpoints.event.comm.TopicSink;
 import org.onap.policy.drools.features.DroolsControllerFeatureAPI;
 import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
@@ -57,806 +57,857 @@ import org.slf4j.LoggerFactory;
  * Drools containers instantiated using Maven.
  */
 public class MavenDroolsController implements DroolsController {
-       
-       /**
-        * logger 
-        */
-       private static Logger  logger = LoggerFactory.getLogger(MavenDroolsController.class);
-       
-       /**
-        * Policy Container, the access object to the policy-core layer
-        */
-       @JsonIgnore
-       protected final PolicyContainer policyContainer;
-       
-       /**
-        * alive status of this drools controller, 
-        * reflects invocation of start()/stop() only
-        */
-       protected volatile boolean alive = false;
-       
-       /**
-        * locked status of this drools controller,
-        * reflects if i/o drools related operations are permitted,
-        * more specifically: offer() and deliver().
-        * It does not affect the ability to start and stop 
-        * underlying drools infrastructure
-        */
-       protected volatile boolean locked = false;
-       
-       /**
-        * list of topics, each with associated decoder classes, each
-        * with a list of associated filters.
-        */
-       protected List<TopicCoderFilterConfiguration> decoderConfigurations;
-       
-       /**
-        * list of topics, each with associated encoder classes, each
-        * with a list of associated filters.
-        */
-       protected List<TopicCoderFilterConfiguration> encoderConfigurations;
-       
-       /**
-        * recent source events processed
-        */
-       protected final CircularFifoQueue<Object> recentSourceEvents = new CircularFifoQueue<>(10);
-       
-       /**
-        * recent sink events processed
-        */
-       protected final CircularFifoQueue<String> recentSinkEvents = new CircularFifoQueue<>(10);
-       
-       /**
-        * original Drools Model/Rules classloader hash
-        */
-       protected int modelClassLoaderHash;
-
-       /**
-        * Expanded version of the constructor 
-        * 
-        * @param groupId maven group id
-        * @param artifactId maven artifact id
-        * @param version maven version
-        * @param decoderConfigurations list of topic -> decoders -> filters mapping
-        * @param encoderConfigurations list of topic -> encoders -> filters mapping
-        * 
-        * @throws IllegalArgumentException invalid arguments passed in
-        */
-       public MavenDroolsController(String groupId, 
-                                                                String artifactId, 
-                                                                String version,
-                                                                List<TopicCoderFilterConfiguration> decoderConfigurations,
-                                                                List<TopicCoderFilterConfiguration> encoderConfigurations) {
-               
-               logger.info("drools-controller instantiation [{}:{}:{}]", groupId, artifactId, version);
-               
-               if (groupId == null || groupId.isEmpty())
-                       throw new IllegalArgumentException("Missing maven group-id coordinate");
-       
-               if (artifactId == null || artifactId.isEmpty())
-                       throw new IllegalArgumentException("Missing maven artifact-id coordinate");
-               
-               if (version == null || version.isEmpty())
-                       throw new IllegalArgumentException("Missing maven version coordinate");
-               
-               this.policyContainer= new PolicyContainer(groupId, artifactId, version);
-               this.init(decoderConfigurations, encoderConfigurations);
-               
-               logger.debug("{}: instantiation completed ", this);
-       }
-       
-       /**
-        * init encoding/decoding configuration
-        * @param decoderConfigurations list of topic -> decoders -> filters mapping
-        * @param encoderConfigurations list of topic -> encoders -> filters mapping
-        */
-       protected void init(List<TopicCoderFilterConfiguration> decoderConfigurations,
-                                   List<TopicCoderFilterConfiguration> encoderConfigurations) {
-               
-               this.decoderConfigurations = decoderConfigurations;
-               this.encoderConfigurations = encoderConfigurations;
-               
-               this.initCoders(decoderConfigurations, true);
-               this.initCoders(encoderConfigurations, false);
-               
-               this.modelClassLoaderHash = this.policyContainer.getClassLoader().hashCode();           
-       }
-       
-       @Override
-       public void updateToVersion(String newGroupId, String newArtifactId, String newVersion,
-                                           List<TopicCoderFilterConfiguration> decoderConfigurations,
-                                           List<TopicCoderFilterConfiguration> encoderConfigurations) 
-               throws LinkageError {
-               
-               logger.info("{}: updating version -> [{}:{}:{}]", newGroupId, newArtifactId, newVersion);
-               
-               if (newGroupId == null || newGroupId.isEmpty())
-                       throw new IllegalArgumentException("Missing maven group-id coordinate");
-       
-               if (newArtifactId == null || newArtifactId.isEmpty())
-                       throw new IllegalArgumentException("Missing maven artifact-id coordinate");
-               
-               if (newVersion == null || newVersion.isEmpty())
-                       throw new IllegalArgumentException("Missing maven version coordinate");
-               
-               if (newGroupId.equalsIgnoreCase(DroolsController.NO_GROUP_ID) || 
-                       newArtifactId.equalsIgnoreCase(DroolsController.NO_ARTIFACT_ID) || 
-                       newVersion.equalsIgnoreCase(DroolsController.NO_VERSION)) {
-                               throw new IllegalArgumentException("BRAINLESS maven coordinates provided: " + 
-                                                                          newGroupId + ":" + newArtifactId + ":" + 
-                                                                          newVersion);
-               }
-               
-               if (newGroupId.equalsIgnoreCase(this.getGroupId()) && 
-                       newArtifactId.equalsIgnoreCase(this.getArtifactId()) &&
-                       newVersion.equalsIgnoreCase(this.getVersion())) {
-                               logger.warn("Al in the right version: " + newGroupId + ":" + 
-                                       newArtifactId + ":" +  newVersion + " vs. " + this);
-                               return;
-               }
-               
-               if (!newGroupId.equalsIgnoreCase(this.getGroupId()) || 
-                       !newArtifactId.equalsIgnoreCase(this.getArtifactId())) {
-                               throw new IllegalArgumentException("Group ID and Artifact ID maven coordinates must be identical for the upgrade: " + 
-                                                                              newGroupId + ":" + newArtifactId + ":" + 
-                                                                              newVersion + " vs. " + this);
-               }
-
-               /* upgrade */
-               String messages = this.policyContainer.updateToVersion(newVersion);
-               if (logger.isWarnEnabled())
-                       logger.warn(this + "UPGRADE results: " + messages);
-               
-               /*
-                * If all sucessful (can load new container), now we can remove all coders from previous sessions
-                */
-               this.removeCoders();
-               
-               /*
-                * add the new coders
-                */
-               this.init(decoderConfigurations, encoderConfigurations);
-               
-               if (logger.isInfoEnabled())
-                       logger.info("UPDATE-TO-VERSION: completed " +  this);
-       }
-
-       /**
-        * initialize decoders for all the topics supported by this controller
-        * Note this is critical to be done after the Policy Container is
-        * instantiated to be able to fetch the corresponding classes.
-        * 
-        * @param coderConfigurations list of topic -> decoders -> filters mapping
-        */
-       protected void initCoders(List<TopicCoderFilterConfiguration> coderConfigurations, 
-                                         boolean decoder) {
-               
-               if (logger.isInfoEnabled())
-                       logger.info("INIT-CODERS: " +  this);
-               
-               if (coderConfigurations == null) {
-                       return;
-               }
-                       
-
-               for (TopicCoderFilterConfiguration coderConfig: coderConfigurations) {
-                       String topic = coderConfig.getTopic();
-                       
-                       CustomGsonCoder customGsonCoder = coderConfig.getCustomGsonCoder();
-                       if (coderConfig.getCustomGsonCoder() != null && 
-                               coderConfig.getCustomGsonCoder().getClassContainer() != null &&
-                               !coderConfig.getCustomGsonCoder().getClassContainer().isEmpty()) {
-                                       
-                               String customGsonCoderClass = coderConfig.getCustomGsonCoder().getClassContainer();
-                               if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(),
-                                                                  customGsonCoderClass)) {
-                                       throw makeRetrieveEx(customGsonCoderClass);
-                               } else {
-                                       if (logger.isInfoEnabled())
-                                               logClassFetched(customGsonCoderClass);
-                               }
-                       }
-                       
-                       CustomJacksonCoder customJacksonCoder = coderConfig.getCustomJacksonCoder();
-                       if (coderConfig.getCustomJacksonCoder() != null && 
-                               coderConfig.getCustomJacksonCoder().getClassContainer() != null &&
-                               !coderConfig.getCustomJacksonCoder().getClassContainer().isEmpty()) {
-                               
-                               String customJacksonCoderClass = coderConfig.getCustomJacksonCoder().getClassContainer();
-                               if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(),
-                                                                  customJacksonCoderClass)) {
-                                       throw makeRetrieveEx(customJacksonCoderClass);
-                               } else {
-                                       if (logger.isInfoEnabled())
-                                               logClassFetched(customJacksonCoderClass);
-                               }
-                       }       
-                       
-                       List<PotentialCoderFilter> coderFilters = coderConfig.getCoderFilters();
-                       if (coderFilters == null || coderFilters.isEmpty()) {
-                               continue;
-                       }
-                       
-                       for (PotentialCoderFilter coderFilter : coderFilters) {
-                               String potentialCodedClass = coderFilter.getCodedClass();
-                               JsonProtocolFilter protocolFilter = coderFilter.getFilter();
-                               
-                               if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(), 
-                                                                  potentialCodedClass)) {
-                                       throw makeRetrieveEx(potentialCodedClass);
-                               } else {
-                                       if (logger.isInfoEnabled())
-                                               logClassFetched(potentialCodedClass);
-                               }                       
-                               
-                               if (decoder)
-                                       EventProtocolCoder.manager.addDecoder(this.getGroupId(), this.getArtifactId(), 
-                                                                                     topic, potentialCodedClass, protocolFilter,
-                                                                                     customGsonCoder,
-                                                                                     customJacksonCoder,
-                                                                                     this.policyContainer.getClassLoader().hashCode());
-                               else
-                                       EventProtocolCoder.manager.addEncoder(this.getGroupId(), this.getArtifactId(), 
-                                                          topic, potentialCodedClass, protocolFilter,
-                                                                                     customGsonCoder,
-                                                                                     customJacksonCoder,
-                                                                                     this.policyContainer.getClassLoader().hashCode());
-                       }
-               }
-       }
-       
-       /**
-        * Logs an error and makes an exception for an item that cannot be retrieved.
-        * @param itemName
-        * @return a new exception
-        */
-       private IllegalArgumentException makeRetrieveEx(String itemName) {
-               logger.error(itemName + " cannot be retrieved");
-               return new IllegalArgumentException(itemName + " cannot be retrieved");
-       }
-
-       /**
-        * Logs the name of the class that was fetched.
-        * @param className
-        */
-       private void logClassFetched(String className) {
-               logger.info("CLASS FETCHED " + className);
-       }
-       
-
-       /**
-        * remove decoders.
-        */
-       protected void removeDecoders(){
-               if (logger.isInfoEnabled())
-                       logger.info("REMOVE-DECODERS: " +  this);
-               
-               if (this.decoderConfigurations == null) {
-                       return;
-               }
-                       
-
-               for (TopicCoderFilterConfiguration coderConfig: decoderConfigurations) {
-                       String topic = coderConfig.getTopic();                                                          
-                       EventProtocolCoder.manager.removeDecoders
-                                               (this.getGroupId(), this.getArtifactId(), topic);
-               }
-       }
-       
-       /**
-        * remove decoders.
-        */
-       protected void removeEncoders() {
-               
-               if (logger.isInfoEnabled())
-                       logger.info("REMOVE-ENCODERS: " +  this);
-               
-               if (this.encoderConfigurations == null)
-                       return;
-                       
-
-               for (TopicCoderFilterConfiguration coderConfig: encoderConfigurations) {
-                       String topic = coderConfig.getTopic();                                                          
-                       EventProtocolCoder.manager.removeEncoders
-                                               (this.getGroupId(), this.getArtifactId(), topic);
-               }
-       }
-       
-
-       @Override
-       public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash) {
-               if (!ReflectionUtil.isClass
-                               (this.policyContainer.getClassLoader(), coderClass.getCanonicalName())) {
-                       logger.error(this + coderClass.getCanonicalName() + " cannot be retrieved. ");
-                       return false;
-               }
-               
-               if (modelHash == this.modelClassLoaderHash) {
-                       if (logger.isInfoEnabled())
-                               logger.info(coderClass.getCanonicalName() + 
-                                                   this + " class loader matches original drools controller rules classloader " +
-                                       coderClass.getClassLoader());
-                       return true;
-               } else {
-                       if (logger.isWarnEnabled())
-                               logger.warn(this + coderClass.getCanonicalName() + " class loaders don't match  " +
-                               coderClass.getClassLoader() + " vs " + 
-                                                   this.policyContainer.getClassLoader());
-                       return false;
-               }
-       }
-       
-       @Override
-       public boolean start() {
-               
-               if (logger.isInfoEnabled())
-                       logger.info("START: " + this);
-               
-               synchronized (this) {                   
-                       if (this.alive)
-                               return true;
-                       
-                       this.alive = true;
-               }
-               
-               return this.policyContainer.start();
-       }
-       
-       @Override
-       public boolean stop() {
-               
-               logger.info("STOP: " + this);
-               
-               synchronized (this) {
-                       if (!this.alive)
-                               return true;
-                       
-                       this.alive = false;
-               }
-               
-               return this.policyContainer.stop();
-       }
-
-       @Override
-       public void shutdown() {                
-               logger.info("{}: SHUTDOWN", this);
-               
-               try {
-                       this.stop();
-                       this.removeCoders();
-               } catch (Exception e) {
-                       logger.error("{} SHUTDOWN FAILED because of {}", this, e.getMessage(), e);
-               } finally {
-                       this.policyContainer.shutdown();
-               }
-
-       }
-       
-       @Override
-       public void halt() {
-               logger.info("{}: HALT", this);
-               
-               try {
-                       this.stop();
-                       this.removeCoders();
-               } catch (Exception e) {
-                       logger.error("{} HALT FAILED because of {}", this, e.getMessage(), e);
-               } finally {
-                       this.policyContainer.destroy();
-               }       
-       }
-       
-       /**
-        * removes this drools controllers and encoders and decoders from operation
-        */
-       protected void removeCoders() {
-               logger.info("{}: REMOVE-CODERS", this);
-               
-               try {
-                       this.removeDecoders();
-               } catch (IllegalArgumentException e) {
-                       logger.error("{} REMOVE-DECODERS FAILED because of {}", this, e.getMessage(), e);
-               }
-               
-               try {
-                       this.removeEncoders();
-               } catch (IllegalArgumentException e) {
-                       logger.error("{} REMOVE-ENCODERS FAILED because of {}", this, e.getMessage(), e);
-               }
-       }
-
-       @Override
-       public boolean isAlive() {
-               return this.alive;
-       }
-       
-       @Override
-       public boolean offer(String topic, String event) {
-               logger.debug("{}: OFFER: {} <- {}", this, topic, event);
-               
-               if (this.locked)
-                       return true;
-               
-               if (!this.alive)
-                       return true;
-               
-               // 0. Check if the policy container has any sessions
-               
-               if (this.policyContainer.getPolicySessions().isEmpty()) {
-                       // no sessions
-                       return true;
-               }
-               
-               // 1. Now, check if this topic has a decoder:
-               
-               if (!EventProtocolCoder.manager.isDecodingSupported(this.getGroupId(), 
-                                                                             this.getArtifactId(), 
-                                                                             topic)) {
-                       
-                       logger.warn("{}: DECODING-UNSUPPORTED {}:{}:{}", this, 
-                                           topic, this.getGroupId(), this.getArtifactId());
-                       return true;
-               }
-               
-               // 2. Decode
-               
-               Object anEvent;
-               try {
-                       anEvent = EventProtocolCoder.manager.decode(this.getGroupId(), 
-                                                                             this.getArtifactId(), 
-                                                                             topic, 
-                                                                             event);
-               } catch (UnsupportedOperationException uoe) {
-                       logger.debug("{}: DECODE FAILED: {} <- {} because of {}", this, topic, 
-                                            event, uoe.getMessage(), uoe);
-                       return true;
-               } catch (Exception e) {
-                       logger.warn("{}: DECODE FAILED: {} <- {} because of {}", this, topic, 
-                                       event, e.getMessage(), e);
-                       return true;
-               }
-               
-               synchronized(this.recentSourceEvents) {
-                       this.recentSourceEvents.add(anEvent);
-               }
-               
-               // increment event count for Nagios monitoring
-               PdpJmx.getInstance().updateOccured();  
-               
-               // Broadcast
-               
-               if (logger.isInfoEnabled())
-                       logger.info(this + "BROADCAST-INJECT of " + event + " FROM " + topic + " INTO " + this.policyContainer.getName());
-
-               for (DroolsControllerFeatureAPI feature : DroolsControllerFeatureAPI.providers.getList()) {
-                       try {
-                               if (feature.beforeInsert(this, anEvent))
-                                       return true;
-                       } catch (Exception e) {
-                               logger.error("{}: feature {} before-insert failure because of {}",
-                                       this, feature.getClass().getName(), e.getMessage(), e);
-                       }
-               }
-
-               boolean successInject = this.policyContainer.insertAll(anEvent);
-               if (!successInject)
-                       logger.warn(this + "Failed to inject into PolicyContainer " + this.getSessionNames());
-
-               for (DroolsControllerFeatureAPI feature : DroolsControllerFeatureAPI.providers.getList()) {
-                       try {
-                               if (feature.afterInsert(this, anEvent, successInject))
-                                       return true;
-                       } catch (Exception e) {
-                               logger.error("{}: feature {} after-insert failure because of {}",
-                                       this, feature.getClass().getName(), e.getMessage(), e);
-                       }
-               }
-
-               return true;
-       }       
-       
-       @Override
-       public boolean deliver(TopicSink sink, Object event) {
-               
-               if (logger.isInfoEnabled())
-                       logger.info(this + "DELIVER: " +  event + " FROM " + this + " TO " + sink);
-               
-               if (sink == null)
-                       throw new IllegalArgumentException
-                                               (this +  " invalid sink");
-               
-               if (event == null)
-                       throw new IllegalArgumentException
-                                               (this +  " invalid event");
-               
-               if (this.locked)
-                       throw new IllegalStateException
-                                                       (this +  " is locked");
-               
-               if (!this.alive)
-                       throw new IllegalStateException
-                                                       (this +  " is stopped");
-               
-               String json =
-                               EventProtocolCoder.manager.encode(sink.getTopic(), event, this);
-               
-               synchronized(this.recentSinkEvents) {
-                       this.recentSinkEvents.add(json);
-               }
-               
-               return sink.send(json);
-               
-       }
-
-       @Override
-       public String getVersion() {
-               return this.policyContainer.getVersion();
-       }
-       
-       @Override
-       public String getArtifactId() {
-               return this.policyContainer.getArtifactId();
-       }
-       
-       @Override
-       public String getGroupId() {
-               return this.policyContainer.getGroupId();
-       }
-
-       /**
-        * @return the modelClassLoaderHash
-        */
-       public int getModelClassLoaderHash() {
-               return modelClassLoaderHash;
-       }
-
-       @Override
-       public synchronized boolean lock() {
-               logger.info("LOCK: " +  this);
-               
-               this.locked = true;
-               return true;
-       }
-
-       @Override
-       public synchronized boolean unlock() {
-               logger.info("UNLOCK: " +  this);
-               
-               this.locked = false;
-               return true;
-       }
-
-       @Override
-       public boolean isLocked() {
-               return this.locked;
-       }
-       
-       @JsonIgnore
-       @Override
-       public PolicyContainer getContainer() {
-               return this.policyContainer;
-       }
-       
-       @JsonProperty("sessions")
-       @Override
-       public List<String> getSessionNames() {
-               return getSessionNames(true);
-       }
-       
-       @JsonProperty("sessionCoordinates")
-       @Override
-       public List<String> getCanonicalSessionNames() {
-               return getSessionNames(false);
-       }
-       
-       /**
-        * get session names
-        * @param abbreviated true for the short form, otherwise the long form
-        * @return session names
-        */
-       protected List<String> getSessionNames(boolean abbreviated) {
-               List<String> sessionNames = new ArrayList<>();
-               try {
-                       for (PolicySession session: this.policyContainer.getPolicySessions()) {
-                               if (abbreviated)
-                                       sessionNames.add(session.getName());
-                               else
-                                       sessionNames.add(session.getFullName());
-                       }
-               } catch (Exception e) {
-                       logger.warn("Can't retrieve CORE sessions: " + e.getMessage(), e);
-                       sessionNames.add(e.getMessage());
-               }
-               return sessionNames;
-       }
-       
-       /**
-        * provides the underlying core layer container sessions
-        * 
-        * @return the attached Policy Container
-        */
-       protected List<PolicySession> getSessions() {
-               List<PolicySession> sessions = new ArrayList<>();
-               sessions.addAll(this.policyContainer.getPolicySessions());
-               return sessions;
-       }
-       
-       /**
-        * provides the underlying core layer container session with name sessionName
-        * 
-        * @param sessionName session name
-        * @return the attached Policy Container
-        * @throws IllegalArgumentException when an invalid session name is provided
-        * @throws IllegalStateException when the drools controller is in an invalid state
-        */
-       protected PolicySession getSession(String sessionName) {
-               if (sessionName == null || sessionName.isEmpty())
-                       throw new IllegalArgumentException("A Session Name must be provided");
-               
-               List<PolicySession> sessions = this.getSessions();
-               for (PolicySession session : sessions) {
-                       if (sessionName.equals(session.getName()) || sessionName.equals(session.getFullName()))
-                               return session;                         
-               }
-               
-               throw invalidSessNameEx(sessionName);
-       }
-
-       private IllegalArgumentException invalidSessNameEx(String sessionName) {
-               return new IllegalArgumentException("Invalid Session Name: " + sessionName);
-       }
-       
-       @Override
-       public Map<String,Integer> factClassNames(String sessionName) {         
-               if (sessionName == null || sessionName.isEmpty())
-                       throw invalidSessNameEx(sessionName);
-
-               Map<String,Integer> classNames = new HashMap<>();
-               
-               PolicySession session = getSession(sessionName);
-               KieSession kieSession = session.getKieSession();
-
-               Collection<FactHandle> facts = session.getKieSession().getFactHandles();
-               for (FactHandle fact : facts) {
-                       try {
-                               String className = kieSession.getObject(fact).getClass().getName();
-                               if (classNames.containsKey(className))
-                                       classNames.put(className, classNames.get(className) + 1);
-                               else
-                                       classNames.put(className, 1);
-                       } catch (Exception e) {
-                               logger.warn("Object cannot be retrieved from fact {}", fact, e);
-                       }                       
-               }       
-               
-               return classNames;
-       }
-       
-       @Override
-       public long factCount(String sessionName) {             
-               if (sessionName == null || sessionName.isEmpty())
-                       throw invalidSessNameEx(sessionName);
-               
-               PolicySession session = getSession(sessionName);
-               return session.getKieSession().getFactCount();  
-       }
-       
-       @Override
-       public List<Object> facts(String sessionName, String className, boolean delete) {               
-               if (sessionName == null || sessionName.isEmpty())
-                       throw invalidSessNameEx(sessionName);
-               
-               if (className == null || className.isEmpty())
-                       throw new IllegalArgumentException("Invalid Class Name: " + className);
-               
-               Class<?> factClass = 
-                               ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className);
-               if (factClass == null)
-                       throw new IllegalArgumentException("Class cannot be fetched in model's classloader: " + className);
-               
-               PolicySession session = getSession(sessionName);
-               KieSession kieSession = session.getKieSession();
-               
-               List<Object> factObjects = new ArrayList<>();
-               
-               Collection<FactHandle> factHandles = kieSession.getFactHandles(new ClassObjectFilter(factClass));
-               for (FactHandle factHandle : factHandles) {
-                       try {
-                               factObjects.add(kieSession.getObject(factHandle));
-                               if (delete)
-                                       kieSession.delete(factHandle);                                  
-                       } catch (Exception e) {
-                               logger.warn("Object cannot be retrieved from fact {}", factHandle, e);
-                       }
-               }               
-               
-               return factObjects;
-       }
-       
-       @Override
-       public List<Object> factQuery(String sessionName, String queryName, String queriedEntity, boolean delete, Object... queryParams) {              
-               if (sessionName == null || sessionName.isEmpty())
-                       throw invalidSessNameEx(sessionName);
-               
-               if (queryName == null || queryName.isEmpty())
-                       throw new IllegalArgumentException("Invalid Query Name: " + queryName);
-               
-               if (queriedEntity == null || queriedEntity.isEmpty())
-                       throw new IllegalArgumentException("Invalid Queried Entity: " + queriedEntity);
-               
-               PolicySession session = getSession(sessionName);
-               KieSession kieSession = session.getKieSession();
-               
-               boolean found = false;
-               for (KiePackage kiePackage : kieSession.getKieBase().getKiePackages()) {
-                       for (Query q : kiePackage.getQueries()) {
-                               if (q.getName() != null && q.getName().equals(queryName)) {
-                                       found = true;
-                                       break;
-                               }
-                       }
-               }
-               if (!found)
-                       throw new IllegalArgumentException("Invalid Query Name: " + queryName);
+
+    /**
+     * logger.
+     */
+    private static Logger  logger = LoggerFactory.getLogger(MavenDroolsController.class);
+
+    /**
+     * Policy Container, the access object to the policy-core layer.
+     */
+    @JsonIgnore
+    protected final PolicyContainer policyContainer;
+
+    /**
+     * alive status of this drools controller, 
+     * reflects invocation of start()/stop() only.
+     */
+    protected volatile boolean alive = false;
+
+    /**
+     * locked status of this drools controller,
+     * reflects if i/o drools related operations are permitted,
+     * more specifically: offer() and deliver().
+     * It does not affect the ability to start and stop 
+     * underlying drools infrastructure
+     */
+    protected volatile boolean locked = false;
+
+    /**
+     * list of topics, each with associated decoder classes, each
+     * with a list of associated filters.
+     */
+    protected List<TopicCoderFilterConfiguration> decoderConfigurations;
+
+    /**
+     * list of topics, each with associated encoder classes, each
+     * with a list of associated filters.
+     */
+    protected List<TopicCoderFilterConfiguration> encoderConfigurations;
+
+    /**
+     * recent source events processed.
+     */
+    protected final CircularFifoQueue<Object> recentSourceEvents = new CircularFifoQueue<>(10);
+
+    /**
+     * recent sink events processed.
+     */
+    protected final CircularFifoQueue<String> recentSinkEvents = new CircularFifoQueue<>(10);
+
+    /**
+     * original Drools Model/Rules classloader hash.
+     */
+    protected int modelClassLoaderHash;
+
+    /**
+     * Expanded version of the constructor.
+     * 
+     * @param groupId maven group id
+     * @param artifactId maven artifact id
+     * @param version maven version
+     * @param decoderConfigurations list of topic -> decoders -> filters mapping
+     * @param encoderConfigurations list of topic -> encoders -> filters mapping
+     * 
+     * @throws IllegalArgumentException invalid arguments passed in
+     */
+    public MavenDroolsController(String groupId, 
+            String artifactId, 
+            String version,
+            List<TopicCoderFilterConfiguration> decoderConfigurations,
+            List<TopicCoderFilterConfiguration> encoderConfigurations) {
+
+        logger.info("drools-controller instantiation [{}:{}:{}]", groupId, artifactId, version);
+
+        if (groupId == null || groupId.isEmpty()) {
+            throw new IllegalArgumentException("Missing maven group-id coordinate");
+        }
+
+        if (artifactId == null || artifactId.isEmpty()) {
+            throw new IllegalArgumentException("Missing maven artifact-id coordinate");
+        }
+
+        if (version == null || version.isEmpty()) {
+            throw new IllegalArgumentException("Missing maven version coordinate");
+        }
+
+        this.policyContainer = new PolicyContainer(groupId, artifactId, version);
+        this.init(decoderConfigurations, encoderConfigurations);
+
+        logger.debug("{}: instantiation completed ", this);
+    }
+
+    /**
+     * init encoding/decoding configuration.
+     * 
+     * @param decoderConfigurations list of topic -> decoders -> filters mapping
+     * @param encoderConfigurations list of topic -> encoders -> filters mapping
+     */
+    protected void init(List<TopicCoderFilterConfiguration> decoderConfigurations,
+            List<TopicCoderFilterConfiguration> encoderConfigurations) {
+
+        this.decoderConfigurations = decoderConfigurations;
+        this.encoderConfigurations = encoderConfigurations;
+
+        this.initCoders(decoderConfigurations, true);
+        this.initCoders(encoderConfigurations, false);
+
+        this.modelClassLoaderHash = this.policyContainer.getClassLoader().hashCode();
+    }
+
+    @Override
+    public void updateToVersion(String newGroupId, String newArtifactId, String newVersion,
+            List<TopicCoderFilterConfiguration> decoderConfigurations,
+            List<TopicCoderFilterConfiguration> encoderConfigurations) 
+                    throws LinkageError {
+
+        logger.info("updating version -> [{}:{}:{}]", newGroupId, newArtifactId, newVersion);
+
+        if (newGroupId == null || newGroupId.isEmpty()) {
+            throw new IllegalArgumentException("Missing maven group-id coordinate");
+        }
+
+        if (newArtifactId == null || newArtifactId.isEmpty()) {
+            throw new IllegalArgumentException("Missing maven artifact-id coordinate");
+        }
+
+        if (newVersion == null || newVersion.isEmpty()) {
+            throw new IllegalArgumentException("Missing maven version coordinate");
+        }
+
+        if (newGroupId.equalsIgnoreCase(DroolsController.NO_GROUP_ID) 
+                || newArtifactId.equalsIgnoreCase(DroolsController.NO_ARTIFACT_ID) 
+                || newVersion.equalsIgnoreCase(DroolsController.NO_VERSION)) {
+            throw new IllegalArgumentException("BRAINLESS maven coordinates provided: " 
+                    + newGroupId + ":" + newArtifactId + ":" 
+                    + newVersion);
+        }
+
+        if (newGroupId.equalsIgnoreCase(this.getGroupId())
+                && newArtifactId.equalsIgnoreCase(this.getArtifactId())
+                && newVersion.equalsIgnoreCase(this.getVersion())) {
+            logger.warn("Al in the right version: " + newGroupId + ":" 
+                    + newArtifactId + ":" +  newVersion + " vs. " + this);
+            return;
+        }
+
+        if (!newGroupId.equalsIgnoreCase(this.getGroupId()) 
+                || !newArtifactId.equalsIgnoreCase(this.getArtifactId())) {
+            throw new IllegalArgumentException(
+                    "Group ID and Artifact ID maven coordinates must be identical for the upgrade: " 
+                    + newGroupId + ":" + newArtifactId + ":" 
+                    + newVersion + " vs. " + this);
+        }
+
+        /* upgrade */
+        String messages = this.policyContainer.updateToVersion(newVersion);
+        if (logger.isWarnEnabled()) {
+            logger.warn("{} UPGRADE results: {}", this, messages);
+        }
+
+        /*
+         * If all sucessful (can load new container), now we can remove all coders from previous sessions
+         */
+        this.removeCoders();
+
+        /*
+         * add the new coders
+         */
+        this.init(decoderConfigurations, encoderConfigurations);
+
+        if (logger.isInfoEnabled()) {
+            logger.info("UPDATE-TO-VERSION: completed " +  this);
+        }
+    }
+
+    /**
+     * initialize decoders for all the topics supported by this controller
+     * Note this is critical to be done after the Policy Container is
+     * instantiated to be able to fetch the corresponding classes.
+     * 
+     * @param coderConfigurations list of topic -> decoders -> filters mapping
+     */
+    protected void initCoders(List<TopicCoderFilterConfiguration> coderConfigurations, 
+            boolean decoder) {
+
+        if (logger.isInfoEnabled()) {
+            logger.info("INIT-CODERS: " +  this);
+        }
+
+        if (coderConfigurations == null) {
+            return;
+        }
+
+
+        for (TopicCoderFilterConfiguration coderConfig: coderConfigurations) {
+            String topic = coderConfig.getTopic();
+
+            CustomGsonCoder customGsonCoder = coderConfig.getCustomGsonCoder();
+            if (coderConfig.getCustomGsonCoder() != null 
+                    && coderConfig.getCustomGsonCoder().getClassContainer() != null
+                    && !coderConfig.getCustomGsonCoder().getClassContainer().isEmpty()) {
+
+                String customGsonCoderClass = coderConfig.getCustomGsonCoder().getClassContainer();
+                if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(),
+                        customGsonCoderClass)) {
+                    throw makeRetrieveEx(customGsonCoderClass);
+                } else {
+                    if (logger.isInfoEnabled()) {
+                        logClassFetched(customGsonCoderClass);
+                    }
+                }
+            }
+
+            CustomJacksonCoder customJacksonCoder = coderConfig.getCustomJacksonCoder();
+            if (coderConfig.getCustomJacksonCoder() != null 
+                    && coderConfig.getCustomJacksonCoder().getClassContainer() != null
+                    && !coderConfig.getCustomJacksonCoder().getClassContainer().isEmpty()) {
+
+                String customJacksonCoderClass = coderConfig.getCustomJacksonCoder().getClassContainer();
+                if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(),
+                        customJacksonCoderClass)) {
+                    throw makeRetrieveEx(customJacksonCoderClass);
+                } else {
+                    if (logger.isInfoEnabled()) {
+                        logClassFetched(customJacksonCoderClass);
+                    }
+                }
+            }
+
+            List<PotentialCoderFilter> coderFilters = coderConfig.getCoderFilters();
+            if (coderFilters == null || coderFilters.isEmpty()) {
+                continue;
+            }
+
+            for (PotentialCoderFilter coderFilter : coderFilters) {
+                String potentialCodedClass = coderFilter.getCodedClass();
+                JsonProtocolFilter protocolFilter = coderFilter.getFilter();
+
+                if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(), 
+                        potentialCodedClass)) {
+                    throw makeRetrieveEx(potentialCodedClass);
+                } else {
+                    if (logger.isInfoEnabled()) {
+                        logClassFetched(potentialCodedClass);
+                    }
+                }
+
+                if (decoder) {
+                    EventProtocolCoder.manager.addDecoder(this.getGroupId(), this.getArtifactId(), 
+                            topic, potentialCodedClass, protocolFilter,
+                            customGsonCoder,
+                            customJacksonCoder,
+                            this.policyContainer.getClassLoader().hashCode());
+                } else {
+                    EventProtocolCoder.manager.addEncoder(this.getGroupId(), this.getArtifactId(), 
+                            topic, potentialCodedClass, protocolFilter,
+                            customGsonCoder,
+                            customJacksonCoder,
+                            this.policyContainer.getClassLoader().hashCode());
+                }
+            }
+        }
+    }
+
+    /**
+     * Logs an error and makes an exception for an item that cannot be retrieved.
+     * @param itemName the item to retrieve
+     * @return a new exception
+     */
+    private IllegalArgumentException makeRetrieveEx(String itemName) {
+        logger.error("{} cannot be retrieved", itemName);
+        return new IllegalArgumentException(itemName + " cannot be retrieved");
+    }
+
+    /**
+     * Logs the name of the class that was fetched.
+     * @param className class name fetched
+     */
+    private void logClassFetched(String className) {
+        logger.info("CLASS FETCHED {}", className);
+    }
+
+
+    /**
+     * remove decoders.
+     */
+    protected void removeDecoders() {
+        if (logger.isInfoEnabled()) {
+            logger.info("REMOVE-DECODERS: {}",  this);
+        }
+
+        if (this.decoderConfigurations == null) {
+            return;
+        }
+
+
+        for (TopicCoderFilterConfiguration coderConfig: decoderConfigurations) {
+            String topic = coderConfig.getTopic();
+            EventProtocolCoder.manager.removeDecoders(this.getGroupId(), this.getArtifactId(), topic);
+        }
+    }
+
+    /**
+     * remove decoders.
+     */
+    protected void removeEncoders() {
+
+        if (logger.isInfoEnabled()) {
+            logger.info("REMOVE-ENCODERS: {}",  this);
+        }
+
+        if (this.encoderConfigurations == null) {
+            return;
+        }
+
+        for (TopicCoderFilterConfiguration coderConfig: encoderConfigurations) {
+            String topic = coderConfig.getTopic();
+            EventProtocolCoder.manager.removeEncoders(this.getGroupId(), this.getArtifactId(), topic);
+        }
+    }
+
+
+    @Override
+    public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash) {
+        if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(), coderClass.getCanonicalName())) {
+            logger.error("{}{} cannot be retrieved. ", this, coderClass.getCanonicalName());
+            return false;
+        }
+
+        if (modelHash == this.modelClassLoaderHash) {
+            if (logger.isInfoEnabled()) {
+                logger.info(coderClass.getCanonicalName() 
+                        + this + " class loader matches original drools controller rules classloader "
+                        + coderClass.getClassLoader());
+            }
+            return true;
+        } else {
+            if (logger.isWarnEnabled()) {
+                logger.warn(this + coderClass.getCanonicalName() + " class loaders don't match  "
+                        + coderClass.getClassLoader() + " vs " 
+                        + this.policyContainer.getClassLoader());
+            }
+            return false;
+        }
+    }
+
+    @Override
+    public boolean start() {
+
+        if (logger.isInfoEnabled()) {
+            logger.info("START: {}", this);
+        }
+
+        synchronized (this) {
+            if (this.alive) {
+                return true;
+            }
+            this.alive = true;
+        }
+
+        return this.policyContainer.start();
+    }
+
+    @Override
+    public boolean stop() {
+
+        logger.info("STOP: {}", this);
+
+        synchronized (this) {
+            if (!this.alive) {
+                return true;
+            }
+            this.alive = false;
+        }
+
+        return this.policyContainer.stop();
+    }
+
+    @Override
+    public void shutdown() {
+        logger.info("{}: SHUTDOWN", this);
+
+        try {
+            this.stop();
+            this.removeCoders();
+        } catch (Exception e) {
+            logger.error("{} SHUTDOWN FAILED because of {}", this, e.getMessage(), e);
+        } finally {
+            this.policyContainer.shutdown();
+        }
+
+    }
+
+    @Override
+    public void halt() {
+        logger.info("{}: HALT", this);
+
+        try {
+            this.stop();
+            this.removeCoders();
+        } catch (Exception e) {
+            logger.error("{} HALT FAILED because of {}", this, e.getMessage(), e);
+        } finally {
+            this.policyContainer.destroy();
+        }
+    }
+
+    /**
+     * removes this drools controllers and encoders and decoders from operation.
+     */
+    protected void removeCoders() {
+        logger.info("{}: REMOVE-CODERS", this);
+
+        try {
+            this.removeDecoders();
+        } catch (IllegalArgumentException e) {
+            logger.error("{} REMOVE-DECODERS FAILED because of {}", this, e.getMessage(), e);
+        }
+
+        try {
+            this.removeEncoders();
+        } catch (IllegalArgumentException e) {
+            logger.error("{} REMOVE-ENCODERS FAILED because of {}", this, e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public boolean isAlive() {
+        return this.alive;
+    }
+
+    @Override
+    public boolean offer(String topic, String event) {
+        logger.debug("{}: OFFER: {} <- {}", this, topic, event);
+
+        if (this.locked) {
+            return true;
+        }
+        if (!this.alive) {
+            return true;
+        }
+
+        // 0. Check if the policy container has any sessions
+
+        if (this.policyContainer.getPolicySessions().isEmpty()) {
+            // no sessions
+            return true;
+        }
+
+        // 1. Now, check if this topic has a decoder:
+
+        if (!EventProtocolCoder.manager.isDecodingSupported(this.getGroupId(), 
+                this.getArtifactId(), 
+                topic)) {
+
+            logger.warn("{}: DECODING-UNSUPPORTED {}:{}:{}", this, 
+                    topic, this.getGroupId(), this.getArtifactId());
+            return true;
+        }
+
+        // 2. Decode
+
+        Object anEvent;
+        try {
+            anEvent = EventProtocolCoder.manager.decode(this.getGroupId(), 
+                    this.getArtifactId(), 
+                    topic, 
+                    event);
+        } catch (UnsupportedOperationException uoe) {
+            logger.debug("{}: DECODE FAILED: {} <- {} because of {}", this, topic, 
+                    event, uoe.getMessage(), uoe);
+            return true;
+        } catch (Exception e) {
+            logger.warn("{}: DECODE FAILED: {} <- {} because of {}", this, topic, 
+                    event, e.getMessage(), e);
+            return true;
+        }
+
+        synchronized (this.recentSourceEvents) {
+            this.recentSourceEvents.add(anEvent);
+        }
+
+        // increment event count for Nagios monitoring
+        PdpJmx.getInstance().updateOccured();  
+
+        // Broadcast
+
+        if (logger.isInfoEnabled()) {
+            logger.info("{} BROADCAST-INJECT of {} FROM {} INTO {}", 
+                    this, event, topic, this.policyContainer.getName());
+        }
+
+        for (DroolsControllerFeatureAPI feature : DroolsControllerFeatureAPI.providers.getList()) {
+            try {
+                if (feature.beforeInsert(this, anEvent)) {
+                    return true;
+                }
+            } catch (Exception e) {
+                logger.error("{}: feature {} before-insert failure because of {}",
+                        this, feature.getClass().getName(), e.getMessage(), e);
+            }
+        }
+
+        boolean successInject = this.policyContainer.insertAll(anEvent);
+        if (!successInject) {
+            logger.warn(this + "Failed to inject into PolicyContainer {}", this.getSessionNames());
+        }
+
+        for (DroolsControllerFeatureAPI feature : DroolsControllerFeatureAPI.providers.getList()) {
+            try {
+                if (feature.afterInsert(this, anEvent, successInject)) {
+                    return true;
+                }
+            } catch (Exception e) {
+                logger.error("{}: feature {} after-insert failure because of {}",
+                        this, feature.getClass().getName(), e.getMessage(), e);
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean deliver(TopicSink sink, Object event) {
+
+        if (logger.isInfoEnabled()) {
+            logger.info("{}DELIVER: {} FROM {} TO {}", this, event, this, sink);
+        }
+        
+        if (sink == null) {
+            throw new IllegalArgumentException(this +  " invalid sink");
+        }
+
+        if (event == null) {
+            throw new IllegalArgumentException(this +  " invalid event");
+        }
         
-               List<Object> factObjects = new ArrayList<>();
-               
-               QueryResults queryResults = kieSession.getQueryResults(queryName, queryParams);
-               for (QueryResultsRow row : queryResults) {
-                       try {
-                               factObjects.add(row.get(queriedEntity));
-                               if (delete)
-                                       kieSession.delete(row.getFactHandle(queriedEntity));
-                       } catch (Exception e) {
-                               logger.warn("Object cannot be retrieved from row: {}", row, e);
-                       }
-               }
-               
-               return factObjects;
-       }
-       
-       @Override
-       public Class<?> fetchModelClass(String className) {
-               return ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className);
-       }
-
-       /**
-        * @return the recentSourceEvents
-        */
-       @Override
-       public Object[] getRecentSourceEvents() {
-               synchronized(this.recentSourceEvents) {
-                       Object[] events = new Object[recentSourceEvents.size()];
-                       return recentSourceEvents.toArray(events);
-               }
-       }
-
-       /**
-        * @return the recentSinkEvents
-        */
-       @Override
-       public String[] getRecentSinkEvents() {
-               synchronized(this.recentSinkEvents) {
-                       String[] events = new String[recentSinkEvents.size()];
-                       return recentSinkEvents.toArray(events);
-               }
-       }
-       
-       @Override
-       public boolean isBrained() {
-               return true;
-       }
-       
-
-       @Override
-       public String toString() {
-               StringBuilder builder = new StringBuilder();
-               builder.append("MavenDroolsController [policyContainer=")
-                      .append((policyContainer != null) ? policyContainer.getName() : "NULL").append(":")
-                      .append(", alive=")
-                          .append(alive).append(", locked=")
-                          .append(", modelClassLoaderHash=").append(modelClassLoaderHash).append("]");
-               return builder.toString();
-       }
+        if (this.locked) {
+            throw new IllegalStateException(this +  " is locked");
+        }
+
+        if (!this.alive) {
+            throw new IllegalStateException(this +  " is stopped");
+        }
+
+        String json =
+                EventProtocolCoder.manager.encode(sink.getTopic(), event, this);
+
+        synchronized (this.recentSinkEvents) {
+            this.recentSinkEvents.add(json);
+        }
+
+        return sink.send(json);
+
+    }
+
+    @Override
+    public String getVersion() {
+        return this.policyContainer.getVersion();
+    }
+
+    @Override
+    public String getArtifactId() {
+        return this.policyContainer.getArtifactId();
+    }
+
+    @Override
+    public String getGroupId() {
+        return this.policyContainer.getGroupId();
+    }
+
+    /**
+     * Get model class loader hash.
+     * 
+     * @return the modelClassLoaderHash
+     */
+    public int getModelClassLoaderHash() {
+        return modelClassLoaderHash;
+    }
+
+    @Override
+    public synchronized boolean lock() {
+        logger.info("LOCK: {}",  this);
+
+        this.locked = true;
+        return true;
+    }
+
+    @Override
+    public synchronized boolean unlock() {
+        logger.info("UNLOCK: {}",  this);
+
+        this.locked = false;
+        return true;
+    }
+
+    @Override
+    public boolean isLocked() {
+        return this.locked;
+    }
+
+    @JsonIgnore
+    @Override
+    public PolicyContainer getContainer() {
+        return this.policyContainer;
+    }
+
+    @JsonProperty("sessions")
+    @Override
+    public List<String> getSessionNames() {
+        return getSessionNames(true);
+    }
+
+    /**
+     * get session names.
+     * 
+     * @param abbreviated true for the short form, otherwise the long form
+     * @return session names
+     */
+    protected List<String> getSessionNames(boolean abbreviated) {
+        List<String> sessionNames = new ArrayList<>();
+        try {
+            for (PolicySession session: this.policyContainer.getPolicySessions()) {
+                if (abbreviated) {
+                    sessionNames.add(session.getName());
+                } else {
+                    sessionNames.add(session.getFullName());
+                }
+            }
+        } catch (Exception e) {
+            logger.warn("Can't retrieve CORE sessions: " + e.getMessage(), e);
+            sessionNames.add(e.getMessage());
+        }
+        return sessionNames;
+    }
+
+    @JsonProperty("sessionCoordinates")
+    @Override
+    public List<String> getCanonicalSessionNames() {
+        return getSessionNames(false);
+    }
+
+    /**
+     * provides the underlying core layer container sessions.
+     * 
+     * @return the attached Policy Container
+     */
+    protected List<PolicySession> getSessions() {
+        List<PolicySession> sessions = new ArrayList<>();
+        sessions.addAll(this.policyContainer.getPolicySessions());
+        return sessions;
+    }
+
+    /**
+     * provides the underlying core layer container session with name sessionName.
+     * 
+     * @param sessionName session name
+     * @return the attached Policy Container
+     * @throws IllegalArgumentException when an invalid session name is provided
+     * @throws IllegalStateException when the drools controller is in an invalid state
+     */
+    protected PolicySession getSession(String sessionName) {
+        if (sessionName == null || sessionName.isEmpty()) {
+            throw new IllegalArgumentException("A Session Name must be provided");
+        }
+
+        List<PolicySession> sessions = this.getSessions();
+        for (PolicySession session : sessions) {
+            if (sessionName.equals(session.getName()) || sessionName.equals(session.getFullName())) {
+                return session;
+            }
+        }
+
+        throw invalidSessNameEx(sessionName);
+    }
+
+    private IllegalArgumentException invalidSessNameEx(String sessionName) {
+        return new IllegalArgumentException("Invalid Session Name: " + sessionName);
+    }
+
+    @Override
+    public Map<String,Integer> factClassNames(String sessionName) {
+        if (sessionName == null || sessionName.isEmpty()) {
+            throw invalidSessNameEx(sessionName);
+        }
+
+        Map<String,Integer> classNames = new HashMap<>();
+
+        PolicySession session = getSession(sessionName);
+        KieSession kieSession = session.getKieSession();
+
+        Collection<FactHandle> facts = session.getKieSession().getFactHandles();
+        for (FactHandle fact : facts) {
+            try {
+                String className = kieSession.getObject(fact).getClass().getName();
+                if (classNames.containsKey(className)) {
+                    classNames.put(className, classNames.get(className) + 1);
+                } else {
+                    classNames.put(className, 1);
+                }
+            } catch (Exception e) {
+                logger.warn("Object cannot be retrieved from fact {}", fact, e);
+            }
+        }
+
+        return classNames;
+    }
+
+    @Override
+    public long factCount(String sessionName) {
+        if (sessionName == null || sessionName.isEmpty()) {
+            throw invalidSessNameEx(sessionName);
+        }
+
+        PolicySession session = getSession(sessionName);
+        return session.getKieSession().getFactCount();
+    }
+
+    @Override
+    public List<Object> facts(String sessionName, String className, boolean delete) {
+        if (sessionName == null || sessionName.isEmpty()) {
+            throw invalidSessNameEx(sessionName);
+        }
+
+        if (className == null || className.isEmpty()) {
+            throw new IllegalArgumentException("Invalid Class Name: " + className);
+        }
+
+        Class<?> factClass = 
+                ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className);
+        if (factClass == null) {
+            throw new IllegalArgumentException("Class cannot be fetched in model's classloader: " + className);
+        }
+
+        PolicySession session = getSession(sessionName);
+        KieSession kieSession = session.getKieSession();
+
+        List<Object> factObjects = new ArrayList<>();
+
+        Collection<FactHandle> factHandles = kieSession.getFactHandles(new ClassObjectFilter(factClass));
+        for (FactHandle factHandle : factHandles) {
+            try {
+                factObjects.add(kieSession.getObject(factHandle));
+                if (delete) {
+                    kieSession.delete(factHandle);
+                }
+            } catch (Exception e) {
+                logger.warn("Object cannot be retrieved from fact {}", factHandle, e);
+            }
+        }
+
+        return factObjects;
+    }
+
+    @Override
+    public List<Object> factQuery(String sessionName, String queryName, String queriedEntity, 
+            boolean delete, Object... queryParams) {
+        if (sessionName == null || sessionName.isEmpty()) {
+            throw invalidSessNameEx(sessionName);
+        }
+
+        if (queryName == null || queryName.isEmpty()) {
+            throw new IllegalArgumentException("Invalid Query Name: " + queryName);
+        }
+
+        if (queriedEntity == null || queriedEntity.isEmpty()) {
+            throw new IllegalArgumentException("Invalid Queried Entity: " + queriedEntity);
+        }
+
+        PolicySession session = getSession(sessionName);
+        KieSession kieSession = session.getKieSession();
+
+        boolean found = false;
+        for (KiePackage kiePackage : kieSession.getKieBase().getKiePackages()) {
+            for (Query q : kiePackage.getQueries()) {
+                if (q.getName() != null && q.getName().equals(queryName)) {
+                    found = true;
+                    break;
+                }
+            }
+        }
+        if (!found) {
+            throw new IllegalArgumentException("Invalid Query Name: " + queryName);
+        }
+
+        List<Object> factObjects = new ArrayList<>();
+
+        QueryResults queryResults = kieSession.getQueryResults(queryName, queryParams);
+        for (QueryResultsRow row : queryResults) {
+            try {
+                factObjects.add(row.get(queriedEntity));
+                if (delete) {
+                    kieSession.delete(row.getFactHandle(queriedEntity));
+                }
+            } catch (Exception e) {
+                logger.warn("Object cannot be retrieved from row: {}", row, e);
+            }
+        }
+
+        return factObjects;
+    }
+
+    @Override
+    public Class<?> fetchModelClass(String className) {
+        return ReflectionUtil.fetchClass(this.policyContainer.getClassLoader(), className);
+    }
+
+    /**
+     * Get recent source events.
+     * 
+     * @return the recentSourceEvents
+     */
+    @Override
+    public Object[] getRecentSourceEvents() {
+        synchronized (this.recentSourceEvents) {
+            Object[] events = new Object[recentSourceEvents.size()];
+            return recentSourceEvents.toArray(events);
+        }
+    }
+
+    /**
+     * Get recent sink events.
+     * 
+     * @return the recentSinkEvents
+     */
+    @Override
+    public String[] getRecentSinkEvents() {
+        synchronized (this.recentSinkEvents) {
+            String[] events = new String[recentSinkEvents.size()];
+            return recentSinkEvents.toArray(events);
+        }
+    }
+
+    @Override
+    public boolean isBrained() {
+        return true;
+    }
+
 
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder
+            .append("MavenDroolsController [policyContainer=")
+            .append((policyContainer != null) ? policyContainer.getName() : "NULL")
+            .append(":")
+            .append(", alive=")
+            .append(alive)
+            .append(", locked=")
+            .append(", modelClassLoaderHash=")
+            .append(modelClassLoaderHash)
+            .append("]");
+        return builder.toString();
+    }
 }
index 31ac100..93cbc65 100644 (file)
@@ -31,153 +31,153 @@ import org.onap.policy.common.endpoints.event.comm.TopicSink;
 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
 
 /**
- * no-op Drools Controller
+ * no-op Drools Controller.
  */
 public class NullDroolsController implements DroolsController {
 
-       @Override
-       public boolean start() {
-               return false;
-       }
-
-       @Override
-       public boolean stop() {
-               return false;
-       }
-
-       @Override
-       public void shutdown() {
-               return;
-       }
-       
-       @Override
-       public void halt() {
-               return;
-       }
-
-       @Override
-       public boolean isAlive() {
-               return false;
-       }
-
-       @Override
-       public boolean lock() {
-               return false;
-       }
-
-       @Override
-       public boolean unlock() {
-               return false;
-       }
-
-       @Override
-       public boolean isLocked() {
-               return false;
-       }
-
-       @Override
-       public String getGroupId() {
-               return NO_GROUP_ID;
-       }
-
-       @Override
-       public String getArtifactId() {
-               return NO_ARTIFACT_ID;
-       }
-
-       @Override
-       public String getVersion() {
-               return NO_VERSION;
-       }       
-
-       @Override
-       public List<String> getSessionNames() {
-               return new ArrayList<>();
-       }
-
-       @Override
-       public List<String> getCanonicalSessionNames() {
-               return new ArrayList<>();
-       }
-
-       @Override
-       public boolean offer(String topic, String event) {
-               return false;
-       }
-
-       @Override
-       public boolean deliver(TopicSink sink, Object event) {
-               throw new IllegalStateException(makeInvokeMsg());
-       }
-
-       @Override
-       public Object[] getRecentSourceEvents() {
-               return new String[0];
-       }
-       
-       @Override
-       public PolicyContainer getContainer() {
-               return null;
-       }
-
-       @Override
-       public String[] getRecentSinkEvents() {
-               return new String[0];
-       }
-
-       @Override
-       public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash) {
-               throw new IllegalStateException(makeInvokeMsg());
-       }
-
-       @Override
-       public Class<?> fetchModelClass(String className) {
-               throw new IllegalArgumentException(makeInvokeMsg());
-       }
-       
-       @Override
-       public boolean isBrained() {
-               return false;
-       }
-       
-       @Override
-       public String toString() {
-               StringBuilder builder = new StringBuilder();
-               builder.append("NullDroolsController []");
-               return builder.toString();
-       }
-
-       @Override
-       public void updateToVersion(String newGroupId, String newArtifactId, String newVersion,
-                       List<TopicCoderFilterConfiguration> decoderConfigurations,
-                       List<TopicCoderFilterConfiguration> encoderConfigurations)
-                       throws LinkageError {
-               throw new IllegalArgumentException(makeInvokeMsg());
-       }
-
-       @Override
-       public Map<String, Integer> factClassNames(String sessionName) {
-               return new HashMap<>();
-       }
-
-       @Override
-       public long factCount(String sessionName) {
-               return 0;
-       }
-
-       @Override
-       public List<Object> facts(String sessionName, String className, boolean delete) {
-               return new ArrayList<>();
-       }
-
-       @Override
-       public List<Object> factQuery(String sessionName, String queryName, 
-                                             String queriedEntity, 
-                                             boolean delete, Object... queryParams) {
-               return new ArrayList<>();
-       }
-
-       private String makeInvokeMsg() {
-               return this.getClass().getCanonicalName() + " invoked";
-       }
+    @Override
+    public boolean start() {
+        return false;
+    }
+
+    @Override
+    public boolean stop() {
+        return false;
+    }
+
+    @Override
+    public void shutdown() {
+        return;
+    }
+
+    @Override
+    public void halt() {
+        return;
+    }
+
+    @Override
+    public boolean isAlive() {
+        return false;
+    }
+
+    @Override
+    public boolean lock() {
+        return false;
+    }
+
+    @Override
+    public boolean unlock() {
+        return false;
+    }
+
+    @Override
+    public boolean isLocked() {
+        return false;
+    }
+
+    @Override
+    public String getGroupId() {
+        return NO_GROUP_ID;
+    }
+
+    @Override
+    public String getArtifactId() {
+        return NO_ARTIFACT_ID;
+    }
+
+    @Override
+    public String getVersion() {
+        return NO_VERSION;
+    }  
+
+    @Override
+    public List<String> getSessionNames() {
+        return new ArrayList<>();
+    }
+
+    @Override
+    public List<String> getCanonicalSessionNames() {
+        return new ArrayList<>();
+    }
+
+    @Override
+    public boolean offer(String topic, String event) {
+        return false;
+    }
+
+    @Override
+    public boolean deliver(TopicSink sink, Object event) {
+        throw new IllegalStateException(makeInvokeMsg());
+    }
+
+    @Override
+    public Object[] getRecentSourceEvents() {
+        return new String[0];
+    }
+
+    @Override
+    public PolicyContainer getContainer() {
+        return null;
+    }
+
+    @Override
+    public String[] getRecentSinkEvents() {
+        return new String[0];
+    }
+
+    @Override
+    public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash) {
+        throw new IllegalStateException(makeInvokeMsg());
+    }
+
+    @Override
+    public Class<?> fetchModelClass(String className) {
+        throw new IllegalArgumentException(makeInvokeMsg());
+    }
+
+    @Override
+    public boolean isBrained() {
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("NullDroolsController []");
+        return builder.toString();
+    }
+
+    @Override
+    public void updateToVersion(String newGroupId, String newArtifactId, String newVersion,
+            List<TopicCoderFilterConfiguration> decoderConfigurations,
+            List<TopicCoderFilterConfiguration> encoderConfigurations)
+                    throws LinkageError {
+        throw new IllegalArgumentException(makeInvokeMsg());
+    }
+
+    @Override
+    public Map<String, Integer> factClassNames(String sessionName) {
+        return new HashMap<>();
+    }
+
+    @Override
+    public long factCount(String sessionName) {
+        return 0;
+    }
+
+    @Override
+    public List<Object> facts(String sessionName, String className, boolean delete) {
+        return new ArrayList<>();
+    }
+
+    @Override
+    public List<Object> factQuery(String sessionName, String queryName, 
+            String queriedEntity, 
+            boolean delete, Object... queryParams) {
+        return new ArrayList<>();
+    }
+
+    private String makeInvokeMsg() {
+        return this.getClass().getCanonicalName() + " invoked";
+    }
 }
index f415880..135e1c5 100644 (file)
@@ -29,28 +29,32 @@ import org.onap.policy.drools.utils.OrderedServiceImpl;
  */
 public interface DroolsControllerFeatureAPI extends OrderedService {
 
-         /**
-          * intercepts before the Drools Controller gives the Policy Container a fact to
-          * insert into its Policy Sessions
-          *
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of
-          * lower priority features.   False, otherwise.
-          */
-         default boolean beforeInsert(DroolsController controller, Object fact) {return false;}
+    /**
+     * intercepts before the Drools Controller gives the Policy Container a fact to
+     * insert into its Policy Sessions.
+     *
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of
+     *     lower priority features.   False, otherwise.
+     */
+    default boolean beforeInsert(DroolsController controller, Object fact) {
+        return false;
+    }
 
-         /**
-          * called after a fact is injected into the Policy Container
-          *
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of
-          * lower priority features.   False, otherwise.
-          */
-         default boolean afterInsert(DroolsController controller, Object fact, boolean successInsert) {return false;}
+    /**
+     * called after a fact is injected into the Policy Container.
+     *
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of
+     *     lower priority features.   False, otherwise.
+     */
+    default boolean afterInsert(DroolsController controller, Object fact, boolean successInsert) {
+        return false;
+    }
 
-         /**
-          * Feature providers implementing this interface
-          */
-         public static final OrderedServiceImpl<DroolsControllerFeatureAPI> providers =
-                                                                       new OrderedServiceImpl<>(DroolsControllerFeatureAPI.class);
+    /**
+     * Feature providers implementing this interface.
+     */
+    public static final OrderedServiceImpl<DroolsControllerFeatureAPI> providers =
+            new OrderedServiceImpl<>(DroolsControllerFeatureAPI.class);
 }
index 94d1b15..286948e 100644 (file)
@@ -28,194 +28,230 @@ import org.onap.policy.drools.utils.OrderedService;
 import org.onap.policy.drools.utils.OrderedServiceImpl;
 
 public interface PolicyControllerFeatureAPI extends OrderedService {
-         
-         /**
-          * Feature providers implementing this interface
-          */
-         public static final OrderedServiceImpl<PolicyControllerFeatureAPI> providers = 
-                                                                       new OrderedServiceImpl<PolicyControllerFeatureAPI>(PolicyControllerFeatureAPI.class);
-
-         /**
-          * called before creating a controller with name 'name' and 
-          * properties 'properties'
-          * 
-          * @param name name of the the controller
-          * @param properties configuration properties
-          * 
-          * @return a policy controller.   A take over of the creation operation
-          * is performed by returning a non-null policy controller.   
-          * 'null' indicates that no take over has taken place, and processing should
-          * continue to the next feature provider.
-          */
-         public default PolicyController beforeCreate(String name, Properties properties) {return null;}
-
-         /**
-          * called after creating a controller with name 'name'
-          * 
-          * @param controller controller
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterCreate(PolicyController controller) {return false;}
-         
-         /**
-          * intercept before the Policy Controller is started.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean beforeStart(PolicyController controller) {return false;}
-         
-         /**
-          * intercept after the Policy Controller is started.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterStart(PolicyController controller) {return false;}
-         
-         /**
-          * intercept before the Policy Controller is stopped.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise..
-          */
-         public default boolean beforeStop(PolicyController controller) {return false;}
-         
-         /**
-          * intercept after the Policy Controller is stopped
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.d.
-          */
-         public default boolean afterStop(PolicyController controller) {return false;}
-         
-         /**
-          * intercept before the Policy Controller is locked
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean beforeLock(PolicyController controller) {return false;}
-         
-         /**
-          * intercept after the Policy Controller is locked
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise..
-          */
-         public default boolean afterLock(PolicyController controller) {return false;}
-         
-         /**
-          * intercept before the Policy Controller is locked
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean beforeUnlock(PolicyController controller) {return false;}
-         
-         /**
-          * intercept after the Policy Controller is locked
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterUnlock(PolicyController controller) {return false;}
-         
-         /**
-          * intercept before the Policy Controller is shut down
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise..
-          */
-         public default boolean beforeShutdown(PolicyController controller) {return false;}
-         
-         /**
-          * called after the Policy Controller is shut down
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterShutdown(PolicyController controller) {return false;}
-         
-         /**
-          * intercept before the Policy Controller is halted
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise..
-          */
-         public default boolean beforeHalt(PolicyController controller) {return false;}
-         
-         /**
-          * called after the Policy Controller is halted
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterHalt(PolicyController controller) {return false;}
-         
-         
-         /**
-          * intercept before the Policy Controller is offered an event
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean beforeOffer(PolicyController controller,
-                                                    CommInfrastructure protocol,
-                                                    String topic,
-                                                    String event) {return false;}
-
-         /**
-          * called after the Policy Controller processes an event offer
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterOffer(PolicyController controller,
-                                        CommInfrastructure protocol,
-                                        String topic,
-                                        String event, 
-                                        boolean success) {return false;}
-         
-         /**
-          * intercept before the Policy Controller delivers (posts) an event
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean beforeDeliver(PolicyController controller,
-                                                                      CommInfrastructure protocol,
-                                                                      String topic,
-                                                                      Object event) {return false;}
-
-         /**
-          * called after the Policy Controller delivers (posts) an event
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterDeliver(PolicyController controller,
-                                                                     CommInfrastructure protocol,
-                                                                     String topic,
-                                                                     Object event, 
-                                                                     boolean success) {return false;}
+
+    /**
+     * Feature providers implementing this interface.
+     */
+    public static final OrderedServiceImpl<PolicyControllerFeatureAPI> providers = 
+            new OrderedServiceImpl<>(PolicyControllerFeatureAPI.class);
+
+    /**
+     * called before creating a controller with name 'name' and 
+     * properties 'properties'.
+     * 
+     * @param name name of the the controller
+     * @param properties configuration properties
+     * 
+     * @return a policy controller.   A take over of the creation operation
+     *     is performed by returning a non-null policy controller.   
+     *     'null' indicates that no take over has taken place, and processing should
+     *     continue to the next feature provider.
+     */
+    public default PolicyController beforeCreate(String name, Properties properties) {
+        return null;
+    }
+
+    /**
+     * called after creating a controller with name 'name'.
+     * 
+     * @param controller controller
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *      of the operation preventing the invocation of 
+     *      lower priority features.   False, otherwise.
+     */
+    public default boolean afterCreate(PolicyController controller) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Controller is started.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean beforeStart(PolicyController controller) {
+        return false;
+    }
+
+    /**
+     * intercept after the Policy Controller is started.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterStart(PolicyController controller) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Controller is stopped.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise..
+     */
+    public default boolean beforeStop(PolicyController controller) {
+        return false;
+    }
+
+    /**
+     * intercept after the Policy Controller is stopped.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.d.
+     */
+    public default boolean afterStop(PolicyController controller) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Controller is locked.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean beforeLock(PolicyController controller) {
+        return false;
+    }
+
+    /**
+     * intercept after the Policy Controller is locked.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise..
+     */
+    public default boolean afterLock(PolicyController controller) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Controller is locked.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean beforeUnlock(PolicyController controller) {
+        return false;
+    }
+
+    /**
+     * intercept after the Policy Controller is locked.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterUnlock(PolicyController controller) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Controller is shut down.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise..
+     */
+    public default boolean beforeShutdown(PolicyController controller) {
+        return false;
+    }
+
+    /**
+     * called after the Policy Controller is shut down.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterShutdown(PolicyController controller) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Controller is halted.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise..
+     */
+    public default boolean beforeHalt(PolicyController controller) {
+        return false;
+    }
+
+    /**
+     * called after the Policy Controller is halted.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterHalt(PolicyController controller) {
+        return false;
+    }
+
+
+    /**
+     * intercept before the Policy Controller is offered an event.
+     * 
+     * @return true if this feature intercepts and takes ownership.
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean beforeOffer(PolicyController controller,
+            CommInfrastructure protocol,
+            String topic,
+            String event) {
+        return false;
+    }
+
+    /**
+     * called after the Policy Controller processes an event offer.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterOffer(PolicyController controller,
+            CommInfrastructure protocol,
+            String topic,
+            String event, 
+            boolean success) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Controller delivers (posts) an event.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean beforeDeliver(PolicyController controller,
+            CommInfrastructure protocol,
+            String topic,
+            Object event) {
+        return false;
+    }
+
+    /**
+     * called after the Policy Controller delivers (posts) an event.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterDeliver(PolicyController controller,
+            CommInfrastructure protocol,
+            String topic,
+            Object event, 
+            boolean success) {
+        return false;
+    }
 }
index 956401a..66b206b 100644 (file)
@@ -30,172 +30,208 @@ import org.onap.policy.drools.utils.OrderedServiceImpl;
  * Policy Engine Feature API.
  * Provides Interception Points during the Policy Engine lifecycle.
  */
-public interface PolicyEngineFeatureAPI extends OrderedService {         
-         /**
-          * Feature providers implementing this interface
-          */
-         public static final OrderedServiceImpl<PolicyEngineFeatureAPI> providers = 
-                                                                       new OrderedServiceImpl<>(PolicyEngineFeatureAPI.class);
-       
-         /**
-          * intercept before the Policy Engine is commanded to boot.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean beforeBoot(PolicyEngine engine, String[] cliArgs) {return false;};
-         
-         /**
-          * intercept after the Policy Engine is booted.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterBoot(PolicyEngine engine) {return false;};
-       
-         /**
-          * intercept before the Policy Engine is configured.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean beforeConfigure(PolicyEngine engine, Properties properties) {return false;};
-         
-         /**
-          * intercept after the Policy Engine is configured.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterConfigure(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept before the Policy Engine goes active.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean beforeActivate(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept after the Policy Engine goes active.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterActivate(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept before the Policy Engine goes standby.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean beforeDeactivate(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept after the Policy Engine goes standby.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterDeactivate(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept before the Policy Engine is started.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean beforeStart(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept after the Policy Engine is started.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterStart(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept before the Policy Engine is stopped.
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise..
-          */
-         public default boolean beforeStop(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept after the Policy Engine is stopped
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.d.
-          */
-         public default boolean afterStop(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept before the Policy Engine is locked
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean beforeLock(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept after the Policy Engine is locked
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise..
-          */
-         public default boolean afterLock(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept before the Policy Engine is locked
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean beforeUnlock(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept after the Policy Engine is locked
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterUnlock(PolicyEngine engine) {return false;};
-         
-         /**
-          * intercept the Policy Engine is shut down
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise..
-          */
-         public default boolean beforeShutdown(PolicyEngine engine){return false;};
-         
-         /**
-          * called after the Policy Engine is shut down
-          * 
-          * @return true if this feature intercepts and takes ownership
-          * of the operation preventing the invocation of 
-          * lower priority features.   False, otherwise.
-          */
-         public default boolean afterShutdown(PolicyEngine engine) {return false;};
+public interface PolicyEngineFeatureAPI extends OrderedService {
+    /**
+     * Feature providers implementing this interface.
+     */
+    public static final OrderedServiceImpl<PolicyEngineFeatureAPI> providers = 
+            new OrderedServiceImpl<>(PolicyEngineFeatureAPI.class);
+
+    /**
+     * intercept before the Policy Engine is commanded to boot.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean beforeBoot(PolicyEngine engine, String[] cliArgs) {
+        return false;
+    }
+
+    /**
+     * intercept after the Policy Engine is booted.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterBoot(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Engine is configured.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean beforeConfigure(PolicyEngine engine, Properties properties) {
+        return false;
+    }
+
+    /**
+     * intercept after the Policy Engine is configured.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterConfigure(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Engine goes active.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean beforeActivate(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept after the Policy Engine goes active.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterActivate(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Engine goes standby.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean beforeDeactivate(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept after the Policy Engine goes standby.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterDeactivate(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Engine is started.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean beforeStart(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept after the Policy Engine is started.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterStart(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Engine is stopped.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise..
+     */
+    public default boolean beforeStop(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept after the Policy Engine is stopped.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.d.
+     */
+    public default boolean afterStop(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Engine is locked.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean beforeLock(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept after the Policy Engine is locked.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise..
+     */
+    public default boolean afterLock(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept before the Policy Engine is locked.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean beforeUnlock(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept after the Policy Engine is locked.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterUnlock(PolicyEngine engine) {
+        return false;
+    }
+
+    /**
+     * intercept the Policy Engine is shut down.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise..
+     */
+    public default boolean beforeShutdown(PolicyEngine engine){
+        return false;
+    }
+
+    /**
+     * called after the Policy Engine is shut down.
+     * 
+     * @return true if this feature intercepts and takes ownership
+     *     of the operation preventing the invocation of 
+     *     lower priority features.   False, otherwise.
+     */
+    public default boolean afterShutdown(PolicyEngine engine) {
+        return false;
+    }
 }
index b1e49ec..6864a34 100644 (file)
@@ -17,6 +17,7 @@
  * limitations under the License.
  * ============LICENSE_END=========================================================
  */
+
 package org.onap.policy.drools.persistence;
 
 import java.io.File;
@@ -37,276 +38,282 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Properties based Persistence
+ * Properties based Persistence.
  */
 public class FileSystemPersistence implements SystemPersistence {
-  /**
-   * policy controllers suffix
-   */
-  public static final String CONTROLLER_SUFFIX_IDENTIFIER = "-controller";
-
-  /**
-   * policy controller properties file suffix
-   */
-  public static final String PROPERTIES_FILE_CONTROLLER_SUFFIX =
-      CONTROLLER_SUFFIX_IDENTIFIER + ".properties";
-
-  /**
-   * policy controller properties file suffix
-   */
-  public static final String PROPERTIES_FILE_CONTROLLER_BACKUP_SUFFIX =
-      CONTROLLER_SUFFIX_IDENTIFIER + ".properties.bak";
-
-  /**
-   * policy engine properties file name
-   */
-  public static final String PROPERTIES_FILE_ENGINE = "policy-engine.properties";
-
-  /**
-   * Installation environment suffix for files
-   */
-  public static final String ENV_SUFFIX = ".environment";
-
-  /**
-   * configuration directory
-   */
-  protected Path configurationDirectory = Paths.get(DEFAULT_CONFIGURATION_DIR);
-
-  /**
-   * logger
-   */
-  private static final Logger logger = LoggerFactory.getLogger(FileSystemPersistence.class);
-
-
-  @Override
-  public void setConfigurationDir(String configDir) {
-    String tempConfigDir = configDir;
     
-    if (tempConfigDir == null) {
-        tempConfigDir = DEFAULT_CONFIGURATION_DIR;
-      this.configurationDirectory = Paths.get(DEFAULT_CONFIGURATION_DIR);
+    /**
+     * policy controllers suffix.
+     */
+    public static final String CONTROLLER_SUFFIX_IDENTIFIER = "-controller";
+
+    /**
+     * policy controller properties file suffix.
+     */
+    public static final String PROPERTIES_FILE_CONTROLLER_SUFFIX =
+            CONTROLLER_SUFFIX_IDENTIFIER + ".properties";
+
+    /**
+     * policy controller properties file suffix.
+     */
+    public static final String PROPERTIES_FILE_CONTROLLER_BACKUP_SUFFIX =
+            CONTROLLER_SUFFIX_IDENTIFIER + ".properties.bak";
+
+    /**
+     * policy engine properties file name.
+     */
+    public static final String PROPERTIES_FILE_ENGINE = "policy-engine.properties";
+
+    /**
+     * Installation environment suffix for files.
+     */
+    public static final String ENV_SUFFIX = ".environment";
+
+    /**
+     * configuration directory.
+     */
+    protected Path configurationDirectory = Paths.get(DEFAULT_CONFIGURATION_DIR);
+
+    /**
+     * logger.
+     */
+    private static final Logger logger = LoggerFactory.getLogger(FileSystemPersistence.class);
+
+
+    @Override
+    public void setConfigurationDir(String configDir) {
+        String tempConfigDir = configDir;
+
+        if (tempConfigDir == null) {
+            tempConfigDir = DEFAULT_CONFIGURATION_DIR;
+            this.configurationDirectory = Paths.get(DEFAULT_CONFIGURATION_DIR);
+        }
+
+        if (!tempConfigDir.equals(DEFAULT_CONFIGURATION_DIR)) {
+            this.configurationDirectory = Paths.get(tempConfigDir);
+        }
+
+        if (Files.notExists(this.configurationDirectory)) {
+            try {
+                Files.createDirectories(this.configurationDirectory);
+            } catch (final IOException e) {
+                throw new IllegalStateException("cannot create " + this.configurationDirectory, e);
+            }
+        }
+
+        if (!Files.isDirectory(this.configurationDirectory)) {
+            throw new IllegalStateException(
+                    "config directory: " + this.configurationDirectory + " is not a directory");
+        }
+    }
+
+    @Override
+    public Path getConfigurationPath() {
+        return this.configurationDirectory;
     }
 
-    if (!tempConfigDir.equals(DEFAULT_CONFIGURATION_DIR))
-      this.configurationDirectory = Paths.get(tempConfigDir);
+    @Override
+    public Properties getEngineProperties() {
+        final Path policyEnginePath =
+                Paths.get(this.configurationDirectory.toString(), PROPERTIES_FILE_ENGINE);
+        try {
+            if (Files.exists(policyEnginePath)) {
+                return PropertyUtil.getProperties(policyEnginePath.toFile());
+            }
+        } catch (final Exception e) {
+            logger.warn("{}: could not find {}", this, policyEnginePath, e);
+        }
 
-    if (Files.notExists(this.configurationDirectory)) {
-      try {
-        Files.createDirectories(this.configurationDirectory);
-      } catch (final IOException e) {
-        throw new IllegalStateException("cannot create " + this.configurationDirectory, e);
-      }
+        return null;
     }
 
-    if (!Files.isDirectory(this.configurationDirectory))
-      throw new IllegalStateException(
-          "config directory: " + this.configurationDirectory + " is not a directory");
-  }
-
-  @Override
-  public Path getConfigurationPath() {
-    return this.configurationDirectory;
-  }
-
-  @Override
-  public Properties getEngineProperties() {
-    final Path policyEnginePath =
-        Paths.get(this.configurationDirectory.toString(), PROPERTIES_FILE_ENGINE);
-    try {
-      if (Files.exists(policyEnginePath))
-        return PropertyUtil.getProperties(policyEnginePath.toFile());
-    } catch (final Exception e) {
-      logger.warn("{}: could not find {}", this, policyEnginePath, e);
+    @Override
+    public boolean backupController(String controllerName) {
+        final Path controllerPropertiesPath = Paths.get(this.configurationDirectory.toString(),
+                controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX);
+
+        if (Files.exists(controllerPropertiesPath)) {
+            try {
+                logger.info("{}: there is an existing configuration file @ {} ", this,
+                        controllerPropertiesPath);
+                final Path controllerPropertiesBakPath = Paths.get(this.configurationDirectory.toString(),
+                        controllerName + PROPERTIES_FILE_CONTROLLER_BACKUP_SUFFIX);
+                Files.copy(controllerPropertiesPath, controllerPropertiesBakPath,
+                        StandardCopyOption.REPLACE_EXISTING);
+            } catch (final Exception e) {
+                logger.warn("{}: {} cannot be backed up", this, controllerName, e);
+                return false;
+            }
+        }
+
+        return true;
     }
 
-    return null;
-  }
-
-  @Override
-  public boolean backupController(String controllerName) {
-    final Path controllerPropertiesPath = Paths.get(this.configurationDirectory.toString(),
-        controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX);
-
-    if (Files.exists(controllerPropertiesPath)) {
-      try {
-        logger.info("{}: there is an existing configuration file @ {} ", this,
-            controllerPropertiesPath);
-        final Path controllerPropertiesBakPath = Paths.get(this.configurationDirectory.toString(),
-            controllerName + PROPERTIES_FILE_CONTROLLER_BACKUP_SUFFIX);
-        Files.copy(controllerPropertiesPath, controllerPropertiesBakPath,
-            StandardCopyOption.REPLACE_EXISTING);
-      } catch (final Exception e) {
-        logger.warn("{}: {} cannot be backed up", this, controllerName, e);
-        return false;
-      }
+    @Override
+    public boolean storeController(String controllerName, Object configuration) {
+        if (!(configuration instanceof Properties)) {
+            throw new IllegalArgumentException(
+                    "configuration must be of type properties to be handled by this manager");
+        }
+
+        final Properties properties = (Properties) configuration;
+
+        final Path controllerPropertiesPath = Paths.get(this.configurationDirectory.toString(),
+                controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX);
+        if (Files.exists(controllerPropertiesPath)) {
+            try {
+                final Properties oldProperties =
+                        PropertyUtil.getProperties(controllerPropertiesPath.toFile());
+                if (oldProperties.equals(properties)) {
+                    logger.info(
+                            "{}: noop: a properties file with the same contents exists for controller {}.", this,
+                            controllerName);
+                    return true;
+                } else {
+                    this.backupController(controllerName);
+                }
+            } catch (final Exception e) {
+                logger.info("{}: no existing {} properties {}", this, controllerName, e);
+                // continue
+            }
+        }
+
+        final File controllerPropertiesFile = controllerPropertiesPath.toFile();
+        try (FileWriter writer = new FileWriter(controllerPropertiesFile)) {
+            properties.store(writer, "Machine created Policy Controller Configuration");
+        } catch (final Exception e) {
+            logger.warn("{}: {} cannot be saved", this, controllerName, e);
+            return false;
+        }
+
+        return true;
     }
 
-    return true;
-  }
-
-  @Override
-  public boolean storeController(String controllerName, Object configuration) {
-    if (!(configuration instanceof Properties))
-      throw new IllegalArgumentException(
-          "configuration must be of type properties to be handled by this manager");
-
-    final Properties properties = (Properties) configuration;
-
-    final Path controllerPropertiesPath = Paths.get(this.configurationDirectory.toString(),
-        controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX);
-    if (Files.exists(controllerPropertiesPath)) {
-      try {
-        final Properties oldProperties =
-            PropertyUtil.getProperties(controllerPropertiesPath.toFile());
-        if (oldProperties.equals(properties)) {
-          logger.info(
-              "{}: noop: a properties file with the same contents exists for controller {}.", this,
-              controllerName);
-          return true;
-        } else {
-          this.backupController(controllerName);
+    @Override
+    public boolean deleteController(String controllerName) {
+        final Path controllerPropertiesPath = Paths.get(this.configurationDirectory.toString(),
+                controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX);
+
+        if (Files.exists(controllerPropertiesPath)) {
+            try {
+                final Path controllerPropertiesBakPath = Paths.get(this.configurationDirectory.toString(),
+                        controllerName + PROPERTIES_FILE_CONTROLLER_BACKUP_SUFFIX);
+                Files.move(controllerPropertiesPath, controllerPropertiesBakPath,
+                        StandardCopyOption.REPLACE_EXISTING);
+            } catch (final Exception e) {
+                logger.warn("{}: {} cannot be deleted", this, controllerName, e);
+                return false;
+            }
         }
-      } catch (final Exception e) {
-        logger.info("{}: no existing {} properties {}", this, controllerName, e);
-        // continue
-      }
+
+        return true;
     }
 
-    final File controllerPropertiesFile = controllerPropertiesPath.toFile();
-    try (FileWriter writer = new FileWriter(controllerPropertiesFile)) {
-      properties.store(writer, "Machine created Policy Controller Configuration");
-    } catch (final Exception e) {
-      logger.warn("{}: {} cannot be saved", this, controllerName, e);
-      return false;
+    @Override
+    public Properties getControllerProperties(String controllerName) {
+        return this.getProperties(controllerName + CONTROLLER_SUFFIX_IDENTIFIER);
     }
 
-    return true;
-  }
-
-  @Override
-  public boolean deleteController(String controllerName) {
-    final Path controllerPropertiesPath = Paths.get(this.configurationDirectory.toString(),
-        controllerName + PROPERTIES_FILE_CONTROLLER_SUFFIX);
-
-    if (Files.exists(controllerPropertiesPath)) {
-      try {
-        final Path controllerPropertiesBakPath = Paths.get(this.configurationDirectory.toString(),
-            controllerName + PROPERTIES_FILE_CONTROLLER_BACKUP_SUFFIX);
-        Files.move(controllerPropertiesPath, controllerPropertiesBakPath,
-            StandardCopyOption.REPLACE_EXISTING);
-      } catch (final Exception e) {
-        logger.warn("{}: {} cannot be deleted", this, controllerName, e);
-        return false;
-      }
+    @Override
+    public List<Properties> getControllerProperties() {
+        final List<Properties> controllers = new ArrayList<>();
+        final File[] controllerFiles = this.sortedListFiles();
+        for (final File controllerFile : controllerFiles) {
+            if (controllerFile.getName().endsWith(PROPERTIES_FILE_CONTROLLER_SUFFIX)) {
+                final int idxSuffix = controllerFile.getName().indexOf(PROPERTIES_FILE_CONTROLLER_SUFFIX);
+                final int lastIdxSuffix =
+                        controllerFile.getName().lastIndexOf(PROPERTIES_FILE_CONTROLLER_SUFFIX);
+                if (idxSuffix != lastIdxSuffix) {
+                    throw new IllegalArgumentException(
+                            "Improper naming of controller properties file: " + "Expected <controller-name>"
+                                    + FileSystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX);
+                }
+
+                final String name = controllerFile.getName().substring(0, lastIdxSuffix);
+                try {
+                    final Properties controllerProperties = this.getControllerProperties(name);
+                    final String controllerName =
+                            controllerProperties.getProperty(DroolsProperties.PROPERTY_CONTROLLER_NAME);
+                    if (controllerName == null) {
+                        controllerProperties.setProperty(DroolsProperties.PROPERTY_CONTROLLER_NAME, name);
+                    } else if (!controllerName.equals(name)) {
+                        logger.error("{}: mismatch controller named {} with file name {}", this, controllerName,
+                                controllerFile.getName());
+                        continue;
+                    }
+                    controllers.add(this.getControllerProperties(name));
+                } catch (final Exception e) {
+                    logger.error("{}: cannot obtain properties for controller {} because of {}", name,
+                            e.getMessage(), e);
+                }
+            }
+        }
+        return controllers;
     }
 
-    return true;
-  }
-
-  @Override
-  public Properties getControllerProperties(String controllerName) {
-    return this.getProperties(controllerName + CONTROLLER_SUFFIX_IDENTIFIER);
-  }
-
-  @Override
-  public List<Properties> getControllerProperties() {
-    final List<Properties> controllers = new ArrayList<>();
-    final File[] controllerFiles = this.sortedListFiles();
-    for (final File controllerFile : controllerFiles) {
-      if (controllerFile.getName().endsWith(PROPERTIES_FILE_CONTROLLER_SUFFIX)) {
-        final int idxSuffix = controllerFile.getName().indexOf(PROPERTIES_FILE_CONTROLLER_SUFFIX);
-        final int lastIdxSuffix =
-            controllerFile.getName().lastIndexOf(PROPERTIES_FILE_CONTROLLER_SUFFIX);
-        if (idxSuffix != lastIdxSuffix)
-          throw new IllegalArgumentException(
-              "Improper naming of controller properties file: " + "Expected <controller-name>"
-                  + FileSystemPersistence.PROPERTIES_FILE_CONTROLLER_SUFFIX);
-
-        final String name = controllerFile.getName().substring(0, lastIdxSuffix);
+    @Override
+    public Properties getProperties(String name) {
+        final Path propertiesPath =
+                Paths.get(this.configurationDirectory.toString(), name + ".properties");
+
+        if (!Files.exists(propertiesPath)) {
+            throw new IllegalArgumentException("properties for " + name + " are not persisted.");
+        }
+
         try {
-          final Properties controllerProperties = this.getControllerProperties(name);
-          final String controllerName =
-              controllerProperties.getProperty(DroolsProperties.PROPERTY_CONTROLLER_NAME);
-          if (controllerName == null) {
-            controllerProperties.setProperty(DroolsProperties.PROPERTY_CONTROLLER_NAME, name);
-          } else if (!controllerName.equals(name)) {
-            logger.error("{}: mismatch controller named {} with file name {}", this, controllerName,
-                controllerFile.getName());
-            continue;
-          }
-          controllers.add(this.getControllerProperties(name));
+            return PropertyUtil.getProperties(propertiesPath.toFile());
         } catch (final Exception e) {
-          logger.error("{}: cannot obtain properties for controller {} because of {}", name,
-              e.getMessage(), e);
+            logger.warn("{}: can't read properties @ {}", name, propertiesPath);
+            throw new IllegalArgumentException(
+                    "can't read properties for " + name + " @ " + propertiesPath, e);
         }
-      }
     }
-    return controllers;
-  }
 
-  @Override
-  public Properties getProperties(String name) {
-    final Path propertiesPath =
-        Paths.get(this.configurationDirectory.toString(), name + ".properties");
-
-    if (!Files.exists(propertiesPath)) {
-      throw new IllegalArgumentException("properties for " + name + " are not persisted.");
+    @Override
+    public List<Properties> getEnvironmentProperties() {
+        final List<Properties> envs = new ArrayList<>();
+        final File[] envFiles = this.sortedListFiles();
+        for (final File envFile : envFiles) {
+            if (envFile.getName().endsWith(ENV_SUFFIX)) {
+                final String name = envFile.getName().substring(0, envFile.getName().indexOf(ENV_SUFFIX));
+                try {
+                    envs.add(this.getEnvironmentProperties(name));
+                } catch (final Exception e) {
+                    logger.error("{}: cannot get environment {} because of {}", name, e.getMessage(), e);
+                }
+            }
+        }
+        return envs;
     }
 
-    try {
-      return PropertyUtil.getProperties(propertiesPath.toFile());
-    } catch (final Exception e) {
-      logger.warn("{}: can't read properties @ {}", name, propertiesPath);
-      throw new IllegalArgumentException(
-          "can't read properties for " + name + " @ " + propertiesPath, e);
-    }
-  }
-
-  @Override
-  public List<Properties> getEnvironmentProperties() {
-    final List<Properties> envs = new ArrayList<>();
-    final File[] envFiles = this.sortedListFiles();
-    for (final File envFile : envFiles) {
-      if (envFile.getName().endsWith(ENV_SUFFIX)) {
-        final String name = envFile.getName().substring(0, envFile.getName().indexOf(ENV_SUFFIX));
+    @Override
+    public Properties getEnvironmentProperties(String name) {
+        final Path envPath = Paths.get(this.configurationDirectory.toString(), name + ENV_SUFFIX);
+        if (!Files.exists(envPath)) {
+            throw new IllegalArgumentException("{} environment" + name + " cannot be retrieved");
+        }
+
         try {
-          envs.add(this.getEnvironmentProperties(name));
+            return PropertyUtil.getProperties(envPath.toFile());
         } catch (final Exception e) {
-          logger.error("{}: cannot get environment {} because of {}", name, e.getMessage(), e);
+            throw new IllegalArgumentException("cannot read environment " + name, e);
         }
-      }
-    }
-    return envs;
-  }
-
-  @Override
-  public Properties getEnvironmentProperties(String name) {
-    final Path envPath = Paths.get(this.configurationDirectory.toString(), name + ENV_SUFFIX);
-    if (!Files.exists(envPath)) {
-      throw new IllegalArgumentException("{} environment" + name + " cannot be retrieved");
     }
 
-    try {
-      return PropertyUtil.getProperties(envPath.toFile());
-    } catch (final Exception e) {
-      throw new IllegalArgumentException("cannot read environment " + name, e);
+    /**
+     * provides a list of files sorted by name in ascending order in the configuration directory.
+     */
+    protected File[] sortedListFiles() {
+        final File[] dirFiles = this.configurationDirectory.toFile().listFiles();
+        Arrays.sort(dirFiles, (a, b) -> a.getName().compareTo(b.getName()));
+        return dirFiles;
     }
-  }
-
-  /**
-   * provides a list of files sorted by name in ascending order in the configuration directory
-   */
-  protected File[] sortedListFiles() {
-    final File[] dirFiles = this.configurationDirectory.toFile().listFiles();
-    Arrays.sort(dirFiles, (a, b) -> a.getName().compareTo(b.getName()));
-    return dirFiles;
-  }
-
-  @Override
-  public String toString() {
-    final StringBuilder builder = new StringBuilder();
-    builder.append("FileSystemPersistence [configurationDirectory=")
+
+    @Override
+    public String toString() {
+        final StringBuilder builder = new StringBuilder();
+        builder.append("FileSystemPersistence [configurationDirectory=")
         .append(this.configurationDirectory).append("]");
-    return builder.toString();
-  }
+        return builder.toString();
+    }
 }
index 0d0a33c..34b27c2 100644 (file)
@@ -25,108 +25,107 @@ import java.util.List;
 import java.util.Properties;
 
 /**
- * System Configuration
+ * System Configuration.
  */
 public interface SystemPersistence {
-  /**
-   * configuration directory
-   */
-  public static final String DEFAULT_CONFIGURATION_DIR = "config";
+    /**
+     * configuration directory.
+     */
+    public static final String DEFAULT_CONFIGURATION_DIR = "config";
 
-  /**
-   * Persistence Manager. For now it is a file-based properties management, In the future, it will
-   * probably be DB based, so manager implementation will change.
-   */
-  public static final SystemPersistence manager = new FileSystemPersistence();
+    /**
+     * Persistence Manager. For now it is a file-based properties management, In the future, it will
+     * probably be DB based, so manager implementation will change.
+     */
+    public static final SystemPersistence manager = new FileSystemPersistence();
 
-  /**
-   * sets a configuration directory and ensures it exists
-   *
-   * @param configDir configuration directory or null to use the default one
-   */
-  public void setConfigurationDir(String configDir);
+    /**
+     * sets a configuration directory and ensures it exists.
+     *
+     * @param configDir configuration directory or null to use the default one
+     */
+    public void setConfigurationDir(String configDir);
 
-  /**
-   * get configuration directory path
-   *
-   * @return configuration directory path
-   */
-  public Path getConfigurationPath();
+    /**
+     * get configuration directory path.
+     *
+     * @return configuration directory path
+     */
+    public Path getConfigurationPath();
 
-  /**
-   * backs up a controller configuration.
-   *
-   * @param controllerName the controller name
-   * @return true if the configuration is backed up
-   */
-  public boolean backupController(String controllerName);
+    /**
+     * backs up a controller configuration.
+     *
+     * @param controllerName the controller name
+     * @return true if the configuration is backed up
+     */
+    public boolean backupController(String controllerName);
 
-  /**
-   * persists controller configuration
-   *
-   * @param controllerName the controller name
-   * @param configuration object containing the configuration
-   *
-   * @return true if storage is succesful, false otherwise
-   * @throws IllegalArgumentException if the configuration cannot be handled by the persistence
-   *         manager
-   */
-  public boolean storeController(String controllerName, Object configuration);
+    /**
+     * persists controller configuration.
+     *
+     * @param controllerName the controller name
+     * @param configuration object containing the configuration
+     *
+     * @return true if storage is succesful, false otherwise
+     * @throws IllegalArgumentException if the configuration cannot be handled by the persistence
+     *         manager
+     */
+    public boolean storeController(String controllerName, Object configuration);
 
-  /**
-   * delete controller configuration
-   *
-   * @param controllerName the controller name
-   * @return true if storage is succesful, false otherwise
-   */
-  public boolean deleteController(String controllerName);
+    /**
+     * delete controller configuration.
+     *
+     * @param controllerName the controller name
+     * @return true if storage is succesful, false otherwise
+     */
+    public boolean deleteController(String controllerName);
 
-  /**
-   * get controller properties
-   *
-   * @param controllerName controller name
-   * @return properties for this controller
-   *
-   * @throws IllegalArgumentException if the controller name does not lead to a properties
-   *         configuration
-   */
-  public Properties getControllerProperties(String controllerName);
+    /**
+     * get controller properties.
+     *
+     * @param controllerName controller name
+     * @return properties for this controller
+     *
+     * @throws IllegalArgumentException if the controller name does not lead to a properties
+     *         configuration
+     */
+    public Properties getControllerProperties(String controllerName);
 
-  /**
-   * get controllers configuration
-   *
-   * @return list of controllers properties
-   */
-  public List<Properties> getControllerProperties();
+    /**
+     * get controllers configuration.
+     *
+     * @return list of controllers properties
+     */
+    public List<Properties> getControllerProperties();
 
-  /**
-   * get environments
-   *
-   * @param environment name
-   */
-  public List<Properties> getEnvironmentProperties();
+    /**
+     * get environments.
+     *
+     */
+    public List<Properties> getEnvironmentProperties();
 
-  /**
-   * get environment properties
-   *
-   * @param environment name
-   */
-  public Properties getEnvironmentProperties(String environmentName);
+    /**
+     * get environment properties.
+     *
+     * @param environmentName name
+     */
+    public Properties getEnvironmentProperties(String environmentName);
 
-  /**
-   * get the engine properties
-   *
-   * @return the engine properties
-   */
-  public Properties getEngineProperties();
+    /**
+     * get the engine properties.
+     *
+     * @return the engine properties
+     */
+    public Properties getEngineProperties();
 
-  /**
-   * get properties by name
-   *
-   * @param name
-   * @return properties
-   *
-   * @throws IllegalArgumentException if the name does not lead to a properties configuration
-   */
-  public Properties getProperties(String name);
+    /**
+     * get properties by name.
+     *
+     * @param name name
+     * @return properties
+     *
+     * @throws IllegalArgumentException if the name does not lead to a properties configuration
+     */
+    public Properties getProperties(String name);
 }
index d0008f0..3e4e7ec 100644 (file)
@@ -38,344 +38,355 @@ import org.slf4j.LoggerFactory;
  * Coder (Encoder/Decoder) of Events.
  */
 public interface EventProtocolCoder {
-       
-       /**
-        * singleton reference to the global event protocol coder
-        */
-       public static EventProtocolCoder manager = new MultiplexorEventProtocolCoder();
-       
-       public static class CoderFilters {
-
-               /**
-                * coder class 
-                */
-               protected String factClass;
-               
-               /**
-                * filters to apply to the selection of the decodedClass;
-                */
-               protected JsonProtocolFilter filter;
-
-               /**
-                * classloader hash
-                */
-               protected int modelClassLoaderHash;
-
-               
-               /**
-                * constructor
-                * 
-                * @param codedClass coder class
-                * @param filter filters to apply
-                */
-               public CoderFilters(String codedClass, JsonProtocolFilter filter, int modelClassLoaderHash) {
-                       this.factClass = codedClass;
-                       this.filter = filter;
-                       this.modelClassLoaderHash = modelClassLoaderHash;
-               }
-
-               /**
-                * @return the codedClass
-                */
-               public String getCodedClass() {
-                       return factClass;
-               }
-
-               /**
-                * @param codedClass the decodedClass to set
-                */
-               public void setCodedClass(String codedClass) {
-                       this.factClass = codedClass;
-               }
-               
-               /**
-                * @return the filter
-                */
-               public JsonProtocolFilter getFilter() {
-                       return filter;
-               }
-
-               /**
-                * @param filter the filter to set
-                */
-               public void setFilter(JsonProtocolFilter filter) {
-                       this.filter = filter;
-               }
-
-               public int getModelClassLoaderHash() {
-                       return modelClassLoaderHash;
-               }
-
-               public void setFromClassLoaderHash(int fromClassLoaderHash) {
-                       this.modelClassLoaderHash = fromClassLoaderHash;
-               }
-
-               @Override
-               public String toString() {
-                       StringBuilder builder = new StringBuilder();
-                       builder.append("CoderFilters [factClass=").append(factClass).append(", filter=").append(filter)
-                                       .append(", modelClassLoaderHash=").append(modelClassLoaderHash).append("]");
-                       return builder.toString();
-               }
-
-       }
-       
-       /**
-        * Adds a Decoder class to decode the protocol over this topic
-        *  
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic the topic 
-        * @param eventClass the event class
-        * @param protocolFilter filters to selectively choose a particular decoder
-        * when there are multiples
-        * 
-        * @throw IllegalArgumentException if an invalid parameter is passed
-        */
-       public void addDecoder(String groupId, String artifactId, 
-                                      String topic, 
-                                      String eventClass, 
-                                      JsonProtocolFilter protocolFilter, 
-                                      CustomGsonCoder customGsonCoder,
-                                      CustomJacksonCoder customJacksonCoder,
-                                      int modelClassLoaderHash);
-
-       /**
-        * removes all decoders associated with the controller id
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic of the controller
-        * 
-        * @throws IllegalArgumentException if invalid arguments have been provided
-        */
-       void removeEncoders(String groupId, String artifactId, String topic);
-       
-       /**
-        * removes decoders associated with the controller id and topic
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic the topic
-        * 
-        * @throws IllegalArgumentException if invalid arguments have been provided
-        */
-       public void removeDecoders(String groupId, String artifactId, String topic);
-       
-       /**
-        * Given a controller id and a topic, it gives back its filters
-        * 
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic the topic
-        * 
-        * return list of decoders
-        * 
-        * @throw IllegalArgumentException if an invalid parameter is passed
-        */
-       public List<CoderFilters> getDecoderFilters(String groupId, String artifactId, String topic);
-       
-
-       /**
-        * Given a controller id and a topic, it gives back the decoding configuration
-        * 
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic the topic
-        * 
-        * return decoding toolset
-        * 
-        * @throw IllegalArgumentException if an invalid parameter is passed
-        */
-       public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic);
-       
-       /**
-        * Given a controller id and a topic, it gives back all the decoding configurations
-        * 
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic the topic
-        * 
-        * return decoding toolset
-        * 
-        * @throw IllegalArgumentException if an invalid parameter is passed
-        */
-       public List<ProtocolCoderToolset> getDecoders(String groupId, String artifactId);
-       
-       
-       /**
-        * gets all decoders associated with the group and artifact ids
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * 
-        * @throws IllegalArgumentException if invalid arguments have been provided
-        */
-       public List<CoderFilters> getDecoderFilters(String groupId, String artifactId);
-       
-
-       /**
-        * Given a controller id and a topic, it gives back the classes that implements the encoding
-        * 
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic the topic
-        * 
-        * return list of decoders
-        * 
-        * @throw IllegalArgumentException if an invalid parameter is passed
-        */
-       public List<CoderFilters> getEncoderFilters(String groupId, String artifactId, String topic);
-       
-       /**
-        * gets all encoders associated with the group and artifact ids
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * 
-        * @throws IllegalArgumentException if invalid arguments have been provided
-        */
-       public List<CoderFilters> getEncoderFilters(String groupId, String artifactId);
-       
-       /**
-        * Given a controller id, a topic, and a classname, it gives back the classes that implements the decoding
-        * 
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic the topic
-        * @param classname classname
-        * 
-        * return list of decoders
-        * 
-        * @throw IllegalArgumentException if an invalid parameter is passed
-        */     
-       public CoderFilters getDecoderFilters(String groupId, String artifactId, String topic, String classname);
-       
-       /**
-        * is there a decoder supported for the controller id and topic
-        * 
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic protocol
-        * @return true if supported
-        */
-       public boolean isDecodingSupported(String groupId, String artifactId, String topic);
-       
-       /**
-        * Adds a Encoder class to encode the protocol over this topic
-        *  
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic the topic 
-        * @param eventClass the event class
-        * @param protocolFilter filters to selectively choose a particular decoder
-        * when there are multiples
-        * 
-        * @throw IllegalArgumentException if an invalid parameter is passed
-        */
-       public void addEncoder(String groupId, String artifactId, String topic, 
-                                                  String eventClass, 
-                                      JsonProtocolFilter protocolFilter,
-                                      CustomGsonCoder customGsonCoder,
-                                      CustomJacksonCoder customJacksonCoder,
-                                      int modelClassLoaderHash);
-       
-       /**
-        * is there an encoder supported for the controller id and topic
-        * 
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic protocol
-        * @return true if supported
-        */
-       public boolean isEncodingSupported(String groupId, String artifactId, String topic);
-       
-       /**
-        * get encoder based on coordinates and classname
-        * 
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic protocol
-        * @param json event string
-        * @return
-        * @throws IllegalArgumentException invalid arguments passed in
-        */
-       public CoderFilters getEncoderFilters(String groupId, String artifactId, String topic, String classname);
-       
-       /**
-        * get encoder based on topic and encoded class
-        * 
-        * @param topic topic
-        * @param encodedClass encoded class
-        * @return
-        * @throws IllegalArgumentException invalid arguments passed in
-        */
-       public List<CoderFilters> getReverseEncoderFilters(String topic, String encodedClass);
-       
-       /**
-        * gets the identifier of the creator of the encoder
-        * 
-        * @param topic topic
-        * @param encodedClass encoded class
-        * @return a drools controller
-        * @throws IllegalArgumentException invalid arguments passed in
-        */
-       public DroolsController getDroolsController(String topic, Object encodedClass);
-       
-       /**
-        * gets the identifier of the creator of the encoder
-        * 
-        * @param topic topic
-        * @param encodedClass encoded class
-        * @return list of drools controllers
-        * @throws IllegalArgumentException invalid arguments passed in
-        */
-       public List<DroolsController> getDroolsControllers(String topic, Object encodedClass);
-       
-       /**
-        * decode topic's stringified event (json) to corresponding Event Object.
-        * 
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic protocol
-        * @param json event string
-        * @return
-        * @throws IllegalArgumentException invalid arguments passed in
-        * @throws UnsupportedOperationException if the operation is not supported
-        * @throws IllegalStateException if the system is in an illegal state
-        */
-       public Object decode(String groupId, String artifactId, String topic, String json);
-
-       /**
-        * encodes topic's stringified event (json) to corresponding Event Object.
-        * 
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic protocol
-        * @param event Object
-        * 
-        * @throws IllegalArgumentException invalid arguments passed in
-        */
-       public String encode(String groupId, String artifactId, String topic, Object event);
-       
-       /**
-        * encodes topic's stringified event (json) to corresponding Event Object.
-        * 
-        * @param topic topic
-        * @param event event object
-        * 
-        * @throws IllegalArgumentException invalid arguments passed in
-        * @throws UnsupportedOperationException operation cannot be performed
-        */
-       public String encode(String topic, Object event);
-       
-       /**
-        * encodes topic's stringified event (json) to corresponding Event Object.
-        * 
-        * @param topic topic
-        * @param event event object
-        * @param droolsController 
-        * 
-        * @throws IllegalArgumentException invalid arguments passed in
-        * @throws UnsupportedOperationException operation cannot be performed
-        */
-       public String encode(String topic, Object event, DroolsController droolsController);
+
+    /**
+     * singleton reference to the global event protocol coder.
+     */
+    public static EventProtocolCoder manager = new MultiplexorEventProtocolCoder();
+
+    public static class CoderFilters {
+
+        /**
+         * coder class.
+         */
+        protected String factClass;
+
+        /**
+         * filters to apply to the selection of the decodedClass.
+         */
+        protected JsonProtocolFilter filter;
+
+        /**
+         * classloader hash.
+         */
+        protected int modelClassLoaderHash;
+
+
+        /**
+         * constructor.
+         * 
+         * @param codedClass coder class
+         * @param filter filters to apply
+         */
+        public CoderFilters(String codedClass, JsonProtocolFilter filter, int modelClassLoaderHash) {
+            this.factClass = codedClass;
+            this.filter = filter;
+            this.modelClassLoaderHash = modelClassLoaderHash;
+        }
+
+        /**
+         * Get coded class.
+         * 
+         * @return the codedClass
+         */
+        public String getCodedClass() {
+            return factClass;
+        }
+
+        /**
+         * Set coded class.
+         * 
+         * @param codedClass the decodedClass to set
+         */
+        public void setCodedClass(String codedClass) {
+            this.factClass = codedClass;
+        }
+
+        /**
+         * Get filter.
+         * 
+         * @return the filter
+         */
+        public JsonProtocolFilter getFilter() {
+            return filter;
+        }
+
+        /**
+         * Set filter.
+         * 
+         * @param filter the filter to set
+         */
+        public void setFilter(JsonProtocolFilter filter) {
+            this.filter = filter;
+        }
+
+        public int getModelClassLoaderHash() {
+            return modelClassLoaderHash;
+        }
+
+        public void setFromClassLoaderHash(int fromClassLoaderHash) {
+            this.modelClassLoaderHash = fromClassLoaderHash;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("CoderFilters [factClass=").append(factClass).append(", filter=").append(filter)
+            .append(", modelClassLoaderHash=").append(modelClassLoaderHash).append("]");
+            return builder.toString();
+        }
+
+    }
+
+    /**
+     * Adds a Decoder class to decode the protocol over this topic.
+     *  
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic the topic 
+     * @param eventClass the event class
+     * @param protocolFilter filters to selectively choose a particular decoder
+     *     when there are multiples
+     * 
+     * @throw IllegalArgumentException if an invalid parameter is passed
+     */
+    public void addDecoder(String groupId, String artifactId, 
+            String topic, 
+            String eventClass, 
+            JsonProtocolFilter protocolFilter, 
+            CustomGsonCoder customGsonCoder,
+            CustomJacksonCoder customJacksonCoder,
+            int modelClassLoaderHash);
+
+    /**
+     * removes all decoders associated with the controller id.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic of the controller
+     * 
+     * @throws IllegalArgumentException if invalid arguments have been provided
+     */
+    void removeEncoders(String groupId, String artifactId, String topic);
+
+    /**
+     * removes decoders associated with the controller id and topic.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic the topic
+     * 
+     * @throws IllegalArgumentException if invalid arguments have been provided
+     */
+    public void removeDecoders(String groupId, String artifactId, String topic);
+
+    /**
+     * Given a controller id and a topic, it gives back its filters.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic the topic
+     * 
+     * @return list of decoders
+     * 
+     * @throw IllegalArgumentException if an invalid parameter is passed
+     */
+    public List<CoderFilters> getDecoderFilters(String groupId, String artifactId, String topic);
+
+
+    /**
+     * Given a controller id and a topic, it gives back the decoding configuration.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic the topic
+     * 
+     * @return decoding toolset
+     * 
+     * @throw IllegalArgumentException if an invalid parameter is passed
+     */
+    public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic);
+
+    /**
+     * Given a controller id and a topic, it gives back all the decoding configurations.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * 
+     * @return decoding toolset
+     * 
+     * @throw IllegalArgumentException if an invalid parameter is passed
+     */
+    public List<ProtocolCoderToolset> getDecoders(String groupId, String artifactId);
+
+    /**
+     * gets all decoders associated with the group and artifact ids.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * 
+     * @throws IllegalArgumentException if invalid arguments have been provided
+     */
+    public List<CoderFilters> getDecoderFilters(String groupId, String artifactId);
+
+
+    /**
+     * Given a controller id, a topic, and a classname, it gives back the classes that implements the decoding.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic the topic
+     * @param classname classname
+     * 
+     * @return list of decoders
+     * 
+     * @throw IllegalArgumentException if an invalid parameter is passed
+     */ 
+    public CoderFilters getDecoderFilters(String groupId, String artifactId, String topic, String classname);
+
+    /**
+     * Given a controller id and a topic, it gives back the classes that implements the encoding.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic the topic
+     * 
+     * @return list of decoders
+     * 
+     * @throw IllegalArgumentException if an invalid parameter is passed
+     */
+    public List<CoderFilters> getEncoderFilters(String groupId, String artifactId, String topic);
+
+    /**
+     * gets all encoders associated with the group and artifact ids.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * 
+     * @throws IllegalArgumentException if invalid arguments have been provided
+     */
+    public List<CoderFilters> getEncoderFilters(String groupId, String artifactId);
+
+    /**
+     * get encoder based on coordinates and classname.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic protocol
+     * @param classname name of the class
+     * @return
+     * 
+     * @throws IllegalArgumentException invalid arguments passed in
+     */
+    public CoderFilters getEncoderFilters(String groupId, String artifactId, String topic, String classname);
+
+    /**
+     * is there a decoder supported for the controller id and topic.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic protocol
+     * @return true if supported
+     */
+    public boolean isDecodingSupported(String groupId, String artifactId, String topic);
+
+    /**
+     * Adds a Encoder class to encode the protocol over this topic.
+     *  
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic the topic 
+     * @param eventClass the event class
+     * @param protocolFilter filters to selectively choose a particular decoder
+     *     when there are multiples
+     * 
+     * @throw IllegalArgumentException if an invalid parameter is passed
+     */
+    public void addEncoder(String groupId, String artifactId, String topic, 
+            String eventClass, 
+            JsonProtocolFilter protocolFilter,
+            CustomGsonCoder customGsonCoder,
+            CustomJacksonCoder customJacksonCoder,
+            int modelClassLoaderHash);
+
+    /**
+     * is there an encoder supported for the controller id and topic.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic protocol
+     * @return true if supported
+     */
+    public boolean isEncodingSupported(String groupId, String artifactId, String topic);
+
+    /**
+     * get encoder based on topic and encoded class.
+     * 
+     * @param topic topic
+     * @param encodedClass encoded class
+     * @return list of filters
+     * @throws IllegalArgumentException invalid arguments passed in
+     */
+    public List<CoderFilters> getReverseEncoderFilters(String topic, String encodedClass);
+
+    /**
+     * gets the identifier of the creator of the encoder.
+     * 
+     * @param topic topic
+     * @param encodedClass encoded class
+     * @return a drools controller
+     * @throws IllegalArgumentException invalid arguments passed in
+     */
+    public DroolsController getDroolsController(String topic, Object encodedClass);
+
+    /**
+     * gets the identifier of the creator of the encoder.
+     * 
+     * @param topic topic
+     * @param encodedClass encoded class
+     * @return list of drools controllers
+     * @throws IllegalArgumentException invalid arguments passed in
+     */
+    public List<DroolsController> getDroolsControllers(String topic, Object encodedClass);
+
+    /**
+     * decode topic's stringified event (json) to corresponding Event Object.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic protocol
+     * @param json event string
+     * @return object
+     * @throws IllegalArgumentException invalid arguments passed in
+     * @throws UnsupportedOperationException if the operation is not supported
+     * @throws IllegalStateException if the system is in an illegal state
+     */
+    public Object decode(String groupId, String artifactId, String topic, String json);
+
+    /**
+     * encodes topic's stringified event (json) to corresponding Event Object.
+     * 
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic protocol
+     * @param event Object
+     * 
+     * @throws IllegalArgumentException invalid arguments passed in
+     */
+    public String encode(String groupId, String artifactId, String topic, Object event);
+
+    /**
+     * encodes topic's stringified event (json) to corresponding Event Object.
+     * 
+     * @param topic topic
+     * @param event event object
+     * 
+     * @throws IllegalArgumentException invalid arguments passed in
+     * @throws UnsupportedOperationException operation cannot be performed
+     */
+    public String encode(String topic, Object event);
+
+    /**
+     * encodes topic's stringified event (json) to corresponding Event Object.
+     * 
+     * @param topic topic
+     * @param event event object
+     * @param droolsController 
+     * 
+     * @throws IllegalArgumentException invalid arguments passed in
+     * @throws UnsupportedOperationException operation cannot be performed
+     */
+    public String encode(String topic, Object event, DroolsController droolsController);
 }
 
 /**
@@ -383,247 +394,251 @@ public interface EventProtocolCoder {
  * class and best fitted json parsing tools.
  */
 class MultiplexorEventProtocolCoder implements EventProtocolCoder {
-       /**
-        * Logger 
-        */
-       private static Logger logger = LoggerFactory.getLogger(MultiplexorEventProtocolCoder.class);
-       
-       /**
-        * Decoders
-        */
-       protected EventProtocolDecoder decoders = new EventProtocolDecoder();
-       
-       /**
-        * Encoders
-        */
-       protected EventProtocolEncoder encoders = new EventProtocolEncoder();
-       
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public void addDecoder(String groupId, String artifactId, String topic, 
-                                      String eventClass, 
-                                      JsonProtocolFilter protocolFilter,
-                                      CustomGsonCoder customGsonCoder,
-                                      CustomJacksonCoder customJacksonCoder,
-                                      int modelClassLoaderHash) {
-               logger.info("{}: add-decoder {}:{}:{}:{}:{}:{}:{}:{}", this, 
-                                   groupId, artifactId, topic, eventClass,
-                                   protocolFilter, customGsonCoder, customJacksonCoder,
-                                   modelClassLoaderHash);
-               this.decoders.add(groupId, artifactId, topic, eventClass, protocolFilter, 
-                                        customGsonCoder, customJacksonCoder, modelClassLoaderHash);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public void addEncoder(String groupId, String artifactId, String topic, 
-                                      String eventClass, 
-                                      JsonProtocolFilter protocolFilter,
-                                      CustomGsonCoder customGsonCoder,
-                                      CustomJacksonCoder customJacksonCoder,
-                                      int modelClassLoaderHash) {
-               logger.info("{}: add-decoder {}:{}:{}:{}:{}:{}:{}:{}", this, 
-                               groupId, artifactId, topic, eventClass,
-                               protocolFilter, customGsonCoder, customJacksonCoder,
-                               modelClassLoaderHash);
-               this.encoders.add(groupId, artifactId, topic, eventClass, protocolFilter, 
-                                 customGsonCoder, customJacksonCoder, modelClassLoaderHash);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public void removeDecoders(String groupId, String artifactId, String topic) {
-               logger.info("{}: remove-decoder {}:{}:{}", this, groupId, artifactId, topic);   
-               this.decoders.remove(groupId, artifactId, topic);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public void removeEncoders(String groupId, String artifactId, String topic) {
-               logger.info("{}: remove-encoder {}:{}:{}", this, groupId, artifactId, topic);
-               this.encoders.remove(groupId, artifactId, topic);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public boolean isDecodingSupported(String groupId, String artifactId, String topic) {   
-               return this.decoders.isCodingSupported(groupId, artifactId, topic);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public boolean isEncodingSupported(String groupId, String artifactId, String topic) {
-               return this.encoders.isCodingSupported(groupId, artifactId, topic);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public Object decode(String groupId, String artifactId, String topic, String json) {
-               logger.debug("{}: decode {}:{}:{}:{}", this, groupId, artifactId, topic, json);
-               return this.decoders.decode(groupId, artifactId, topic, json);
-       }
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public String encode(String groupId, String artifactId, String topic, Object event) {
-               logger.debug("{}: encode {}:{}:{}:{}", this, groupId, artifactId, topic, event);
-               return this.encoders.encode(groupId, artifactId, topic, event);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public String encode(String topic, Object event) {
-               logger.debug("{}: encode {}:{}", this, topic, event);
-               return this.encoders.encode(topic, event);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public String encode(String topic, Object event, DroolsController droolsController) {
-               logger.debug("{}: encode {}:{}:{}", this, topic, event, droolsController);
-               return this.encoders.encode(topic, event, droolsController);
-       }
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public List<CoderFilters> getDecoderFilters(String groupId, String artifactId, String topic) {
-               return this.decoders.getFilters(groupId, artifactId, topic);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic) {
-               Pair<ProtocolCoderToolset,ProtocolCoderToolset> decoderToolsets = this.decoders.getCoders(groupId, artifactId, topic);
-               if (decoderToolsets == null)
-                       throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId + ":" + topic);
-               
-               return decoderToolsets.first();
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public List<CoderFilters> getEncoderFilters(String groupId, String artifactId, String topic) {
-               return this.encoders.getFilters(groupId, artifactId, topic);
-       }
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public CoderFilters getDecoderFilters(String groupId, String artifactId, String topic, String classname) {
-               return this.decoders.getFilters(groupId, artifactId, topic, classname);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public CoderFilters getEncoderFilters(String groupId, String artifactId, String topic, String classname) {
-               return this.encoders.getFilters(groupId, artifactId, topic, classname);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public List<CoderFilters> getReverseEncoderFilters(String topic, String encodedClass) {
-               return this.encoders.getReverseFilters(topic, encodedClass);
-       }
-
-       /**
-        * get all deocders by maven coordinates and topic
-        * 
-        * @param groupId group id
-        * @param artifactId artifact id
-        * 
-        * @return list of decoders
-        * @throws IllegalArgumentException if invalid input
-        */
-       @Override
-       public List<ProtocolCoderToolset> getDecoders(String groupId, String artifactId) {
-
-               List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> decoderToolsets = this.decoders.getCoders(groupId, artifactId);
-               if (decoderToolsets == null)
-                       throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId);
-               
-               List<ProtocolCoderToolset> parser1CoderToolset = new ArrayList<>();
-               for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderToolsetPair : decoderToolsets) {
-                       parser1CoderToolset.add(coderToolsetPair.first());
-               }
-               
-               return parser1CoderToolset;
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public List<CoderFilters> getDecoderFilters(String groupId, String artifactId) {
-               return this.decoders.getFilters(groupId, artifactId);
-               
-       }
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public List<CoderFilters> getEncoderFilters(String groupId, String artifactId) {
-               return this.encoders.getFilters(groupId, artifactId);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public DroolsController getDroolsController(String topic, Object encodedClass) {
-               return this.encoders.getDroolsController(topic, encodedClass);
-       }
-       
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public List<DroolsController> getDroolsControllers(String topic, Object encodedClass) {
-               return this.encoders.getDroolsControllers(topic, encodedClass);
-       }
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       public String toString() {
-               StringBuilder builder = new StringBuilder();
-               builder.append("MultiplexorEventProtocolCoder [decoders=").append(decoders).append(", encoders=")
-                               .append(encoders).append("]");
-               return builder.toString();
-       }
+    /**
+     * Logger.
+     */
+    private static Logger logger = LoggerFactory.getLogger(MultiplexorEventProtocolCoder.class);
+
+    /**
+     * Decoders.
+     */
+    protected EventProtocolDecoder decoders = new EventProtocolDecoder();
+
+    /**
+     * Encoders.
+     */
+    protected EventProtocolEncoder encoders = new EventProtocolEncoder();
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void addDecoder(String groupId, String artifactId, String topic, 
+            String eventClass, 
+            JsonProtocolFilter protocolFilter,
+            CustomGsonCoder customGsonCoder,
+            CustomJacksonCoder customJacksonCoder,
+            int modelClassLoaderHash) {
+        logger.info("{}: add-decoder {}:{}:{}:{}:{}:{}:{}:{}", this, 
+                groupId, artifactId, topic, eventClass,
+                protocolFilter, customGsonCoder, customJacksonCoder,
+                modelClassLoaderHash);
+        this.decoders.add(groupId, artifactId, topic, eventClass, protocolFilter, 
+                customGsonCoder, customJacksonCoder, modelClassLoaderHash);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void addEncoder(String groupId, String artifactId, String topic, 
+            String eventClass, 
+            JsonProtocolFilter protocolFilter,
+            CustomGsonCoder customGsonCoder,
+            CustomJacksonCoder customJacksonCoder,
+            int modelClassLoaderHash) {
+        logger.info("{}: add-decoder {}:{}:{}:{}:{}:{}:{}:{}", this, 
+                groupId, artifactId, topic, eventClass,
+                protocolFilter, customGsonCoder, customJacksonCoder,
+                modelClassLoaderHash);
+        this.encoders.add(groupId, artifactId, topic, eventClass, protocolFilter, 
+                customGsonCoder, customJacksonCoder, modelClassLoaderHash);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void removeDecoders(String groupId, String artifactId, String topic) {
+        logger.info("{}: remove-decoder {}:{}:{}", this, groupId, artifactId, topic);
+        this.decoders.remove(groupId, artifactId, topic);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void removeEncoders(String groupId, String artifactId, String topic) {
+        logger.info("{}: remove-encoder {}:{}:{}", this, groupId, artifactId, topic);
+        this.encoders.remove(groupId, artifactId, topic);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isDecodingSupported(String groupId, String artifactId, String topic) {
+        return this.decoders.isCodingSupported(groupId, artifactId, topic);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isEncodingSupported(String groupId, String artifactId, String topic) {
+        return this.encoders.isCodingSupported(groupId, artifactId, topic);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Object decode(String groupId, String artifactId, String topic, String json) {
+        logger.debug("{}: decode {}:{}:{}:{}", this, groupId, artifactId, topic, json);
+        return this.decoders.decode(groupId, artifactId, topic, json);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String encode(String groupId, String artifactId, String topic, Object event) {
+        logger.debug("{}: encode {}:{}:{}:{}", this, groupId, artifactId, topic, event);
+        return this.encoders.encode(groupId, artifactId, topic, event);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String encode(String topic, Object event) {
+        logger.debug("{}: encode {}:{}", this, topic, event);
+        return this.encoders.encode(topic, event);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String encode(String topic, Object event, DroolsController droolsController) {
+        logger.debug("{}: encode {}:{}:{}", this, topic, event, droolsController);
+        return this.encoders.encode(topic, event, droolsController);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<CoderFilters> getDecoderFilters(String groupId, String artifactId, String topic) {
+        return this.decoders.getFilters(groupId, artifactId, topic);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public CoderFilters getDecoderFilters(String groupId, String artifactId, String topic, String classname) {
+        return this.decoders.getFilters(groupId, artifactId, topic, classname);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<CoderFilters> getDecoderFilters(String groupId, String artifactId) {
+        return this.decoders.getFilters(groupId, artifactId);
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic) {
+        Pair<ProtocolCoderToolset,ProtocolCoderToolset> decoderToolsets = 
+                this.decoders.getCoders(groupId, artifactId, topic);
+        if (decoderToolsets == null) {
+            throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId + ":" + topic);
+        }
+
+        return decoderToolsets.first();
+    }
+
+    /**
+     * get all deocders by maven coordinates and topic.
+     * 
+     * @param groupId group id
+     * @param artifactId artifact id
+     * 
+     * @return list of decoders
+     * @throws IllegalArgumentException if invalid input
+     */
+    @Override
+    public List<ProtocolCoderToolset> getDecoders(String groupId, String artifactId) {
+
+        List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> decoderToolsets = 
+                this.decoders.getCoders(groupId, artifactId);
+        if (decoderToolsets == null) {
+            throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId);
+        }
+
+        List<ProtocolCoderToolset> parser1CoderToolset = new ArrayList<>();
+        for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderToolsetPair : decoderToolsets) {
+            parser1CoderToolset.add(coderToolsetPair.first());
+        }
+
+        return parser1CoderToolset;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<CoderFilters> getEncoderFilters(String groupId, String artifactId, String topic) {
+        return this.encoders.getFilters(groupId, artifactId, topic);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public CoderFilters getEncoderFilters(String groupId, String artifactId, String topic, String classname) {
+        return this.encoders.getFilters(groupId, artifactId, topic, classname);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<CoderFilters> getEncoderFilters(String groupId, String artifactId) {
+        return this.encoders.getFilters(groupId, artifactId);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<CoderFilters> getReverseEncoderFilters(String topic, String encodedClass) {
+        return this.encoders.getReverseFilters(topic, encodedClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public DroolsController getDroolsController(String topic, Object encodedClass) {
+        return this.encoders.getDroolsController(topic, encodedClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<DroolsController> getDroolsControllers(String topic, Object encodedClass) {
+        return this.encoders.getDroolsControllers(topic, encodedClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("MultiplexorEventProtocolCoder [decoders=").append(decoders).append(", encoders=")
+        .append(encoders).append("]");
+        return builder.toString();
+    }
 }
 
 /**
@@ -631,723 +646,758 @@ class MultiplexorEventProtocolCoder implements EventProtocolCoder {
  * class and best fitted json parsing tools.
  */
 abstract class GenericEventProtocolCoder  {
-       private static final String INVALID_ARTIFACT_ID_MSG = "Invalid artifact id";
-
-       private static final String INVALID_GROUP_ID_MSG = "Invalid group id";
-
-       private static final String INVALID_TOPIC_MSG = "Invalid Topic";
-
-       private static final String UNSUPPORTED_MSG = "Unsupported";
-
-       private static final String MISSING_CLASS = "class must be provided";
-
-       private static Logger  logger = LoggerFactory.getLogger(GenericEventProtocolCoder.class);       
-       
-       /**
-        * Mapping topic:controller-id -> <protocol-decoder-toolset-pair> 
-        * where protocol-coder-toolset-pair contains both a jackson-protocol-coder-toolset
-        * and a gson-protocol-coder-toolset.   The first value of the pair will the 
-        * protocol coder toolset most likely to be successful with the encoding or decoding,
-        * and consequently the second value will be the less likely.
-        */
-       protected final HashMap<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> coders = 
-                       new HashMap<>();
-       
-       /**
-        * Mapping topic + classname -> Protocol Set 
-        */
-       protected final HashMap<String, List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>> reverseCoders = 
-                       new HashMap<>();
-       
-       protected boolean multipleToolsetRetries = false;
-       
-       GenericEventProtocolCoder(boolean multipleToolsetRetries) {
-               this.multipleToolsetRetries = multipleToolsetRetries;
-       }
-       
-       /**
-        * Index a new coder
-        *  
-        * @param groupId of the controller
-        * @param artifactId of the controller
-        * @param topic the topic 
-        * @param eventClass the event class
-        * @param protocolFilter filters to selectively choose a particular decoder
-        * when there are multiples
-        * 
-        * @throw IllegalArgumentException if an invalid parameter is passed
-        */
-       public void add(String groupId, String artifactId, 
-                               String topic, 
-                               String eventClass, 
-                               JsonProtocolFilter protocolFilter, 
-                               CustomGsonCoder customGsonCoder, 
-                               CustomJacksonCoder customJacksonCoder,
-                               int modelClassLoaderHash) {
-               if (groupId == null || groupId.isEmpty()) {                     
-                       throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
-               }
-               
-               if (artifactId == null || artifactId.isEmpty())
-                       throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
-               
-               if (topic == null || topic.isEmpty())
-                       throw new IllegalArgumentException(INVALID_TOPIC_MSG);
-               
-               if (eventClass == null) {
-                       throw new IllegalArgumentException("Invalid Event Class");
-               }
-               
-               String key = this.codersKey(groupId, artifactId, topic);
-               String reverseKey = this.reverseCodersKey(topic, eventClass);
-               
-               synchronized(this) {
-                       if (coders.containsKey(key)) {                          
-                               Pair<ProtocolCoderToolset, ProtocolCoderToolset> toolsets = coders.get(key);
-                               
-                               logger.info("{}: adding coders for existing {}: ", this, key, toolsets.first());
-                               
-                               toolsets.first().addCoder(eventClass, protocolFilter, modelClassLoaderHash);
-                               toolsets.second().addCoder(eventClass, protocolFilter, modelClassLoaderHash);
-                               
-                               if (!reverseCoders.containsKey(reverseKey)) {
-                                       logger.info("{}: adding new reverse coders (multiple classes case) for {}:{}: {}",
-                                                           this, reverseKey, key, toolsets.first());
-                                       
-                                       List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> reverseMappings =
-                                                       new ArrayList<>();
-                                       reverseMappings.add(toolsets);
-                                       reverseCoders.put(reverseKey, reverseMappings);
-                               }
-                               return;
-                       }
-               
-                       GsonProtocolCoderToolset gsonCoderTools = 
-                                                                               new GsonProtocolCoderToolset
-                                                                                                               (topic, key, 
-                                                                                                                groupId, artifactId, 
-                                                                                                                eventClass, protocolFilter,
-                                                                                                                customGsonCoder,
-                                                                                                                modelClassLoaderHash);
-                       
-                       JacksonProtocolCoderToolset jacksonCoderTools = 
-                                                                               new JacksonProtocolCoderToolset
-                                                                                                               (topic, key, 
-                                                                                                                groupId, artifactId, 
-                                                                                                                eventClass, protocolFilter,
-                                                                                                                customJacksonCoder,
-                                                                                                                modelClassLoaderHash);
-                       
-                       // Use Gson as the first priority encoding/decoding toolset, and Jackson
-                       // as second.  This is because it has been observed that they can diverge
-                       // somewhat in the encoding/decoding data types, which can produce json
-                       // that may result incompatible with what some network elements are 
-                       // expecting.   As decoding takes place, this element will reconfigure
-                       // itself to set the jackson one as the favoured one first, if errors
-                       // are detected in the gson encoding
-                       
-                       Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = 
-                                       new Pair<>(gsonCoderTools, 
-                                                                                                   jacksonCoderTools);
-                       
-                       logger.info("{}: adding coders for new {}: {}", this, key, coderTools.first());
-                       
-                       coders.put(key, coderTools);
-                       
-                       if (reverseCoders.containsKey(reverseKey)) {
-                               // There is another controller (different group id/artifact id/topic)
-                               // that shares the class and the topic.
-                               
-                               List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets = 
-                                                                                                                       reverseCoders.get(reverseKey);
-                               boolean present = false;
-                               for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> parserSet: toolsets) {
-                                       // just doublecheck
-                                       present = parserSet.first().getControllerId().equals(key);
-                                       if (present) {
-                                               /* anomaly */
-                                               logger.error("{}: unexpected toolset reverse mapping found for {}:{}: {}", 
-                                                                    this, reverseKey, key, parserSet.first());
-                                       }
-                               }
-                               
-                               if (present) {
-                                       return;
-                               } else {
-                                       logger.info("{}: adding coder set for {}: {} ", this, 
-                                                           reverseKey, coderTools.getFirst());
-                                       toolsets.add(coderTools);
-                               }
-                       } else {
-                               List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets =
-                                       new ArrayList<>();
-                               toolsets.add(coderTools);
-                               
-                               logger.info("{}: adding toolset for reverse key {}: {}", this, reverseKey, toolsets);
-                               reverseCoders.put(reverseKey, toolsets);
-                       }
-                       
-               }
-       }
-
-       /**
-        * produces key for indexing toolset entries
-        * 
-        * @param group group id
-        * @param artifactId artifact id
-        * @param topic topic
-        * @return index key
-        */
-       protected String codersKey(String groupId, String artifactId, String topic) {
-               return groupId + ":" + artifactId + ":" + topic;
-       }
-       
-       /**
-        * produces a key for the reverse index
-        * 
-        * @param topic topic 
-        * @param eventClass coded class
-        * @return reverse index key
-        */
-       protected String reverseCodersKey(String topic, String eventClass) {
-               return topic + ":" + eventClass;
-       }
-       
-       /**
-        * remove coder 
-        * 
-        * @param groupId group id
-        * @param artifactId artifact id
-        * @param topic topic
-        * @throws IllegalArgumentException if invalid input
-        */
-       public void remove(String groupId, String artifactId, String topic) {
-               
-               if (groupId == null || groupId.isEmpty())
-                       throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
-               
-               if (artifactId == null || artifactId.isEmpty())
-                       throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
-               
-               if (topic == null || topic.isEmpty())
-                       throw new IllegalArgumentException(INVALID_TOPIC_MSG);
-               
-               String key = this.codersKey(groupId, artifactId, topic);
-               
-               synchronized(this) {
-                       if (coders.containsKey(key)) {
-                               Pair<ProtocolCoderToolset, ProtocolCoderToolset> p = coders.remove(key);
-                               
-                               logger.info("{}: removed toolset for {}: {}", this, key, p.getFirst());
-                               
-                               for (CoderFilters codeFilter : p.first().getCoders()) {
-                                       String className = codeFilter.getCodedClass();
-                                       String reverseKey = this.reverseCodersKey(topic, className);
-                                       if (this.reverseCoders.containsKey(reverseKey) ) {
-                                               List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsets = 
-                                                                                                                               this.reverseCoders.get(reverseKey);
-                                               Iterator<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsetsIter = 
-                                                                                                                                                               toolsets.iterator();
-                                               while (toolsetsIter.hasNext()) {
-                                                       Pair<ProtocolCoderToolset, ProtocolCoderToolset> toolset = toolsetsIter.next();
-                                                       if (toolset.first().getControllerId().equals(key)) {
-                                                               logger.info("{}: removed coder from toolset for {} from reverse mapping {}: ", 
-                                                                                   this, reverseKey);
-                                                               toolsetsIter.remove();
-                                                       }
-                                               }
-                                               
-                                               if (this.reverseCoders.get(reverseKey).isEmpty()) {
-                                                       logger.info("{}: removing reverse mapping for {}: ", this, reverseKey);                                         
-                                                       this.reverseCoders.remove(reverseKey);
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-
-       /**
-        * does it support coding?
-        * 
-        * @param groupId group id
-        * @param artifactId artifact id
-        * @param topic topic
-        * @return true if its is codable
-        */
-       public boolean isCodingSupported(String groupId, String artifactId, String topic) {
-               
-               if (groupId == null || groupId.isEmpty())
-                       throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
-               
-               if (artifactId == null || artifactId.isEmpty())
-                       throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
-               
-               if (topic == null || topic.isEmpty())
-                       throw new IllegalArgumentException(INVALID_TOPIC_MSG);
-               
-               String key = this.codersKey(groupId, artifactId, topic);
-               synchronized(this) {
-                       return coders.containsKey(key);
-               }
-       }
-       
-       /**
-        * decode a json string into an Object
-        * 
-        * @param groupId group id
-        * @param artifactId artifact id
-        * @param topic topic
-        * @param json json string to convert to object
-        * @return the decoded object
-        * @throws IllegalArgumentException if invalid argument is provided
-        * @throws UnsupportedOperationException if the operation cannot be performed
-        */
-       public Object decode(String groupId, String artifactId, String topic, String json) {
-               
-               if (!isCodingSupported(groupId, artifactId, topic))
-                       throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic) + " for encoding");
-               
-               String key = this.codersKey(groupId, artifactId, topic);
-               Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
-               try {
-                       Object event = coderTools.first().decode(json);
-                       if (event != null)
-                               return event;
-               } catch (Exception e) {
-                       logger.debug("{}, cannot decode {}", this, json, e);
-               }
-               
-               if (multipleToolsetRetries) {
-                       // try the less favored toolset
-                       try {
-                               Object event = coderTools.second().decode(json);
-                               if (event != null) {
-                                       // change the priority of the toolset
-                                       synchronized(this) {
-                                               ProtocolCoderToolset first = coderTools.first();
-                                               ProtocolCoderToolset second = coderTools.second();
-                                               coderTools.first(second);
-                                               coderTools.second(first);
-                                       }
-                                       
-                                       return event;
-                               }
-                       } catch (Exception e) {
-                               throw new UnsupportedOperationException(e);
-                       }
-               } 
-               
-               throw new UnsupportedOperationException("Cannot decode neither with gson or jackson");
-       }
-
-       /**
-        * encode an object into a json string
-        * 
-        * @param groupId group id
-        * @param artifactId artifact id
-        * @param topic topic
-        * @param event object to convert to string
-        * @return the json string
-        * @throws IllegalArgumentException if invalid argument is provided
-        * @throws UnsupportedOperationException if the operation cannot be performed
-        */
-       public String encode(String groupId, String artifactId, String topic, Object event) {
-               
-               if (!isCodingSupported(groupId, artifactId, topic))
-                       throw new IllegalArgumentException
-                               ("Unsupported:" + codersKey(groupId, artifactId, topic));
-               
-               if (event == null)
-                       throw new IllegalArgumentException("Unsupported topic:" + topic);
-               
-               // reuse the decoder set, since there must be affinity in the model
-               String key = this.codersKey(groupId, artifactId, topic);
-               return this.encodeInternal(key, event);
-       }
-       
-       /**
-        * encode an object into a json string
-        * 
-        * @param key identifier
-        * @param event object to convert to string
-        * @return the json string
-        * @throws IllegalArgumentException if invalid argument is provided
-        * @throws UnsupportedOperationException if the operation cannot be performed
-        */
-       protected String encodeInternal(String key, Object event) {
-               
-               logger.debug("{}: encode for {}: {}", this, key, event);
-               
-               Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
-               try {
-                       String json = coderTools.first().encode(event);
-                       if (json != null && !json.isEmpty())
-                               return json;
-               } catch (Exception e) {
-                       logger.warn("{}: cannot encode (first) for {}: {}", this, key, event, e);
-               }
-               
-               if (multipleToolsetRetries) {
-                       // try the less favored toolset
-                       try {
-                               String json = coderTools.second().encode(event);
-                               if (json != null) {
-                                       // change the priority of the toolset
-                                       synchronized(this) {
-                                               ProtocolCoderToolset first = coderTools.first();
-                                               ProtocolCoderToolset second = coderTools.second();
-                                               coderTools.first(second);
-                                               coderTools.second(first);
-                                       }
-                                       
-                                       return json;
-                               }
-                       } catch (Exception e) {
-                               logger.error("{}: cannot encode (second) for {}: {}", this, key, event, e);
-                               throw new UnsupportedOperationException(e);
-                       }
-               }
-               
-               throw new UnsupportedOperationException("Cannot decode neither with gson or jackson");
-       }
-       
-       /**
-        * encode an object into a json string
-        * 
-        * @param topic topic
-        * @param event object to convert to string
-        * @return the json string
-        * @throws IllegalArgumentException if invalid argument is provided
-        * @throws UnsupportedOperationException if the operation cannot be performed
-        */
-       public String encode(String topic, Object event) {
-               
-               if (event == null)
-                       throw new IllegalArgumentException("Invalid encoded class");
-               
-               if (topic == null || topic.isEmpty())
-                       throw new IllegalArgumentException("Invalid topic");
-               
+    private static final String INVALID_ARTIFACT_ID_MSG = "Invalid artifact id";
+
+    private static final String INVALID_GROUP_ID_MSG = "Invalid group id";
+
+    private static final String INVALID_TOPIC_MSG = "Invalid Topic";
+
+    private static final String UNSUPPORTED_MSG = "Unsupported";
+
+    private static final String MISSING_CLASS = "class must be provided";
+
+    private static Logger  logger = LoggerFactory.getLogger(GenericEventProtocolCoder.class);
+
+    /**
+     * Mapping topic:controller-id -> /<protocol-decoder-toolset-pair/> 
+     * where protocol-coder-toolset-pair contains both a jackson-protocol-coder-toolset
+     * and a gson-protocol-coder-toolset.   The first value of the pair will the 
+     * protocol coder toolset most likely to be successful with the encoding or decoding,
+     * and consequently the second value will be the less likely.
+     */
+    protected final HashMap<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> coders = 
+            new HashMap<>();
+
+    /**
+     * Mapping topic + classname -> Protocol Set.
+     */
+    protected final HashMap<String, List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>> reverseCoders = 
+            new HashMap<>();
+
+    protected boolean multipleToolsetRetries = false;
+
+    GenericEventProtocolCoder(boolean multipleToolsetRetries) {
+        this.multipleToolsetRetries = multipleToolsetRetries;
+    }
+
+    /**
+     * Index a new coder.
+     *  
+     * @param groupId of the controller
+     * @param artifactId of the controller
+     * @param topic the topic 
+     * @param eventClass the event class
+     * @param protocolFilter filters to selectively choose a particular decoder
+     *     when there are multiples
+     * 
+     * @throw IllegalArgumentException if an invalid parameter is passed
+     */
+    public void add(String groupId, String artifactId, 
+            String topic, 
+            String eventClass, 
+            JsonProtocolFilter protocolFilter, 
+            CustomGsonCoder customGsonCoder, 
+            CustomJacksonCoder customJacksonCoder,
+            int modelClassLoaderHash) {
+        if (groupId == null || groupId.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
+        }
+
+        if (artifactId == null || artifactId.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
+        }
+
+        if (topic == null || topic.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_TOPIC_MSG);
+        }
+
+        if (eventClass == null) {
+            throw new IllegalArgumentException("Invalid Event Class");
+        }
+
+        String key = this.codersKey(groupId, artifactId, topic);
+        String reverseKey = this.reverseCodersKey(topic, eventClass);
+
+        synchronized (this) {
+            if (coders.containsKey(key)) {
+                Pair<ProtocolCoderToolset, ProtocolCoderToolset> toolsets = coders.get(key);
+
+                logger.info("{}: adding coders for existing {}: ", this, key, toolsets.first());
+
+                toolsets.first().addCoder(eventClass, protocolFilter, modelClassLoaderHash);
+                toolsets.second().addCoder(eventClass, protocolFilter, modelClassLoaderHash);
+
+                if (!reverseCoders.containsKey(reverseKey)) {
+                    logger.info("{}: adding new reverse coders (multiple classes case) for {}:{}: {}",
+                            this, reverseKey, key, toolsets.first());
+
+                    List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> reverseMappings =
+                            new ArrayList<>();
+                    reverseMappings.add(toolsets);
+                    reverseCoders.put(reverseKey, reverseMappings);
+                }
+                return;
+            }
+
+            GsonProtocolCoderToolset gsonCoderTools = 
+                    new GsonProtocolCoderToolset(topic, key, 
+                            groupId, artifactId, 
+                            eventClass, protocolFilter,
+                            customGsonCoder,
+                            modelClassLoaderHash);
+
+            JacksonProtocolCoderToolset jacksonCoderTools = 
+                    new JacksonProtocolCoderToolset(topic, key, 
+                            groupId, artifactId, 
+                            eventClass, protocolFilter,
+                            customJacksonCoder,
+                            modelClassLoaderHash);
+
+            // Use Gson as the first priority encoding/decoding toolset, and Jackson
+            // as second.  This is because it has been observed that they can diverge
+            // somewhat in the encoding/decoding data types, which can produce json
+            // that may result incompatible with what some network elements are 
+            // expecting.   As decoding takes place, this element will reconfigure
+            // itself to set the jackson one as the favoured one first, if errors
+            // are detected in the gson encoding
+
+            Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = 
+                    new Pair<>(gsonCoderTools, 
+                            jacksonCoderTools);
+
+            logger.info("{}: adding coders for new {}: {}", this, key, coderTools.first());
+
+            coders.put(key, coderTools);
+
+            if (reverseCoders.containsKey(reverseKey)) {
+                // There is another controller (different group id/artifact id/topic)
+                // that shares the class and the topic.
+
+                List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets = 
+                        reverseCoders.get(reverseKey);
+                boolean present = false;
+                for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> parserSet: toolsets) {
+                    // just doublecheck
+                    present = parserSet.first().getControllerId().equals(key);
+                    if (present) {
+                        /* anomaly */
+                        logger.error("{}: unexpected toolset reverse mapping found for {}:{}: {}", 
+                                this, reverseKey, key, parserSet.first());
+                    }
+                }
+
+                if (present) {
+                    return;
+                } else {
+                    logger.info("{}: adding coder set for {}: {} ", this, 
+                            reverseKey, coderTools.getFirst());
+                    toolsets.add(coderTools);
+                }
+            } else {
+                List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets =
+                        new ArrayList<>();
+                toolsets.add(coderTools);
+
+                logger.info("{}: adding toolset for reverse key {}: {}", this, reverseKey, toolsets);
+                reverseCoders.put(reverseKey, toolsets);
+            }
+
+        }
+    }
+
+    /**
+     * produces key for indexing toolset entries.
+     * 
+     * @param group group id
+     * @param artifactId artifact id
+     * @param topic topic
+     * @return index key
+     */
+    protected String codersKey(String groupId, String artifactId, String topic) {
+        return groupId + ":" + artifactId + ":" + topic;
+    }
+
+    /**
+     * produces a key for the reverse index.
+     * 
+     * @param topic topic 
+     * @param eventClass coded class
+     * @return reverse index key
+     */
+    protected String reverseCodersKey(String topic, String eventClass) {
+        return topic + ":" + eventClass;
+    }
+
+    /**
+     * remove coder.
+     * 
+     * @param groupId group id
+     * @param artifactId artifact id
+     * @param topic topic
+     * @throws IllegalArgumentException if invalid input
+     */
+    public void remove(String groupId, String artifactId, String topic) {
+
+        if (groupId == null || groupId.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
+        }
+
+        if (artifactId == null || artifactId.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
+        }
+
+        if (topic == null || topic.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_TOPIC_MSG);
+        }
+
+        String key = this.codersKey(groupId, artifactId, topic);
+
+        synchronized (this) {
+            if (coders.containsKey(key)) {
+                Pair<ProtocolCoderToolset, ProtocolCoderToolset> pair = coders.remove(key);
+
+                logger.info("{}: removed toolset for {}: {}", this, key, pair.getFirst());
+
+                for (CoderFilters codeFilter : pair.first().getCoders()) {
+                    String className = codeFilter.getCodedClass();
+                    String reverseKey = this.reverseCodersKey(topic, className);
+                    if (this.reverseCoders.containsKey(reverseKey) ) {
+                        List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsets = 
+                                this.reverseCoders.get(reverseKey);
+                        Iterator<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsetsIter = 
+                                toolsets.iterator();
+                        while (toolsetsIter.hasNext()) {
+                            Pair<ProtocolCoderToolset, ProtocolCoderToolset> toolset = toolsetsIter.next();
+                            if (toolset.first().getControllerId().equals(key)) {
+                                logger.info("{}: removed coder from toolset for {} from reverse mapping {}: ", 
+                                        this, reverseKey);
+                                toolsetsIter.remove();
+                            }
+                        }
+
+                        if (this.reverseCoders.get(reverseKey).isEmpty()) {
+                            logger.info("{}: removing reverse mapping for {}: ", this, reverseKey);
+                            this.reverseCoders.remove(reverseKey);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * does it support coding.
+     * 
+     * @param groupId group id
+     * @param artifactId artifact id
+     * @param topic topic
+     * @return true if its is codable
+     */
+    public boolean isCodingSupported(String groupId, String artifactId, String topic) {
+
+        if (groupId == null || groupId.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
+        }
+
+        if (artifactId == null || artifactId.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
+        }
+
+        if (topic == null || topic.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_TOPIC_MSG);
+        }
+
+        String key = this.codersKey(groupId, artifactId, topic);
+        synchronized (this) {
+            return coders.containsKey(key);
+        }
+    }
+
+    /**
+     * decode a json string into an Object.
+     * 
+     * @param groupId group id
+     * @param artifactId artifact id
+     * @param topic topic
+     * @param json json string to convert to object
+     * @return the decoded object
+     * @throws IllegalArgumentException if invalid argument is provided
+     * @throws UnsupportedOperationException if the operation cannot be performed
+     */
+    public Object decode(String groupId, String artifactId, String topic, String json) {
+
+        if (!isCodingSupported(groupId, artifactId, topic)) {
+            throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic) 
+                + " for encoding");
+        }
+
+        String key = this.codersKey(groupId, artifactId, topic);
+        Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
+        try {
+            Object event = coderTools.first().decode(json);
+            if (event != null) {
+                return event;
+            }
+        } catch (Exception e) {
+            logger.debug("{}, cannot decode {}", this, json, e);
+        }
+
+        if (multipleToolsetRetries) {
+            // try the less favored toolset
+            try {
+                Object event = coderTools.second().decode(json);
+                if (event != null) {
+                    // change the priority of the toolset
+                    synchronized (this) {
+                        ProtocolCoderToolset first = coderTools.first();
+                        ProtocolCoderToolset second = coderTools.second();
+                        coderTools.first(second);
+                        coderTools.second(first);
+                    }
+
+                    return event;
+                }
+            } catch (Exception e) {
+                throw new UnsupportedOperationException(e);
+            }
+        } 
+
+        throw new UnsupportedOperationException("Cannot decode neither with gson or jackson");
+    }
+
+    /**
+     * encode an object into a json string.
+     * 
+     * @param groupId group id
+     * @param artifactId artifact id
+     * @param topic topic
+     * @param event object to convert to string
+     * @return the json string
+     * @throws IllegalArgumentException if invalid argument is provided
+     * @throws UnsupportedOperationException if the operation cannot be performed
+     */
+    public String encode(String groupId, String artifactId, String topic, Object event) {
+
+        if (!isCodingSupported(groupId, artifactId, topic)) {
+            throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
+        }
+
+        if (event == null) {
+            throw new IllegalArgumentException("Unsupported topic:" + topic);
+        }
+
+        // reuse the decoder set, since there must be affinity in the model
+        String key = this.codersKey(groupId, artifactId, topic);
+        return this.encodeInternal(key, event);
+    }
+
+    /**
+     * encode an object into a json string.
+     * 
+     * @param topic topic
+     * @param event object to convert to string
+     * @return the json string
+     * @throws IllegalArgumentException if invalid argument is provided
+     * @throws UnsupportedOperationException if the operation cannot be performed
+     */
+    public String encode(String topic, Object event) {
+
+        if (event == null) {
+            throw new IllegalArgumentException("Invalid encoded class");
+        }
+
+        if (topic == null || topic.isEmpty()) {
+            throw new IllegalArgumentException("Invalid topic");
+        }
+
         String reverseKey = this.reverseCodersKey(topic, event.getClass().getCanonicalName());
-        if (!this.reverseCoders.containsKey(reverseKey))
+        if (!this.reverseCoders.containsKey(reverseKey)) {
             throw new IllegalArgumentException("no reverse coder has been found");
-        
-        List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> 
-                            toolsets = this.reverseCoders.get(reverseKey);
-        
+        }
+
+        List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsets = this.reverseCoders.get(reverseKey);
+
         String key = codersKey(toolsets.get(0).first().getGroupId(), toolsets.get(0).first().getArtifactId(), topic);
         return this.encodeInternal(key, event);
-       }
-       
-       /**
-        * encode an object into a json string
-        * 
-        * @param topic topic
-        * @param encodedClass object to convert to string
-        * @return the json string
-        * @throws IllegalArgumentException if invalid argument is provided
-        * @throws UnsupportedOperationException if the operation cannot be performed
-        */
-       public String encode(String topic, Object encodedClass, DroolsController droolsController) {
-               
-               if (encodedClass == null)
-                       throw new IllegalArgumentException("Invalid encoded class");
-               
-               if (topic == null || topic.isEmpty())
-                       throw new IllegalArgumentException("Invalid topic");
-               
-               String key = codersKey(droolsController.getGroupId(), droolsController.getArtifactId(), topic);
-               return this.encodeInternal(key, encodedClass);
-       }
-
-       /**
-        * @param topic
-        * @param encodedClass
-        * @param reverseKey
-        * @return
-        * @throws IllegalStateException
-        * @throws IllegalArgumentException
-        */
-       protected List<DroolsController> droolsCreators(String topic, Object encodedClass) {
-               
-               List<DroolsController> droolsControllers = new ArrayList<>();
-               
-               String reverseKey = this.reverseCodersKey(topic, encodedClass.getClass().getCanonicalName());
-               if (!this.reverseCoders.containsKey(reverseKey)) {
-                       logger.warn("{}: no reverse mapping for {}", this, reverseKey);
-                       return droolsControllers;
-               }
-               
-               List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> 
-                                       toolsets = this.reverseCoders.get(reverseKey);
-               
-               // There must be multiple toolset pairs associated with <topic,classname> reverseKey
-               // case 2 different controllers use the same models and register the same encoder for
-               // the same topic.  This is assumed not to occur often but for the purpose of encoding
-               // but there should be no side-effects.  Ownership is crosscheck against classname and 
-               // classloader reference.
-               
-               if (toolsets == null || toolsets.isEmpty())
-                       throw new IllegalStateException("No Encoders toolsets available for topic "+ topic +
-                                                               " encoder " + encodedClass.getClass().getCanonicalName());
-               
-               for (Pair<ProtocolCoderToolset, ProtocolCoderToolset> encoderSet : toolsets) {
-                       // figure out the right toolset
-                       String groupId = encoderSet.first().getGroupId();
-                       String artifactId = encoderSet.first().getArtifactId();
-                       List<CoderFilters> coderFilters = encoderSet.first().getCoders();
-                       for (CoderFilters coder : coderFilters) {
-                               if (coder.getCodedClass().equals(encodedClass.getClass().getCanonicalName())) {
-                                       DroolsController droolsController = 
-                                                       DroolsController.factory.get(groupId, artifactId, "");
-                                       if (droolsController.ownsCoder(encodedClass.getClass(), coder.getModelClassLoaderHash())) {
-                                               droolsControllers.add(droolsController);
-                                       }
-                               }
-                       }
-               }
-               
-               if (droolsControllers.isEmpty())
-                       throw new IllegalStateException("No Encoders toolsets available for "+ topic +
-                                                   ":" + encodedClass.getClass().getCanonicalName());
-               
-               return droolsControllers;
-       }
-
-
-       /**
-        * get all filters by maven coordinates and topic
-        * 
-        * @param groupId group id
-        * @param artifactId artifact id
-        * @param topic topic
-        * @return list of coders
-        * @throws IllegalArgumentException if invalid input
-        */
-       public List<CoderFilters> getFilters(String groupId, String artifactId, String topic) {
-               
-               if (!isCodingSupported(groupId, artifactId, topic))
-                       throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
-               
-               String key = this.codersKey(groupId, artifactId, topic);
-               Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
-               return coderTools.first().getCoders();
-       }
-       
-       /**
-        * get all coders by maven coordinates and topic
-        * 
-        * @param groupId group id
-        * @param artifactId artifact id
-        * @param topic topic
-        * @return list of coders
-        * @throws IllegalArgumentException if invalid input
-        */
-       public Pair<ProtocolCoderToolset,ProtocolCoderToolset> getCoders(String groupId, String artifactId, String topic) {
-               
-               if (!isCodingSupported(groupId, artifactId, topic))
-                       throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
-               
-               String key = this.codersKey(groupId, artifactId, topic);
-               return coders.get(key);
-       }
-       
-       /**
-        * get all coders by maven coordinates and topic
-        * 
-        * @param groupId group id
-        * @param artifactId artifact id
-        * @return list of coders
-        * @throws IllegalArgumentException if invalid input
-        */
-       public List<CoderFilters> getFilters(String groupId, String artifactId) {
-               
-               if (groupId == null || groupId.isEmpty())
-                       throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
-               
-               if (artifactId == null || artifactId.isEmpty())
-                       throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
-               
-               String key = this.codersKey(groupId, artifactId, "");
-               
-               List<CoderFilters> codersFilters = new ArrayList<>();
-               for (Map.Entry<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> entry : coders.entrySet()) {
-                       if (entry.getKey().startsWith(key)) {
-                               codersFilters.addAll(entry.getValue().first().getCoders());
-                       }
-               }
-               
-               return codersFilters;
-       }
-       
-       /**
-        * get all coders by maven coordinates and topic
-        * 
-        * @param groupId group id
-        * @param artifactId artifact id
-        * @return list of coders
-        * @throws IllegalArgumentException if invalid input
-        */
-       public List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> getCoders(String groupId, String artifactId) {
-               
-               if (groupId == null || groupId.isEmpty())
-                       throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
-               
-               if (artifactId == null || artifactId.isEmpty())
-                       throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
-               
-               String key = this.codersKey(groupId, artifactId, "");
-               
-               List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> coderToolset = new ArrayList<>();
-               for (Map.Entry<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> entry : coders.entrySet()) {
-                       if (entry.getKey().startsWith(key)) {
-                               coderToolset.add(entry.getValue());
-                       }
-               }
-               
-               return coderToolset;
-       }
-
-
-       /**
-        * get all filters by maven coordinates, topic, and classname
-        * 
-        * @param groupId group id
-        * @param artifactId artifact id
-        * @param topic topic
-        * @param classname
-        * @return list of coders
-        * @throws IllegalArgumentException if invalid input
-        */
-       public CoderFilters getFilters(String groupId, String artifactId, String topic, String classname) {
-               
-               if (!isCodingSupported(groupId, artifactId, topic))
-                       throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
-               
-               if (classname == null || classname.isEmpty())
-                       throw new IllegalArgumentException("classname must be provided");
-               
-               String key = this.codersKey(groupId, artifactId, topic);
-               Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
-               return coderTools.first().getCoder(classname);
-       }
-       
-       /**
-        * get coded based on class and topic
-        * 
-        * @param topic
-        * @param codedClass
-        * @return
-        * @throws IllegalArgumentException
-        */
-       public List<CoderFilters> getReverseFilters(String topic, String codedClass) {
-               
-               if (topic == null || topic.isEmpty())
-                       throw new IllegalArgumentException(UNSUPPORTED_MSG);
-               
-               if (codedClass == null)
-                       throw new IllegalArgumentException(MISSING_CLASS);
-               
-               String key = this.reverseCodersKey(topic, codedClass);
-               List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets = this.reverseCoders.get(key);
-               if (toolsets == null)
-                       throw new IllegalArgumentException("No Coder found for " + key);
-               
-               
-               List<CoderFilters> coderFilters = new ArrayList<>();
-               for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> toolset: toolsets) {
-                       coderFilters.addAll(toolset.first().getCoders());
-               }
-               
-               return coderFilters;
-       }
-       
-       /**
-        * returns group and artifact id of the creator of the encoder
-        * 
-        * @param topic
-        * @param fact
-        * @return
-        * @throws IllegalArgumentException
-        */
-       DroolsController getDroolsController(String topic, Object fact) {
-               
-               if (topic == null || topic.isEmpty())
-                       throw new IllegalArgumentException(UNSUPPORTED_MSG);
-               
-               if (fact == null)
-                       throw new IllegalArgumentException(MISSING_CLASS);
-               
-               List<DroolsController> droolsControllers = droolsCreators(topic, fact);
-               
-               if (droolsControllers.isEmpty())        
-                       throw new IllegalArgumentException("Invalid Topic: " + topic);
-               
-               if (droolsControllers.size() > 1) {
-                       logger.warn("{}: multiple drools-controller {} for {}:{} ", this,
-                                       droolsControllers, topic, fact.getClass().getCanonicalName());
-                       // continue
-               }
-               return droolsControllers.get(0);
-       }
-       
-       /**
-        * returns group and artifact id of the creator of the encoder
-        * 
-        * @param topic
-        * @param fact
-        * @return
-        * @throws IllegalArgumentException
-        */
-       List<DroolsController> getDroolsControllers(String topic, Object fact) {
-               
-               if (topic == null || topic.isEmpty())
-                       throw new IllegalArgumentException(UNSUPPORTED_MSG);
-               
-               if (fact == null)
-                       throw new IllegalArgumentException(MISSING_CLASS);
-               
-               List<DroolsController> droolsControllers = droolsCreators(topic, fact);
-               if (droolsControllers.size() > 1) {
-                       // unexpected
-                       logger.warn("{}: multiple drools-controller {} for {}:{} ", this,
-                                           droolsControllers, topic, fact.getClass().getCanonicalName());              
-                       // continue
-               }
-               return droolsControllers;
-       }
-
-       @Override
-       public String toString() {
-               StringBuilder builder = new StringBuilder();
-               builder.append("GenericEventProtocolCoder [coders=").append(coders.keySet()).append(", reverseCoders=")
-                               .append(reverseCoders.keySet()).append("]");
-               return builder.toString();
-       }
+    }
+
+    /**
+     * encode an object into a json string.
+     * 
+     * @param key identifier
+     * @param event object to convert to string
+     * @return the json string
+     * @throws IllegalArgumentException if invalid argument is provided
+     * @throws UnsupportedOperationException if the operation cannot be performed
+     */
+    protected String encodeInternal(String key, Object event) {
+
+        logger.debug("{}: encode for {}: {}", this, key, event);
+
+        Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
+        try {
+            String json = coderTools.first().encode(event);
+            if (json != null && !json.isEmpty()) {
+                return json;
+            }
+        } catch (Exception e) {
+            logger.warn("{}: cannot encode (first) for {}: {}", this, key, event, e);
+        }
+
+        if (multipleToolsetRetries) {
+            // try the less favored toolset
+            try {
+                String json = coderTools.second().encode(event);
+                if (json != null) {
+                    // change the priority of the toolset
+                    synchronized (this) {
+                        ProtocolCoderToolset first = coderTools.first();
+                        ProtocolCoderToolset second = coderTools.second();
+                        coderTools.first(second);
+                        coderTools.second(first);
+                    }
+
+                    return json;
+                }
+            } catch (Exception e) {
+                logger.error("{}: cannot encode (second) for {}: {}", this, key, event, e);
+                throw new UnsupportedOperationException(e);
+            }
+        }
+
+        throw new UnsupportedOperationException("Cannot decode neither with gson or jackson");
+    }
+
+    /**
+     * encode an object into a json string.
+     * 
+     * @param topic topic
+     * @param encodedClass object to convert to string
+     * @return the json string
+     * @throws IllegalArgumentException if invalid argument is provided
+     * @throws UnsupportedOperationException if the operation cannot be performed
+     */
+    public String encode(String topic, Object encodedClass, DroolsController droolsController) {
+
+        if (encodedClass == null) {
+            throw new IllegalArgumentException("Invalid encoded class");
+        }
+
+        if (topic == null || topic.isEmpty()) {
+            throw new IllegalArgumentException("Invalid topic");
+        }
+
+        String key = codersKey(droolsController.getGroupId(), droolsController.getArtifactId(), topic);
+        return this.encodeInternal(key, encodedClass);
+    }
+
+    /**
+     * Drools creators.
+     * 
+     * @param topic topic
+     * @param encodedClass encoded class
+     * @return list of controllers
+     * 
+     * @throws IllegalStateException illegal state
+     * @throws IllegalArgumentException argument
+     */
+    protected List<DroolsController> droolsCreators(String topic, Object encodedClass) {
+
+        List<DroolsController> droolsControllers = new ArrayList<>();
+
+        String reverseKey = this.reverseCodersKey(topic, encodedClass.getClass().getCanonicalName());
+        if (!this.reverseCoders.containsKey(reverseKey)) {
+            logger.warn("{}: no reverse mapping for {}", this, reverseKey);
+            return droolsControllers;
+        }
+
+        List<Pair<ProtocolCoderToolset, ProtocolCoderToolset>> toolsets = this.reverseCoders.get(reverseKey);
+
+        // There must be multiple toolset pairs associated with <topic,classname> reverseKey
+        // case 2 different controllers use the same models and register the same encoder for
+        // the same topic.  This is assumed not to occur often but for the purpose of encoding
+        // but there should be no side-effects.  Ownership is crosscheck against classname and 
+        // classloader reference.
+
+        if (toolsets == null || toolsets.isEmpty()) {
+            throw new IllegalStateException("No Encoders toolsets available for topic "
+                + topic
+                + " encoder " + encodedClass.getClass().getCanonicalName());
+        }
+
+        for (Pair<ProtocolCoderToolset, ProtocolCoderToolset> encoderSet : toolsets) {
+            // figure out the right toolset
+            String groupId = encoderSet.first().getGroupId();
+            String artifactId = encoderSet.first().getArtifactId();
+            List<CoderFilters> coderFilters = encoderSet.first().getCoders();
+            for (CoderFilters coder : coderFilters) {
+                if (coder.getCodedClass().equals(encodedClass.getClass().getCanonicalName())) {
+                    DroolsController droolsController = 
+                            DroolsController.factory.get(groupId, artifactId, "");
+                    if (droolsController.ownsCoder(encodedClass.getClass(), coder.getModelClassLoaderHash())) {
+                        droolsControllers.add(droolsController);
+                    }
+                }
+            }
+        }
+
+        if (droolsControllers.isEmpty()) {
+            throw new IllegalStateException("No Encoders toolsets available for "
+                + topic
+                + ":" + encodedClass.getClass().getCanonicalName());
+        }
+
+        return droolsControllers;
+    }
+
+
+    /**
+     * get all filters by maven coordinates and topic.
+     * 
+     * @param groupId group id
+     * @param artifactId artifact id
+     * @param topic topic
+     * @return list of coders
+     * @throws IllegalArgumentException if invalid input
+     */
+    public List<CoderFilters> getFilters(String groupId, String artifactId, String topic) {
+
+        if (!isCodingSupported(groupId, artifactId, topic)) {
+            throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
+        }
+
+        String key = this.codersKey(groupId, artifactId, topic);
+        Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
+        return coderTools.first().getCoders();
+    }
+
+    /**
+     * get all coders by maven coordinates and topic.
+     * 
+     * @param groupId group id
+     * @param artifactId artifact id
+     * @return list of coders
+     * @throws IllegalArgumentException if invalid input
+     */
+    public List<CoderFilters> getFilters(String groupId, String artifactId) {
+
+        if (groupId == null || groupId.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
+        }
+
+        if (artifactId == null || artifactId.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
+        }
+
+        String key = this.codersKey(groupId, artifactId, "");
+
+        List<CoderFilters> codersFilters = new ArrayList<>();
+        for (Map.Entry<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> entry : coders.entrySet()) {
+            if (entry.getKey().startsWith(key)) {
+                codersFilters.addAll(entry.getValue().first().getCoders());
+            }
+        }
+
+        return codersFilters;
+    }
+    
+    /**
+     * get all coders by maven coordinates and topic.
+     * 
+     * @param groupId group id
+     * @param artifactId artifact id
+     * @param topic topic
+     * @return list of coders
+     * @throws IllegalArgumentException if invalid input
+     */
+    public Pair<ProtocolCoderToolset,ProtocolCoderToolset> getCoders(String groupId, String artifactId, String topic) {
+
+        if (!isCodingSupported(groupId, artifactId, topic)) {
+            throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
+        }
+
+        String key = this.codersKey(groupId, artifactId, topic);
+        return coders.get(key);
+    }
+
+    /**
+     * get all coders by maven coordinates and topic.
+     * 
+     * @param groupId group id
+     * @param artifactId artifact id
+     * @return list of coders
+     * @throws IllegalArgumentException if invalid input
+     */
+    public List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> getCoders(String groupId, String artifactId) {
+
+        if (groupId == null || groupId.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_GROUP_ID_MSG);
+        }
+
+        if (artifactId == null || artifactId.isEmpty()) {
+            throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG);
+        }
+
+        String key = this.codersKey(groupId, artifactId, "");
+
+        List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> coderToolset = new ArrayList<>();
+        for (Map.Entry<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>> entry : coders.entrySet()) {
+            if (entry.getKey().startsWith(key)) {
+                coderToolset.add(entry.getValue());
+            }
+        }
+
+        return coderToolset;
+    }
+
+    /**
+     * get all filters by maven coordinates, topic, and classname.
+     * 
+     * @param groupId group id
+     * @param artifactId artifact id
+     * @param topic topic
+     * @param classname classname
+     * @return list of coders
+     * @throws IllegalArgumentException if invalid input
+     */
+    public CoderFilters getFilters(String groupId, String artifactId, String topic, String classname) {
+
+        if (!isCodingSupported(groupId, artifactId, topic)) {
+            throw new IllegalArgumentException("Unsupported:" + codersKey(groupId, artifactId, topic));
+        }
+
+        if (classname == null || classname.isEmpty()) {
+            throw new IllegalArgumentException("classname must be provided");
+        }
+
+        String key = this.codersKey(groupId, artifactId, topic);
+        Pair<ProtocolCoderToolset,ProtocolCoderToolset> coderTools = coders.get(key);
+        return coderTools.first().getCoder(classname);
+    }
+
+    /**
+     * get coded based on class and topic.
+     * 
+     * @param topic topic
+     * @param codedClass class
+     * @return list of reverse filters
+     */
+    public List<CoderFilters> getReverseFilters(String topic, String codedClass) {
+
+        if (topic == null || topic.isEmpty()) {
+            throw new IllegalArgumentException(UNSUPPORTED_MSG);
+        }
+
+        if (codedClass == null) {
+            throw new IllegalArgumentException(MISSING_CLASS);
+        }
+
+        String key = this.reverseCodersKey(topic, codedClass);
+        List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets = this.reverseCoders.get(key);
+        if (toolsets == null) {
+            throw new IllegalArgumentException("No Coder found for " + key);
+        }
+
+        List<CoderFilters> coderFilters = new ArrayList<>();
+        for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> toolset: toolsets) {
+            coderFilters.addAll(toolset.first().getCoders());
+        }
+
+        return coderFilters;
+    }
+
+    /**
+     * returns group and artifact id of the creator of the encoder.
+     * 
+     * @param topic topic
+     * @param fact fact
+     * @return the drools controller
+     */
+    DroolsController getDroolsController(String topic, Object fact) {
+
+        if (topic == null || topic.isEmpty()) {
+            throw new IllegalArgumentException(UNSUPPORTED_MSG);
+        }
+
+        if (fact == null) {
+            throw new IllegalArgumentException(MISSING_CLASS);
+        }
+
+        List<DroolsController> droolsControllers = droolsCreators(topic, fact);
+
+        if (droolsControllers.isEmpty()) {
+            throw new IllegalArgumentException("Invalid Topic: " + topic);
+        }
+
+        if (droolsControllers.size() > 1) {
+            logger.warn("{}: multiple drools-controller {} for {}:{} ", this,
+                    droolsControllers, topic, fact.getClass().getCanonicalName());
+            // continue
+        }
+        return droolsControllers.get(0);
+    }
+
+    /**
+     * returns group and artifact id of the creator of the encoder.
+     * 
+     * @param topic topic
+     * @param fact fact
+     * @return
+     */
+    List<DroolsController> getDroolsControllers(String topic, Object fact) {
+
+        if (topic == null || topic.isEmpty()) {
+            throw new IllegalArgumentException(UNSUPPORTED_MSG);
+        }
+
+        if (fact == null) {
+            throw new IllegalArgumentException(MISSING_CLASS);
+        }
+
+        List<DroolsController> droolsControllers = droolsCreators(topic, fact);
+        if (droolsControllers.size() > 1) {
+            // unexpected
+            logger.warn("{}: multiple drools-controller {} for {}:{} ", this,
+                    droolsControllers, topic, fact.getClass().getCanonicalName());
+            // continue
+        }
+        return droolsControllers;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("GenericEventProtocolCoder [coders=").append(coders.keySet()).append(", reverseCoders=")
+        .append(reverseCoders.keySet()).append("]");
+        return builder.toString();
+    }
 }
 
 class EventProtocolDecoder extends GenericEventProtocolCoder {
 
-       public EventProtocolDecoder(){super(false);}
-       
-       @Override
-       public String toString() {
-               StringBuilder builder = new StringBuilder();
-               builder.append("EventProtocolDecoder [toString()=").append(super.toString()).append("]");
-               return builder.toString();
-       }
-       
+    public EventProtocolDecoder() {
+        super(false);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("EventProtocolDecoder [toString()=").append(super.toString()).append("]");
+        return builder.toString();
+    }
+
 }
-       
+
 class EventProtocolEncoder extends GenericEventProtocolCoder {
-       
-       public EventProtocolEncoder(){super(false);}
-
-       @Override
-       public String toString() {
-               StringBuilder builder = new StringBuilder();
-               builder.append("EventProtocolEncoder [toString()=").append(super.toString()).append("]");
-               return builder.toString();
-       }
+
+    public EventProtocolEncoder() {
+        super(false);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("EventProtocolEncoder [toString()=").append(super.toString()).append("]");
+        return builder.toString();
+    }
 }
index a5902d6..4fd2f52 100644 (file)
 
 package org.onap.policy.drools.protocol.coders;
 
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
 import java.util.ArrayList;
 import java.util.List;
-
 import java.util.concurrent.CopyOnWriteArrayList;
 import org.onap.policy.drools.utils.Pair;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-
 /**
  * JSON Protocol Filter.
  */
 public class JsonProtocolFilter {
-       
-       private static final String MISSING_RULE_NAME = "no rule name provided";
-       /**
-        * Logger
-        */
-       private static final Logger logger = LoggerFactory.getLogger(JsonProtocolFilter.class);
-       
-       /**
-        * Helper class to collect Filter information
-        */
-       public static class FilterRule {
-               /**
-                * Field name
-                */
-               private String name;
-               
-               /**
-                * Field Value regex
-                */
-               private String regex;
-               
-               /**
-                * Filter Constructor
-                * 
-                * @param name field name
-                * @param regex field regex value
-                */
-               public FilterRule(String name, String regex) {
-                       this.setName(name);
-                       this.setRegex(regex);
-               }
-
-               /**
-                * Default constructor (for serialization only)
-                */
-               public FilterRule() {
-                       super();
-               }
-
-               /**
-                * gets name
-                * 
-                * @return
-                */
-               public String getName() {
-                       return name;
-               }
-
-               /**
-                * gets regex
-                * 
-                * @return
-                */
-               public String getRegex() {
-                       return regex;
-               }
-
-               /**
-                * sets field name
-                * @param name field name
-                */
-               public void setName(String name) {
-                       if (name == null || name.isEmpty())
-                               throw new IllegalArgumentException("filter field name must be provided");
-
-                       this.name = name;
-               }
-
-               /**
-                * sets regex name
-                * @param regex
-                */
-               public void setRegex(String regex) {
-                   if (regex == null || regex.isEmpty())
-                       this.regex = ".*";
-
-                       this.regex = regex;
-               }
-
-               @Override
-               public String toString() {
-                       StringBuilder builder = new StringBuilder();
-                       builder.append("Filter [name=").append(name).append(", regex=").append(regex).append("]");
-                       return builder.toString();
-               }
-       }
-       
-       /**
-        * all the filters to be applied
-        */
-       protected List<FilterRule> rules = new CopyOnWriteArrayList<>();
-       
-       /**
-        * Create a Protocol Filter
-        * 
-        * @throws IllegalArgumentException an invalid input has been provided
-        */
-       public JsonProtocolFilter() {}
-       
-       /**
-        * 
-        * @param filters filter list
-        * 
-        * @throws IllegalArgumentException an invalid input has been provided
-        */
-       public JsonProtocolFilter(List<FilterRule> filters) {
-               List<FilterRule> temp = new ArrayList<>();
-               for (FilterRule rule : filters) {
-                       if (rule.getName() == null || rule.getName().isEmpty()) {
-                                       continue;
-                       }
-
-                       if (rule.getRegex() == null || rule.getRegex().isEmpty()) {
-                               rule.setRegex(".*");
-                       }
-
-                       temp.add(rule);
-               }
-
-               this.rules.addAll(temp);
-       }
-       
-       /**
-        * 
-        * @param rawFilters raw filter initialization
-        * 
-        * @throws IllegalArgumentException an invalid input has been provided
-        */
-       public static JsonProtocolFilter fromRawFilters(List<Pair<String, String>> rawFilters) {
-               
-               if (rawFilters == null) {
-                       throw new IllegalArgumentException("No raw filters provided");
-               }
-               
-               List<FilterRule> filters = new ArrayList<>();
-               for (Pair<String, String> filterPair: rawFilters) {
-                       if  (filterPair.first() == null || filterPair.first().isEmpty()) {
-                               continue;
-                       }
-                       
-                       filters.add(new FilterRule(filterPair.first(), filterPair.second()));
-               }
-               return new JsonProtocolFilter(filters);
-       }
-
-       /**
-        * are there any filters?
-        * 
-        * @return true if there are filters, false otherwise
-        */
-       public boolean isRules() {
-               return !this.rules.isEmpty();
-       }
-
-       /**
-        * accept a JSON string as conformant it if passes all filters
-        * 
-        * @param json json is a JSON object
-        * @return true if json string is conformant
-        * 
-        * @throws IllegalArgumentException an invalid input has been provided
-        */
-       public boolean accept(JsonElement json) {
-               if (json == null) {
-                       throw new IllegalArgumentException("no JSON provided");
-               }
-
-               if (!json.isJsonObject()) {
-                       return false;
-               }
-
-               if (rules.isEmpty()) {
-                       return true;
-               }
-
-               try {
-                       JsonObject event = json.getAsJsonObject();
-                       for (FilterRule filter: rules) {
-                               if (filter.getRegex() == null ||
-                                       filter.getRegex().isEmpty() ||
-                                       ".*".equals(filter.getRegex())) {
-                                       
-                                       // Only check for presence
-                                       if (!event.has(filter.getName())) {
-                                               return false;
-                                       }
-                               } else {
-                                       JsonElement field = event.get(filter.getName());
-                                       if (field == null) {
-                                               return false;
-                                       }
-                                       
-                                       String fieldValue = field.getAsString();
-                                       if (!fieldValue.matches(filter.getRegex())) {
-                                               return false;
-                                       }
-                               }
-                       }
-                       return true;
-               } catch (Exception e) {
-                       throw new IllegalArgumentException(e);
-               }
-       }
-       
-       /**
-        * accept a JSON string as conformant it if passes all filters
-        * 
-        * @param json json string
-        * @return true if json string is conformant
-        * 
-        * @throws IllegalArgumentException an invalid input has been provided
-        */
-       public boolean accept(String json) {
-               if (json == null || json.isEmpty()) {
-                       throw new IllegalArgumentException("no JSON provided");
-               }
-               
-               if (rules.isEmpty()) {
-                       return true;
-               }
-               
-               try {
-                       JsonElement element = new JsonParser().parse(json);
-                       if (element == null || !element.isJsonObject()) {
-                               return false;
-                       }
-                       
-                       return this.accept(element.getAsJsonObject());
-               } catch (IllegalArgumentException ile) {
-                       throw ile;
-               } catch (Exception e) {
-                       logger.info("{}: cannot accept {} because of {}", 
-                                           this, json, e.getMessage(), e);
-                       throw new IllegalArgumentException(e);                  
-               }
-       }
-
-       public List<FilterRule> getRules() {
-               return new ArrayList<>(this.rules);
-       }
-
-       public List<FilterRule> getRules(String name) {
-               if (name == null || name.isEmpty())
-                       throw new IllegalArgumentException(MISSING_RULE_NAME);
-
-               ArrayList<FilterRule> temp = new ArrayList<>();
-               for (FilterRule rule : this.rules) {
-                       if (rule.getName().equals(name)) {
-                               temp.add(rule);
-                       }
-               }
-               return temp;
-       }
-
-       public void setRules(List<FilterRule> rulesFilters) {
-               if (rulesFilters == null)
-                       throw new IllegalArgumentException("no rules provided");
-
-           this.rules.clear();
-           this.rules.addAll(rulesFilters);
-       }
-       
-       public void deleteRules(String name) {
-               if (name == null || name.isEmpty())
-                       throw new IllegalArgumentException(MISSING_RULE_NAME);
-
-               List<FilterRule> temp = new ArrayList<>();
-               for (FilterRule rule : this.rules) {
-                       if (rule.name.equals(name)) {
-                               temp.add(rule);
-                       }
-               }
-               this.rules.removeAll(temp);
-       }
-
-       public void deleteRule(String name, String regex) {
-               if (name == null || name.isEmpty())
-                       throw new IllegalArgumentException(MISSING_RULE_NAME);
-
-               String nonNullRegex = regex;
-               if (regex == null || regex.isEmpty()) {
-                       nonNullRegex = ".*";
-               }
-
-               List<FilterRule> temp = new ArrayList<>();
-               for (FilterRule rule : this.rules) {
-                   if (rule.name.equals(name) && rule.getRegex().equals(nonNullRegex)) {
-                       temp.add(rule);
-                   }
-               }
-
-               this.rules.removeAll(temp);
-       }
-       
-       public void addRule(String name, String regex) {
-               if (name == null || name.isEmpty())
-                       throw new IllegalArgumentException(MISSING_RULE_NAME);
-
-               String nonNullRegex = regex;
-               if (regex == null || regex.isEmpty()) {
-                       nonNullRegex = ".*";
-               }
-
-               for (FilterRule rule : this.rules) {
-                   if (rule.getName().equals(name) && rule.getRegex().equals(regex)) {
-                                       return;
-                   }
-               }
-
-               this.rules.add(new FilterRule(name, nonNullRegex));
-       }
-
-       @Override
-       public String toString() {
-               StringBuilder builder = new StringBuilder();
-               builder.append("JsonProtocolFilter [rules=").append(rules).append("]");
-               return builder.toString();
-       }
+
+    private static final String MISSING_RULE_NAME = "no rule name provided";
+    /**
+     * Logger.
+     */
+    private static final Logger logger = LoggerFactory.getLogger(JsonProtocolFilter.class);
+
+    /**
+     * Helper class to collect Filter information.
+     */
+    public static class FilterRule {
+        /**
+         * Field name.
+         */
+        private String name;
+
+        /**
+         * Field Value regex.
+         */
+        private String regex;
+
+        /**
+         * Filter Constructor.
+         * 
+         * @param name field name
+         * @param regex field regex value
+         */
+        public FilterRule(String name, String regex) {
+            this.setName(name);
+            this.setRegex(regex);
+        }
+
+        /**
+         * Default constructor (for serialization only).
+         */
+        public FilterRule() {
+            super();
+        }
+
+        /**
+         * gets name.
+         * 
+         * @return name
+         */
+        public String getName() {
+            return name;
+        }
+
+        /**
+         * gets regex.
+         * 
+         * @return regular expression string
+         */
+        public String getRegex() {
+            return regex;
+        }
+
+        /**
+         * Sets field name.
+         * 
+         * @param name field name
+         */
+        public void setName(String name) {
+            if (name == null || name.isEmpty()) {
+                throw new IllegalArgumentException("filter field name must be provided");
+            }
+
+            this.name = name;
+        }
+
+        /**
+         * sets regex name.
+         * 
+         * @param regex expression
+         */
+        public void setRegex(String regex) {
+            if (regex == null || regex.isEmpty()) {
+                this.regex = ".*";
+            }
+
+            this.regex = regex;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("Filter [name=").append(name).append(", regex=").append(regex).append("]");
+            return builder.toString();
+        }
+    }
+
+    /**
+     * all the filters to be applied.
+     */
+    protected List<FilterRule> rules = new CopyOnWriteArrayList<>();
+
+    /**
+     * Create a Protocol Filter.
+     * 
+     * @throws IllegalArgumentException an invalid input has been provided
+     */
+    public JsonProtocolFilter() {
+        super();
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param filters filter list
+     * 
+     * @throws IllegalArgumentException an invalid input has been provided
+     */
+    public JsonProtocolFilter(List<FilterRule> filters) {
+        List<FilterRule> temp = new ArrayList<>();
+        for (FilterRule rule : filters) {
+            if (rule.getName() == null || rule.getName().isEmpty()) {
+                continue;
+            }
+
+            if (rule.getRegex() == null || rule.getRegex().isEmpty()) {
+                rule.setRegex(".*");
+            }
+
+            temp.add(rule);
+        }
+
+        this.rules.addAll(temp);
+    }
+
+    /**
+     * From raw filters.
+     * 
+     * @param rawFilters raw filter initialization
+     * 
+     * @throws IllegalArgumentException an invalid input has been provided
+     */
+    public static JsonProtocolFilter fromRawFilters(List<Pair<String, String>> rawFilters) {
+
+        if (rawFilters == null) {
+            throw new IllegalArgumentException("No raw filters provided");
+        }
+
+        List<FilterRule> filters = new ArrayList<>();
+        for (Pair<String, String> filterPair: rawFilters) {
+            if  (filterPair.first() == null || filterPair.first().isEmpty()) {
+                continue;
+            }
+
+            filters.add(new FilterRule(filterPair.first(), filterPair.second()));
+        }
+        return new JsonProtocolFilter(filters);
+    }
+
+    /**
+     * are there any filters.
+     * 
+     * @return true if there are filters, false otherwise
+     */
+    public boolean isRules() {
+        return !this.rules.isEmpty();
+    }
+
+    /**
+     * accept a JSON string as conformant it if passes all filters.
+     * 
+     * @param json json is a JSON object
+     * @return true if json string is conformant
+     * 
+     * @throws IllegalArgumentException an invalid input has been provided
+     */
+    public boolean accept(JsonElement json) {
+        if (json == null) {
+            throw new IllegalArgumentException("no JSON provided");
+        }
+
+        if (!json.isJsonObject()) {
+            return false;
+        }
+
+        if (rules.isEmpty()) {
+            return true;
+        }
+
+        try {
+            JsonObject event = json.getAsJsonObject();
+            for (FilterRule filter: rules) {
+                if (filter.getRegex() == null
+                        || filter.getRegex().isEmpty()
+                        || ".*".equals(filter.getRegex())) {
+
+                    // Only check for presence
+                    if (!event.has(filter.getName())) {
+                        return false;
+                    }
+                } else {
+                    JsonElement field = event.get(filter.getName());
+                    if (field == null) {
+                        return false;
+                    }
+
+                    String fieldValue = field.getAsString();
+                    if (!fieldValue.matches(filter.getRegex())) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        } catch (Exception e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * Accept a JSON string as conformant it if passes all filters.
+     * 
+     * @param json json string
+     * @return true if json string is conformant
+     * 
+     * @throws IllegalArgumentException an invalid input has been provided
+     */
+    public boolean accept(String json) {
+        if (json == null || json.isEmpty()) {
+            throw new IllegalArgumentException("no JSON provided");
+        }
+
+        if (rules.isEmpty()) {
+            return true;
+        }
+
+        try {
+            JsonElement element = new JsonParser().parse(json);
+            if (element == null || !element.isJsonObject()) {
+                return false;
+            }
+
+            return this.accept(element.getAsJsonObject());
+        } catch (IllegalArgumentException ile) {
+            throw ile;
+        } catch (Exception e) {
+            logger.info("{}: cannot accept {} because of {}", 
+                    this, json, e.getMessage(), e);
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    public List<FilterRule> getRules() {
+        return new ArrayList<>(this.rules);
+    }
+
+    /**
+     * Get rules.
+     * 
+     * @param name name
+     * @return
+     */
+    public List<FilterRule> getRules(String name) {
+        if (name == null || name.isEmpty()) {
+            throw new IllegalArgumentException(MISSING_RULE_NAME);
+        }
+
+        ArrayList<FilterRule> temp = new ArrayList<>();
+        for (FilterRule rule : this.rules) {
+            if (rule.getName().equals(name)) {
+                temp.add(rule);
+            }
+        }
+        return temp;
+    }
+
+    /**
+     * Set Rules.
+     * 
+     * @param rulesFilters filters
+     */
+    public void setRules(List<FilterRule> rulesFilters) {
+        if (rulesFilters == null) {
+            throw new IllegalArgumentException("no rules provided");
+        }
+
+        this.rules.clear();
+        this.rules.addAll(rulesFilters);
+    }
+
+    /**
+     * Delete rules.
+     * 
+     * @param name name
+     */
+    public void deleteRules(String name) {
+        if (name == null || name.isEmpty()) {
+            throw new IllegalArgumentException(MISSING_RULE_NAME);
+        }
+
+        List<FilterRule> temp = new ArrayList<>();
+        for (FilterRule rule : this.rules) {
+            if (rule.name.equals(name)) {
+                temp.add(rule);
+            }
+        }
+        this.rules.removeAll(temp);
+    }
+
+    /**
+     * Delete rule.
+     * 
+     * @param name name
+     * @param regex regex
+     */
+    public void deleteRule(String name, String regex) {
+        if (name == null || name.isEmpty()) {
+            throw new IllegalArgumentException(MISSING_RULE_NAME);
+        }
+
+        String nonNullRegex = regex;
+        if (regex == null || regex.isEmpty()) {
+            nonNullRegex = ".*";
+        }
+
+        List<FilterRule> temp = new ArrayList<>();
+        for (FilterRule rule : this.rules) {
+            if (rule.name.equals(name) && rule.getRegex().equals(nonNullRegex)) {
+                temp.add(rule);
+            }
+        }
+
+        this.rules.removeAll(temp);
+    }
+
+    /**
+     * Add rule.
+     * 
+     * @param name name
+     * @param regex regex
+     */
+    public void addRule(String name, String regex) {
+        if (name == null || name.isEmpty()) {
+            throw new IllegalArgumentException(MISSING_RULE_NAME);
+        }
+
+        String nonNullRegex = regex;
+        if (regex == null || regex.isEmpty()) {
+            nonNullRegex = ".*";
+        }
+
+        for (FilterRule rule : this.rules) {
+            if (rule.getName().equals(name) && rule.getRegex().equals(regex)) {
+                return;
+            }
+        }
+
+        this.rules.add(new FilterRule(name, nonNullRegex));
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("JsonProtocolFilter [rules=").append(rules).append("]");
+        return builder.toString();
+    }
 
 }
index 4fb4d92..47baa07 100644 (file)
@@ -37,7 +37,7 @@ public class DroolsControllerFactoryTest {
         DroolsController droolsController = DroolsController.factory.build(droolsProps, null, null);
 
         if (!isNullController(droolsController)) {
-                       fail("drools controller is not a null controller");
+            fail("drools controller is not a null controller");
         }
     }
 
@@ -60,7 +60,7 @@ public class DroolsControllerFactoryTest {
         
         for (int i = 0; i < controllers.size(); i++) {
             if (!isNullController(controllers.get(i)) && !isActualController(controllers.get(i))) {
-                       fail("drools controller is not a null controller");
+                fail("drools controller is not a null controller");
             }
         }
     }
@@ -81,15 +81,15 @@ public class DroolsControllerFactoryTest {
 
     private boolean isNullController(DroolsController droolsController) {
         if (droolsController == null) {
-                       return false;
+            return false;
         }
         
         if (!DroolsController.NO_GROUP_ID.equals(droolsController.getGroupId())) {
-                       return false;
+            return false;
         }
         
         if (!DroolsController.NO_ARTIFACT_ID.equals(droolsController.getArtifactId())) {
-                       return false;
+            return false;
         }
 
         return DroolsController.NO_VERSION.equals(droolsController.getVersion());
@@ -97,15 +97,15 @@ public class DroolsControllerFactoryTest {
 
     private boolean isActualController(DroolsController droolsController) {
         if (droolsController == null) {
-                       return false;
+            return false;
         }
         
         if (!"org.onap.policy.drools.test".equals(droolsController.getGroupId())) {
-                       return false;
+            return false;
         }
         
         if (!"protocolcoder".equals(droolsController.getArtifactId())) {
-                       return false;
+            return false;
         }
         
         return droolsController.getVersion() != null && droolsController.getVersion().substring(0, 1).matches("[0-9]");
index a41c3c1..5df6eb8 100644 (file)
@@ -40,6 +40,11 @@ public class MavenDroolsControllerTest {
 
     private static volatile ReleaseId releaseId;
 
+    /**
+     * Set up.
+     * 
+     * @throws IOException throws an IO exception
+     */
     @BeforeClass
     public static void setUp() throws IOException {
         releaseId =
@@ -74,8 +79,9 @@ public class MavenDroolsControllerTest {
     }
 
     private DroolsController createDroolsController(long courtesyStartTimeMs) throws InterruptedException {
-        if (releaseId == null)
+        if (releaseId == null) {
             throw new IllegalStateException("no prereq artifact installed in maven repository");
+        }
 
         DroolsController controller = new MavenDroolsController(releaseId.getGroupId(),
             releaseId.getArtifactId(), releaseId.getVersion(), null, null);
index 9b2e616..1e51cfe 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP
  * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2018 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.
@@ -17,6 +17,7 @@
  * limitations under the License.
  * ============LICENSE_END=========================================================
  */
+
 package org.onap.policy.drools.persistence.test;
 
 import static org.junit.Assert.assertEquals;
@@ -43,145 +44,150 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * (File) System Persistence Tests
+ * (File) System Persistence Tests.
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class SystemPersistenceTest {
 
-  /**
-   * logger
-   */
-  private static final Logger logger = LoggerFactory.getLogger(SystemPersistenceTest.class);
-
-  /**
-   * sample configuration dir
-   */
-  public static final String OTHER_CONFIG_DIR = "tmp";
-
-  /**
-   * Test JUnit Controller Name
-   */
-  public static final String TEST_CONTROLLER_NAME = "foo";
-
-  /**
-   * Test JUnit Controller Name
-   */
-  public static final String TEST_CONTROLLER_FILE = TEST_CONTROLLER_NAME + "-controller.properties";
-
-  /**
-   * Test JUnit Controller Name Backup
-   */
-  public static final String TEST_CONTROLLER_FILE_BAK = TEST_CONTROLLER_FILE + ".bak";
-
-  /**
-   * Test JUnit Environment/Engine properties
-   */
-  private static final String ENV_PROPS = "envProps";
-  private static final String ENV_PROPS_FILE = ENV_PROPS + ".environment";
-  private static final String POLICY_ENGINE_PROPERTIES_FILE = "policy-engine.properties";
-
-  @BeforeClass
-  public static void setUp() throws IOException {
-    cleanUpWorkingDirs();
-  }
-
-  @AfterClass
-  public static void tearDown() throws IOException {
-    cleanUpWorkingDirs();
-  }
-
-  @Test
-  public void test1NonDefaultConfigDir() throws IOException {
-    logger.info("enter");
-
-    SystemPersistence.manager.setConfigurationDir(OTHER_CONFIG_DIR);
-    assertTrue(
-        SystemPersistence.manager.getConfigurationPath().toString().equals(OTHER_CONFIG_DIR));
-
-    SystemPersistence.manager.setConfigurationDir(null);
-    assertTrue(SystemPersistence.manager.getConfigurationPath().toString()
-        .equals(SystemPersistence.DEFAULT_CONFIGURATION_DIR));
-  }
-
-  @Test
-  public void test2Engine() throws IOException {
-    logger.info("enter");
-
-    SystemPersistence.manager.setConfigurationDir(OTHER_CONFIG_DIR);
-
-    final Path policyEnginePropsPath =
-        Paths.get(SystemPersistence.manager.getConfigurationPath().toString(),
-            FileSystemPersistence.PROPERTIES_FILE_ENGINE);
-
-    final Properties engineProps = new Properties();
-    engineProps.setProperty("foo", "bar");
-    engineProps.setProperty("fiz", "buz");
-    if (Files.notExists(policyEnginePropsPath)) {
-      try (final OutputStream fout = new FileOutputStream(policyEnginePropsPath.toFile())) {
-        engineProps.store(fout, "");
-      }
+    /**
+     * logger.
+     */
+    private static final Logger logger = LoggerFactory.getLogger(SystemPersistenceTest.class);
+
+    /**
+     * sample configuration dir.
+     */
+    public static final String OTHER_CONFIG_DIR = "tmp";
+
+    /**
+     * Test JUnit Controller Name.
+     */
+    public static final String TEST_CONTROLLER_NAME = "foo";
+
+    /**
+     * Test JUnit Controller Name.
+     */
+    public static final String TEST_CONTROLLER_FILE = TEST_CONTROLLER_NAME + "-controller.properties";
+
+    /**
+     * Test JUnit Controller Name Backup.
+     */
+    public static final String TEST_CONTROLLER_FILE_BAK = TEST_CONTROLLER_FILE + ".bak";
+
+    /**
+     * Test JUnit Environment/Engine properties.
+     */
+    private static final String ENV_PROPS = "envProps";
+    private static final String ENV_PROPS_FILE = ENV_PROPS + ".environment";
+    private static final String POLICY_ENGINE_PROPERTIES_FILE = "policy-engine.properties";
+
+    @BeforeClass
+    public static void setUp() throws IOException {
+        cleanUpWorkingDirs();
+    }
+
+    @AfterClass
+    public static void tearDown() throws IOException {
+        cleanUpWorkingDirs();
     }
 
-    assertEquals(SystemPersistence.manager.getEngineProperties(), engineProps);
+    @Test
+    public void test1NonDefaultConfigDir() throws IOException {
+        logger.info("enter");
+
+        SystemPersistence.manager.setConfigurationDir(OTHER_CONFIG_DIR);
+        assertTrue(
+                SystemPersistence.manager.getConfigurationPath().toString().equals(OTHER_CONFIG_DIR));
 
-    final Path environmentPropertiesPath =
-        Paths.get(SystemPersistence.manager.getConfigurationPath().toString(), ENV_PROPS_FILE);
-    if (Files.notExists(environmentPropertiesPath)) {
-      Files.createFile(environmentPropertiesPath);
+        SystemPersistence.manager.setConfigurationDir(null);
+        assertTrue(SystemPersistence.manager.getConfigurationPath().toString()
+                .equals(SystemPersistence.DEFAULT_CONFIGURATION_DIR));
     }
-    assertTrue(SystemPersistence.manager.getEnvironmentProperties(ENV_PROPS).isEmpty());
-    assertTrue(SystemPersistence.manager.getEnvironmentProperties().size() == 1);
-  }
 
-  @Test
-  public void test3PersistConfiguration() {
-    logger.info("enter");
+    @Test
+    public void test2Engine() throws IOException {
+        logger.info("enter");
+
+        SystemPersistence.manager.setConfigurationDir(OTHER_CONFIG_DIR);
+
+        final Path policyEnginePropsPath =
+                Paths.get(SystemPersistence.manager.getConfigurationPath().toString(),
+                        FileSystemPersistence.PROPERTIES_FILE_ENGINE);
+
+        final Properties engineProps = new Properties();
+        engineProps.setProperty("foo", "bar");
+        engineProps.setProperty("fiz", "buz");
+        if (Files.notExists(policyEnginePropsPath)) {
+            try (final OutputStream fout = new FileOutputStream(policyEnginePropsPath.toFile())) {
+                engineProps.store(fout, "");
+            }
+        }
+
+        assertEquals(SystemPersistence.manager.getEngineProperties(), engineProps);
+
+        final Path environmentPropertiesPath =
+                Paths.get(SystemPersistence.manager.getConfigurationPath().toString(), ENV_PROPS_FILE);
+        if (Files.notExists(environmentPropertiesPath)) {
+            Files.createFile(environmentPropertiesPath);
+        }
+        assertTrue(SystemPersistence.manager.getEnvironmentProperties(ENV_PROPS).isEmpty());
+        assertTrue(SystemPersistence.manager.getEnvironmentProperties().size() == 1);
+    }
+
+    @Test
+    public void test3PersistConfiguration() {
+        logger.info("enter");
 
-    SystemPersistence.manager.setConfigurationDir(null);
+        SystemPersistence.manager.setConfigurationDir(null);
 
-    final Path controllerPath = Paths
-        .get(SystemPersistence.manager.getConfigurationPath().toString(), TEST_CONTROLLER_FILE);
+        final Path controllerPath = Paths
+                .get(SystemPersistence.manager.getConfigurationPath().toString(), TEST_CONTROLLER_FILE);
 
-    final Path controllerBakPath = Paths
-        .get(SystemPersistence.manager.getConfigurationPath().toString(), TEST_CONTROLLER_FILE_BAK);
+        final Path controllerBakPath = Paths
+                .get(SystemPersistence.manager.getConfigurationPath().toString(), TEST_CONTROLLER_FILE_BAK);
 
-    assertTrue(Files.notExists(controllerPath));
-    assertTrue(Files.notExists(controllerBakPath));
+        assertTrue(Files.notExists(controllerPath));
+        assertTrue(Files.notExists(controllerBakPath));
 
-    Properties properties = new Properties();
-    properties.put(DroolsProperties.PROPERTY_CONTROLLER_NAME, TEST_CONTROLLER_NAME);
-    SystemPersistence.manager.storeController(TEST_CONTROLLER_NAME, properties);
+        Properties properties = new Properties();
+        properties.put(DroolsProperties.PROPERTY_CONTROLLER_NAME, TEST_CONTROLLER_NAME);
+        SystemPersistence.manager.storeController(TEST_CONTROLLER_NAME, properties);
 
-    assertTrue(Files.exists(controllerPath));
+        assertTrue(Files.exists(controllerPath));
 
-    properties = SystemPersistence.manager.getControllerProperties(TEST_CONTROLLER_NAME);
-    assertTrue(properties != null);
+        properties = SystemPersistence.manager.getControllerProperties(TEST_CONTROLLER_NAME);
+        assertTrue(properties != null);
 
-    SystemPersistence.manager.backupController(TEST_CONTROLLER_NAME);
-    assertTrue(Files.exists(controllerBakPath));
+        SystemPersistence.manager.backupController(TEST_CONTROLLER_NAME);
+        assertTrue(Files.exists(controllerBakPath));
 
-    assertFalse(SystemPersistence.manager.getControllerProperties().isEmpty());
+        assertFalse(SystemPersistence.manager.getControllerProperties().isEmpty());
 
-    SystemPersistence.manager.deleteController(TEST_CONTROLLER_NAME);
-    assertTrue(Files.notExists(controllerPath));
-  }
+        SystemPersistence.manager.deleteController(TEST_CONTROLLER_NAME);
+        assertTrue(Files.notExists(controllerPath));
+    }
 
-  public static void cleanUpWorkingDirs() throws IOException {
+    /**
+     * Clean up the working directories.
+     * 
+     * @throws IOException throws IO exception
+     */
+    public static void cleanUpWorkingDirs() throws IOException {
 
-    SystemPersistence.manager.setConfigurationDir(null);
+        SystemPersistence.manager.setConfigurationDir(null);
 
-    final Path testControllerPath = Paths
-        .get(SystemPersistence.manager.getConfigurationPath().toString(), TEST_CONTROLLER_FILE);
-    final Path testControllerBakPath = Paths
-        .get(SystemPersistence.manager.getConfigurationPath().toString(), TEST_CONTROLLER_FILE_BAK);
+        final Path testControllerPath = Paths
+                .get(SystemPersistence.manager.getConfigurationPath().toString(), TEST_CONTROLLER_FILE);
+        final Path testControllerBakPath = Paths
+                .get(SystemPersistence.manager.getConfigurationPath().toString(), TEST_CONTROLLER_FILE_BAK);
 
-    final Path policyEnginePath = Paths.get(OTHER_CONFIG_DIR, POLICY_ENGINE_PROPERTIES_FILE);
-    final Path environmentPath = Paths.get(OTHER_CONFIG_DIR, ENV_PROPS_FILE);
+        final Path policyEnginePath = Paths.get(OTHER_CONFIG_DIR, POLICY_ENGINE_PROPERTIES_FILE);
+        final Path environmentPath = Paths.get(OTHER_CONFIG_DIR, ENV_PROPS_FILE);
 
-    Files.deleteIfExists(testControllerPath);
-    Files.deleteIfExists(testControllerBakPath);
-    Files.deleteIfExists(policyEnginePath);
-    Files.deleteIfExists(environmentPath);
-  }
+        Files.deleteIfExists(testControllerPath);
+        Files.deleteIfExists(testControllerBakPath);
+        Files.deleteIfExists(policyEnginePath);
+        Files.deleteIfExists(environmentPath);
+    }
 
 }
index b42c64b..d6330cd 100644 (file)
@@ -31,32 +31,32 @@ import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
 import org.onap.policy.drools.protocol.configuration.DroolsConfiguration;
 
 /**
- * Tests Coders
+ * Tests Coders.
  */
 public class EventProtocolCoderTest {
 
     /**
-     * Coder Group
+     * Coder Group.
      */
     private static final String ENCODER_GROUP = "foo";
 
     /**
-     * Coder Artifact
+     * Coder Artifact.
      */
     private static final String ENCODER_ARTIFACT = "bar";
 
     /**
-     * Coder Version
+     * Coder Version.
      */
     private static final String ENCODER_VERSION = null;
 
     /**
-     * noop topic
+     * noop topic.
      */
     private static final String NOOP_TOPIC = "JUNIT";
 
     /**
-     * Event Test Class
+     * Event Test Class.
      */
     public static class EventTest {
 
index 624bc2c..e83e588 100644 (file)
@@ -160,14 +160,14 @@ public class JsonProtocolFilterTest {
         assertTrue(protocolFilterB.getRules(NAME4).get(1).getName().equals(NAME4));
         assertTrue(protocolFilterB.getRules(NAME4).get(1).getRegex().equals(REGEX4b));
 
-        String jsonA = "{ \"name1\":\"regex1\",\"name2\":\"regex2\"," +
-                        "\"name3\":\"regex3\",\"name4\":\"regex4a\",\"name4\":\"regex4b\"}";
-        String jsonB = "{ \"name1\":\"regex1\",\"name2\":\"regex2\"," +
-                        "\"name3\":\"regex3\",\"name4\":\"regex4a-regex4b\"}";
-        String jsonC = "{ \"name1\":\"regex1\",\"name2\":\"regex2\"," +
-                        "\"name3\":\"regex3\",\"name4\":\"regex4a\"}";
-        String jsonD = "{ \"name1\":\"regex1\",\"name2\":\"regex2\"," +
-                        "\"name3\":\"regex3\",\"name4\":\"regex4b\"}";
+        final String jsonA = "{ \"name1\":\"regex1\",\"name2\":\"regex2\","
+                        "\"name3\":\"regex3\",\"name4\":\"regex4a\",\"name4\":\"regex4b\"}";
+        final String jsonB = "{ \"name1\":\"regex1\",\"name2\":\"regex2\","
+                        "\"name3\":\"regex3\",\"name4\":\"regex4a-regex4b\"}";
+        final String jsonC = "{ \"name1\":\"regex1\",\"name2\":\"regex2\","
+                        "\"name3\":\"regex3\",\"name4\":\"regex4a\"}";
+        final String jsonD = "{ \"name1\":\"regex1\",\"name2\":\"regex2\","
+                        "\"name3\":\"regex3\",\"name4\":\"regex4b\"}";
 
         assertFalse(protocolFilterB.accept(jsonA));
         assertTrue(protocolFilterB.accept(jsonB));
index aa04f40..2816817 100644 (file)
@@ -51,7 +51,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * ProtocolCoder Toolset JUNITs
+ * ProtocolCoder Toolset JUNITs.
  */
 public class ProtocolCoderToolsetTest {
     public static final String JUNIT_PROTOCOL_CODER_ARTIFACT_ID = "protocolcoder";
@@ -66,6 +66,11 @@ public class ProtocolCoderToolsetTest {
 
     public static final Gson customCoder = new GsonBuilder().create();
 
+    /**
+     * Setup.
+     * 
+     * @throws IOException throws IO Exception
+     */
     @Before
     public void setUp() throws IOException {
         if (releaseId != null) {
@@ -94,6 +99,11 @@ public class ProtocolCoderToolsetTest {
         testJacksonToolset(createFilterSet());
     }
 
+    /**
+     * Test the Gson toolset.
+     * 
+     * @param protocolFilter protocol filter
+     */
     public void testGsonToolset(JsonProtocolFilter protocolFilter) {
         GsonProtocolCoderToolset gsonToolset = new GsonProtocolCoderToolset(JUNIT_PROTOCOL_CODER_TOPIC, CONTROLLER_ID,
                 this.releaseId.getGroupId(), this.releaseId.getArtifactId(), Triple.class.getCanonicalName(),
@@ -114,6 +124,11 @@ public class ProtocolCoderToolsetTest {
         return new Triple<>("v1", "v2", "v3");
     }
 
+    /**
+     * Test Jackson toolset.
+     * 
+     * @param protocolFilter protocol filter
+     */
     public void testJacksonToolset(JsonProtocolFilter protocolFilter) {
         JacksonProtocolCoderToolset jacksonToolset = new JacksonProtocolCoderToolset(JUNIT_PROTOCOL_CODER_TOPIC,
                 CONTROLLER_ID, this.releaseId.getGroupId(), this.releaseId.getArtifactId(),
@@ -242,7 +257,7 @@ public class ProtocolCoderToolsetTest {
 
         Properties sinkConfig = new Properties();
         sinkConfig.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, JUNIT_PROTOCOL_CODER_TOPIC);
-        List<? extends TopicSink> noopTopics = TopicEndpoint.manager.addTopicSinks(sinkConfig);
+        final List<? extends TopicSink> noopTopics = TopicEndpoint.manager.addTopicSinks(sinkConfig);
 
         Properties droolsControllerConfig = new Properties();
         droolsControllerConfig.put(DroolsProperties.RULES_GROUPID, releaseId.getGroupId());
index bfebeac..f3817d5 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * Configuration Test
  * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2018 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.
@@ -17,6 +17,7 @@
  * limitations under the License.
  * ============LICENSE_END=========================================================
  */
+
 package org.onap.policy.drools.protocol.configuration;
 
 import static org.junit.Assert.assertEquals;
@@ -50,6 +51,10 @@ public class ControllerConfigurationTest {
     private static final DroolsConfiguration DROOLS_CONFIG2 = new DroolsConfiguration(ARTIFACT2, GROUPID2, VERSION2);
     
     private static final String DROOLS_STRING = "drools";
+    
+    /**
+     * Test.
+     */
     @Test
     public void test() {
         
@@ -77,7 +82,8 @@ public class ControllerConfigurationTest {
         controllerConfig2.setAdditionalProperty(ADDITIONAL_PROPERTY_KEY, ADDITIONAL_PROPERTY_VALUE);
         assertEquals(controllerConfig2.getAdditionalProperties(), additionalProperties);
         
-        assertEquals(controllerConfig2, controllerConfig2.withAdditionalProperty(ADDITIONAL_PROPERTY_KEY, ADDITIONAL_PROPERTY_VALUE));
+        assertEquals(controllerConfig2, controllerConfig2.withAdditionalProperty(ADDITIONAL_PROPERTY_KEY, 
+                ADDITIONAL_PROPERTY_VALUE));
         
         assertTrue(controllerConfig2.declaredProperty(NAME, NAME2));
         assertTrue(controllerConfig2.declaredProperty(OPERATION, OPERATION2));
@@ -90,10 +96,9 @@ public class ControllerConfigurationTest {
         assertEquals(controllerConfig2.declaredPropertyOrNotFound(DROOLS_STRING, DROOLS_CONFIG2), DROOLS_CONFIG2);
         assertEquals(controllerConfig2.declaredPropertyOrNotFound("dummy", NAME), NAME);
         
-        int hashCode = new HashCodeBuilder().append(NAME2).append(OPERATION2).append(DROOLS_CONFIG2).append(additionalProperties).toHashCode();
+        int hashCode = new HashCodeBuilder().append(NAME2).append(OPERATION2).append(DROOLS_CONFIG2)
+                .append(additionalProperties).toHashCode();
         assertEquals(controllerConfig2.hashCode(), hashCode);
         
     }
-
-
 }
index f4c2410..7d9b655 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * Configuration Test
  * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2018 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.
@@ -17,6 +17,7 @@
  * limitations under the License.
  * ============LICENSE_END=========================================================
  */
+
 package org.onap.policy.drools.protocol.configuration;
 
 import static org.junit.Assert.assertEquals;
@@ -29,73 +30,68 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.junit.Test;
 
 public class DroolsConfigurationTest {
-  private static final String ARTIFACT_ID_STRING = "artifactId";
-  private static final String GROUP_ID_STRING = "groupId";
-  private static final String VERSION_STRING = "version";
-
-
-  private static final String NAME = "name";
-  private static final String ARTIFACT = "org.onap.artifact";
-  private static final String GROUPID = "group";
-  private static final String VERSION = "1.0.0";
-
-  private static final String ARTIFACT2 = "org.onap.artifact2";
-  private static final String GROUPID2 = "group2";
-  private static final String VERSION2 = "1.0.1";
-
-  private static final String ADDITIONAL_PROPERTY_KEY = "foo";
-  private static final String ADDITIONAL_PROPERTY_VALUE = "bar";
-
-  @Test
-  public void test() {
-    final Properties additionalProperties = new Properties();
-    additionalProperties.put(ADDITIONAL_PROPERTY_KEY, ADDITIONAL_PROPERTY_VALUE);
+    private static final String ARTIFACT_ID_STRING = "artifactId";
+    private static final String GROUP_ID_STRING = "groupId";
+    private static final String VERSION_STRING = "version";
 
-    final DroolsConfiguration droolsConfig = new DroolsConfiguration(ARTIFACT, GROUPID, VERSION);
-    assertTrue(droolsConfig.equals(droolsConfig));
 
-    droolsConfig.set(ARTIFACT_ID_STRING, "foobar");
-    assertEquals(droolsConfig.get(ARTIFACT_ID_STRING), "foobar");
+    private static final String NAME = "name";
+    private static final String ARTIFACT = "org.onap.artifact";
+    private static final String GROUPID = "group";
+    private static final String VERSION = "1.0.0";
 
-    assertEquals(droolsConfig.with(ARTIFACT_ID_STRING, "foobar2"), droolsConfig);
+    private static final String ARTIFACT2 = "org.onap.artifact2";
+    private static final String GROUPID2 = "group2";
+    private static final String VERSION2 = "1.0.1";
 
-    final DroolsConfiguration droolsConfig2 = new DroolsConfiguration();
-    droolsConfig2.setArtifactId(ARTIFACT2);
-    droolsConfig2.setGroupId(GROUPID2);
-    droolsConfig2.setVersion(VERSION2);
+    private static final String ADDITIONAL_PROPERTY_KEY = "foo";
+    private static final String ADDITIONAL_PROPERTY_VALUE = "bar";
 
-    assertEquals(droolsConfig2.getArtifactId(), ARTIFACT2);
-    assertEquals(droolsConfig2.getGroupId(), GROUPID2);
-    assertEquals(droolsConfig2.getVersion(), VERSION2);
+    @Test
+    public void test() {
+        final Properties additionalProperties = new Properties();
+        additionalProperties.put(ADDITIONAL_PROPERTY_KEY, ADDITIONAL_PROPERTY_VALUE);
 
-    assertEquals(droolsConfig2.withArtifactId(ARTIFACT2), droolsConfig2);
-    assertEquals(droolsConfig2.withGroupId(GROUPID2), droolsConfig2);
-    assertEquals(droolsConfig2.withVersion(VERSION2), droolsConfig2);
+        final DroolsConfiguration droolsConfig = new DroolsConfiguration(ARTIFACT, GROUPID, VERSION);
+        assertTrue(droolsConfig.equals(droolsConfig));
 
-    droolsConfig2.setAdditionalProperty(ADDITIONAL_PROPERTY_KEY, ADDITIONAL_PROPERTY_VALUE);
-    assertEquals(droolsConfig2.getAdditionalProperties(), additionalProperties);
+        droolsConfig.set(ARTIFACT_ID_STRING, "foobar");
+        assertEquals(droolsConfig.get(ARTIFACT_ID_STRING), "foobar");
 
-    assertEquals(droolsConfig2,
-        droolsConfig2.withAdditionalProperty(ADDITIONAL_PROPERTY_KEY, ADDITIONAL_PROPERTY_VALUE));
+        assertEquals(droolsConfig.with(ARTIFACT_ID_STRING, "foobar2"), droolsConfig);
 
-    assertTrue(droolsConfig2.declaredProperty(ARTIFACT_ID_STRING, ARTIFACT2));
-    assertTrue(droolsConfig2.declaredProperty(GROUP_ID_STRING, GROUPID2));
-    assertTrue(droolsConfig2.declaredProperty(VERSION_STRING, VERSION2));
-    assertFalse(droolsConfig2.declaredProperty("dummy", NAME));
+        final DroolsConfiguration droolsConfig2 = new DroolsConfiguration();
+        droolsConfig2.setArtifactId(ARTIFACT2);
+        droolsConfig2.setGroupId(GROUPID2);
+        droolsConfig2.setVersion(VERSION2);
 
-    assertEquals(droolsConfig2.declaredPropertyOrNotFound(ARTIFACT_ID_STRING, ARTIFACT2),
-        ARTIFACT2);
-    assertEquals(droolsConfig2.declaredPropertyOrNotFound(GROUP_ID_STRING, GROUPID2), GROUPID2);
-    assertEquals(droolsConfig2.declaredPropertyOrNotFound(VERSION_STRING, VERSION2), VERSION2);
-    assertEquals(droolsConfig2.declaredPropertyOrNotFound("dummy", ARTIFACT2), ARTIFACT2);
+        assertEquals(droolsConfig2.getArtifactId(), ARTIFACT2);
+        assertEquals(droolsConfig2.getGroupId(), GROUPID2);
+        assertEquals(droolsConfig2.getVersion(), VERSION2);
 
-    final int hashCode = new HashCodeBuilder().append(ARTIFACT2).append(GROUPID2).append(VERSION2)
-        .append(additionalProperties).toHashCode();
-    assertEquals(droolsConfig2.hashCode(), hashCode);
+        assertEquals(droolsConfig2.withArtifactId(ARTIFACT2), droolsConfig2);
+        assertEquals(droolsConfig2.withGroupId(GROUPID2), droolsConfig2);
+        assertEquals(droolsConfig2.withVersion(VERSION2), droolsConfig2);
 
+        droolsConfig2.setAdditionalProperty(ADDITIONAL_PROPERTY_KEY, ADDITIONAL_PROPERTY_VALUE);
+        assertEquals(droolsConfig2.getAdditionalProperties(), additionalProperties);
 
+        assertEquals(droolsConfig2,
+                droolsConfig2.withAdditionalProperty(ADDITIONAL_PROPERTY_KEY, ADDITIONAL_PROPERTY_VALUE));
 
-  }
+        assertTrue(droolsConfig2.declaredProperty(ARTIFACT_ID_STRING, ARTIFACT2));
+        assertTrue(droolsConfig2.declaredProperty(GROUP_ID_STRING, GROUPID2));
+        assertTrue(droolsConfig2.declaredProperty(VERSION_STRING, VERSION2));
+        assertFalse(droolsConfig2.declaredProperty("dummy", NAME));
 
+        assertEquals(droolsConfig2.declaredPropertyOrNotFound(ARTIFACT_ID_STRING, ARTIFACT2),
+                ARTIFACT2);
+        assertEquals(droolsConfig2.declaredPropertyOrNotFound(GROUP_ID_STRING, GROUPID2), GROUPID2);
+        assertEquals(droolsConfig2.declaredPropertyOrNotFound(VERSION_STRING, VERSION2), VERSION2);
+        assertEquals(droolsConfig2.declaredPropertyOrNotFound("dummy", ARTIFACT2), ARTIFACT2);
 
+        final int hashCode = new HashCodeBuilder().append(ARTIFACT2).append(GROUPID2).append(VERSION2)
+                .append(additionalProperties).toHashCode();
+        assertEquals(droolsConfig2.hashCode(), hashCode);
+    }
 }
index 84c85b8..b5f3c53 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * Configuration Test
  * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2018 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.
@@ -17,6 +17,7 @@
  * limitations under the License.
  * ============LICENSE_END=========================================================
  */
+
 package org.onap.policy.drools.protocol.configuration;
 
 import static org.junit.Assert.assertEquals;
@@ -32,219 +33,222 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class PdpdConfigurationTest {
-       
-       private static final Logger logger = LoggerFactory.getLogger(PdpdConfigurationTest.class);
-       
-       private static final String REQUEST_ID = UUID.randomUUID().toString();
-       private static final String REQUEST_ID2 = UUID.randomUUID().toString();
-       
-       private static final String ENTITY = "entity1";
-       private static final String ENTITY2 = "entity2";
-       
-       private static final String PROPERTY1 = "property1";
-       private static final String PROPERTY2 = "property2";
-       
-       private static final String VALUE1 = "value1";
-       private static final String VALUE2 = "value2";
-       
-       private static final String ARTIFACT = "org.onap.artifact";
-       private static final String GROUPID = "group";
-       private static final String VERSION = "1.0.0";
-
-       private static final String ARTIFACT2 = "org.onap.artifact2";
-       private static final String GROUPID2 = "group2";
-       private static final String VERSION2 = "1.0.1";
-       
-       private static final String NAME = "name";
-       private static final String OPERATION = "operation";
-
-       private static final String NAME2 = "name2";
-       private static final String OPERATION2 = "operation2";
-
-       @Test
-       public void test() {
-               //
-               // Empty constructor test
-               //
-               DroolsConfiguration drools = new DroolsConfiguration();
-               drools.set("artifactId", ARTIFACT);
-               drools.set("groupId", GROUPID);
-               drools.set("version", VERSION);
-               drools.set(PROPERTY1, VALUE1);
-               
-               assertTrue(drools.equals(drools));
-               assertFalse(drools.equals(new Object()));
-
-               logger.info("Drools HashCode {}", drools.hashCode());
-               
-               //
-               // Constructor with values test get calls
-               //
-               DroolsConfiguration drools2 = new DroolsConfiguration(
-                               drools.get("artifactId"), 
-                               drools.get("groupId"), 
-                               drools.get("version"));
-               
-               //
-               // get Property
-               //
-               
-               drools2.set(PROPERTY1, drools.get(PROPERTY1));
-               
-               assertTrue(drools.equals(drools2));
-               
-               //
-               // with methods
-               //
-               drools2.withArtifactId(ARTIFACT2).withGroupId(GROUPID2).withVersion(VERSION2).withAdditionalProperty(PROPERTY2, VALUE2);
-               
-               assertFalse(drools.equals(drools2));
-               
-               //
-               // Test get additional properties
-               //
-               assertEquals(drools.getAdditionalProperties().size(), 1);
-               
-               //
-               // Test Not found
-               //
-               assertEquals(drools.declaredPropertyOrNotFound(PROPERTY2, DroolsConfiguration.NOT_FOUND_VALUE), DroolsConfiguration.NOT_FOUND_VALUE);
-                               
-               logger.info("drools {}", drools);
-               logger.info("drools2 {}", drools2);
-               
-               //
-               // Test Controller Default Constructor
-               //
-               ControllerConfiguration controller = new ControllerConfiguration();
-               
-               //
-               // Test set
-               //
-
-               controller.set("name", NAME);
-               controller.set("operation", OPERATION);
-               controller.set("drools", drools);
-               controller.set(PROPERTY1, VALUE1);
-               
-               assertTrue(controller.equals(controller));
-               assertFalse(controller.equals(new Object()));
-               
-               logger.info("Controller HashCode {}", controller.hashCode());
-               
-               //
-               // Controller Constructor gets
-               //
-               ControllerConfiguration controller2 = new ControllerConfiguration(
-                               controller.get("name"), 
-                               controller.get("operation"), 
-                               controller.get("drools"));
-               
-               //
-               // Test get property
-               //
-               
-               controller2.set(PROPERTY1, controller.get(PROPERTY1));
-               
-               assertTrue(controller.equals(controller2));
-               
-               //
-               // test with methods
-               //
-               
-               controller2.withDrools(drools2).withName(NAME2).withOperation(OPERATION2).withAdditionalProperty(PROPERTY2, VALUE2);
-               
-               assertFalse(controller.equals(controller2));
-               
-               //
-               // Test additional properties
-               //
-               assertEquals(controller.getAdditionalProperties().size(), 1);
-               
-               //
-               // Not found
-               //
-               assertEquals(controller.declaredPropertyOrNotFound(PROPERTY2, ControllerConfiguration.NOT_FOUND_VALUE), ControllerConfiguration.NOT_FOUND_VALUE);
-               
-               //
-               // toString
-               //
-               logger.info("Controller {}", controller);
-               logger.info("Controller2 {}", controller2);
-               
-               //
-               // PDP Configuration empty constructor
-               //
-               PdpdConfiguration config = new PdpdConfiguration();
-               
-               //
-               // Test set
-               //
-               
-               config.set("requestID", REQUEST_ID);
-               config.set("entity", ENTITY);
-               List<ControllerConfiguration> controllers = new ArrayList<>();
-               controllers.add(controller);
-               config.set("controllers", controllers);
-               config.set(PROPERTY1, VALUE1);
-               
-               assertTrue(config.equals(config));
-               assertFalse(config.equals(new Object()));
-               
-               logger.info("Config HashCode {}", config.hashCode());
-               
-               //
-               // Test constructor with values
-               //
-               
-               PdpdConfiguration config2 = new PdpdConfiguration(
-                               config.get("requestID"),
-                               config.get("entity"),
-                               config.get("controllers"));
-               
-               //
-               // Test set
-               //
-               
-               config2.set(PROPERTY1, config.get(PROPERTY1));
-               
-               assertTrue(config.equals(config2));
-               
-               //
-               // Test with methods
-               //
-               List<ControllerConfiguration> controllers2 = new ArrayList<>();
-               controllers2.add(controller2);
-               config2.withRequestID(REQUEST_ID2).withEntity(ENTITY2).withController(controllers2);
-               
-               assertFalse(config.equals(config2));
-               
-               //
-               // Test additional properties
-               //
-               
-               assertEquals(config.getAdditionalProperties().size(), 1);
-               
-               //
-               // Test NOT FOUND
-               //
-               assertEquals(config.declaredPropertyOrNotFound(PROPERTY2, ControllerConfiguration.NOT_FOUND_VALUE), ControllerConfiguration.NOT_FOUND_VALUE);
-
-               //
-               // toString
-               //
-               logger.info("Config {}", config);
-               logger.info("Config2 {}", config2);
-
-       }
-       
-       @Test
-       public void testConstructor() {
-
-               PdpdConfiguration config = new PdpdConfiguration(REQUEST_ID, ENTITY, null);
-               assertEquals(config.getRequestID(), REQUEST_ID);
-               assertEquals(config.getEntity(), ENTITY);
-               
-       }
+
+    private static final Logger logger = LoggerFactory.getLogger(PdpdConfigurationTest.class);
+
+    private static final String REQUEST_ID = UUID.randomUUID().toString();
+    private static final String REQUEST_ID2 = UUID.randomUUID().toString();
+
+    private static final String ENTITY = "entity1";
+    private static final String ENTITY2 = "entity2";
+
+    private static final String PROPERTY1 = "property1";
+    private static final String PROPERTY2 = "property2";
+
+    private static final String VALUE1 = "value1";
+    private static final String VALUE2 = "value2";
+
+    private static final String ARTIFACT = "org.onap.artifact";
+    private static final String GROUPID = "group";
+    private static final String VERSION = "1.0.0";
+
+    private static final String ARTIFACT2 = "org.onap.artifact2";
+    private static final String GROUPID2 = "group2";
+    private static final String VERSION2 = "1.0.1";
+
+    private static final String NAME = "name";
+    private static final String OPERATION = "operation";
+
+    private static final String NAME2 = "name2";
+    private static final String OPERATION2 = "operation2";
+
+    @Test
+    public void test() {
+        //
+        // Empty constructor test
+        //
+        DroolsConfiguration drools = new DroolsConfiguration();
+        drools.set("artifactId", ARTIFACT);
+        drools.set("groupId", GROUPID);
+        drools.set("version", VERSION);
+        drools.set(PROPERTY1, VALUE1);
+
+        assertTrue(drools.equals(drools));
+        assertFalse(drools.equals(new Object()));
+
+        logger.info("Drools HashCode {}", drools.hashCode());
+
+        //
+        // Constructor with values test get calls
+        //
+        DroolsConfiguration drools2 = new DroolsConfiguration(
+                drools.get("artifactId"), 
+                drools.get("groupId"), 
+                drools.get("version"));
+
+        //
+        // get Property
+        //
+
+        drools2.set(PROPERTY1, drools.get(PROPERTY1));
+
+        assertTrue(drools.equals(drools2));
+
+        //
+        // with methods
+        //
+        drools2.withArtifactId(ARTIFACT2).withGroupId(GROUPID2).withVersion(VERSION2)
+            .withAdditionalProperty(PROPERTY2, VALUE2);
+
+        assertFalse(drools.equals(drools2));
+
+        //
+        // Test get additional properties
+        //
+        assertEquals(drools.getAdditionalProperties().size(), 1);
+
+        //
+        // Test Not found
+        //
+        assertEquals(DroolsConfiguration.NOT_FOUND_VALUE,
+                drools.declaredPropertyOrNotFound(PROPERTY2, DroolsConfiguration.NOT_FOUND_VALUE));
+
+        logger.info("drools {}", drools);
+        logger.info("drools2 {}", drools2);
+
+        //
+        // Test Controller Default Constructor
+        //
+        ControllerConfiguration controller = new ControllerConfiguration();
+
+        //
+        // Test set
+        //
+
+        controller.set("name", NAME);
+        controller.set("operation", OPERATION);
+        controller.set("drools", drools);
+        controller.set(PROPERTY1, VALUE1);
+
+        assertTrue(controller.equals(controller));
+        assertFalse(controller.equals(new Object()));
+
+        logger.info("Controller HashCode {}", controller.hashCode());
+
+        //
+        // Controller Constructor gets
+        //
+        ControllerConfiguration controller2 = new ControllerConfiguration(
+                controller.get("name"), 
+                controller.get("operation"), 
+                controller.get("drools"));
+
+        //
+        // Test get property
+        //
+
+        controller2.set(PROPERTY1, controller.get(PROPERTY1));
+
+        assertTrue(controller.equals(controller2));
+
+        //
+        // test with methods
+        //
+
+        controller2.withDrools(drools2).withName(NAME2)
+            .withOperation(OPERATION2).withAdditionalProperty(PROPERTY2, VALUE2);
+
+        assertFalse(controller.equals(controller2));
+
+        //
+        // Test additional properties
+        //
+        assertEquals(controller.getAdditionalProperties().size(), 1);
+
+        //
+        // Not found
+        //
+        assertEquals(ControllerConfiguration.NOT_FOUND_VALUE,
+                controller.declaredPropertyOrNotFound(PROPERTY2, ControllerConfiguration.NOT_FOUND_VALUE));
+
+        //
+        // toString
+        //
+        logger.info("Controller {}", controller);
+        logger.info("Controller2 {}", controller2);
+
+        //
+        // PDP Configuration empty constructor
+        //
+        PdpdConfiguration config = new PdpdConfiguration();
+
+        //
+        // Test set
+        //
+
+        config.set("requestID", REQUEST_ID);
+        config.set("entity", ENTITY);
+        List<ControllerConfiguration> controllers = new ArrayList<>();
+        controllers.add(controller);
+        config.set("controllers", controllers);
+        config.set(PROPERTY1, VALUE1);
+
+        assertTrue(config.equals(config));
+        assertFalse(config.equals(new Object()));
+
+        logger.info("Config HashCode {}", config.hashCode());
+
+        //
+        // Test constructor with values
+        //
+
+        PdpdConfiguration config2 = new PdpdConfiguration(
+                config.get("requestID"),
+                config.get("entity"),
+                config.get("controllers"));
+
+        //
+        // Test set
+        //
+
+        config2.set(PROPERTY1, config.get(PROPERTY1));
+
+        assertTrue(config.equals(config2));
+
+        //
+        // Test with methods
+        //
+        List<ControllerConfiguration> controllers2 = new ArrayList<>();
+        controllers2.add(controller2);
+        config2.withRequestID(REQUEST_ID2).withEntity(ENTITY2).withController(controllers2);
+
+        assertFalse(config.equals(config2));
+
+        //
+        // Test additional properties
+        //
+
+        assertEquals(config.getAdditionalProperties().size(), 1);
+
+        //
+        // Test NOT FOUND
+        //
+        assertEquals(ControllerConfiguration.NOT_FOUND_VALUE,
+                config.declaredPropertyOrNotFound(PROPERTY2, ControllerConfiguration.NOT_FOUND_VALUE));
+
+        //
+        // toString
+        //
+        logger.info("Config {}", config);
+        logger.info("Config2 {}", config2);
+
+    }
+
+    @Test
+    public void testConstructor() {
+        PdpdConfiguration config = new PdpdConfiguration(REQUEST_ID, ENTITY, null);
+        assertEquals(config.getRequestID(), REQUEST_ID);
+        assertEquals(config.getEntity(), ENTITY);
+    }
 
 }
index e96a4b9..68a52ad 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * policy-management
  * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2018 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.
@@ -94,6 +94,11 @@ public class RestManagerTest {
 
     private static final Logger logger = LoggerFactory.getLogger(RestManagerTest.class);
 
+    /**
+     * Set up.
+     * 
+     * @throws IOException throws an IO exception
+     */
     @BeforeClass
     public static void setUp() throws IOException {
         cleanUpWorkingDirs();
@@ -133,6 +138,12 @@ public class RestManagerTest {
 
     }
 
+    /**
+     * Tear down.
+     * 
+     * @throws IOException IO exception
+     * @throws InterruptedException Interrupted exception
+     */
     @AfterClass
     public static void tearDown() throws IOException, InterruptedException {
         /* Shutdown managed resources */
@@ -147,7 +158,6 @@ public class RestManagerTest {
 
     @Test
     public void putDeleteTest() throws ClientProtocolException, IOException, InterruptedException {
-        HttpPut httpPut;
         HttpDelete httpDelete;
         CloseableHttpResponse response;
 
@@ -172,7 +182,7 @@ public class RestManagerTest {
          * PUT: /engine/switches/lock /engine/controllers/controllername/switches/lock DELETE:
          * /engine/switches/lock /engine/controllers/controllername
          */
-        httpPut = new HttpPut(HOST_URL + "/engine/switches/lock");
+        HttpPut httpPut = new HttpPut(HOST_URL + "/engine/switches/lock");
         response = client.execute(httpPut);
         logger.info(httpPut.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode());
         assertEquals(406, response.getStatusLine().getStatusCode());
@@ -351,7 +361,6 @@ public class RestManagerTest {
     public void getTest() throws ClientProtocolException, IOException, InterruptedException {
         HttpGet httpGet;
         CloseableHttpResponse response;
-        String responseBody;
 
         /*
          * GET: /engine /engine/features /engine/features/inventory /engine/features/featurename
@@ -403,7 +412,7 @@ public class RestManagerTest {
         PolicyEngine.manager.setEnvironmentProperty("foo", "bar");
         httpGet = new HttpGet(HOST_URL + "/engine/environment/foo");
         response = client.execute(httpGet);
-        responseBody = this.getResponseBody(response);
+        String responseBody = this.getResponseBody(response);
         logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode());
         logger.info(httpGet.getRequestLine() + " response body: {}", responseBody);
         assertEquals(200, response.getStatusLine().getStatusCode());
@@ -839,7 +848,12 @@ public class RestManagerTest {
 
     }
 
-
+    /**
+     * Get response body.
+     * 
+     * @param response incoming response
+     * @return the body or null
+     */
     public String getResponseBody(CloseableHttpResponse response) {
 
         HttpEntity entity;
@@ -848,7 +862,7 @@ public class RestManagerTest {
             return EntityUtils.toString(entity);
 
         } catch (final IOException e) {
-
+            logger.info(e.toString());
         }
 
         return null;
index c6a4ffb..7b02d75 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * policy-management
  * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2018 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,58 +49,58 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * PolicyEngine unit tests
+ * PolicyEngine unit tests.
  */
 
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class PolicyEngineTest {
     /**
-     * Default Telemetry port for JUnits
+     * Default Telemetry port for JUnits.
      */
     public static final int DEFAULT_TELEMETRY_PORT = 9698;
 
     /**
-     * Test JUnit Controller Name
+     * Test JUnit Controller Name.
      */
     public static final String TEST_CONTROLLER_NAME = "foo";
 
     /**
-     * Controller Configuration File
+     * Controller Configuration File.
      */
     public static final String TEST_CONTROLLER_FILE = TEST_CONTROLLER_NAME + "-controller.properties";
 
     /**
-     * Controller Configuration Backup File
+     * Controller Configuration Backup File.
      */
     public static final String TEST_CONTROLLER_FILE_BAK = TEST_CONTROLLER_FILE + ".bak";
 
     /**
-     * Coder Group
+     * Coder Group.
      */
     private static final String ENCODER_GROUP = "foo";
 
     /**
-     * Coder Artifact
+     * Coder Artifact.
      */
     private static final String ENCODER_ARTIFACT = "bar";
 
     /**
-     * Coder Version
+     * Coder Version.
      */
     private static final String ENCODER_VERSION = null;
 
     /**
-     * noop topic
+     * noop topic.
      */
     private static final String NOOP_TOPIC = "JUNIT";
 
     /**
-     * logger
+     * logger.
      */
     private static Logger logger = LoggerFactory.getLogger(PolicyEngineTest.class);
 
     /**
-     * clean up working directory
+     * clean up working directory.
      */
     protected static void cleanUpWorkingDir() {
         final Path testControllerPath =
@@ -120,6 +120,11 @@ public class PolicyEngineTest {
         }
     }
 
+    /**
+     * Start up.
+     * 
+     * @throws IOException throws IO exception
+     */
     @BeforeClass
     public static void startUp() throws IOException {
         logger.info("enter");