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 org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult;
34 import org.onap.policy.common.utils.validation.Assertions;
37 * The Class AxKeyInformation holds a map of the key information for the entire Apex model. All Apex models
38 * {@link AxModel} must have an {@link AxKeyInformation} field. The {@link AxKeyInformation} class implements the helper
39 * methods of the {@link AxConceptGetter} interface to allow {@link AxKeyInfo} instances to be retrieved by calling
40 * methods directly on this class without referencing the contained map.
42 * <p>Validation checks that the key is not null, that the key information map is not empty, that each key and value in
43 * the map is defined, that the key in each map entry matches the key if each entry value, and that no duplicate UUIDs
44 * exist. Each key information entry is then validated individually.
46 public class AxKeyInformation extends AxConcept implements AxConceptGetter<AxKeyInfo> {
47 private static final long serialVersionUID = -2746380769017043888L;
49 private AxArtifactKey key;
50 private Map<AxArtifactKey, AxKeyInfo> keyInfoMap;
53 * The Default Constructor creates this concept with a null key.
55 public AxKeyInformation() {
56 this(new AxArtifactKey());
62 * @param copyConcept the concept to copy from
64 public AxKeyInformation(final AxKeyInformation copyConcept) {
69 * Constructor to create this concept with the specified key.
71 * @param key the key of the concept
73 public AxKeyInformation(final AxArtifactKey key) {
74 this(key, new TreeMap<>());
78 * Constructor to create this concept and set all its fields.
80 * @param key the key of the concept
81 * @param keyInfoMap the key info map of the concept
83 public AxKeyInformation(final AxArtifactKey key, final Map<AxArtifactKey, AxKeyInfo> keyInfoMap) {
85 Assertions.argumentNotNull(key, "key may not be null");
86 Assertions.argumentNotNull(keyInfoMap, "keyInfoMap may not be null");
89 this.keyInfoMap = new TreeMap<>();
90 this.keyInfoMap.putAll(keyInfoMap);
94 * This method generates default key information for all keys found in the concept passed in as a parameter that do
95 * not already have key information.
97 * @param concept the concept for which to generate key information
99 public void generateKeyInfo(final AxConcept concept) {
100 for (final AxKey axKey : concept.getKeys()) {
101 if (!(axKey instanceof AxArtifactKey)) {
105 final AxArtifactKey artifactKey = (AxArtifactKey) axKey;
107 keyInfoMap.computeIfAbsent(artifactKey, unusedKey -> {
108 final var keyInfo = new AxKeyInfo(artifactKey);
109 // generate a reproducible UUID
110 keyInfo.setUuid(AxKeyInfo.generateReproducibleUuid(keyInfo.getId() + keyInfo.getDescription()));
120 public AxArtifactKey getKey() {
128 public List<AxKey> getKeys() {
129 final List<AxKey> keyList = key.getKeys();
130 keyList.addAll(keyInfoMap.keySet());
139 public void buildReferences() {
140 keyInfoMap.values().stream().forEach(keyInfo -> keyInfo.buildReferences());
144 * Sets the key of this concept.
146 * @param key the key of this concept
148 public void setKey(final AxArtifactKey key) {
149 Assertions.argumentNotNull(key, "key may not be null");
154 * Gets the key info map of this concept.
156 * @return the key info map of this concept
158 public Map<AxArtifactKey, AxKeyInfo> getKeyInfoMap() {
163 * Sets the key info map of this concept.
165 * @param keyInfoMap the key info map of this concept
167 public void setKeyInfoMap(final Map<AxArtifactKey, AxKeyInfo> keyInfoMap) {
168 Assertions.argumentNotNull(keyInfoMap, "keyInfoMap may not be null");
169 this.keyInfoMap = new TreeMap<>();
170 this.keyInfoMap.putAll(keyInfoMap);
177 public AxValidationResult validate(final AxValidationResult resultIn) {
178 AxValidationResult result = resultIn;
180 if (key.equals(AxArtifactKey.getNullKey())) {
181 result.addValidationMessage(
182 new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key"));
185 result = key.validate(result);
187 if (keyInfoMap.size() == 0) {
188 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
189 "keyInfoMap may not be empty"));
191 final Set<UUID> uuidSet = new TreeSet<>();
193 for (final Entry<AxArtifactKey, AxKeyInfo> keyInfoEntry : keyInfoMap.entrySet()) {
194 result = validateKeyInfoEntry(keyInfoEntry, uuidSet, result);
202 * Validate a key information entry.
204 * @param keyInfoEntry the key information entry
205 * @param uuidSet the set of UUIDs encountered in validation so far, the UUID of this entry is added to the set
206 * @param result the validation result to append to
207 * @return The validation result
209 private AxValidationResult validateKeyInfoEntry(final Entry<AxArtifactKey, AxKeyInfo> keyInfoEntry,
210 final Set<UUID> uuidSet, AxValidationResult result) {
211 if (keyInfoEntry.getKey().equals(AxArtifactKey.getNullKey())) {
212 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
213 "key on keyInfoMap entry " + keyInfoEntry.getKey() + " may not be the null key"));
214 } else if (keyInfoEntry.getValue() == null) {
215 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
216 "value on keyInfoMap entry " + keyInfoEntry.getKey() + " may not be null"));
218 if (!keyInfoEntry.getKey().equals(keyInfoEntry.getValue().getKey())) {
219 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
220 "key on keyInfoMap entry " + keyInfoEntry.getKey() + " does not equal entry key "
221 + keyInfoEntry.getValue().getKey()));
224 result = keyInfoEntry.getValue().validate(result);
226 if (uuidSet.contains(keyInfoEntry.getValue().getUuid())) {
227 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
228 "duplicate UUID found on keyInfoMap entry " + keyInfoEntry.getKey() + ":"
229 + keyInfoEntry.getValue().getUuid()));
231 uuidSet.add(keyInfoEntry.getValue().getUuid());
242 public void clean() {
244 for (final Entry<AxArtifactKey, AxKeyInfo> keyInfoEntry : keyInfoMap.entrySet()) {
245 keyInfoEntry.getKey().clean();
246 keyInfoEntry.getValue().clean();
254 public String toString() {
255 final var builder = new StringBuilder();
256 builder.append(this.getClass().getSimpleName());
257 builder.append(":(");
258 builder.append("key=");
260 builder.append(",keyInfoMap=");
261 builder.append(keyInfoMap);
263 return builder.toString();
270 public AxConcept copyTo(final AxConcept target) {
271 Assertions.argumentNotNull(target, "target may not be null");
273 final Object copyObject = target;
274 Assertions.instanceOf(copyObject, AxKeyInformation.class);
276 final AxKeyInformation copy = ((AxKeyInformation) copyObject);
277 copy.setKey(new AxArtifactKey(key));
278 final Map<AxArtifactKey, AxKeyInfo> newKeyInfoMap = new TreeMap<>();
279 for (final Entry<AxArtifactKey, AxKeyInfo> keyInfoMapEntry : keyInfoMap.entrySet()) {
280 newKeyInfoMap.put(new AxArtifactKey(keyInfoMapEntry.getKey()), new AxKeyInfo(keyInfoMapEntry.getValue()));
282 copy.setKeyInfoMap(newKeyInfoMap);
291 public int hashCode() {
292 final var prime = 31;
294 result = prime * result + key.hashCode();
295 result = prime * result + keyInfoMap.hashCode();
303 public boolean equals(final Object obj) {
311 if (getClass() != obj.getClass()) {
315 final AxKeyInformation other = (AxKeyInformation) obj;
316 if (!key.equals(other.key)) {
319 return keyInfoMap.equals(other.keyInfoMap);
326 public int compareTo(final AxConcept otherObj) {
327 if (otherObj == null) {
330 if (this == otherObj) {
333 if (getClass() != otherObj.getClass()) {
334 return this.hashCode() - otherObj.hashCode();
337 final AxKeyInformation other = (AxKeyInformation) otherObj;
338 if (!key.equals(other.key)) {
339 return key.compareTo(other.key);
341 if (!keyInfoMap.equals(other.keyInfoMap)) {
342 return (keyInfoMap.hashCode() - other.keyInfoMap.hashCode());
352 public AxKeyInfo get(final AxArtifactKey conceptKey) {
353 return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).get(conceptKey);
360 public AxKeyInfo get(final String conceptKeyName) {
361 return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).get(conceptKeyName);
368 public AxKeyInfo get(final String conceptKeyName, final String conceptKeyVersion) {
369 return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).get(conceptKeyName,
377 public Set<AxKeyInfo> getAll(final String conceptKeyName) {
378 return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).getAll(conceptKeyName);
385 public Set<AxKeyInfo> getAll(final String conceptKeyName, final String conceptKeyVersion) {
386 return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).getAll(conceptKeyName,