2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2016-2018 Ericsson. All rights reserved.
4 * Modifications Copyright (C) 2019 Nordix Foundation.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.apex.model.eventmodel.concepts;
24 import java.util.List;
26 import java.util.Map.Entry;
28 import java.util.SortedMap;
29 import java.util.TreeMap;
30 import java.util.TreeSet;
31 import javax.persistence.CascadeType;
32 import javax.persistence.Column;
33 import javax.persistence.EmbeddedId;
34 import javax.persistence.Entity;
35 import javax.persistence.OneToMany;
36 import javax.persistence.Table;
37 import javax.xml.bind.Unmarshaller;
38 import javax.xml.bind.annotation.XmlAccessType;
39 import javax.xml.bind.annotation.XmlAccessorType;
40 import javax.xml.bind.annotation.XmlElement;
41 import javax.xml.bind.annotation.XmlRootElement;
42 import javax.xml.bind.annotation.XmlType;
43 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
44 import org.onap.policy.apex.model.basicmodel.concepts.AxConcept;
45 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
46 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationMessage;
47 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult;
48 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult;
49 import org.onap.policy.common.utils.validation.Assertions;
52 * This class defines an Apex event. An {@link AxEvent} is used to kick off execution of policies in Apex and is emitted
53 * by policies when they completer execution. In addition, Apex uses {@link AxEvent} instances internally to pass
54 * control from one Apex state to the next during execution.
56 * <p>The {@link AxArtifactKey} of an event uniquely identifies it in an Apex system and the name field in the key is
57 * the name of the event.
59 * <p>Each {@link AxEvent} has a name space, which is usually set to identify the domain of application of an event. For
60 * example a 4G cell power event might have the name space {@code org.onap.radio.4g} and the name {@code PowerEvent}.
61 * The source and target of the event are reserved to hold an identifier that defines the sender and receiver of an
62 * event respectively. The definition and structure of these fields is reserved for future use and their use by
63 * applications is currently not recommended.
65 * <p>The parameters that an event has are defined as a map of {@link AxField} instances.
67 * <p>Validation checks that the event key is valid. If name space is a blank string, a warning is issued. Blank source
68 * or target fields result in observations being issued. An event may not have any parameters. If it has parameters, the
69 * name and value of each parameter entry is checked to ensure they are not null. Then the local name of each parameter
70 * is checked to ensure it matches the event parameter key on the event. Finally, the parent key of each parameter is
71 * checked to ensure it matches the event key.
74 @Table(name = "AxEvent")
76 @XmlAccessorType(XmlAccessType.FIELD)
77 @XmlRootElement(name = "apexEvent", namespace = "http://www.onap.org/policy/apex-pdp")
78 @XmlType(name = "AxEvent", namespace = "http://www.onap.org/policy/apex-pdp", propOrder =
79 { "key", "nameSpace", "source", "target", "parameterMap" })
81 public class AxEvent extends AxConcept {
82 private static final long serialVersionUID = -1460388382582984269L;
84 private static final String WHITESPACE_REGEXP = "\\s+$";
86 /** The key of the event, unique in the Apex system. */
88 @XmlElement(name = "key", required = true)
89 // CHECKSTYLE:OFF: checkstyle:VisibilityMonitor
90 protected AxArtifactKey key;
91 // CHECKSTYLE:ON: checkstyle:VisibilityMonitor
93 @Column(name = "nameSpace")
94 @XmlElement(required = true)
95 private String nameSpace;
97 @Column(name = "source")
98 @XmlElement(required = true)
99 private String source;
101 @Column(name = "target")
102 @XmlElement(required = true)
103 private String target;
105 @OneToMany(cascade = CascadeType.ALL)
106 @XmlElement(name = "parameter", required = true)
107 private Map<String, AxField> parameterMap;
110 * The default constructor creates an event with a null artifact key. The event name space, source, and target are
111 * all defined as empty strings and the parameter map is initialized as an empty map.
114 this(new AxArtifactKey());
120 * @param copyConcept the concept to copy from
122 public AxEvent(final AxEvent copyConcept) {
127 * The default constructor creates an event with the given artifact key. The event name space, source, and target
128 * are all defined as empty strings and the parameter map is initialized as an empty map.
130 * @param key the key of the event
132 public AxEvent(final AxArtifactKey key) {
133 this(key, "", "", "", new TreeMap<String, AxField>());
137 * This constructor creates an event with the given artifact key and name space. The event source, and target are
138 * all defined as empty strings and the parameter map is initialized as an empty map.
140 * @param key the key of the event
141 * @param nameSpace the name space of the event
143 public AxEvent(final AxArtifactKey key, final String nameSpace) {
144 this(key, nameSpace, "", "", new TreeMap<String, AxField>());
148 * This constructor creates an event with the given artifact key, name space, source and target. The parameter map
149 * is initialized as an empty map.
151 * @param key the key of the event
152 * @param nameSpace the name space of the event
153 * @param source the source of the event
154 * @param target the target of the event
156 public AxEvent(final AxArtifactKey key, final String nameSpace, final String source, final String target) {
157 this(key, nameSpace, source, target, new TreeMap<String, AxField>());
161 * This constructor creates an event with all its fields defined.
163 * @param key the key of the event
164 * @param nameSpace the name space of the event
165 * @param source the source of the event
166 * @param target the target of the event
167 * @param parameterMap the map of parameters that the event has
169 public AxEvent(final AxArtifactKey key, final String nameSpace, final String source, final String target,
170 final SortedMap<String, AxField> parameterMap) {
172 Assertions.argumentNotNull(key, "key may not be null");
173 Assertions.argumentNotNull(nameSpace, "nameSpace may not be null");
174 Assertions.argumentNotNull(source, "source may not be null");
175 Assertions.argumentNotNull(target, "target may not be null");
176 Assertions.argumentNotNull(parameterMap, "parameterMap may not be null");
179 this.nameSpace = nameSpace;
180 this.source = source;
181 this.target = target;
182 this.parameterMap = parameterMap;
186 * This method checks that an event has all the fields in the {@code otherFieldSet} set defined on it.
188 * @param otherFieldSet the set of fields to check for existence on this event
189 * @return true, if all the {@code otherFieldSet} fields are defined on this event
191 public boolean hasFields(final Set<AxField> otherFieldSet) {
192 return parameterMap.values().containsAll(otherFieldSet);
196 * When an event is unmarshalled from disk or from the database, the parent key in the reference keys in its
197 * parameter map are not set. This method is called by JAXB after unmarshaling and is used to set the parent key of
198 * the {@link AxField} instances in the parameter map to be the key of the event that contains them.
200 * @param unmarshaler the unmarshaler that is unmarshaling the model
201 * @param parent the parent object of this object in the unmarshaler
203 public void afterUnmarshal(final Unmarshaller unmarshaler, final Object parent) {
204 for (final AxField parameter : parameterMap.values()) {
205 parameter.getKey().setParentArtifactKey(key);
213 public AxArtifactKey getKey() {
221 public List<AxKey> getKeys() {
222 final List<AxKey> keyList = key.getKeys();
224 for (final AxField field : parameterMap.values()) {
225 keyList.addAll(field.getKeys());
231 * Sets the key of the event.
233 * @param key the key of the event
235 public void setKey(final AxArtifactKey key) {
236 Assertions.argumentNotNull(key, "key may not be null");
239 for (final AxField parameter : parameterMap.values()) {
240 parameter.getKey().setParentArtifactKey(key);
245 * Gets the name space of the event.
247 * @return the name space of the event
249 public String getNameSpace() {
254 * Sets the name space of the event.
256 * @param nameSpace the name space of the event
258 public void setNameSpace(final String nameSpace) {
259 Assertions.argumentNotNull(nameSpace, "nameSpace may not be null");
260 this.nameSpace = nameSpace.trim();
264 * Gets the source of the event.
266 * @return the source of the event
268 public String getSource() {
273 * Sets the source of the event.
275 * @param source the source of the event
277 public void setSource(final String source) {
278 Assertions.argumentNotNull(source, "source may not be null");
279 this.source = source.trim();
283 * Gets the target of the event.
285 * @return the target of the event
287 public String getTarget() {
292 * Sets the target of the event.
294 * @param target the target of the event
296 public void setTarget(final String target) {
297 Assertions.argumentNotNull(target, "target may not be null");
298 this.target = target.trim();
302 * Gets the event parameter map.
304 * @return the event parameter map
306 public Map<String, AxField> getParameterMap() {
311 * Gets the fields defined on the event as a set.
313 * @return the fields defined on the event as a set
315 public Set<AxField> getFields() {
316 return new TreeSet<>(parameterMap.values());
320 * Sets the event parameter map, containing all the fields of the event.
322 * @param parameterMap the event parameter map
324 public void setParameterMap(final Map<String, AxField> parameterMap) {
325 Assertions.argumentNotNull(parameterMap, "parameterMap may not be null");
326 this.parameterMap = parameterMap;
333 public AxValidationResult validate(final AxValidationResult resultIn) {
334 AxValidationResult result = resultIn;
336 if (key.equals(AxArtifactKey.getNullKey())) {
337 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
338 "key is a null key"));
341 result = key.validate(result);
343 if (nameSpace.replaceAll(WHITESPACE_REGEXP, "").length() == 0) {
344 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.WARNING,
345 "nameSpace on event is blank"));
348 if (source.replaceAll(WHITESPACE_REGEXP, "").length() == 0) {
349 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.OBSERVATION,
350 "source on event is blank"));
353 if (target.replaceAll(WHITESPACE_REGEXP, "").length() == 0) {
354 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.OBSERVATION,
355 "target on event is blank"));
358 for (final Entry<String, AxField> eventParameterEntry : parameterMap.entrySet()) {
359 if (eventParameterEntry.getKey() == null || eventParameterEntry.getKey().equals(AxKey.NULL_KEY_NAME)) {
360 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
361 "key on parameter " + eventParameterEntry.getKey() + " may not be the null key"));
362 } else if (eventParameterEntry.getValue() == null) {
363 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
364 "value on parameter " + eventParameterEntry.getKey() + " may not be null"));
366 result = vaidateEventParameters(eventParameterEntry, result);
374 * Validate an event parameter entry.
376 * @param eventParameterEntry the event parameter entry
377 * @param result the validation result to append to
378 * @return The validation result
380 private AxValidationResult vaidateEventParameters(final Entry<String, AxField> eventParameterEntry,
381 final AxValidationResult result) {
382 if (!eventParameterEntry.getKey().equals(eventParameterEntry.getValue().getKey().getLocalName())) {
383 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
384 "key on parameter " + eventParameterEntry.getKey()
385 + " does not equal parameter field local name "
386 + eventParameterEntry.getValue().getKey().getLocalName()));
389 if (!eventParameterEntry.getValue().getKey().getParentArtifactKey().equals(key)) {
390 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
391 "parent key on parameter field " + eventParameterEntry.getValue().getKey()
392 + " does not equal event key"));
395 return eventParameterEntry.getValue().validate(result);
402 public void clean() {
404 nameSpace = nameSpace.trim();
405 source = source.trim();
406 target = target.trim();
413 public String toString() {
414 final StringBuilder builder = new StringBuilder();
415 builder.append(this.getClass().getSimpleName());
416 builder.append(":(");
417 builder.append("key=");
419 builder.append(",nameSpace=");
420 builder.append(nameSpace);
421 builder.append(",source=");
422 builder.append(source);
423 builder.append(",target=");
424 builder.append(target);
425 builder.append(",parameter=");
426 builder.append(parameterMap);
428 return builder.toString();
435 public AxConcept copyTo(final AxConcept targetObject) {
436 Assertions.argumentNotNull(targetObject, "targetObject may not be null");
438 final Object copyObject = targetObject;
439 Assertions.instanceOf(copyObject, AxEvent.class);
441 final AxEvent copy = (AxEvent) copyObject;
443 final Map<String, AxField> newParameterMap = new TreeMap<>();
444 for (final Entry<String, AxField> eventParameterMapEntry : parameterMap.entrySet()) {
445 newParameterMap.put(eventParameterMapEntry.getKey(), new AxField(eventParameterMapEntry.getValue()));
447 copy.setParameterMap(newParameterMap);
449 copy.setKey(new AxArtifactKey(key));
450 copy.setNameSpace(nameSpace);
451 copy.setSource(source);
452 copy.setTarget(target);
461 public int hashCode() {
462 final int prime = 31;
464 result = prime * result + key.hashCode();
465 result = prime * result + nameSpace.hashCode();
466 result = prime * result + source.hashCode();
467 result = prime * result + target.hashCode();
468 result = prime * result + parameterMap.hashCode();
476 public boolean equals(final Object obj) {
484 if (getClass() != obj.getClass()) {
488 final AxEvent other = (AxEvent) obj;
489 if (!key.equals(other.key)) {
492 if (!nameSpace.equals(other.nameSpace)) {
495 if (!source.equals(other.source)) {
498 if (!target.equals(other.target)) {
501 return parameterMap.equals(other.parameterMap);
508 public int compareTo(final AxConcept otherObj) {
509 if (otherObj == null) {
512 if (this == otherObj) {
515 if (getClass() != otherObj.getClass()) {
516 return this.hashCode() - otherObj.hashCode();
519 final AxEvent other = (AxEvent) otherObj;
520 if (!key.equals(other.key)) {
521 return key.compareTo(other.key);
523 if (!nameSpace.equals(other.nameSpace)) {
524 return nameSpace.compareTo(other.nameSpace);
526 if (!source.equals(other.source)) {
527 return source.compareTo(other.source);
529 if (!target.equals(other.target)) {
530 return target.compareTo(other.target);
532 if (!parameterMap.equals(other.parameterMap)) {
533 return (parameterMap.hashCode() - other.parameterMap.hashCode());