diff options
Diffstat (limited to 'policy-management/src/main/java/org/openecomp/policy/drools/protocol')
7 files changed, 3573 insertions, 0 deletions
diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/EventProtocolCoder.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/EventProtocolCoder.java new file mode 100644 index 00000000..8f8a4ba7 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/EventProtocolCoder.java @@ -0,0 +1,1451 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.protocol.coders; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.openecomp.policy.common.logging.eelf.MessageCodes; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.controller.DroolsController; +import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; +import org.openecomp.policy.drools.utils.Pair; + +/** + * Coder (Encoder/Decoder) of Events. + */ +public interface EventProtocolCoder { + + 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 synchronized JsonProtocolFilter getFilter() { + return filter; + } + + /** + * @param filter the filter to set + */ + public synchronized 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) + throws IllegalArgumentException; + + /** + * 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) throws IllegalArgumentException; + + /** + * 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) throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + + /** + * 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) throws IllegalArgumentException; + + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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) throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException; + + /** + * 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) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException; + + /** + * 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) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException; + + /** + * 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) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException; + + /** + * 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) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException; + + /** + * singleton reference to the global event protocol coder + */ + public static EventProtocolCoder manager = new MultiplexorEventProtocolCoder(); +} + +/** + * Protocol Coder that does its best attempt to decode/encode, selecting the best + * class and best fitted json parsing tools. + */ +class MultiplexorEventProtocolCoder implements EventProtocolCoder { + // get an instance of logger + private static Logger logger = FlexLogger.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) + throws IllegalArgumentException { + logger.info("ADD-DECODER: " + groupId + ":" + artifactId + ":" + + topic + ":" + eventClass + ":" + + protocolFilter + ":" + customGsonCoder + + ":" + customJacksonCoder + ":" + modelClassLoaderHash + + " INTO " + this); + 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) + throws IllegalArgumentException { + logger.info("ADD-ENCODER: " + groupId + ":" + artifactId + ":" + + topic + ":" + eventClass + ":" + + protocolFilter + ":" + customGsonCoder + + ":" + customJacksonCoder + ":" + modelClassLoaderHash + + " INTO " + this); + this.encoders.add(groupId, artifactId, topic, eventClass, protocolFilter, + customGsonCoder, customJacksonCoder, modelClassLoaderHash); + } + + /** + * {@inheritDoc} + */ + @Override + public void removeDecoders(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + logger.info("REMOVE-DECODER: " + groupId + ":" + artifactId + ":" + + topic + " FROM " + this); + this.decoders.remove(groupId, artifactId, topic); + } + + /** + * {@inheritDoc} + */ + @Override + public void removeEncoders(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + logger.info("REMOVE-ENCODER: " + groupId + ":" + artifactId + ":" + + topic + " FROM " + this); + 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) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { + logger.info("DECODE: " + groupId + ":" + artifactId + ":" + + topic + ":" + json + " WITH " + this); + return this.decoders.decode(groupId, artifactId, topic, json); + } + + /** + * {@inheritDoc} + */ + @Override + public String encode(String groupId, String artifactId, String topic, Object event) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { + logger.info("ENCODE: " + groupId + ":" + artifactId + ":" + + topic + ":" + event + " WITH " + this); + return this.encoders.encode(groupId, artifactId, topic, event); + } + + /** + * {@inheritDoc} + */ + @Override + public String encode(String topic, Object event) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { + logger.info("ENCODE: " + topic + ":" + event + " WITH " + this); + return this.encoders.encode(topic, event); + } + + /** + * {@inheritDoc} + */ + @Override + public String encode(String topic, Object event, DroolsController droolsController) + throws IllegalArgumentException, IllegalStateException, UnsupportedOperationException { + logger.info("ENCODE: " + topic + ":" + event + ":" + droolsController + " WITH " + this); + return this.encoders.encode(topic, event, droolsController); + } + + /** + * {@inheritDoc} + */ + @Override + public List<CoderFilters> getDecoderFilters(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + + return this.decoders.getFilters(groupId, artifactId, topic); + } + + /** + * {@inheritDoc} + */ + @Override + public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic) + throws IllegalArgumentException { + + 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) + throws IllegalArgumentException { + + return this.encoders.getFilters(groupId, artifactId, topic); + } + + /** + * {@inheritDoc} + */ + @Override + public CoderFilters getDecoderFilters(String groupId, String artifactId, String topic, String classname) + throws IllegalArgumentException { + + return this.decoders.getFilters(groupId, artifactId, topic, classname); + } + + /** + * {@inheritDoc} + */ + @Override + public CoderFilters getEncoderFilters(String groupId, String artifactId, String topic, String classname) + throws IllegalArgumentException { + + return this.encoders.getFilters(groupId, artifactId, topic, classname); + } + + /** + * {@inheritDoc} + */ + @Override + public List<CoderFilters> getReverseEncoderFilters(String topic, String encodedClass) throws IllegalArgumentException { + 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) + throws IllegalArgumentException { + + 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) throws IllegalArgumentException { + return this.decoders.getFilters(groupId, artifactId); + + } + + /** + * {@inheritDoc} + */ + @Override + public List<CoderFilters> getEncoderFilters(String groupId, String artifactId) throws IllegalArgumentException { + return this.encoders.getFilters(groupId, artifactId); + } + + /** + * {@inheritDoc} + */ + @Override + public DroolsController getDroolsController(String topic, Object encodedClass) throws IllegalArgumentException { + return this.encoders.getDroolsController(topic, encodedClass); + } + + /** + * {@inheritDoc} + */ + @Override + public List<DroolsController> getDroolsControllers(String topic, Object encodedClass) throws IllegalArgumentException { + 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(); + } +} + +/** + * This protocol Coder that does its best attempt to decode/encode, selecting the best + * class and best fitted json parsing tools. + */ +abstract class GenericEventProtocolCoder { + private static Logger logger = FlexLogger.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<String, Pair<ProtocolCoderToolset,ProtocolCoderToolset>>(); + + /** + * Mapping topic + classname -> Protocol Set + */ + protected final HashMap<String, List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>> reverseCoders = + new HashMap<String, List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>>(); + + 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) + throws IllegalArgumentException { + if (groupId == null || groupId.isEmpty()) { + throw new IllegalArgumentException("Invalid group id"); + } + + if (artifactId == null || artifactId.isEmpty()) { + throw new IllegalArgumentException("Invalid artifact id"); + } + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Invalid Topic"); + } + + 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); + + if (logger.isInfoEnabled()) + logger.info("ADDING CODER TO EXISTING: " + toolsets + " for " + key); + + toolsets.first().addCoder(eventClass, protocolFilter, modelClassLoaderHash); + toolsets.second().addCoder(eventClass, protocolFilter, modelClassLoaderHash); + + if (!reverseCoders.containsKey(reverseKey)) { + if (logger.isInfoEnabled()) + logger.info("Multiple coder classes case: " + toolsets.first() + + " for " + reverseKey + " - " + key); + + List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> reverseMappings = + new ArrayList<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>(); + 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<ProtocolCoderToolset,ProtocolCoderToolset>(gsonCoderTools, + jacksonCoderTools); + + logger.info("ADDED TOOLSET: " + key + " : " + + coderTools + ":" + this); + + 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: " + parserSet.first() + + " for " + reverseKey + " - " + key); + } + } + + if (present) { + return; + } else { + logger.info("ADDING TOOLSET REVERSE MAPPING: " + reverseKey + " : " + + toolsets + ":" + coderTools + ":" + this); + toolsets.add(coderTools); + } + } else { + List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> toolsets = + new ArrayList<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>(); + logger.info("ADDING TOOLSET REVERSE MAPPING: " + reverseKey + " : " + + toolsets + ":" + coderTools + ":" + this); + toolsets.add(coderTools); + 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) + throws IllegalArgumentException { + + if (groupId == null || groupId.isEmpty()) { + throw new IllegalArgumentException("Invalid group id"); + } + + if (artifactId == null || artifactId.isEmpty()) { + throw new IllegalArgumentException("Invalid artifact id"); + } + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Invalid Topic"); + } + + String key = this.codersKey(groupId, artifactId, topic); + + synchronized(this) { + if (coders.containsKey(key)) { + Pair<ProtocolCoderToolset, ProtocolCoderToolset> p = coders.remove(key); + logger.info("REMOVED TOOLSET: " + key + " : " + p + " FROM " + + coders + " : " + this); + + 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 REVERSE MAPPING of TOOLSET: " + reverseKey + " : " + toolset + " FROM " + + reverseCoders); + toolsetsIter.remove(); + } + } + + if (this.reverseCoders.get(reverseKey).isEmpty()) { + logger.info("REMOVE FULL REVERSE MAPPING of TOOLSET: " + reverseKey + " FROM " + + reverseCoders); + 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"); + } + + if (artifactId == null || artifactId.isEmpty()) { + throw new IllegalArgumentException("Invalid artifact id"); + } + + if (topic == null || topic.isEmpty()) + return false; + + 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) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { + + 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) { + // TODO Auto-generated catch block + logger.warn("Can't decode @ " + this); + } + + 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 e2) { + // TODO Auto-generated catch block + e2.printStackTrace(); + throw new UnsupportedOperationException(e2); + } + } + + 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) + throws IllegalArgumentException, UnsupportedOperationException { + + 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) + throws IllegalArgumentException, UnsupportedOperationException { + + logger.debug("ENCODE: " + key + ":" + event + this); + + 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.error(MessageCodes.EXCEPTION_ERROR, e, "FIRST-ENCODE-INTERNAL: " + + key + ":" + event, this.toString()); + } + + 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 e2) { + // TODO Auto-generated catch block + logger.error(MessageCodes.EXCEPTION_ERROR, e2, "SECOND-ENCODE-INTERNAL: " + + key + ":" + event, this.toString()); + throw new UnsupportedOperationException(e2); + } + } + + 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) + throws IllegalArgumentException, IllegalArgumentException, UnsupportedOperationException { + + if (encodedClass == null) { + throw new IllegalArgumentException("Invalid encoded class"); + } + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Invalid topic"); + } + + logger.info("ENCODE: " + topic + ":" + + encodedClass.getClass().getCanonicalName() + ":" + + encodedClass); + + List<DroolsController> droolsControllers = droolsCreators(topic, encodedClass); + if (droolsControllers.size() > 1) { + // unexpected + logger.warn("MULTIPLE DROOLS CONTROLLERS FOUND for: " + topic + ":" + + encodedClass.getClass().getCanonicalName() + ":" + + droolsControllers + " IN " + this); + // continue + } + + String key = codersKey(droolsControllers.get(0).getGroupId(), droolsControllers.get(0).getArtifactId(), topic); + return this.encodeInternal(key, encodedClass); + } + + /** + * 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) + throws IllegalArgumentException, IllegalArgumentException, UnsupportedOperationException { + + if (encodedClass == null) { + throw new IllegalArgumentException("Invalid encoded class"); + } + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Invalid topic"); + } + + logger.info("ENCODE: " + topic + ":" + + encodedClass.getClass().getCanonicalName() + ":" + + encodedClass + ":" + droolsController); + + 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) + throws IllegalStateException, IllegalArgumentException { + + List<DroolsController> droolsControllers = new ArrayList<DroolsController>(); + + String reverseKey = this.reverseCodersKey(topic, encodedClass.getClass().getCanonicalName()); + if (!this.reverseCoders.containsKey(reverseKey)) { + logger.warn("NO MAPPING for REVERSE KEY: " + topic + ":" + + encodedClass.getClass().getCanonicalName() + ":" + + encodedClass + ":" + reverseKey + " : " + this); + 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()) { + logger.warn("ENCODE: " + topic + ":" + + encodedClass.getClass().getCanonicalName() + ":" + + encodedClass + " ENCODER NOT FOUND"); + 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> coders = encoderSet.first().getCoders(); + for (CoderFilters coder : coders) { + 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 "+ topic + + " : encoder " + 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) + throws IllegalArgumentException { + + 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) + throws IllegalArgumentException { + + 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; + } + + /** + * 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) + throws IllegalArgumentException { + + if (groupId == null || groupId.isEmpty()) { + throw new IllegalArgumentException("Invalid group id"); + } + + if (artifactId == null || artifactId.isEmpty()) { + throw new IllegalArgumentException("Invalid artifact id"); + } + + String key = this.codersKey(groupId, artifactId, ""); + + List<CoderFilters> codersFilters = new ArrayList<CoderFilters>(); + 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) + throws IllegalArgumentException { + + if (groupId == null || groupId.isEmpty()) { + throw new IllegalArgumentException("Invalid group id"); + } + + if (artifactId == null || artifactId.isEmpty()) { + throw new IllegalArgumentException("Invalid artifact id"); + } + + String key = this.codersKey(groupId, artifactId, ""); + + List<Pair<ProtocolCoderToolset,ProtocolCoderToolset>> coderToolset = new ArrayList<Pair<ProtocolCoderToolset,ProtocolCoderToolset>>(); + 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) + throws IllegalArgumentException { + + 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) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Unsupported"); + } + + if (codedClass == null) { + throw new IllegalArgumentException("class must be provided"); + } + + 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> coders = new ArrayList<CoderFilters>(); + for (Pair<ProtocolCoderToolset,ProtocolCoderToolset> toolset: toolsets) { + coders.addAll(toolset.first().getCoders()); + } + + return coders; + } + + /** + * returns group and artifact id of the creator of the encoder + * + * @param topic + * @param fact + * @return + * @throws IllegalArgumentException + */ + DroolsController getDroolsController(String topic, Object fact) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Unsupported"); + } + + if (fact == null) { + throw new IllegalArgumentException("class must be provided"); + } + + List<DroolsController> droolsControllers = droolsCreators(topic, fact); + if (droolsControllers.size() > 1) { + // unexpected + logger.warn("MULTIPLE DROOLS CONTROLLERS FOUND for: " + topic + ":" + + fact.getClass().getCanonicalName() + ":" + + droolsControllers + " IN " + this); + // 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) + throws IllegalArgumentException { + + if (topic == null || topic.isEmpty()) { + throw new IllegalArgumentException("Unsupported"); + } + + if (fact == null) { + throw new IllegalArgumentException("class must be provided"); + } + + List<DroolsController> droolsControllers = droolsCreators(topic, fact); + if (droolsControllers.size() > 1) { + // unexpected + logger.warn("MULTIPLE DROOLS CONTROLLERS FOUND for: " + topic + ":" + + fact.getClass().getCanonicalName() + ":" + + droolsControllers + " IN " + this); + // 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(); + } + +} + +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(); + } +}
\ No newline at end of file diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/JsonProtocolFilter.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/JsonProtocolFilter.java new file mode 100644 index 00000000..a2ce3123 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/JsonProtocolFilter.java @@ -0,0 +1,304 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.protocol.coders; + +import java.util.ArrayList; +import java.util.List; + +import org.openecomp.policy.drools.utils.Pair; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +/** + * JSON Protocol Filter. Evaluates an JSON string and evaluates if it + * passes its filters. + */ +public class JsonProtocolFilter { + + /** + * Helper class to collect Filter information + */ + public static class FilterRule { + /** + * Field name + */ + protected String name; + + /** + * Field Value regex + */ + protected String regex; + + /** + * Filter Constructor + * + * @param name field name + * @param regex field regex value + */ + public FilterRule(String name, String regex) { + this.name = name; + this.regex = 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) { + this.name = name; + } + + /** + * sets regex name + * @param regex + */ + public void setRegex(String 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 ArrayList<FilterRule>(); + + /** + * + * @param rawFilters raw filter initialization + * + * @throws IllegalArgumentException an invalid input has been provided + */ + public static JsonProtocolFilter fromRawFilters(List<Pair<String, String>> rawFilters) + throws IllegalArgumentException { + + if (rawFilters == null) { + throw new IllegalArgumentException("No raw filters provided"); + } + + List<FilterRule> filters = new ArrayList<FilterRule>(); + for (Pair<String, String> filterPair: rawFilters) { + if (filterPair.first() == null || filterPair.first().isEmpty()) { + // TODO: warn + continue; + } + + filters.add(new FilterRule(filterPair.first(), filterPair.second())); + } + return new JsonProtocolFilter(filters); + } + + /** + * Create a Protocol Filter + * + * @throws IllegalArgumentException an invalid input has been provided + */ + public JsonProtocolFilter() throws IllegalArgumentException {} + + /** + * + * @param rawFilters raw filter initialization + * + * @throws IllegalArgumentException an invalid input has been provided + */ + public JsonProtocolFilter(List<FilterRule> filters) throws IllegalArgumentException { + this.rules = 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 synchronized boolean accept(JsonElement json) throws IllegalArgumentException { + if (json == null) { + throw new IllegalArgumentException("no JSON provided"); + } + + if (rules.isEmpty()) { + return true; + } + + try { + if (json == null || !json.isJsonObject()) { + return false; + } + + JsonObject event = json.getAsJsonObject(); + for (FilterRule filter: rules) { + if (filter.regex == null || + filter.regex.isEmpty() || + filter.regex.equals(".*")) { + + // Only check for presence + if (!event.has(filter.name)) { + return false; + } + } else { + JsonElement field = event.get(filter.name); + if (field == null) { + return false; + } + + String fieldValue = field.getAsString(); + if (!fieldValue.matches(filter.regex)) { + return false; + } + } + } + return true; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + 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 synchronized boolean accept(String json) throws IllegalArgumentException { + 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) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new IllegalArgumentException(e); + } + } + + public List<FilterRule> getRules() { + return rules; + } + + public synchronized void setRules(List<FilterRule> rulesFilters) { + this.rules = rulesFilters; + } + + public synchronized void deleteRules(String name) { + for (FilterRule rule : new ArrayList<>(this.rules)) { + if (rule.name.equals(name)) { + this.rules.remove(rule); + } + } + } + + public List<FilterRule> getRules(String name) { + ArrayList<FilterRule> temp = new ArrayList<>(); + for (FilterRule rule : new ArrayList<>(this.rules)) { + if (rule.name.equals(name)) { + temp.add(rule); + } + } + return temp; + } + + public synchronized void deleteRule(String name, String regex) { + for (FilterRule rule : new ArrayList<>(this.rules)) { + if (rule.name.equals(name) && rule.regex.equals(regex)) { + this.rules.remove(rule); + } + } + } + + public synchronized void addRule(String name, String regex) { + for (FilterRule rule : new ArrayList<>(this.rules)) { + if (rule.name.equals(name) && rule.regex.equals(regex)) { + return; + } + } + + this.rules.add(new FilterRule(name,regex)); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("JsonProtocolFilter [rules=").append(rules).append("]"); + return builder.toString(); + } + +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/ProtocolCoderToolset.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/ProtocolCoderToolset.java new file mode 100644 index 00000000..9e079ff5 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/ProtocolCoderToolset.java @@ -0,0 +1,668 @@ +package org.openecomp.policy.drools.protocol.coders; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.openecomp.policy.common.logging.eelf.MessageCodes; +import org.openecomp.policy.common.logging.flexlogger.FlexLogger; +import org.openecomp.policy.common.logging.flexlogger.Logger; +import org.openecomp.policy.drools.controller.DroolsController; +import org.openecomp.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomCoder; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; +import org.openecomp.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomJacksonCoder; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +/** + * Protocol Coding/Decoding Toolset + */ +public abstract class ProtocolCoderToolset { + + /** + * topic + */ + protected final String topic; + + /** + * controller id + */ + protected final String controllerId; + + /** + * group id + */ + protected final String groupId; + + /** + * artifact id + */ + protected final String artifactId; + + /** + * Protocols and associated Filters + */ + protected final List<CoderFilters> coders = new ArrayList<CoderFilters>(); + + /** + * Tree model (instead of class model) generic parsing to be able to inspect elements + */ + protected JsonParser filteringParser = new JsonParser(); + + /** + * custom coder + */ + protected CustomCoder customCoder; + + /** + * Constructor + * + * @param topic the topic + * @param controllerId the controller id + * @param codedClass the decoded class + * @param filters list of filters that apply to the + * selection of this decodedClass in case of multiplicity + * @throws IllegalArgumentException if invalid data has been passed in + */ + public ProtocolCoderToolset(String topic, + String controllerId, + String groupId, + String artifactId, + String codedClass, + JsonProtocolFilter filters, + CustomCoder customCoder, + int modelClassLoaderHash) + throws IllegalArgumentException { + + if (topic == null || controllerId == null || + groupId == null || artifactId == null || + codedClass == null || filters == null || + topic.isEmpty() || controllerId.isEmpty()) { + // TODO + throw new IllegalArgumentException("Invalid input"); + } + + this.topic = topic; + this.controllerId = controllerId; + this.groupId = groupId; + this.artifactId = artifactId; + this.coders.add(new CoderFilters(codedClass, filters, modelClassLoaderHash)); + this.customCoder = customCoder; + } + + /** + * gets the coder + filters associated with this class name + * + * @param classname class name + * @return the decoder filters or null if not found + */ + public CoderFilters getCoder(String classname) { + for (CoderFilters decoder: this.coders) { + if (decoder.factClass.equals(classname)) { + return decoder; + } + } + return null; + } + + /** + * get all coder filters in use + * + * @return coder filters + */ + public List<CoderFilters> getCoders() { + return this.coders; + } + + /** + * add coder or replace it exists + * + * @param eventClass decoder + * @param filter filter + */ + public void addCoder(String eventClass, JsonProtocolFilter filter, int modelClassLoaderHash) { + synchronized(this) { + for (CoderFilters coder: this.coders) { + if (coder.factClass.equals(eventClass)) { + // this is a better check than checking pointers, just + // in case classloader is different and this is just an update + coder.factClass = eventClass; + coder.filter = filter; + coder.modelClassLoaderHash = modelClassLoaderHash; + return; + } + } + } + + this.coders.add(new CoderFilters(eventClass, filter, modelClassLoaderHash)); + } + + /** + * remove coder + * + * @param eventClass decoder + * @param filter filter + */ + public void removeCoders(String eventClass) { + synchronized(this) { + Iterator<CoderFilters> codersIt = this.coders.iterator(); + while (codersIt.hasNext()) { + CoderFilters coder = codersIt.next(); + if (coder.factClass.equals(eventClass)) { + codersIt.remove(); + } + } + } + } + + /** + * gets the topic + * + * @return the topic + */ + public String getTopic() {return topic;} + + /** + * gets the controller id + * + * @return the controller id + */ + public String getControllerId() {return controllerId;} + + /** + * @return the groupId + */ + public String getGroupId() { + return groupId; + } + + /** + * @return the artifactId + */ + public String getArtifactId() { + return artifactId; + } + + /** + * @return the customCoder + */ + public CustomCoder getCustomCoder() { + return customCoder; + } + + /** + * @param customCoder the customCoder to set + */ + public void setCustomCoder(CustomCoder customCoder) { + this.customCoder = customCoder; + } + + /** + * performs filtering on a json string + * + * @param json json string + * @return the decoder that passes the filter, otherwise null + * @throws UnsupportedOperationException can't filter + * @throws IllegalArgumentException invalid input + */ + protected CoderFilters filter(String json) + throws UnsupportedOperationException, IllegalArgumentException, IllegalStateException { + + + // 1. Get list of decoding classes for this controller Id and topic + // 2. If there are no classes, return error + // 3. Otherwise, from the available classes for decoding, pick the first one that + // passes the filters + + // Don't parse if it is not necessary + + if (this.coders.isEmpty()) { + // TODO this is an error + throw new IllegalStateException("No coders available"); + } + + if (this.coders.size() == 1) { + JsonProtocolFilter filter = this.coders.get(0).getFilter(); + if (!filter.isRules()) { + return this.coders.get(0); + } + } + + JsonElement event; + try { + event = this.filteringParser.parse(json); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new UnsupportedOperationException(e); + } + + for (CoderFilters decoder: this.coders) { + try { + boolean accepted = decoder.getFilter().accept(event); + if (accepted) { + return decoder; + } + } catch (Exception e) { + // TODO: handle exception + e.printStackTrace(); + } + } + + return null; + } + + /** + * Decode json into a POJO object + * @param json json string + * + * @return a POJO object for the json string + * @throws IllegalArgumentException if an invalid parameter has been received + * @throws UnsupportedOperationException if parsing into POJO is not possible + */ + public abstract Object decode(String json) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException; + + /** + * Encodes a POJO object into a JSON String + * + * @param event JSON POJO event to be converted to String + * @return JSON string version of POJO object + * @throws IllegalArgumentException if an invalid parameter has been received + * @throws UnsupportedOperationException if parsing into POJO is not possible + */ + public abstract String encode(Object event) + throws IllegalArgumentException, UnsupportedOperationException; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("ProtocolCoderToolset [topic=").append(topic).append(", controllerId=").append(controllerId) + .append(", groupId=").append(groupId).append(", artifactId=").append(artifactId).append(", coders=") + .append(coders).append(", filteringParser=").append(filteringParser).append(", customCoder=") + .append(customCoder).append("]"); + return builder.toString(); + } +} + +/** + * Tools used for encoding/decoding using Jackson + */ +class JacksonProtocolCoderToolset extends ProtocolCoderToolset { + private static Logger logger = FlexLogger.getLogger(JacksonProtocolCoderToolset.class); + /** + * decoder + */ + @JsonIgnore + protected final ObjectMapper decoder = new ObjectMapper(); + + /** + * encoder + */ + @JsonIgnore + protected final ObjectMapper encoder = new ObjectMapper(); + + /** + * Toolset to encode/decode tools associated with a topic + * + * @param topic topic + * @param decodedClass decoded class of an event + * @param filter + */ + public JacksonProtocolCoderToolset(String topic, String controllerId, + String groupId, String artifactId, + String decodedClass, + JsonProtocolFilter filter, + CustomJacksonCoder customJacksonCoder, + int modelClassLoaderHash) { + super(topic, controllerId, groupId, artifactId, decodedClass, filter, customJacksonCoder, modelClassLoaderHash); + decoder.registerModule(new JavaTimeModule()); + decoder.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, + false); + } + + /** + * gets the Jackson decoder + * + * @return the Jackson decoder + */ + @JsonIgnore + protected ObjectMapper getDecoder() {return decoder;} + + /** + * gets the Jackson encoder + * + * @return the Jackson encoder + */ + @JsonIgnore + protected ObjectMapper getEncoder() {return encoder;} + + /** + * {@inheritDoc} + */ + @Override + public Object decode(String json) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { + + // 0. Use custom coder if available + + if (this.customCoder != null) { + throw new UnsupportedOperationException + ("Jackon Custom Decoder is not supported at this time"); + } + + DroolsController droolsController = + DroolsController.factory.get(groupId, artifactId, ""); + if (droolsController == null) { + String error = "NO-DROOLS-CONTROLLER for: " + json + " IN " + this; + logger.warn(error); + throw new IllegalStateException(error); + } + + CoderFilters decoderFilter = filter(json); + if (decoderFilter == null) { + String error = "NO-DECODER for: " + json + " IN " + this; + logger.warn(error); + throw new UnsupportedOperationException(error); + } + + Class<?> decoderClass; + try { + decoderClass = + droolsController.fetchModelClass(decoderFilter.getCodedClass()); + if (decoderClass == null) { + String error = "DECODE-ERROR FETCHING MODEL CLASS: " + ":" + json + ":" + this; + logger.error(error); + throw new IllegalStateException(error); + } + } catch (Exception e) { + String error = "DECODE-ERROR FETCHING MODEL CLASS: "+ e.getMessage() + ":" + json + ":" + this; + logger.warn(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + + + try { + Object fact = this.decoder.readValue(json, decoderClass); + return fact; + } catch (Exception e) { + String error = "DECODE-ERROR FROM PDP-D FRAMEWORK: "+ json + ":" + e.getMessage() + ":" + this; + logger.error(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String encode(Object event) + throws IllegalArgumentException, UnsupportedOperationException { + + // 0. Use custom coder if available + + if (this.customCoder != null) { + throw new UnsupportedOperationException + ("Jackon Custom Encoder is not supported at this time"); + } + + try { + String encodedEvent = this.encoder.writeValueAsString(event); + return encodedEvent; + } catch (JsonProcessingException e) { + String error = "ENCODE-ERROR: "+ event + " IN " + this; + logger.error(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("JacksonProtocolCoderToolset [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + +} + +/** + * Tools used for encoding/decoding using Jackson + */ +class GsonProtocolCoderToolset extends ProtocolCoderToolset { + + private static Logger logger = FlexLogger.getLogger(GsonProtocolCoderToolset.class); + /** + * Formatter for JSON encoding/decoding + */ + @JsonIgnore + public static DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSxxx"); + + @JsonIgnore + public static DateTimeFormatter zuluFormat = DateTimeFormatter.ISO_INSTANT; + + /** + * Adapter for ZonedDateTime + */ + + public static class GsonUTCAdapter implements JsonSerializer<ZonedDateTime>, JsonDeserializer<ZonedDateTime> { + + public ZonedDateTime deserialize(JsonElement element, Type type, JsonDeserializationContext context) + throws JsonParseException { + try { + return ZonedDateTime.parse(element.getAsString(), format); + } catch (Exception e) { + System.err.println(e); + } + return null; + } + + public JsonElement serialize(ZonedDateTime datetime, Type type, JsonSerializationContext context) { + return new JsonPrimitive(datetime.format(format)); + } + } + + public static class GsonInstantAdapter implements JsonSerializer<Instant>, JsonDeserializer<Instant> { + + @Override + public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + return Instant.ofEpochMilli(json.getAsLong()); + } + + @Override + public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(src.toEpochMilli()); + } + + } + + + /** + * decoder + */ + @JsonIgnore + protected final Gson decoder = new GsonBuilder().disableHtmlEscaping(). + registerTypeAdapter(ZonedDateTime.class, new GsonUTCAdapter()). + create(); + + /** + * encoder + */ + @JsonIgnore + protected final Gson encoder = new GsonBuilder().disableHtmlEscaping(). + registerTypeAdapter(ZonedDateTime.class, new GsonUTCAdapter()). + create(); + + /** + * Toolset to encode/decode tools associated with a topic + * + * @param topic topic + * @param decodedClass decoded class of an event + * @param filter + */ + public GsonProtocolCoderToolset(String topic, String controllerId, + String groupId, String artifactId, + String decodedClass, + JsonProtocolFilter filter, + CustomGsonCoder customGsonCoder, + int modelClassLoaderHash) { + super(topic, controllerId, groupId, artifactId, decodedClass, filter, customGsonCoder, modelClassLoaderHash); + } + + /** + * gets the Gson decoder + * + * @return the Gson decoder + */ + @JsonIgnore + protected Gson getDecoder() {return decoder;} + + /** + * gets the Gson encoder + * + * @return the Gson encoder + */ + @JsonIgnore + protected Gson getEncoder() {return encoder;} + + /** + * {@inheritDoc} + */ + @Override + public Object decode(String json) + throws IllegalArgumentException, UnsupportedOperationException, IllegalStateException { + + DroolsController droolsController = + DroolsController.factory.get(groupId, artifactId, ""); + if (droolsController == null) { + String error = "NO-DROOLS-CONTROLLER for: " + json + " IN " + this; + logger.warn(error); + throw new IllegalStateException(error); + } + + CoderFilters decoderFilter = filter(json); + if (decoderFilter == null) { + String error = "NO-DECODER for: " + json + " IN " + this; + logger.warn(error); + throw new UnsupportedOperationException(error); + } + + Class<?> decoderClass; + try { + decoderClass = + droolsController.fetchModelClass(decoderFilter.getCodedClass()); + if (decoderClass == null) { + String error = "DECODE-ERROR FETCHING MODEL CLASS: " + ":" + json + ":" + this; + logger.error(error); + throw new IllegalStateException(error); + } + } catch (Exception e) { + String error = "DECODE-ERROR FETCHING MODEL CLASS: "+ e.getMessage() + ":" + json + ":" + this; + logger.warn(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + + if (this.customCoder != null) { + try { + Class<?> gsonClassContainer = + droolsController.fetchModelClass(this.customCoder.getClassContainer()); + Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField); + Object gsonObject = gsonField.get(null); + Method fromJsonMethod = gsonObject.getClass(). + getDeclaredMethod + ("fromJson", new Class[]{String.class, Class.class}); + Object fact = fromJsonMethod.invoke(gsonObject, json, decoderClass); + return fact; + } catch (NoSuchFieldException | SecurityException | IllegalAccessException | + NoSuchMethodException | InvocationTargetException e) { + String error = "DECODE-ERROR-FROM-CUSTOM-CODER: " + e.getMessage() + ":" + json + ":" + this; + logger.error(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + } else { + try { + Object fact = this.decoder.fromJson(json, decoderClass); + return fact; + } catch (Exception e) { + String error = "DECODE-ERROR FROM PDP-D FRAMEWORK: "+ json + ":" + e.getMessage() + ":" + this; + logger.error(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + } + } + + + + /** + * {@inheritDoc} + */ + @Override + public String encode(Object event) + throws IllegalArgumentException, UnsupportedOperationException { + + DroolsController droolsController = + DroolsController.factory.get(groupId, artifactId, ""); + if (droolsController == null) { + String error = "NO-DROOLS-CONTROLLER for: " + event + " IN " + this; + logger.warn(error); + throw new IllegalStateException(error); + } + + if (this.customCoder != null) { + try { + Class<?> gsonClassContainer = + droolsController.fetchModelClass(this.customCoder.getClassContainer()); + Field gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField); + Object gsonObject = gsonField.get(null); + Method toJsonMethod = gsonObject.getClass(). + getDeclaredMethod + ("toJson", new Class[]{Object.class}); + String encodedJson = (String) toJsonMethod.invoke(gsonObject, event); + return encodedJson; + } catch (NoSuchFieldException | SecurityException | IllegalAccessException | + NoSuchMethodException | InvocationTargetException e) { + String error = "DECODE-ERROR-FROM-CUSTOM-CODER: " + e.getMessage() + ":" + event + ":" + this; + logger.error(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + } else { + try { + String encodedEvent = this.encoder.toJson(event); + return encodedEvent; + } catch (Exception e) { + String error = "ENCODE-ERROR: "+ event + " IN " + this; + logger.error(MessageCodes.EXCEPTION_ERROR, e, error); + throw new UnsupportedOperationException(error, e); + } + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("GsonProtocolCoderToolset [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java new file mode 100644 index 00000000..3c112573 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java @@ -0,0 +1,309 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.protocol.coders; + +import java.util.List; + +public class TopicCoderFilterConfiguration { + + /** + * Custom coder, contains class and static field to access parser that the controller + * desires to use instead of the framework provided parser + */ + public static abstract class CustomCoder { + protected String className; + protected String staticCoderField; + + /** + * create custom coder from raw string in the following format + * (typically embedded in a property file): + * + * Note this is to support decoding/encoding of partial structures that are + * only known by the model. + * + * @param rawCustomCoder with format: <class-containing-custom-coder>,<static-coder-field> + */ + public CustomCoder(String rawCustomCoder) throws IllegalArgumentException { + if (rawCustomCoder != null && !rawCustomCoder.isEmpty()) { + + this.className = rawCustomCoder.substring(0,rawCustomCoder.indexOf(",")); + if (this.className == null || this.className.isEmpty()) { + throw new IllegalArgumentException("No classname to create CustomCoder cannot be created"); + } + + this.staticCoderField = rawCustomCoder.substring(rawCustomCoder.indexOf(",")+1); + if (this.staticCoderField == null || this.staticCoderField.isEmpty()) { + throw new IllegalArgumentException + ("No staticCoderField to create CustomCoder cannot be created for class " + + className); + } + + } + } + /** + * @param classContainer + * @param staticCoderField + */ + public CustomCoder(String className, String staticCoderField) throws IllegalArgumentException { + if (className == null || className.isEmpty()) { + throw new IllegalArgumentException("No classname to create CustomCoder cannot be created"); + } + + if (staticCoderField == null || staticCoderField.isEmpty()) { + throw new IllegalArgumentException + ("No staticCoderField to create CustomCoder cannot be created for class " + + className); + } + + this.className = className; + this.staticCoderField = staticCoderField; + } + + /** + * @return the className + */ + public String getClassContainer() { + return className; + } + + /** + * @param className the className to set + */ + public void setClassContainer(String className) { + this.className = className; + } + + /** + * @return the staticCoderField + */ + public String getStaticCoderField() { + return staticCoderField; + } + + /** + * @param staticCoderField the staticGson to set + */ + public void setStaticCoderField(String staticCoderField) { + this.staticCoderField = staticCoderField; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("CustomCoder [className=").append(className).append(", staticCoderField=") + .append(staticCoderField).append("]"); + return builder.toString(); + } + } + + public static class CustomGsonCoder extends CustomCoder { + + public CustomGsonCoder(String className, String staticCoderField) { + super(className, staticCoderField); + } + + public CustomGsonCoder(String customGson) throws IllegalArgumentException { + super(customGson); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("CustomGsonCoder [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + + } + + public static class CustomJacksonCoder extends CustomCoder { + + public CustomJacksonCoder(String className, String staticCoderField) { + super(className, staticCoderField); + } + + public CustomJacksonCoder(String customJackson) throws IllegalArgumentException { + super(customJackson); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("CustomJacksonCoder [toString()=").append(super.toString()).append("]"); + return builder.toString(); + } + + } + + /** + * Coder/Decoder class and Filter container. The decoder class is potential, + * in order to be operational needs to be fetched from an available + * class loader. + * + */ + public static class PotentialCoderFilter { + + /** + * decoder class (pending from being able to be fetched and found + * in some class loader) + */ + protected String codedClass; + + /** + * filters to apply to the selection of the decodedClass; + */ + protected JsonProtocolFilter filter; + + /** + * constructor + * + * @param codedClass decoder class + * @param filter filters to apply + */ + public PotentialCoderFilter(String codedClass, JsonProtocolFilter filter) { + this.codedClass = codedClass; + this.filter = filter; + } + + /** + * @return the decodedClass + */ + public String getCodedClass() { + return codedClass; + } + + /** + * @param decodedClass the decodedClass to set + */ + public void setCodedClass(String decodedClass) { + this.codedClass = decodedClass; + } + + /** + * @return the filter + */ + public JsonProtocolFilter getFilter() { + return filter; + } + + /** + * @param filter the filter to set + */ + public void setFilter(JsonProtocolFilter filter) { + this.filter = filter; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("PotentialCoderFilter [codedClass=").append(codedClass).append(", filter=").append(filter) + .append("]"); + return builder.toString(); + } + } + + /** + * the source topic + */ + protected final String topic; + + /** + * List of decoder -> filters + */ + protected final List<PotentialCoderFilter> coderFilters; + + /** + * custom gson coder that this controller prefers to use instead of the framework ones + */ + protected CustomGsonCoder customGsonCoder; + + /** + * custom jackson coder that this controller prefers to use instead of the framework ones + */ + protected CustomJacksonCoder customJacksonCoder; + + /** + * Constructor + * + * @param decoderFilters list of decoders and associated filters + * @param topic the topic + */ + public TopicCoderFilterConfiguration(String topic, List<PotentialCoderFilter> decoderFilters, + CustomGsonCoder customGsonCoder, + CustomJacksonCoder customJacksonCoder) { + this.coderFilters = decoderFilters; + this.topic = topic; + this.customGsonCoder = customGsonCoder; + this.customJacksonCoder = customJacksonCoder; + } + + /** + * @return the topic + */ + public String getTopic() { + return topic; + } + + /** + * @return the decoderFilters + */ + public List<PotentialCoderFilter> getCoderFilters() { + return coderFilters; + } + + /** + * @return the customGsonCoder + */ + public CustomGsonCoder getCustomGsonCoder() { + return customGsonCoder; + } + + /** + * @param customGsonCoder the customGsonCoder to set + */ + public void setCustomGsonCoder(CustomGsonCoder customGsonCoder) { + this.customGsonCoder = customGsonCoder; + } + + /** + * @return the customJacksonCoder + */ + public CustomJacksonCoder getCustomJacksonCoder() { + return customJacksonCoder; + } + + /** + * @param customJacksonCoder the customJacksonCoder to set + */ + public void setCustomJacksonCoder(CustomJacksonCoder customJacksonCoder) { + this.customJacksonCoder = customJacksonCoder; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("TopicCoderFilterConfiguration [topic=").append(topic).append(", coderFilters=") + .append(coderFilters).append(", customGsonCoder=").append(customGsonCoder) + .append(", customJacksonCoder=").append(customJacksonCoder).append("]"); + return builder.toString(); + } + + +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/ControllerConfiguration.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/ControllerConfiguration.java new file mode 100644 index 00000000..98af02ee --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/ControllerConfiguration.java @@ -0,0 +1,280 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.protocol.configuration; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + + +/** + * Drools Related Information + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ControllerConfiguration { + + public static final String CONFIG_CONTROLLER_OPERATION_CREATE = "create"; + public static final String CONFIG_CONTROLLER_OPERATION_UPDATE = "update"; + public static final String CONFIG_CONTROLLER_OPERATION_LOCK = "lock"; + public static final String CONFIG_CONTROLLER_OPERATION_UNLOCK = "unlock"; + + /** + * + * (Required) + * + */ + @JsonProperty("name") + private String name; + /** + * Set of operations that can be applied to a controller: create, lock + * (Required) + * + */ + @JsonProperty("operation") + private String operation; + /** + * Maven Related Information + * + */ + @JsonProperty("drools") + private DroolsConfiguration drools; + @JsonIgnore + private Map<String, Object> additionalProperties = new HashMap<String, Object>(); + protected final static Object NOT_FOUND_VALUE = new Object(); + + /** + * No args constructor for use in serialization + * + */ + public ControllerConfiguration() { + } + + /** + * + * @param name + * @param drools + * @param operation + */ + public ControllerConfiguration(String name, String operation, DroolsConfiguration drools) { + this.name = name; + this.operation = operation; + this.drools = drools; + } + + /** + * + * (Required) + * + * @return + * The name + */ + @JsonProperty("name") + public String getName() { + return name; + } + + /** + * + * (Required) + * + * @param name + * The name + */ + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + public ControllerConfiguration withName(String name) { + this.name = name; + return this; + } + + /** + * Set of operations that can be applied to a controller: create, lock + * (Required) + * + * @return + * The operation + */ + @JsonProperty("operation") + public String getOperation() { + return operation; + } + + /** + * Set of operations that can be applied to a controller: create, lock + * (Required) + * + * @param operation + * The operation + */ + @JsonProperty("operation") + public void setOperation(String operation) { + this.operation = operation; + } + + public ControllerConfiguration withOperation(String operation) { + this.operation = operation; + return this; + } + + /** + * Maven Related Information + * + * @return + * The drools + */ + @JsonProperty("drools") + public DroolsConfiguration getDrools() { + return drools; + } + + /** + * Maven Related Information + * + * @param drools + * The drools + */ + @JsonProperty("drools") + public void setDrools(DroolsConfiguration drools) { + this.drools = drools; + } + + public ControllerConfiguration withDrools(DroolsConfiguration drools) { + this.drools = drools; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + @JsonAnyGetter + public Map<String, Object> getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public ControllerConfiguration withAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + return this; + } + + protected boolean declaredProperty(String name, Object value) { + switch (name) { + case "name": + if (value instanceof String) { + setName(((String) value)); + } else { + throw new IllegalArgumentException(("property \"name\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "operation": + if (value instanceof String) { + setOperation(((String) value)); + } else { + throw new IllegalArgumentException(("property \"operation\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "drools": + if (value instanceof DroolsConfiguration) { + setDrools(((DroolsConfiguration) value)); + } else { + throw new IllegalArgumentException(("property \"drools\" is of type \"org.openecomp.policy.drools.protocol.configuration.Drools\", but got "+ value.getClass().toString())); + } + return true; + default: + return false; + } + } + + protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { + switch (name) { + case "name": + return getName(); + case "operation": + return getOperation(); + case "drools": + return getDrools(); + default: + return notFoundValue; + } + } + + @SuppressWarnings({ + "unchecked" + }) + public<T >T get(String name) { + Object value = declaredPropertyOrNotFound(name, ControllerConfiguration.NOT_FOUND_VALUE); + if (ControllerConfiguration.NOT_FOUND_VALUE!= value) { + return ((T) value); + } else { + return ((T) getAdditionalProperties().get(name)); + } + } + + public void set(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + } + + public ControllerConfiguration with(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + return this; + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(name).append(operation).append(drools).append(additionalProperties).toHashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof ControllerConfiguration) == false) { + return false; + } + ControllerConfiguration rhs = ((ControllerConfiguration) other); + return new EqualsBuilder().append(name, rhs.name).append(operation, rhs.operation).append(drools, rhs.drools).append(additionalProperties, rhs.additionalProperties).isEquals(); + } + +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/DroolsConfiguration.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/DroolsConfiguration.java new file mode 100644 index 00000000..87cf2348 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/DroolsConfiguration.java @@ -0,0 +1,278 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.protocol.configuration; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + + +/** + * Maven Related Information + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DroolsConfiguration { + + /** + * Maven Artifact ID + * (Required) + * + */ + @JsonProperty("artifactId") + private String artifactId; + /** + * Maven Group ID + * (Required) + * + */ + @JsonProperty("groupId") + private String groupId; + /** + * Maven Version + * (Required) + * + */ + @JsonProperty("version") + private String version; + @JsonIgnore + private Map<String, Object> additionalProperties = new HashMap<String, Object>(); + protected final static Object NOT_FOUND_VALUE = new Object(); + + /** + * No args constructor for use in serialization + * + */ + public DroolsConfiguration() { + } + + /** + * + * @param groupId + * @param artifactId + * @param version + */ + public DroolsConfiguration(String artifactId, String groupId, String version) { + this.artifactId = artifactId; + this.groupId = groupId; + this.version = version; + } + + /** + * Maven Artifact ID + * (Required) + * + * @return + * The artifactId + */ + @JsonProperty("artifactId") + public String getArtifactId() { + return artifactId; + } + + /** + * Maven Artifact ID + * (Required) + * + * @param artifactId + * The artifactId + */ + @JsonProperty("artifactId") + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public DroolsConfiguration withArtifactId(String artifactId) { + this.artifactId = artifactId; + return this; + } + + /** + * Maven Group ID + * (Required) + * + * @return + * The groupId + */ + @JsonProperty("groupId") + public String getGroupId() { + return groupId; + } + + /** + * Maven Group ID + * (Required) + * + * @param groupId + * The groupId + */ + @JsonProperty("groupId") + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public DroolsConfiguration withGroupId(String groupId) { + this.groupId = groupId; + return this; + } + + /** + * Maven Version + * (Required) + * + * @return + * The version + */ + @JsonProperty("version") + public String getVersion() { + return version; + } + + /** + * Maven Version + * (Required) + * + * @param version + * The version + */ + @JsonProperty("version") + public void setVersion(String version) { + this.version = version; + } + + public DroolsConfiguration withVersion(String version) { + this.version = version; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + @JsonAnyGetter + public Map<String, Object> getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public DroolsConfiguration withAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + return this; + } + + protected boolean declaredProperty(String name, Object value) { + switch (name) { + case "artifactId": + if (value instanceof String) { + setArtifactId(((String) value)); + } else { + throw new IllegalArgumentException(("property \"artifactId\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "groupId": + if (value instanceof String) { + setGroupId(((String) value)); + } else { + throw new IllegalArgumentException(("property \"groupId\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "version": + if (value instanceof String) { + setVersion(((String) value)); + } else { + throw new IllegalArgumentException(("property \"version\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + default: + return false; + } + } + + protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { + switch (name) { + case "artifactId": + return getArtifactId(); + case "groupId": + return getGroupId(); + case "version": + return getVersion(); + default: + return notFoundValue; + } + } + + @SuppressWarnings({ + "unchecked" + }) + public<T >T get(String name) { + Object value = declaredPropertyOrNotFound(name, DroolsConfiguration.NOT_FOUND_VALUE); + if (DroolsConfiguration.NOT_FOUND_VALUE!= value) { + return ((T) value); + } else { + return ((T) getAdditionalProperties().get(name)); + } + } + + public void set(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + } + + public DroolsConfiguration with(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + return this; + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(artifactId).append(groupId).append(version).append(additionalProperties).toHashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof DroolsConfiguration) == false) { + return false; + } + DroolsConfiguration rhs = ((DroolsConfiguration) other); + return new EqualsBuilder().append(artifactId, rhs.artifactId).append(groupId, rhs.groupId).append(version, rhs.version).append(additionalProperties, rhs.additionalProperties).isEquals(); + } + +} diff --git a/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/PdpdConfiguration.java b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/PdpdConfiguration.java new file mode 100644 index 00000000..65de6656 --- /dev/null +++ b/policy-management/src/main/java/org/openecomp/policy/drools/protocol/configuration/PdpdConfiguration.java @@ -0,0 +1,283 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.policy.drools.protocol.configuration; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; + + +/** + * ENGINE-CONFIGURATION + * <p> + * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class PdpdConfiguration { + + /** + * Controller Entity ID + */ + public static final String CONFIG_ENTITY_CONTROLLER = "controller"; + + /** + * Unique Transaction ID. This is an UUID. + * (Required) + * + */ + @JsonProperty("requestID") + private String requestID; + /** + * Set of entities on which configuration can be performed: controller + * (Required) + * + */ + @JsonProperty("entity") + private String entity; + /** + * Controller Information, only applicable when the entity is set to controller + * + */ + @JsonProperty("controllers") + private List<ControllerConfiguration> controllers = new ArrayList<ControllerConfiguration>(); + @JsonIgnore + private Map<String, Object> additionalProperties = new HashMap<String, Object>(); + protected final static Object NOT_FOUND_VALUE = new Object(); + + /** + * No args constructor for use in serialization + * + */ + public PdpdConfiguration() { + } + + /** + * + * @param controller + * @param requestID + * @param entity + */ + public PdpdConfiguration(String requestID, String entity, List<ControllerConfiguration> controllers) { + this.requestID = requestID; + this.entity = entity; + this.controllers = controllers; + } + + /** + * Unique Transaction ID. This is an UUID. + * (Required) + * + * @return + * The requestID + */ + @JsonProperty("requestID") + public String getRequestID() { + return requestID; + } + + /** + * Unique Transaction ID. This is an UUID. + * (Required) + * + * @param requestID + * The requestID + */ + @JsonProperty("requestID") + public void setRequestID(String requestID) { + this.requestID = requestID; + } + + public PdpdConfiguration withRequestID(String requestID) { + this.requestID = requestID; + return this; + } + + /** + * Set of entities on which configuration can be performed: controller + * (Required) + * + * @return + * The entity + */ + @JsonProperty("entity") + public String getEntity() { + return entity; + } + + /** + * Set of entities on which configuration can be performed: controller + * (Required) + * + * @param entity + * The entity + */ + @JsonProperty("entity") + public void setEntity(String entity) { + this.entity = entity; + } + + public PdpdConfiguration withEntity(String entity) { + this.entity = entity; + return this; + } + + /** + * Controller Information, only applicable when the entity is set to controller + * + * @return + * The controller + */ + @JsonProperty("controller") + public List<ControllerConfiguration> getControllers() { + return controllers; + } + + /** + * Controller Information, only applicable when the entity is set to controller + * + * @param controller + * The controller + */ + @JsonProperty("controller") + public void setControllers(List<ControllerConfiguration> controllers) { + this.controllers = controllers; + } + + public PdpdConfiguration withController(List<ControllerConfiguration> controllers) { + this.controllers = controllers; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + @JsonAnyGetter + public Map<String, Object> getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public PdpdConfiguration withAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + return this; + } + + @SuppressWarnings("unchecked") + protected boolean declaredProperty(String name, Object value) { + switch (name) { + case "requestID": + if (value instanceof String) { + setRequestID(((String) value)); + } else { + throw new IllegalArgumentException(("property \"requestID\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "entity": + if (value instanceof String) { + setEntity(((String) value)); + } else { + throw new IllegalArgumentException(("property \"entity\" is of type \"java.lang.String\", but got "+ value.getClass().toString())); + } + return true; + case "controllers": + if (value instanceof List) { + setControllers(((List<ControllerConfiguration> ) value)); + } else { + throw new IllegalArgumentException(("property \"controllers\" is of type \"java.util.List<org.openecomp.policy.drools.protocol.configuration.Controller>\", but got "+ value.getClass().toString())); + } + return true; + default: + return false; + } + } + + protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { + switch (name) { + case "requestID": + return getRequestID(); + case "entity": + return getEntity(); + case "controllers": + return getControllers(); + default: + return notFoundValue; + } + } + + @SuppressWarnings({ + "unchecked" + }) + public<T >T get(String name) { + Object value = declaredPropertyOrNotFound(name, PdpdConfiguration.NOT_FOUND_VALUE); + if (PdpdConfiguration.NOT_FOUND_VALUE!= value) { + return ((T) value); + } else { + return ((T) getAdditionalProperties().get(name)); + } + } + + public void set(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + } + + public PdpdConfiguration with(String name, Object value) { + if (!declaredProperty(name, value)) { + getAdditionalProperties().put(name, ((Object) value)); + } + return this; + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(requestID).append(entity).append(controllers).append(additionalProperties).toHashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof PdpdConfiguration) == false) { + return false; + } + PdpdConfiguration rhs = ((PdpdConfiguration) other); + return new EqualsBuilder().append(requestID, rhs.requestID).append(entity, rhs.entity).append(controllers, rhs.controllers).append(additionalProperties, rhs.additionalProperties).isEquals(); + } + +} |