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;
31 import org.onap.policy.apex.service.parameters.engineservice.EngineServiceParameters;
32 import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
33 import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerPeeredMode;
34 import org.onap.policy.common.parameters.GroupValidationResult;
35 import org.onap.policy.common.parameters.ParameterGroup;
36 import org.onap.policy.common.parameters.ValidationStatus;
37 import org.onap.policy.common.utils.validation.ParameterValidationUtils;
40 * The main container parameter class for an Apex service.
42 * <p>The following parameters are defined: <ol> <li>engineServiceParameters: The parameters for the Apex engine service
43 * itself, such as the number of engine threads to run and the deployment port number to use. <li>eventOutputParameters:
44 * A map of parameters for event outputs that Apex will use to emit events. Apex emits events on all outputs
45 * <li>eventInputParameters: A map or parameters for event inputs from which Apex will consume events. Apex reads events
46 * from all its event inputs. </ol>
48 * @author Liam Fallon (liam.fallon@ericsson.com)
50 public class ApexParameters implements ParameterGroup {
51 // Parameter group name
54 // Constants for recurring strings
55 private static final String JAVA_PROPERTIES = "javaProperties";
56 private static final String PEER_STRING = "peer ";
57 private static final String EVENT_INPUT_PARAMETERS_STRING = "eventInputParameters";
58 private static final String EVENT_OUTPUT_PARAMETERS_STRING = "eventOutputParameters";
59 private static final String FOR_PEERED_MODE_STRING = " for peered mode ";
61 // Properties for the Java JVM
62 private String[][] javaProperties = null;
64 // Parameters for the engine service and the engine threads in the engine service
65 private EngineServiceParameters engineServiceParameters;
67 // Parameters for the event outputs that Apex will use to send events on its outputs
68 private Map<String, EventHandlerParameters> eventOutputParameters = new LinkedHashMap<>();
70 // Parameters for the event inputs that Apex will use to receive events on its inputs
71 private Map<String, EventHandlerParameters> eventInputParameters = new LinkedHashMap<>();
74 * Constructor to create an apex parameters instance and register the instance with the parameter service.
76 public ApexParameters() {
79 // Set the name for the parameters
80 this.name = ApexParameterConstants.MAIN_GROUP_NAME;
84 * Gets the parameters for the Apex engine service.
86 * @return the engine service parameters
88 public EngineServiceParameters getEngineServiceParameters() {
89 return engineServiceParameters;
93 * Sets the engine service parameters.
95 * @param engineServiceParameters the engine service parameters
97 public void setEngineServiceParameters(final EngineServiceParameters engineServiceParameters) {
98 this.engineServiceParameters = engineServiceParameters;
102 * Gets the event output parameter map.
104 * @return the parameters for all event outputs
106 public Map<String, EventHandlerParameters> getEventOutputParameters() {
107 return eventOutputParameters;
111 * Sets the event output parameters.
113 * @param eventOutputParameters the event outputs parameters
115 public void setEventOutputParameters(final Map<String, EventHandlerParameters> eventOutputParameters) {
116 this.eventOutputParameters = eventOutputParameters;
120 * Gets the event input parameter map.
122 * @return the parameters for all event inputs
124 public Map<String, EventHandlerParameters> getEventInputParameters() {
125 return eventInputParameters;
129 * Sets the event input parameters.
131 * @param eventInputParameters the event input parameters
133 public void setEventInputParameters(final Map<String, EventHandlerParameters> eventInputParameters) {
134 this.eventInputParameters = eventInputParameters;
138 public String getName() {
143 public void setName(final String name) {
148 * Check if Java properties have been specified.
150 * @return true if Java properties have been specified
152 public boolean checkJavaPropertiesSet() {
153 return javaProperties != null && javaProperties.length > 0;
157 * Gets the Java properties that have been specified.
159 * @return the Java properties that have been specified
161 public String[][] getJavaProperties() {
162 return javaProperties;
166 public GroupValidationResult validate() {
167 GroupValidationResult result = new GroupValidationResult(this);
169 validateJavaProperties(result);
171 if (engineServiceParameters == null) {
172 result.setResult("engineServiceParameters", ValidationStatus.INVALID,
173 "engine service parameters are not specified");
175 result.setResult("engineServiceParameters", engineServiceParameters.validate());
178 // Sanity check, we must have an entry in both output and input maps
179 if (eventInputParameters.isEmpty()) {
180 result.setResult(EVENT_INPUT_PARAMETERS_STRING, ValidationStatus.INVALID,
181 "at least one event input must be specified");
184 if (eventOutputParameters.isEmpty()) {
185 result.setResult(EVENT_OUTPUT_PARAMETERS_STRING, ValidationStatus.INVALID,
186 "at least one event output must be specified");
189 // Validate that the values of all parameters are ok
190 validateEventHandlerMap(EVENT_INPUT_PARAMETERS_STRING, result, eventInputParameters);
191 validateEventHandlerMap(EVENT_OUTPUT_PARAMETERS_STRING, result, eventOutputParameters);
193 // Only do peer mode validate if there are no other errors
194 if (result.isValid()) {
195 for (final EventHandlerPeeredMode peeredMode : EventHandlerPeeredMode.values()) {
196 validatePeeredMode(result, peeredMode);
204 * This method validates the java properties variable if it is present.
206 * @param result the result of the validation
208 private void validateJavaProperties(GroupValidationResult result) {
209 if (javaProperties == null) {
213 StringBuilder errorMessageBuilder = new StringBuilder();
214 for (String[] javaProperty : javaProperties) {
215 if (javaProperty == null) {
216 errorMessageBuilder.append("java properties array entry is null\n");
217 } else if (javaProperty.length != 2) {
218 errorMessageBuilder.append("java properties array entries must have one key and one value: "
219 + Arrays.deepToString(javaProperty) + "\n");
220 } else if (!ParameterValidationUtils.validateStringParameter(javaProperty[0])) {
222 .append("java properties key is null or blank: " + Arrays.deepToString(javaProperty) + "\n");
223 } else if (!ParameterValidationUtils.validateStringParameter(javaProperty[1])) {
225 .append("java properties value is null or blank: " + Arrays.deepToString(javaProperty) + "\n");
229 if (errorMessageBuilder.length() > 0) {
230 result.setResult(JAVA_PROPERTIES, ValidationStatus.INVALID, errorMessageBuilder.toString());
235 * This method validates the parameters in an event handler map.
237 * @param eventHandlerType the type of the event handler to use on error messages
238 * @param result the result object to use to return validation messages
239 * @param parsForValidation The event handler parameters to validate (input or output)
241 private void validateEventHandlerMap(final String eventHandlerType, final GroupValidationResult result,
242 final Map<String, EventHandlerParameters> parsForValidation) {
243 for (final Entry<String, EventHandlerParameters> parameterEntry : parsForValidation.entrySet()) {
244 if (parameterEntry.getKey() == null || parameterEntry.getKey().trim().isEmpty()) {
245 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID,
246 "invalid " + eventHandlerType + " name \"" + parameterEntry.getKey() + "\"");
247 } else if (parameterEntry.getValue() == null) {
248 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID,
249 "invalid/Null event input prameters specified for " + eventHandlerType + " name \""
250 + parameterEntry.getKey() + "\" ");
252 result.setResult(eventHandlerType, parameterEntry.getKey(), parameterEntry.getValue().validate());
255 parameterEntry.getValue().setName(parameterEntry.getKey());
257 // Validate parameters for peered mode settings
258 for (final EventHandlerPeeredMode peeredMode : EventHandlerPeeredMode.values()) {
259 validatePeeredModeParameters(eventHandlerType, result, parameterEntry, peeredMode);
265 * Validate parameter values for event handlers in a peered mode.
267 * @param eventHandlerType The event handler type we are checking
268 * @param result The result object to which to append any error messages
269 * @param parameterEntry The entry to check the peered mode on
270 * @param peeredMode The mode to check
272 private void validatePeeredModeParameters(final String eventHandlerType, final GroupValidationResult result,
273 final Entry<String, EventHandlerParameters> parameterEntry, final EventHandlerPeeredMode peeredMode) {
274 final String messagePreamble = "specified peered mode \"" + peeredMode + "\"";
275 final String peer = parameterEntry.getValue().getPeer(peeredMode);
277 if (parameterEntry.getValue().isPeeredMode(peeredMode)) {
278 if (peer == null || peer.trim().isEmpty()) {
279 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID,
280 messagePreamble + " mandatory parameter not specified or is null");
282 if (parameterEntry.getValue().getPeerTimeout(peeredMode) < 0) {
283 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID,
284 messagePreamble + " timeout value \"" + parameterEntry.getValue().getPeerTimeout(peeredMode)
285 + "\" is illegal, specify a non-negative timeout value in milliseconds");
289 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID, messagePreamble
290 + " peer is illegal on " + eventHandlerType + " \"" + parameterEntry.getKey() + "\" ");
292 if (parameterEntry.getValue().getPeerTimeout(peeredMode) != 0) {
293 result.setResult(eventHandlerType, parameterEntry.getKey(), ValidationStatus.INVALID, messagePreamble
294 + " timeout is illegal on " + eventHandlerType + " \"" + parameterEntry.getKey() + "\"");
300 * This method validates that the settings are valid for the given peered mode.
302 * @param result The result object to which to append any error messages
303 * @param peeredMode The peered mode to check
305 private void validatePeeredMode(final GroupValidationResult result, final EventHandlerPeeredMode peeredMode) {
306 // Find the input and output event handlers that use this peered mode
307 final Map<String, EventHandlerParameters> inputParametersUsingMode = new HashMap<>();
308 final Map<String, EventHandlerParameters> outputParametersUsingMode = new HashMap<>();
310 // Find input and output parameters using this mode
311 for (final Entry<String, EventHandlerParameters> inputParameterEntry : eventInputParameters.entrySet()) {
312 if (inputParameterEntry.getValue().isPeeredMode(peeredMode)) {
313 inputParametersUsingMode.put(inputParameterEntry.getKey(), inputParameterEntry.getValue());
316 for (final Entry<String, EventHandlerParameters> outputParameterEntry : eventOutputParameters.entrySet()) {
317 if (outputParameterEntry.getValue().isPeeredMode(peeredMode)) {
318 outputParametersUsingMode.put(outputParameterEntry.getKey(), outputParameterEntry.getValue());
322 // Validate the parameters for each side of the peered mode parameters
323 validatePeeredModePeers(EVENT_INPUT_PARAMETERS_STRING, result, peeredMode, inputParametersUsingMode,
324 outputParametersUsingMode);
325 validatePeeredModePeers(EVENT_OUTPUT_PARAMETERS_STRING, result, peeredMode, outputParametersUsingMode,
326 inputParametersUsingMode);
330 * This method validates that the settings are valid for the event handlers on one.
332 * @param handlerMapVariableName the variable name of the map on which the paired parameters are being checked
333 * @param result The result object to which to append any error messages
334 * @param leftModeParameters The mode parameters being checked
335 * @param rightModeParameters The mode parameters being referenced by the checked parameters
337 private void validatePeeredModePeers(final String handlerMapVariableName, final GroupValidationResult result,
338 final EventHandlerPeeredMode peeredMode, final Map<String, EventHandlerParameters> leftModeParameterMap,
339 final Map<String, EventHandlerParameters> rightModeParameterMap) {
341 // These sets are used to check for duplicate references on the both sides
342 final Set<String> leftCheckDuplicateSet = new HashSet<>();
343 final Set<String> rightCheckDuplicateSet = new HashSet<>();
345 // Check for missing peers, all peers are set because we have checked them previously so no
346 // need for null checks
347 for (final Entry<String, EventHandlerParameters> leftModeParameterEntry : leftModeParameterMap.entrySet()) {
348 final String leftSidePeer = leftModeParameterEntry.getValue().getPeer(peeredMode);
350 final EventHandlerParameters leftModeParameters = leftModeParameterEntry.getValue();
351 final EventHandlerParameters rightModeParameters = rightModeParameterMap.get(leftSidePeer);
353 // Check that the peer reference is OK
354 if (rightModeParameters == null) {
355 result.setResult(handlerMapVariableName, leftModeParameterEntry.getKey(), ValidationStatus.INVALID,
356 PEER_STRING + '"' + leftModeParameters.getPeer(peeredMode) + FOR_PEERED_MODE_STRING + peeredMode
357 + " does not exist or is not defined with the same peered mode");
361 // Now check that the right side peer is the left side event handler
362 final String rightSidePeer = rightModeParameters.getPeer(peeredMode);
363 if (!rightSidePeer.equals(leftModeParameterEntry.getKey())) {
364 result.setResult(handlerMapVariableName, leftModeParameterEntry.getKey(), ValidationStatus.INVALID,
365 PEER_STRING + '"' + leftModeParameters.getPeer(peeredMode) + FOR_PEERED_MODE_STRING + peeredMode
366 + ", value \"" + rightSidePeer + "\" on peer \"" + leftSidePeer
367 + "\" does not equal event handler \"" + leftModeParameterEntry.getKey() + "\"");
369 // Check for duplicates
370 if (!leftCheckDuplicateSet.add(leftSidePeer)) {
371 result.setResult(handlerMapVariableName, leftModeParameterEntry.getKey(), ValidationStatus.INVALID,
372 PEER_STRING + '"' + leftModeParameters.getPeer(peeredMode) + FOR_PEERED_MODE_STRING + peeredMode
373 + ", peer value \"" + leftSidePeer + "\" on event handler \""
374 + leftModeParameterEntry.getKey() + "\" is used more than once");
376 if (!rightCheckDuplicateSet.add(rightSidePeer)) {
377 result.setResult(handlerMapVariableName, leftModeParameterEntry.getKey(), ValidationStatus.INVALID,
378 PEER_STRING + '"' + leftModeParameters.getPeer(peeredMode) + FOR_PEERED_MODE_STRING + peeredMode
379 + ", peer value \"" + rightSidePeer + "\" on peer \"" + leftSidePeer
380 + "\" on event handler \"" + leftModeParameterEntry.getKey() + "\" is used more than once");
384 if (!crossCheckPeeredTimeoutValues(leftModeParameters, rightModeParameters, peeredMode)) {
385 result.setResult(handlerMapVariableName, leftModeParameterEntry.getKey(), ValidationStatus.INVALID,
386 PEER_STRING + '"' + leftModeParameters.getPeer(peeredMode) + FOR_PEERED_MODE_STRING + peeredMode
387 + " timeout " + leftModeParameters.getPeerTimeout(peeredMode) + " on event handler \""
388 + leftModeParameters.getName() + "\" does not equal timeout "
389 + rightModeParameters.getPeerTimeout(peeredMode) + " on event handler \""
390 + rightModeParameters.getName() + "\"");
397 * Validate the timeout values on two peers.
399 * @param leftModeParameters The parameters of the left hand peer
400 * @param peeredMode The peered mode being checked
401 * @return true if the timeout values are cross checked as being OK
403 private boolean crossCheckPeeredTimeoutValues(final EventHandlerParameters leftModeParameters,
404 final EventHandlerParameters rightModeParameters, final EventHandlerPeeredMode peeredMode) {
405 // Cross-set the timeouts if they are not specified
406 if (leftModeParameters.getPeerTimeout(peeredMode) != 0) {
407 if (rightModeParameters.getPeerTimeout(peeredMode) != 0) {
408 if (leftModeParameters.getPeerTimeout(peeredMode) != rightModeParameters.getPeerTimeout(peeredMode)) {
412 rightModeParameters.setPeerTimeout(peeredMode, leftModeParameters.getPeerTimeout(peeredMode));
415 if (rightModeParameters.getPeerTimeout(peeredMode) != 0) {
416 leftModeParameters.setPeerTimeout(peeredMode, rightModeParameters.getPeerTimeout(peeredMode));