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;
28 import lombok.EqualsAndHashCode;
30 import lombok.ToString;
31 import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * The Class ApexEvent is an event class that external systems use to send events to and receive
37 * events from Apex engines. The event itself is a hash map of string keys and object values, used
40 * @author Liam Fallon (liam.fallon@ericsson.com)
44 @EqualsAndHashCode(callSuper = false)
45 public class ApexEvent extends HashMap<String, Object> implements Serializable {
46 private static final long serialVersionUID = -4451918242101961685L;
48 // Get a reference to the logger
49 private static final Logger LOGGER = LoggerFactory.getLogger(ApexEvent.class);
51 // Recurring string constants
52 private static final String EVENT_PREAMBLE = "event \"";
54 // Holds the next identifier for event execution.
55 private static AtomicLong nextExecutionID = new AtomicLong(0L);
58 * The name of the Apex event, a mandatory field. All Apex events must have a name so that the
59 * event can be looked up in the Apex policy model.
61 public static final String NAME_HEADER_FIELD = "name";
64 * The version of the Apex event, an optional field. If a version is specified on an Apex event,
65 * the definition of that version of the event is taken from the Apex policy model. If no
66 * version is specified, the latest version of the event is used.
68 public static final String VERSION_HEADER_FIELD = "version";
71 * The name space of the Apex event, an optional field. If a name space is specified on an Apex
72 * event it must match the name space on the event definition taken from the Apex policy model.
73 * If no name space is specified, the name space from the event definition in the Apex policy
76 public static final String NAMESPACE_HEADER_FIELD = "nameSpace";
79 * The source of the Apex event, an optional field. It specifies where the Apex event has come
80 * from and its use is reserved for now. If no source is specified, the source from the event
81 * definition in the Apex policy model is used.
83 public static final String SOURCE_HEADER_FIELD = "source";
86 * The target of the Apex event, an optional field. It specifies where the Apex event is going
87 * to and its use is reserved for now. If no target is specified, the target from the event
88 * definition in the Apex policy model is used.
90 public static final String TARGET_HEADER_FIELD = "target";
93 * The exception message field of an Apex event is an exception message indicating that an event
96 public static final String EXCEPTION_MESSAGE_HEADER_FIELD = "exceptionMessage";
98 /** The name of an Apex event must match this regular expression. */
99 public static final String NAME_REGEXP = "[A-Za-z0-9\\-_.]+";
101 /** The version of an Apex event must match this regular expression. */
102 public static final String VERSION_REGEXP = "[A-Za-z0-9.]+";
104 /** The name space of an Apex event must match this regular expression. */
105 public static final String NAMESPACE_REGEXP = "([a-zA_Z_][\\.\\w]*)";
107 /** The source of an Apex event must match this regular expression. */
108 public static final String SOURCE_REGEXP = "^$|[A-Za-z0-9\\.\\-_:]+";
110 /** The target of an Apex event must match this regular expression. */
111 public static final String TARGET_REGEXP = SOURCE_REGEXP;
113 // The standard fields of the event
114 private final String name;
115 private final String version;
116 private final String nameSpace;
117 private final String source;
118 private final String target;
120 // An identifier for the current event execution. The default value here will always be unique
122 private long executionId = ApexEvent.getNextExecutionId();
124 // Event related properties used during processing of this event
125 private Properties executionProperties = new Properties();
127 // A string holding a message that indicates why processing of this event threw an exception
128 private String exceptionMessage;
131 * Instantiates a new apex event.
133 * @param name the name of the event
134 * @param version the version of the event
135 * @param nameSpace the name space (java package) of the event
136 * @param source the source of the event
137 * @param target the target of the event
138 * @throws ApexEventException thrown on validation errors on event names and versions
140 public ApexEvent(final String name, final String version, final String nameSpace, final String source,
141 final String target) throws ApexEventException {
143 this.name = validateField(NAME_HEADER_FIELD, name, NAME_REGEXP);
144 this.version = validateField(VERSION_HEADER_FIELD, version, VERSION_REGEXP);
145 this.nameSpace = validateField(NAMESPACE_HEADER_FIELD, nameSpace, NAMESPACE_REGEXP);
146 this.source = validateField(SOURCE_HEADER_FIELD, source, SOURCE_REGEXP);
147 this.target = validateField(TARGET_HEADER_FIELD, target, TARGET_REGEXP);
152 * Private utility to get the next candidate value for a Execution ID. This value will always be
153 * unique in a single JVM
155 * @return the next candidate value for a Execution ID
157 private static synchronized long getNextExecutionId() {
158 return nextExecutionID.getAndIncrement();
162 * Check that a field of the event is valid.
164 * @param fieldName the name of the field to check
165 * @param fieldValue the value of the field to check
166 * @param fieldRegexp the regular expression to check the field against
167 * @return the validated field value
168 * @throws ApexEventException thrown if the field is invalid
170 private String validateField(final String fieldName, final String fieldValue, final String fieldRegexp)
171 throws ApexEventException {
172 if (fieldValue.matches(fieldRegexp)) {
175 String message = EVENT_PREAMBLE + name + ": field \"" + fieldName + "=" + fieldValue
176 + "\" is illegal. It doesn't match regex '" + fieldRegexp + "'";
177 LOGGER.warn(message);
178 throw new ApexEventException(message);
183 * Check that the key of an event is valid.
187 * @throws ApexEventException the apex event exception
189 private String validKey(final String key) throws ApexEventException {
190 if (key.matches(AxReferenceKey.LOCAL_NAME_REGEXP)) {
193 String message = EVENT_PREAMBLE + name + ": key \"" + key + "\" is illegal";
194 LOGGER.warn(message);
195 throw new ApexEventException(message);
200 * Sets the pass-thru executionID for this event.
202 * <p>The default value for executionID is unique in the current JVM. For some applications/deployments this
203 * executionID may need to be globally unique
205 * @param executionId the executionID
207 public void setExecutionId(final long executionId) {
208 this.executionId = executionId;
212 * Set the execution properties for this event.
214 * @param executionProperties the execution properties to set
216 public void setExecutionProperties(Properties executionProperties) {
217 this.executionProperties = executionProperties;
221 * Sets the exception message explaining why processing of this event to fail.
223 * @param exceptionMessage the exception message
225 public void setExceptionMessage(final String exceptionMessage) {
226 this.exceptionMessage = exceptionMessage;
230 * Map overrides from here
237 public Object put(final String key, final Object value) {
238 // Check if the key is valid
240 return super.put(validKey(key), value);
241 } catch (final ApexEventException e) {
242 if (LOGGER.isTraceEnabled()) {
243 LOGGER.trace("put failed", e);
253 public void putAll(final Map<? extends String, ? extends Object> incomingMap) {
254 // Check the keys are valid
256 for (final String key : incomingMap.keySet()) {
259 } catch (final ApexEventException e) {
260 if (LOGGER.isTraceEnabled()) {
261 LOGGER.trace("putAll failed", e);
264 // One of the keys is invalid
268 // Go ahead and put everything
269 super.putAll(incomingMap);