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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.apex.service.parameters;
23 import java.util.Arrays;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.LinkedHashMap;
28 import java.util.Map.Entry;
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;
39 * The main container parameter class for an Apex service.
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>
47 * @author Liam Fallon (liam.fallon@ericsson.com)
49 public class ApexParameters implements ParameterGroup {
50 // Parameter group name
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 ";
60 // Properties for the Java JVM
61 private String[][] javaProperties = null;
63 // Parameters for the engine service and the engine threads in the engine service
64 private EngineServiceParameters engineServiceParameters;
66 // Parameters for the event outputs that Apex will use to send events on its outputs
67 private Map<String, EventHandlerParameters> eventOutputParameters = new LinkedHashMap<>();
69 // Parameters for the event inputs that Apex will use to receive events on its inputs
70 private Map<String, EventHandlerParameters> eventInputParameters = new LinkedHashMap<>();
73 * Constructor to create an apex parameters instance and register the instance with the parameter service.
75 public ApexParameters() {
78 // Set the name for the parameters
79 this.name = ApexParameterConstants.MAIN_GROUP_NAME;
83 * Gets the parameters for the Apex engine service.
85 * @return the engine service parameters
87 public EngineServiceParameters getEngineServiceParameters() {
88 return engineServiceParameters;
92 * Sets the engine service parameters.
94 * @param engineServiceParameters the engine service parameters
96 public void setEngineServiceParameters(final EngineServiceParameters engineServiceParameters) {
97 this.engineServiceParameters = engineServiceParameters;
101 * Gets the event output parameter map.
103 * @return the parameters for all event outputs
105 public Map<String, EventHandlerParameters> getEventOutputParameters() {
106 return eventOutputParameters;
110 * Sets the event output parameters.
112 * @param eventOutputParameters the event outputs parameters
114 public void setEventOutputParameters(final Map<String, EventHandlerParameters> eventOutputParameters) {
115 this.eventOutputParameters = eventOutputParameters;
119 * Gets the event input parameter map.
121 * @return the parameters for all event inputs
123 public Map<String, EventHandlerParameters> getEventInputParameters() {
124 return eventInputParameters;
128 * Sets the event input parameters.
130 * @param eventInputParameters the event input parameters
132 public void setEventInputParameters(final Map<String, EventHandlerParameters> eventInputParameters) {
133 this.eventInputParameters = eventInputParameters;
137 public String getName() {
142 public void setName(final String name) {
147 * Check if Java properties have been specified.
149 * @return true if Java properties have been specified
151 public boolean checkJavaPropertiesSet() {
152 return javaProperties != null && javaProperties.length > 0;
156 * Gets the Java properties that have been specified.
158 * @return the Java properties that have been specified
160 public String[][] getJavaProperties() {
161 return javaProperties;
165 public GroupValidationResult validate() {
166 GroupValidationResult result = new GroupValidationResult(this);
168 validateJavaProperties(result);
170 if (engineServiceParameters == null) {
171 result.setResult("engineServiceParameters", ValidationStatus.INVALID,
172 "engine service parameters are not specified");
174 result.setResult("engineServiceParameters", engineServiceParameters.validate());
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");
183 if (eventOutputParameters.isEmpty()) {
184 result.setResult(EVENT_OUTPUT_PARAMETERS_STRING, ValidationStatus.INVALID,
185 "at least one event output must be specified");
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);
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);
203 * This method validates the java properties variable if it is present.
205 * @param result the result of the validation
207 private void validateJavaProperties(GroupValidationResult result) {
208 if (javaProperties == null) {
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])) {
221 .append("java properties key is null or blank: " + Arrays.deepToString(javaProperty) + "\n");
222 } else if (!ParameterValidationUtils.validateStringParameter(javaProperty[1])) {
224 .append("java properties value is null or blank: " + Arrays.deepToString(javaProperty) + "\n");
228 if (errorMessageBuilder.length() > 0) {
229 result.setResult(JAVA_PROPERTIES, ValidationStatus.INVALID, errorMessageBuilder.toString());
234 * This method validates the parameters in an event handler map.
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)
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() + "\" ");
251 result.setResult(eventHandlerType, parameterEntry.getKey(), parameterEntry.getValue().validate());
254 parameterEntry.getValue().setName(parameterEntry.getKey());
256 // Validate parameters for peered mode settings
257 for (final EventHandlerPeeredMode peeredMode : EventHandlerPeeredMode.values()) {
258 validatePeeredModeParameters(eventHandlerType, result, parameterEntry, peeredMode);
264 * Validate parameter values for event handlers in a peered mode.
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
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);
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");
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");
288 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID, messagePreamble
289 + " peer is illegal on " + eventHandlerType + " \"" + parameterEntry.getKey() + "\" ");
291 if (parameterEntry.getValue().getPeerTimeout(peeredMode) != 0) {
292 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID, messagePreamble
293 + " timeout is illegal on " + eventHandlerType + " \"" + parameterEntry.getKey() + "\"");
299 * This method validates that the settings are valid for the given peered mode.
301 * @param result The result object to which to append any error messages
302 * @param peeredMode The peered mode to check
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<>();
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());
315 for (final Entry<String, EventHandlerParameters> outputParameterEntry : eventOutputParameters.entrySet()) {
316 if (outputParameterEntry.getValue().isPeeredMode(peeredMode)) {
317 outputParametersUsingMode.put(outputParameterEntry.getKey(), outputParameterEntry.getValue());
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);
329 * This method validates that the settings are valid for the event handlers on one.
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
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) {
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<>();
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);
349 final EventHandlerParameters leftModeParameters = leftModeParameterEntry.getValue();
350 final EventHandlerParameters rightModeParameters = rightModeParameterMap.get(leftSidePeer);
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");
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() + "\"");
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");
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");
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() + "\"");
396 * Validate the timeout values on two peers.
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
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)) {
411 rightModeParameters.setPeerTimeout(peeredMode, leftModeParameters.getPeerTimeout(peeredMode));
414 if (rightModeParameters.getPeerTimeout(peeredMode) != 0) {
415 leftModeParameters.setPeerTimeout(peeredMode, rightModeParameters.getPeerTimeout(peeredMode));