2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2016-2018 Ericsson. All rights reserved.
4 * Modifications Copyright (C) 2019-2022 Nordix Foundation.
5 * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * SPDX-License-Identifier: Apache-2.0
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.apex.model.basicmodel.concepts;
25 import java.util.List;
27 import java.util.Map.Entry;
28 import java.util.NavigableMap;
30 import java.util.TreeMap;
31 import java.util.TreeSet;
32 import java.util.UUID;
33 import javax.xml.bind.Unmarshaller;
34 import javax.xml.bind.annotation.XmlAccessType;
35 import javax.xml.bind.annotation.XmlAccessorType;
36 import javax.xml.bind.annotation.XmlElement;
37 import javax.xml.bind.annotation.XmlType;
38 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult;
39 import org.onap.policy.common.utils.validation.Assertions;
42 * The Class AxKeyInformation holds a map of the key information for the entire Apex model. All Apex models
43 * {@link AxModel} must have an {@link AxKeyInformation} field. The {@link AxKeyInformation} class implements the helper
44 * methods of the {@link AxConceptGetter} interface to allow {@link AxKeyInfo} instances to be retrieved by calling
45 * methods directly on this class without referencing the contained map.
47 * <p>Validation checks that the key is not null, that the key information map is not empty, that each key and value in
48 * the map is defined, that the key in each map entry matches the key if each entry value, and that no duplicate UUIDs
49 * exist. Each key information entry is then validated individually.
51 @XmlAccessorType(XmlAccessType.FIELD)
52 @XmlType(name = "AxKeyInformation", namespace = "http://www.onap.org/policy/apex-pdp",
53 propOrder = { "key", "keyInfoMap" })
55 public class AxKeyInformation extends AxConcept implements AxConceptGetter<AxKeyInfo> {
56 private static final long serialVersionUID = -2746380769017043888L;
58 @XmlElement(name = "key", required = true)
59 private AxArtifactKey key;
61 private Map<AxArtifactKey, AxKeyInfo> keyInfoMap;
64 * The Default Constructor creates this concept with a null key.
66 public AxKeyInformation() {
67 this(new AxArtifactKey());
73 * @param copyConcept the concept to copy from
75 public AxKeyInformation(final AxKeyInformation copyConcept) {
80 * Constructor to create this concept with the specified key.
82 * @param key the key of the concept
84 public AxKeyInformation(final AxArtifactKey key) {
85 this(key, new TreeMap<>());
89 * Constructor to create this concept and set all its fields.
91 * @param key the key of the concept
92 * @param keyInfoMap the key info map of the concept
94 public AxKeyInformation(final AxArtifactKey key, final Map<AxArtifactKey, AxKeyInfo> keyInfoMap) {
96 Assertions.argumentNotNull(key, "key may not be null");
97 Assertions.argumentNotNull(keyInfoMap, "keyInfoMap may not be null");
100 this.keyInfoMap = new TreeMap<>();
101 this.keyInfoMap.putAll(keyInfoMap);
105 * When a model is unmarshalled from disk or from the database, the key information map is returned as a raw Hash
106 * Map. This method is called by JAXB after unmarshaling and is used to convert the hash map to a
107 * {@link NavigableMap} so that it will work with the {@link AxConceptGetter} interface.
109 * @param unmarshaler the unmarshaler that is unmarshaling the model
110 * @param parent the parent object of this object in the unmarshaler
112 public void afterUnmarshal(final Unmarshaller unmarshaler, final Object parent) {
113 // The map must be navigable to allow name and version searching,
114 // unmarshaling returns a hash map
115 final NavigableMap<AxArtifactKey, AxKeyInfo> navigablekeyInfoMap = new TreeMap<>();
116 navigablekeyInfoMap.putAll(keyInfoMap);
117 keyInfoMap = navigablekeyInfoMap;
121 * This method generates default key information for all keys found in the concept passed in as a parameter that do
122 * not already have key information.
124 * @param concept the concept for which to generate key information
126 public void generateKeyInfo(final AxConcept concept) {
127 for (final AxKey axKey : concept.getKeys()) {
128 if (!(axKey instanceof AxArtifactKey)) {
132 final AxArtifactKey artifactKey = (AxArtifactKey) axKey;
134 keyInfoMap.computeIfAbsent(artifactKey, unusedKey -> {
135 final var keyInfo = new AxKeyInfo(artifactKey);
136 // generate a reproducible UUID
137 keyInfo.setUuid(AxKeyInfo.generateReproducibleUuid(keyInfo.getId() + keyInfo.getDescription()));
147 public AxArtifactKey getKey() {
155 public List<AxKey> getKeys() {
156 final List<AxKey> keyList = key.getKeys();
157 keyList.addAll(keyInfoMap.keySet());
163 * Sets the key of this concept.
165 * @param key the key of this concept
167 public void setKey(final AxArtifactKey key) {
168 Assertions.argumentNotNull(key, "key may not be null");
173 * Gets the key info map of this concept.
175 * @return the key info map of this concept
177 public Map<AxArtifactKey, AxKeyInfo> getKeyInfoMap() {
182 * Sets the key info map of this concept.
184 * @param keyInfoMap the key info map of this concept
186 public void setKeyInfoMap(final Map<AxArtifactKey, AxKeyInfo> keyInfoMap) {
187 Assertions.argumentNotNull(keyInfoMap, "keyInfoMap may not be null");
188 this.keyInfoMap = new TreeMap<>();
189 this.keyInfoMap.putAll(keyInfoMap);
196 public AxValidationResult validate(final AxValidationResult resultIn) {
197 AxValidationResult result = resultIn;
199 if (key.equals(AxArtifactKey.getNullKey())) {
200 result.addValidationMessage(
201 new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key"));
204 result = key.validate(result);
206 if (keyInfoMap.size() == 0) {
207 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
208 "keyInfoMap may not be empty"));
210 final Set<UUID> uuidSet = new TreeSet<>();
212 for (final Entry<AxArtifactKey, AxKeyInfo> keyInfoEntry : keyInfoMap.entrySet()) {
213 result = validateKeyInfoEntry(keyInfoEntry, uuidSet, result);
221 * Validate an key information entry.
223 * @param keyInfoEntry the key information entry
224 * @param uuidSet the set of UUIDs encountered in validation so far, the UUID of this entry is added to the set
225 * @param result the validation result to append to
226 * @return The validation result
228 private AxValidationResult validateKeyInfoEntry(final Entry<AxArtifactKey, AxKeyInfo> keyInfoEntry,
229 final Set<UUID> uuidSet, AxValidationResult result) {
230 if (keyInfoEntry.getKey().equals(AxArtifactKey.getNullKey())) {
231 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
232 "key on keyInfoMap entry " + keyInfoEntry.getKey() + " may not be the null key"));
233 } else if (keyInfoEntry.getValue() == null) {
234 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
235 "value on keyInfoMap entry " + keyInfoEntry.getKey() + " may not be null"));
237 if (!keyInfoEntry.getKey().equals(keyInfoEntry.getValue().getKey())) {
238 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
239 "key on keyInfoMap entry " + keyInfoEntry.getKey() + " does not equal entry key "
240 + keyInfoEntry.getValue().getKey()));
243 result = keyInfoEntry.getValue().validate(result);
245 if (uuidSet.contains(keyInfoEntry.getValue().getUuid())) {
246 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
247 "duplicate UUID found on keyInfoMap entry " + keyInfoEntry.getKey() + ":"
248 + keyInfoEntry.getValue().getUuid()));
250 uuidSet.add(keyInfoEntry.getValue().getUuid());
261 public void clean() {
263 for (final Entry<AxArtifactKey, AxKeyInfo> keyInfoEntry : keyInfoMap.entrySet()) {
264 keyInfoEntry.getKey().clean();
265 keyInfoEntry.getValue().clean();
273 public String toString() {
274 final var builder = new StringBuilder();
275 builder.append(this.getClass().getSimpleName());
276 builder.append(":(");
277 builder.append("key=");
279 builder.append(",keyInfoMap=");
280 builder.append(keyInfoMap);
282 return builder.toString();
289 public AxConcept copyTo(final AxConcept target) {
290 Assertions.argumentNotNull(target, "target may not be null");
292 final Object copyObject = target;
293 Assertions.instanceOf(copyObject, AxKeyInformation.class);
295 final AxKeyInformation copy = ((AxKeyInformation) copyObject);
296 copy.setKey(new AxArtifactKey(key));
297 final Map<AxArtifactKey, AxKeyInfo> newKeyInfoMap = new TreeMap<>();
298 for (final Entry<AxArtifactKey, AxKeyInfo> keyInfoMapEntry : keyInfoMap.entrySet()) {
299 newKeyInfoMap.put(new AxArtifactKey(keyInfoMapEntry.getKey()), new AxKeyInfo(keyInfoMapEntry.getValue()));
301 copy.setKeyInfoMap(newKeyInfoMap);
310 public int hashCode() {
311 final var prime = 31;
313 result = prime * result + key.hashCode();
314 result = prime * result + keyInfoMap.hashCode();
322 public boolean equals(final Object obj) {
330 if (getClass() != obj.getClass()) {
334 final AxKeyInformation other = (AxKeyInformation) obj;
335 if (!key.equals(other.key)) {
338 return keyInfoMap.equals(other.keyInfoMap);
345 public int compareTo(final AxConcept otherObj) {
346 if (otherObj == null) {
349 if (this == otherObj) {
352 if (getClass() != otherObj.getClass()) {
353 return this.hashCode() - otherObj.hashCode();
356 final AxKeyInformation other = (AxKeyInformation) otherObj;
357 if (!key.equals(other.key)) {
358 return key.compareTo(other.key);
360 if (!keyInfoMap.equals(other.keyInfoMap)) {
361 return (keyInfoMap.hashCode() - other.keyInfoMap.hashCode());
371 public AxKeyInfo get(final AxArtifactKey conceptKey) {
372 return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).get(conceptKey);
379 public AxKeyInfo get(final String conceptKeyName) {
380 return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).get(conceptKeyName);
387 public AxKeyInfo get(final String conceptKeyName, final String conceptKeyVersion) {
388 return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).get(conceptKeyName,
396 public Set<AxKeyInfo> getAll(final String conceptKeyName) {
397 return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).getAll(conceptKeyName);
404 public Set<AxKeyInfo> getAll(final String conceptKeyName, final String conceptKeyVersion) {
405 return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).getAll(conceptKeyName,