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;
32 import javax.persistence.CascadeType;
33 import javax.persistence.Column;
34 import javax.persistence.EmbeddedId;
35 import javax.persistence.Entity;
36 import javax.persistence.OneToMany;
37 import javax.persistence.Table;
38 import javax.xml.bind.Unmarshaller;
39 import javax.xml.bind.annotation.XmlAccessType;
40 import javax.xml.bind.annotation.XmlAccessorType;
41 import javax.xml.bind.annotation.XmlElement;
42 import javax.xml.bind.annotation.XmlRootElement;
43 import javax.xml.bind.annotation.XmlType;
45 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
46 import org.onap.policy.apex.model.basicmodel.concepts.AxConcept;
47 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
48 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationMessage;
49 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult;
50 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult;
51 import org.onap.policy.common.utils.validation.Assertions;
54 * This class defines an Apex event. An {@link AxEvent} is used to kick off execution of policies in Apex and is emitted
55 * by policies when they completer execution. In addition, Apex uses {@link AxEvent} instances internally to pass
56 * control from one Apex state to the next during execution.
58 * <p>The {@link AxArtifactKey} of an event uniquely identifies it in an Apex system and the name field in the key is
59 * the name of the event.
61 * <p>Each {@link AxEvent} has a name space, which is usually set to identify the domain of application of an event. For
62 * example a 4G cell power event might have the name space {@code org.onap.radio.4g} and the name {@code PowerEvent}.
63 * The source and target of the event are reserved to hold an identifier that defines the sender and receiver of an
64 * event respectively. The definition and structure of these fields is reserved for future use and their use by
65 * applications is currently not recommended.
67 * <p>The parameters that an event has are defined as a map of {@link AxField} instances.
69 * <p>Validation checks that the event key is valid. If name space is a blank string, a warning is issued. Blank source
70 * or target fields result in observations being issued. An event may not have any parameters. If it has parameters, the
71 * name and value of each parameter entry is checked to ensure they are not null. Then the local name of each parameter
72 * is checked to ensure it matches the event parameter key on the event. Finally, the parent key of each parameter is
73 * checked to ensure it matches the event key.
76 @Table(name = "AxEvent")
78 @XmlAccessorType(XmlAccessType.FIELD)
79 @XmlRootElement(name = "apexEvent", namespace = "http://www.onap.org/policy/apex-pdp")
80 @XmlType(name = "AxEvent", namespace = "http://www.onap.org/policy/apex-pdp", propOrder =
81 { "key", "nameSpace", "source", "target", "parameterMap" })
83 public class AxEvent extends AxConcept {
84 private static final long serialVersionUID = -1460388382582984269L;
86 private static final String WHITESPACE_REGEXP = "\\s+$";
88 /** The key of the event, unique in the Apex system. */
90 @XmlElement(name = "key", required = true)
91 // CHECKSTYLE:OFF: checkstyle:VisibilityMonitor
92 protected AxArtifactKey key;
93 // CHECKSTYLE:ON: checkstyle:VisibilityMonitor
95 @Column(name = "nameSpace")
96 @XmlElement(required = true)
97 private String nameSpace;
99 @Column(name = "source")
100 @XmlElement(required = true)
101 private String source;
103 @Column(name = "target")
104 @XmlElement(required = true)
105 private String target;
107 @OneToMany(cascade = CascadeType.ALL)
108 @XmlElement(name = "parameter", required = true)
109 private Map<String, AxField> parameterMap;
112 * The default constructor creates an event with a null artifact key. The event name space, source, and target are
113 * all defined as empty strings and the parameter map is initialized as an empty map.
116 this(new AxArtifactKey());
122 * @param copyConcept the concept to copy from
124 public AxEvent(final AxEvent copyConcept) {
129 * The default constructor creates an event with the given artifact key. The event name space, source, and target
130 * are all defined as empty strings and the parameter map is initialized as an empty map.
132 * @param key the key of the event
134 public AxEvent(final AxArtifactKey key) {
135 this(key, "", "", "", new TreeMap<String, AxField>());
139 * This constructor creates an event with the given artifact key and name space. The event source, and target are
140 * all defined as empty strings and the parameter map is initialized as an empty map.
142 * @param key the key of the event
143 * @param nameSpace the name space of the event
145 public AxEvent(final AxArtifactKey key, final String nameSpace) {
146 this(key, nameSpace, "", "", new TreeMap<String, AxField>());
150 * This constructor creates an event with the given artifact key, name space, source and target. The parameter map
151 * is initialized as an empty map.
153 * @param key the key of the event
154 * @param nameSpace the name space of the event
155 * @param source the source of the event
156 * @param target the target of the event
158 public AxEvent(final AxArtifactKey key, final String nameSpace, final String source, final String target) {
159 this(key, nameSpace, source, target, new TreeMap<String, AxField>());
163 * This constructor creates an event with all its fields defined.
165 * @param key the key of the event
166 * @param nameSpace the name space of the event
167 * @param source the source of the event
168 * @param target the target of the event
169 * @param parameterMap the map of parameters that the event has
171 public AxEvent(final AxArtifactKey key, final String nameSpace, final String source, final String target,
172 final SortedMap<String, AxField> parameterMap) {
174 Assertions.argumentNotNull(key, "key may not be null");
175 Assertions.argumentNotNull(nameSpace, "nameSpace may not be null");
176 Assertions.argumentNotNull(source, "source may not be null");
177 Assertions.argumentNotNull(target, "target may not be null");
178 Assertions.argumentNotNull(parameterMap, "parameterMap may not be null");
181 this.nameSpace = nameSpace;
182 this.source = source;
183 this.target = target;
184 this.parameterMap = parameterMap;
188 * This method checks that an event has all the fields in the {@code otherFieldSet} set defined on it.
190 * @param otherFieldSet the set of fields to check for existence on this event
191 * @return true, if all the {@code otherFieldSet} fields are defined on this event
193 public boolean hasFields(final Set<AxField> otherFieldSet) {
194 return parameterMap.values().containsAll(otherFieldSet);
198 * When an event is unmarshalled from disk or from the database, the parent key in the reference keys in its
199 * parameter map are not set. This method is called by JAXB after unmarshaling and is used to set the parent key of
200 * the {@link AxField} instances in the parameter map to be the key of the event that contains them.
202 * @param unmarshaler the unmarshaler that is unmarshaling the model
203 * @param parent the parent object of this object in the unmarshaler
205 public void afterUnmarshal(final Unmarshaller unmarshaler, final Object parent) {
206 for (final AxField parameter : parameterMap.values()) {
207 parameter.getKey().setParentArtifactKey(key);
215 public AxArtifactKey getKey() {
223 public List<AxKey> getKeys() {
224 final List<AxKey> keyList = key.getKeys();
226 for (final AxField field : parameterMap.values()) {
227 keyList.addAll(field.getKeys());
233 * Sets the key of the event.
235 * @param key the key of the event
237 public void setKey(final AxArtifactKey key) {
238 Assertions.argumentNotNull(key, "key may not be null");
241 for (final AxField parameter : parameterMap.values()) {
242 parameter.getKey().setParentArtifactKey(key);
247 * Gets the name space of the event.
249 * @return the name space of the event
251 public String getNameSpace() {
256 * Sets the name space of the event.
258 * @param nameSpace the name space of the event
260 public void setNameSpace(final String nameSpace) {
261 Assertions.argumentNotNull(nameSpace, "nameSpace may not be null");
262 this.nameSpace = nameSpace.trim();
266 * Gets the source of the event.
268 * @return the source of the event
270 public String getSource() {
275 * Sets the source of the event.
277 * @param source the source of the event
279 public void setSource(final String source) {
280 Assertions.argumentNotNull(source, "source may not be null");
281 this.source = source.trim();
285 * Gets the target of the event.
287 * @return the target of the event
289 public String getTarget() {
294 * Sets the target of the event.
296 * @param target the target of the event
298 public void setTarget(final String target) {
299 Assertions.argumentNotNull(target, "target may not be null");
300 this.target = target.trim();
304 * Gets the event parameter map.
306 * @return the event parameter map
308 public Map<String, AxField> getParameterMap() {
313 * Gets the fields defined on the event as a set.
315 * @return the fields defined on the event as a set
317 public Set<AxField> getFields() {
318 return new TreeSet<>(parameterMap.values());
322 * Sets the event parameter map, containing all the fields of the event.
324 * @param parameterMap the event parameter map
326 public void setParameterMap(final Map<String, AxField> parameterMap) {
327 Assertions.argumentNotNull(parameterMap, "parameterMap may not be null");
328 this.parameterMap = parameterMap;
335 public AxValidationResult validate(final AxValidationResult resultIn) {
336 AxValidationResult result = resultIn;
338 if (key.equals(AxArtifactKey.getNullKey())) {
339 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
340 "key is a null key"));
343 result = key.validate(result);
345 if (nameSpace.replaceAll(WHITESPACE_REGEXP, "").length() == 0) {
346 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.WARNING,
347 "nameSpace on event is blank"));
350 if (source.replaceAll(WHITESPACE_REGEXP, "").length() == 0) {
351 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.OBSERVATION,
352 "source on event is blank"));
355 if (target.replaceAll(WHITESPACE_REGEXP, "").length() == 0) {
356 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.OBSERVATION,
357 "target on event is blank"));
360 for (final Entry<String, AxField> eventParameterEntry : parameterMap.entrySet()) {
361 if (eventParameterEntry.getKey() == null || eventParameterEntry.getKey().equals(AxKey.NULL_KEY_NAME)) {
362 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
363 "key on parameter " + eventParameterEntry.getKey() + " may not be the null key"));
364 } else if (eventParameterEntry.getValue() == null) {
365 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
366 "value on parameter " + eventParameterEntry.getKey() + " may not be null"));
368 result = vaidateEventParameters(eventParameterEntry, result);
376 * Validate an event parameter entry.
378 * @param eventParameterEntry the event parameter entry
379 * @param result the validation result to append to
380 * @return The validation result
382 private AxValidationResult vaidateEventParameters(final Entry<String, AxField> eventParameterEntry,
383 final AxValidationResult result) {
384 if (!eventParameterEntry.getKey().equals(eventParameterEntry.getValue().getKey().getLocalName())) {
385 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
386 "key on parameter " + eventParameterEntry.getKey()
387 + " does not equal parameter field local name "
388 + eventParameterEntry.getValue().getKey().getLocalName()));
391 if (!eventParameterEntry.getValue().getKey().getParentArtifactKey().equals(key)) {
392 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
393 "parent key on parameter field " + eventParameterEntry.getValue().getKey()
394 + " does not equal event key"));
397 return eventParameterEntry.getValue().validate(result);
404 public void clean() {
406 nameSpace = nameSpace.trim();
407 source = source.trim();
408 target = target.trim();
415 public String toString() {
416 final StringBuilder builder = new StringBuilder();
417 builder.append(this.getClass().getSimpleName());
418 builder.append(":(");
419 builder.append("key=");
421 builder.append(",nameSpace=");
422 builder.append(nameSpace);
423 builder.append(",source=");
424 builder.append(source);
425 builder.append(",target=");
426 builder.append(target);
427 builder.append(",parameter=");
428 builder.append(parameterMap);
430 return builder.toString();
437 public AxConcept copyTo(final AxConcept targetObject) {
438 Assertions.argumentNotNull(targetObject, "targetObject may not be null");
440 final Object copyObject = targetObject;
441 Assertions.instanceOf(copyObject, AxEvent.class);
443 final AxEvent copy = (AxEvent) copyObject;
445 final Map<String, AxField> newParameterMap = new TreeMap<>();
446 for (final Entry<String, AxField> eventParameterMapEntry : parameterMap.entrySet()) {
447 newParameterMap.put(eventParameterMapEntry.getKey(), new AxField(eventParameterMapEntry.getValue()));
449 copy.setParameterMap(newParameterMap);
451 copy.setKey(new AxArtifactKey(key));
452 copy.setNameSpace(nameSpace);
453 copy.setSource(source);
454 copy.setTarget(target);
463 public int hashCode() {
464 final int prime = 31;
466 result = prime * result + key.hashCode();
467 result = prime * result + nameSpace.hashCode();
468 result = prime * result + source.hashCode();
469 result = prime * result + target.hashCode();
470 result = prime * result + parameterMap.hashCode();
478 public boolean equals(final Object obj) {
486 if (getClass() != obj.getClass()) {
490 final AxEvent other = (AxEvent) obj;
491 if (!key.equals(other.key)) {
494 if (!nameSpace.equals(other.nameSpace)) {
497 if (!source.equals(other.source)) {
500 if (!target.equals(other.target)) {
503 return parameterMap.equals(other.parameterMap);
510 public int compareTo(final AxConcept otherObj) {
511 if (otherObj == null) {
514 if (this == otherObj) {
517 if (getClass() != otherObj.getClass()) {
518 return this.hashCode() - otherObj.hashCode();
521 final AxEvent other = (AxEvent) otherObj;
522 if (!key.equals(other.key)) {
523 return key.compareTo(other.key);
525 if (!nameSpace.equals(other.nameSpace)) {
526 return nameSpace.compareTo(other.nameSpace);
528 if (!source.equals(other.source)) {
529 return target.compareTo(other.source);
531 if (!target.equals(other.target)) {
532 return target.compareTo(other.target);
534 if (!parameterMap.equals(other.parameterMap)) {
535 return (parameterMap.hashCode() - other.parameterMap.hashCode());