Changes for checkstyle 8.32
[policy/apex-pdp.git] / services / services-engine / src / main / java / org / onap / policy / apex / service / parameters / ApexParameters.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  * 
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  * 
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  * 
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.apex.service.parameters;
22
23 import java.util.Arrays;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.LinkedHashMap;
27 import java.util.Map;
28 import java.util.Map.Entry;
29 import java.util.Set;
30 import org.onap.policy.apex.service.parameters.engineservice.EngineServiceParameters;
31 import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
32 import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
33 import org.onap.policy.common.parameters.GroupValidationResult;
34 import org.onap.policy.common.parameters.ParameterGroup;
35 import org.onap.policy.common.parameters.ValidationStatus;
36 import org.onap.policy.common.utils.validation.ParameterValidationUtils;
37
38 /**
39  * The main container parameter class for an Apex service.
40  * 
41  * <p>The following parameters are defined: <ol> <li>engineServiceParameters: The parameters for the Apex engine service
42  * itself, such as the number of engine threads to run and the deployment port number to use. <li>eventOutputParameters:
43  * A map of parameters for event outputs that Apex will use to emit events. Apex emits events on all outputs
44  * <li>eventInputParameters: A map or parameters for event inputs from which Apex will consume events. Apex reads events
45  * from all its event inputs. </ol>
46  *
47  * @author Liam Fallon (liam.fallon@ericsson.com)
48  */
49 public class ApexParameters implements ParameterGroup {
50     // Parameter group name
51     private String name;
52
53     // Constants for recurring strings
54     private static final String JAVA_PROPERTIES = "javaProperties";
55     private static final String PEER_STRING = "peer ";
56     private static final String EVENT_INPUT_PARAMETERS_STRING = "eventInputParameters";
57     private static final String EVENT_OUTPUT_PARAMETERS_STRING = "eventOutputParameters";
58     private static final String FOR_PEERED_MODE_STRING = " for peered mode ";
59
60     // Properties for the Java JVM
61     private String[][] javaProperties = null;
62
63     // Parameters for the engine service and the engine threads in the engine service
64     private EngineServiceParameters engineServiceParameters;
65
66     // Parameters for the event outputs that Apex will use to send events on its outputs
67     private Map<String, EventHandlerParameters> eventOutputParameters = new LinkedHashMap<>();
68
69     // Parameters for the event inputs that Apex will use to receive events on its inputs
70     private Map<String, EventHandlerParameters> eventInputParameters = new LinkedHashMap<>();
71
72     /**
73      * Constructor to create an apex parameters instance and register the instance with the parameter service.
74      */
75     public ApexParameters() {
76         super();
77
78         // Set the name for the parameters
79         this.name = ApexParameterConstants.MAIN_GROUP_NAME;
80     }
81
82     /**
83      * Gets the parameters for the Apex engine service.
84      *
85      * @return the engine service parameters
86      */
87     public EngineServiceParameters getEngineServiceParameters() {
88         return engineServiceParameters;
89     }
90
91     /**
92      * Sets the engine service parameters.
93      *
94      * @param engineServiceParameters the engine service parameters
95      */
96     public void setEngineServiceParameters(final EngineServiceParameters engineServiceParameters) {
97         this.engineServiceParameters = engineServiceParameters;
98     }
99
100     /**
101      * Gets the event output parameter map.
102      *
103      * @return the parameters for all event outputs
104      */
105     public Map<String, EventHandlerParameters> getEventOutputParameters() {
106         return eventOutputParameters;
107     }
108
109     /**
110      * Sets the event output parameters.
111      *
112      * @param eventOutputParameters the event outputs parameters
113      */
114     public void setEventOutputParameters(final Map<String, EventHandlerParameters> eventOutputParameters) {
115         this.eventOutputParameters = eventOutputParameters;
116     }
117
118     /**
119      * Gets the event input parameter map.
120      *
121      * @return the parameters for all event inputs
122      */
123     public Map<String, EventHandlerParameters> getEventInputParameters() {
124         return eventInputParameters;
125     }
126
127     /**
128      * Sets the event input parameters.
129      *
130      * @param eventInputParameters the event input parameters
131      */
132     public void setEventInputParameters(final Map<String, EventHandlerParameters> eventInputParameters) {
133         this.eventInputParameters = eventInputParameters;
134     }
135
136     @Override
137     public String getName() {
138         return name;
139     }
140
141     @Override
142     public void setName(final String name) {
143         this.name = name;
144     }
145
146     /**
147      * Check if Java properties have been specified.
148      *
149      * @return true if Java properties have been specified
150      */
151     public boolean checkJavaPropertiesSet() {
152         return javaProperties != null && javaProperties.length > 0;
153     }
154
155     /**
156      * Gets the Java properties that have been specified.
157      *
158      * @return the Java properties that have been specified
159      */
160     public String[][] getJavaProperties() {
161         return javaProperties;
162     }
163
164     @Override
165     public GroupValidationResult validate() {
166         GroupValidationResult result = new GroupValidationResult(this);
167
168         validateJavaProperties(result);
169
170         if (engineServiceParameters == null) {
171             result.setResult("engineServiceParameters", ValidationStatus.INVALID,
172                 "engine service parameters are not specified");
173         } else {
174             result.setResult("engineServiceParameters", engineServiceParameters.validate());
175         }
176
177         // Sanity check, we must have an entry in both output and input maps
178         if (eventInputParameters.isEmpty()) {
179             result.setResult(EVENT_INPUT_PARAMETERS_STRING, ValidationStatus.INVALID,
180                 "at least one event input must be specified");
181         }
182
183         if (eventOutputParameters.isEmpty()) {
184             result.setResult(EVENT_OUTPUT_PARAMETERS_STRING, ValidationStatus.INVALID,
185                 "at least one event output must be specified");
186         }
187
188         // Validate that the values of all parameters are ok
189         validateEventHandlerMap(EVENT_INPUT_PARAMETERS_STRING, result, eventInputParameters);
190         validateEventHandlerMap(EVENT_OUTPUT_PARAMETERS_STRING, result, eventOutputParameters);
191
192         // Only do peer mode validate if there are no other errors
193         if (result.isValid()) {
194             for (final EventHandlerPeeredMode peeredMode : EventHandlerPeeredMode.values()) {
195                 validatePeeredMode(result, peeredMode);
196             }
197         }
198
199         return result;
200     }
201
202     /**
203      * This method validates the java properties variable if it is present.
204      *
205      * @param result the result of the validation
206      */
207     private void validateJavaProperties(GroupValidationResult result) {
208         if (javaProperties == null) {
209             return;
210         }
211
212         StringBuilder errorMessageBuilder = new StringBuilder();
213         for (String[] javaProperty : javaProperties) {
214             if (javaProperty == null) {
215                 errorMessageBuilder.append("java properties array entry is null\n");
216             } else if (javaProperty.length != 2) {
217                 errorMessageBuilder.append("java properties array entries must have one key and one value: "
218                     + Arrays.deepToString(javaProperty) + "\n");
219             } else if (!ParameterValidationUtils.validateStringParameter(javaProperty[0])) {
220                 errorMessageBuilder
221                     .append("java properties key is null or blank: " + Arrays.deepToString(javaProperty) + "\n");
222             } else if (!ParameterValidationUtils.validateStringParameter(javaProperty[1])) {
223                 errorMessageBuilder
224                     .append("java properties value is null or blank: " + Arrays.deepToString(javaProperty) + "\n");
225             }
226         }
227
228         if (errorMessageBuilder.length() > 0) {
229             result.setResult(JAVA_PROPERTIES, ValidationStatus.INVALID, errorMessageBuilder.toString());
230         }
231     }
232
233     /**
234      * This method validates the parameters in an event handler map.
235      * 
236      * @param eventHandlerType the type of the event handler to use on error messages
237      * @param result the result object to use to return validation messages
238      * @param parsForValidation The event handler parameters to validate (input or output)
239      */
240     private void validateEventHandlerMap(final String eventHandlerType, final GroupValidationResult result,
241         final Map<String, EventHandlerParameters> parsForValidation) {
242         for (final Entry<String, EventHandlerParameters> parameterEntry : parsForValidation.entrySet()) {
243             if (parameterEntry.getKey() == null || parameterEntry.getKey().trim().isEmpty()) {
244                 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID,
245                     "invalid " + eventHandlerType + " name \"" + parameterEntry.getKey() + "\"");
246             } else if (parameterEntry.getValue() == null) {
247                 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID,
248                     "invalid/Null event input prameters specified for " + eventHandlerType + " name \""
249                         + parameterEntry.getKey() + "\" ");
250             } else {
251                 result.setResult(eventHandlerType, parameterEntry.getKey(), parameterEntry.getValue().validate());
252             }
253
254             parameterEntry.getValue().setName(parameterEntry.getKey());
255
256             // Validate parameters for peered mode settings
257             for (final EventHandlerPeeredMode peeredMode : EventHandlerPeeredMode.values()) {
258                 validatePeeredModeParameters(eventHandlerType, result, parameterEntry, peeredMode);
259             }
260         }
261     }
262
263     /**
264      * Validate parameter values for event handlers in a peered mode.
265      * 
266      * @param eventHandlerType The event handler type we are checking
267      * @param result The result object to which to append any error messages
268      * @param parameterEntry The entry to check the peered mode on
269      * @param peeredMode The mode to check
270      */
271     private void validatePeeredModeParameters(final String eventHandlerType, final GroupValidationResult result,
272         final Entry<String, EventHandlerParameters> parameterEntry, final EventHandlerPeeredMode peeredMode) {
273         final String messagePreamble = "specified peered mode \"" + peeredMode + "\"";
274         final String peer = parameterEntry.getValue().getPeer(peeredMode);
275
276         if (parameterEntry.getValue().isPeeredMode(peeredMode)) {
277             if (peer == null || peer.trim().isEmpty()) {
278                 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID,
279                     messagePreamble + " mandatory parameter not specified or is null");
280             }
281             if (parameterEntry.getValue().getPeerTimeout(peeredMode) < 0) {
282                 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID,
283                     messagePreamble + " timeout value \"" + parameterEntry.getValue().getPeerTimeout(peeredMode)
284                         + "\" is illegal, specify a non-negative timeout value in milliseconds");
285             }
286         } else {
287             if (peer != null) {
288                 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID, messagePreamble
289                     + " peer is illegal on " + eventHandlerType + " \"" + parameterEntry.getKey() + "\" ");
290             }
291             if (parameterEntry.getValue().getPeerTimeout(peeredMode) != 0) {
292                 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID, messagePreamble
293                     + " timeout is illegal on " + eventHandlerType + " \"" + parameterEntry.getKey() + "\"");
294             }
295         }
296     }
297
298     /**
299      * This method validates that the settings are valid for the given peered mode.
300      * 
301      * @param result The result object to which to append any error messages
302      * @param peeredMode The peered mode to check
303      */
304     private void validatePeeredMode(final GroupValidationResult result, final EventHandlerPeeredMode peeredMode) {
305         // Find the input and output event handlers that use this peered mode
306         final Map<String, EventHandlerParameters> inputParametersUsingMode = new HashMap<>();
307         final Map<String, EventHandlerParameters> outputParametersUsingMode = new HashMap<>();
308
309         // Find input and output parameters using this mode
310         for (final Entry<String, EventHandlerParameters> inputParameterEntry : eventInputParameters.entrySet()) {
311             if (inputParameterEntry.getValue().isPeeredMode(peeredMode)) {
312                 inputParametersUsingMode.put(inputParameterEntry.getKey(), inputParameterEntry.getValue());
313             }
314         }
315         for (final Entry<String, EventHandlerParameters> outputParameterEntry : eventOutputParameters.entrySet()) {
316             if (outputParameterEntry.getValue().isPeeredMode(peeredMode)) {
317                 outputParametersUsingMode.put(outputParameterEntry.getKey(), outputParameterEntry.getValue());
318             }
319         }
320
321         // Validate the parameters for each side of the peered mode parameters
322         validatePeeredModePeers(EVENT_INPUT_PARAMETERS_STRING, result, peeredMode, inputParametersUsingMode,
323             outputParametersUsingMode);
324         validatePeeredModePeers(EVENT_OUTPUT_PARAMETERS_STRING, result, peeredMode, outputParametersUsingMode,
325             inputParametersUsingMode);
326     }
327
328     /**
329      * This method validates that the settings are valid for the event handlers on one.
330      * 
331      * @param handlerMapVariableName the variable name of the map on which the paired parameters are being checked
332      * @param result The result object to which to append any error messages
333      * @param leftModeParameters The mode parameters being checked
334      * @param rightModeParameters The mode parameters being referenced by the checked parameters
335      */
336     private void validatePeeredModePeers(final String handlerMapVariableName, final GroupValidationResult result,
337         final EventHandlerPeeredMode peeredMode, final Map<String, EventHandlerParameters> leftModeParameterMap,
338         final Map<String, EventHandlerParameters> rightModeParameterMap) {
339
340         // These sets are used to check for duplicate references on the both sides
341         final Set<String> leftCheckDuplicateSet = new HashSet<>();
342         final Set<String> rightCheckDuplicateSet = new HashSet<>();
343
344         // Check for missing peers, all peers are set because we have checked them previously so no
345         // need for null checks
346         for (final Entry<String, EventHandlerParameters> leftModeParameterEntry : leftModeParameterMap.entrySet()) {
347             final String leftSidePeer = leftModeParameterEntry.getValue().getPeer(peeredMode);
348
349             final EventHandlerParameters leftModeParameters = leftModeParameterEntry.getValue();
350             final EventHandlerParameters rightModeParameters = rightModeParameterMap.get(leftSidePeer);
351
352             // Check that the peer reference is OK
353             if (rightModeParameters == null) {
354                 result.setResult(handlerMapVariableName, leftModeParameterEntry.getKey(), ValidationStatus.INVALID,
355                     PEER_STRING + '"' + leftModeParameters.getPeer(peeredMode) + FOR_PEERED_MODE_STRING + peeredMode
356                         + " does not exist or is not defined with the same peered mode");
357                 continue;
358             }
359
360             // Now check that the right side peer is the left side event handler
361             final String rightSidePeer = rightModeParameters.getPeer(peeredMode);
362             if (!rightSidePeer.equals(leftModeParameterEntry.getKey())) {
363                 result.setResult(handlerMapVariableName, leftModeParameterEntry.getKey(), ValidationStatus.INVALID,
364                     PEER_STRING + '"' + leftModeParameters.getPeer(peeredMode) + FOR_PEERED_MODE_STRING + peeredMode
365                         + ", value \"" + rightSidePeer + "\" on peer \"" + leftSidePeer
366                         + "\" does not equal event handler \"" + leftModeParameterEntry.getKey() + "\"");
367             } else {
368                 // Check for duplicates
369                 if (!leftCheckDuplicateSet.add(leftSidePeer)) {
370                     result.setResult(handlerMapVariableName, leftModeParameterEntry.getKey(), ValidationStatus.INVALID,
371                         PEER_STRING + '"' + leftModeParameters.getPeer(peeredMode) + FOR_PEERED_MODE_STRING + peeredMode
372                             + ", peer value \"" + leftSidePeer + "\" on event handler \""
373                             + leftModeParameterEntry.getKey() + "\" is used more than once");
374                 }
375                 if (!rightCheckDuplicateSet.add(rightSidePeer)) {
376                     result.setResult(handlerMapVariableName, leftModeParameterEntry.getKey(), ValidationStatus.INVALID,
377                         PEER_STRING + '"' + leftModeParameters.getPeer(peeredMode) + FOR_PEERED_MODE_STRING + peeredMode
378                             + ", peer value \"" + rightSidePeer + "\" on peer \"" + leftSidePeer
379                             + "\" on event handler \"" + leftModeParameterEntry.getKey() + "\" is used more than once");
380                 }
381             }
382
383             if (!crossCheckPeeredTimeoutValues(leftModeParameters, rightModeParameters, peeredMode)) {
384                 result.setResult(handlerMapVariableName, leftModeParameterEntry.getKey(), ValidationStatus.INVALID,
385                     PEER_STRING + '"' + leftModeParameters.getPeer(peeredMode) + FOR_PEERED_MODE_STRING + peeredMode
386                         + " timeout " + leftModeParameters.getPeerTimeout(peeredMode) + " on event handler \""
387                         + leftModeParameters.getName() + "\" does not equal timeout "
388                         + rightModeParameters.getPeerTimeout(peeredMode) + " on event handler \""
389                         + rightModeParameters.getName() + "\"");
390
391             }
392         }
393     }
394
395     /**
396      * Validate the timeout values on two peers.
397      * 
398      * @param leftModeParameters The parameters of the left hand peer
399      * @param peeredMode The peered mode being checked
400      * @return true if the timeout values are cross checked as being OK
401      */
402     private boolean crossCheckPeeredTimeoutValues(final EventHandlerParameters leftModeParameters,
403         final EventHandlerParameters rightModeParameters, final EventHandlerPeeredMode peeredMode) {
404         // Cross-set the timeouts if they are not specified
405         if (leftModeParameters.getPeerTimeout(peeredMode) != 0) {
406             if (rightModeParameters.getPeerTimeout(peeredMode) != 0) {
407                 if (leftModeParameters.getPeerTimeout(peeredMode) != rightModeParameters.getPeerTimeout(peeredMode)) {
408                     return false;
409                 }
410             } else {
411                 rightModeParameters.setPeerTimeout(peeredMode, leftModeParameters.getPeerTimeout(peeredMode));
412             }
413         } else {
414             if (rightModeParameters.getPeerTimeout(peeredMode) != 0) {
415                 leftModeParameters.setPeerTimeout(peeredMode, rightModeParameters.getPeerTimeout(peeredMode));
416             }
417         }
418         return true;
419     }
420 }