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.engine.event;
23 import java.io.Serializable;
24 import java.util.HashMap;
26 import java.util.Properties;
27 import java.util.concurrent.atomic.AtomicLong;
29 import lombok.EqualsAndHashCode;
31 import lombok.ToString;
33 import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * The Class ApexEvent is an event class that external systems use to send events to and receive
39 * events from Apex engines. The event itself is a hash map of string keys and object values, used
42 * @author Liam Fallon (liam.fallon@ericsson.com)
46 @EqualsAndHashCode(callSuper = false)
47 public class ApexEvent extends HashMap<String, Object> implements Serializable {
48 private static final long serialVersionUID = -4451918242101961685L;
50 // Get a reference to the logger
51 private static final Logger LOGGER = LoggerFactory.getLogger(ApexEvent.class);
53 // Recurring string constants
54 private static final String EVENT_PREAMBLE = "event \"";
56 // Holds the next identifier for event execution.
57 private static AtomicLong nextExecutionID = new AtomicLong(0L);
60 * The name of the Apex event, a mandatory field. All Apex events must have a name so that the
61 * event can be looked up in the Apex policy model.
63 public static final String NAME_HEADER_FIELD = "name";
66 * The version of the Apex event, an optional field. If a version is specified on an Apex event,
67 * the definition of that version of the event is taken from the Apex policy model. If no
68 * version is specified, the latest version of the event is used.
70 public static final String VERSION_HEADER_FIELD = "version";
73 * The name space of the Apex event, an optional field. If a name space is specified on an Apex
74 * event it must match the name space on the event definition taken from the Apex policy model.
75 * If no name space is specified, the name space from the event definition in the Apex policy
78 public static final String NAMESPACE_HEADER_FIELD = "nameSpace";
81 * The source of the Apex event, an optional field. It specifies where the Apex event has come
82 * from and its use is reserved for now. If no source is specified, the source from the event
83 * definition in the Apex policy model is used.
85 public static final String SOURCE_HEADER_FIELD = "source";
88 * The target of the Apex event, an optional field. It specifies where the Apex event is going
89 * to and its use is reserved for now. If no target is specified, the target from the event
90 * definition in the Apex policy model is used.
92 public static final String TARGET_HEADER_FIELD = "target";
95 * The exception message field of an Apex event is an exception message indicating that an event
98 public static final String EXCEPTION_MESSAGE_HEADER_FIELD = "exceptionMessage";
100 /** The name of an Apex event must match this regular expression. */
101 public static final String NAME_REGEXP = "[A-Za-z0-9\\-_.]+";
103 /** The version of an Apex event must match this regular expression. */
104 public static final String VERSION_REGEXP = "[A-Za-z0-9.]+";
106 /** The name space of an Apex event must match this regular expression. */
107 public static final String NAMESPACE_REGEXP = "([a-zA_Z_][\\.\\w]*)";
109 /** The source of an Apex event must match this regular expression. */
110 public static final String SOURCE_REGEXP = "^$|[A-Za-z0-9\\.\\-_:]+";
112 /** The target of an Apex event must match this regular expression. */
113 public static final String TARGET_REGEXP = SOURCE_REGEXP;
115 // The standard fields of the event
116 private final String name;
117 private final String version;
118 private final String nameSpace;
119 private final String source;
120 private final String target;
122 // An identifier for the current event execution. The default value here will always be unique
124 private long executionId = ApexEvent.getNextExecutionId();
126 // Event related properties used during processing of this event
127 private Properties executionProperties = new Properties();
129 // A string holding a message that indicates why processing of this event threw an exception
130 private String exceptionMessage;
133 * Instantiates a new apex event.
135 * @param name the name of the event
136 * @param version the version of the event
137 * @param nameSpace the name space (java package) of the event
138 * @param source the source of the event
139 * @param target the target of the event
140 * @throws ApexEventException thrown on validation errors on event names and versions
142 public ApexEvent(final String name, final String version, final String nameSpace, final String source,
143 final String target) throws ApexEventException {
145 this.name = validateField(NAME_HEADER_FIELD, name, NAME_REGEXP);
146 this.version = validateField(VERSION_HEADER_FIELD, version, VERSION_REGEXP);
147 this.nameSpace = validateField(NAMESPACE_HEADER_FIELD, nameSpace, NAMESPACE_REGEXP);
148 this.source = validateField(SOURCE_HEADER_FIELD, source, SOURCE_REGEXP);
149 this.target = validateField(TARGET_HEADER_FIELD, target, TARGET_REGEXP);
154 * Private utility to get the next candidate value for a Execution ID. This value will always be
155 * unique in a single JVM
157 * @return the next candidate value for a Execution ID
159 private static synchronized long getNextExecutionId() {
160 return nextExecutionID.getAndIncrement();
164 * Check that a field of the event is valid.
166 * @param fieldName the name of the field to check
167 * @param fieldValue the value of the field to check
168 * @param fieldRegexp the regular expression to check the field against
169 * @return the validated field value
170 * @throws ApexEventException thrown if the field is invalid
172 private String validateField(final String fieldName, final String fieldValue, final String fieldRegexp)
173 throws ApexEventException {
174 if (fieldValue.matches(fieldRegexp)) {
177 String message = EVENT_PREAMBLE + name + ": field \"" + fieldName + "=" + fieldValue
178 + "\" is illegal. It doesn't match regex '" + fieldRegexp + "'";
179 LOGGER.warn(message);
180 throw new ApexEventException(message);
185 * Check that the key of an event is valid.
189 * @throws ApexEventException the apex event exception
191 private String validKey(final String key) throws ApexEventException {
192 if (key.matches(AxReferenceKey.LOCAL_NAME_REGEXP)) {
195 String message = EVENT_PREAMBLE + name + ": key \"" + key + "\" is illegal";
196 LOGGER.warn(message);
197 throw new ApexEventException(message);
202 * Sets the pass-thru executionID for this event.
204 * <p>The default value for executionID is unique in the current JVM. For some applications/deployments this
205 * executionID may need to be globally unique
207 * @param executionId the executionID
209 public void setExecutionId(final long executionId) {
210 this.executionId = executionId;
214 * Set the execution properties for this event.
216 * @param executionProperties the execution properties to set
218 public void setExecutionProperties(Properties executionProperties) {
219 this.executionProperties = executionProperties;
223 * Sets the exception message explaining why processing of this event to fail.
225 * @param exceptionMessage the exception message
227 public void setExceptionMessage(final String exceptionMessage) {
228 this.exceptionMessage = exceptionMessage;
232 * Map overrides from here
239 public Object put(final String key, final Object value) {
240 // Check if the key is valid
242 return super.put(validKey(key), value);
243 } catch (final ApexEventException e) {
244 if (LOGGER.isTraceEnabled()) {
245 LOGGER.trace("put failed", e);
255 public void putAll(final Map<? extends String, ? extends Object> incomingMap) {
256 // Check the keys are valid
258 for (final String key : incomingMap.keySet()) {
261 } catch (final ApexEventException e) {
262 if (LOGGER.isTraceEnabled()) {
263 LOGGER.trace("putAll failed", e);
266 // One of the keys is invalid
270 // Go ahead and put everything
271 super.putAll(incomingMap);