Changes for checkstyle 8.32
[policy/apex-pdp.git] / model / basic-model / src / main / java / org / onap / policy / apex / model / basicmodel / concepts / AxKeyInformation.java
1 /*-
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.apex.model.basicmodel.concepts;
23
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import java.util.NavigableMap;
28 import java.util.Set;
29 import java.util.TreeMap;
30 import java.util.TreeSet;
31 import java.util.UUID;
32 import javax.persistence.CascadeType;
33 import javax.persistence.EmbeddedId;
34 import javax.persistence.Entity;
35 import javax.persistence.JoinColumn;
36 import javax.persistence.JoinTable;
37 import javax.persistence.ManyToMany;
38 import javax.persistence.Table;
39 import javax.xml.bind.Unmarshaller;
40 import javax.xml.bind.annotation.XmlAccessType;
41 import javax.xml.bind.annotation.XmlAccessorType;
42 import javax.xml.bind.annotation.XmlElement;
43 import javax.xml.bind.annotation.XmlType;
44 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult;
45 import org.onap.policy.common.utils.validation.Assertions;
46
47 /**
48  * The Class AxKeyInformation holds a map of the key information for the entire Apex model. All Apex models
49  * {@link AxModel} must have an {@link AxKeyInformation} field. The {@link AxKeyInformation} class implements the helper
50  * methods of the {@link AxConceptGetter} interface to allow {@link AxKeyInfo} instances to be retrieved by calling
51  * methods directly on this class without referencing the contained map.
52  *
53  * <p>Validation checks that the key is not null, that the key information map is not empty, that each key and value in
54  * the map is defined, that the key in each map entry matches the key if each entry value, and that no duplicate UUIDs
55  * exist. Each key information entry is then validated individually.
56  */
57 @Entity
58 @Table(name = "AxKeyInformation")
59
60 @XmlAccessorType(XmlAccessType.FIELD)
61 @XmlType(name = "AxKeyInformation", namespace = "http://www.onap.org/policy/apex-pdp",
62         propOrder = { "key", "keyInfoMap" })
63
64 public class AxKeyInformation extends AxConcept implements AxConceptGetter<AxKeyInfo> {
65     private static final long serialVersionUID = -2746380769017043888L;
66
67     @EmbeddedId
68     @XmlElement(name = "key", required = true)
69     private AxArtifactKey key;
70
71     // @formatter:off
72     @ManyToMany(cascade = CascadeType.ALL)
73     @JoinTable(
74             joinColumns = { @JoinColumn(name = "keyInfoMapName", referencedColumnName = "name"),
75                     @JoinColumn(name = "keyInfoMapVersion", referencedColumnName = "version"), },
76             inverseJoinColumns = { @JoinColumn(name = "keyInfoName", referencedColumnName = "name"),
77                     @JoinColumn(name = "keyInfoVersion", referencedColumnName = "version") })
78     private Map<AxArtifactKey, AxKeyInfo> keyInfoMap;
79     // @formatter:on
80
81     /**
82      * The Default Constructor creates this concept with a null key.
83      */
84     public AxKeyInformation() {
85         this(new AxArtifactKey());
86     }
87
88     /**
89      * Copy constructor.
90      *
91      * @param copyConcept the concept to copy from
92      */
93     public AxKeyInformation(final AxKeyInformation copyConcept) {
94         super(copyConcept);
95     }
96
97     /**
98      * Constructor to create this concept with the specified key.
99      *
100      * @param key the key of the concept
101      */
102     public AxKeyInformation(final AxArtifactKey key) {
103         this(key, new TreeMap<AxArtifactKey, AxKeyInfo>());
104     }
105
106     /**
107      * Constructor to create this concept and set all its fields.
108      *
109      * @param key the key of the concept
110      * @param keyInfoMap the key info map of the concept
111      */
112     public AxKeyInformation(final AxArtifactKey key, final Map<AxArtifactKey, AxKeyInfo> keyInfoMap) {
113         super();
114         Assertions.argumentNotNull(key, "key may not be null");
115         Assertions.argumentNotNull(keyInfoMap, "keyInfoMap may not be null");
116
117         this.key = key;
118         this.keyInfoMap = new TreeMap<>();
119         this.keyInfoMap.putAll(keyInfoMap);
120     }
121
122     /**
123      * When a model is unmarshalled from disk or from the database, the key information map is returned as a raw Hash
124      * Map. This method is called by JAXB after unmarshaling and is used to convert the hash map to a
125      * {@link NavigableMap} so that it will work with the {@link AxConceptGetter} interface.
126      *
127      * @param unmarshaler the unmarshaler that is unmarshaling the model
128      * @param parent the parent object of this object in the unmarshaler
129      */
130     public void afterUnmarshal(final Unmarshaller unmarshaler, final Object parent) {
131         // The map must be navigable to allow name and version searching,
132         // unmarshaling returns a hash map
133         final NavigableMap<AxArtifactKey, AxKeyInfo> navigablekeyInfoMap = new TreeMap<>();
134         navigablekeyInfoMap.putAll(keyInfoMap);
135         keyInfoMap = navigablekeyInfoMap;
136     }
137
138     /**
139      * This method generates default key information for all keys found in the concept passed in as a parameter that do
140      * not already have key information.
141      *
142      * @param concept the concept for which to generate key information
143      */
144     public void generateKeyInfo(final AxConcept concept) {
145         for (final AxKey axKey : concept.getKeys()) {
146             if (!(axKey instanceof AxArtifactKey)) {
147                 continue;
148             }
149
150             final AxArtifactKey artifactKey = (AxArtifactKey) axKey;
151             if (!keyInfoMap.containsKey(artifactKey)) {
152                 final AxKeyInfo keyInfo = new AxKeyInfo(artifactKey);
153                 // generate a reproducible UUID
154                 keyInfo.setUuid(AxKeyInfo.generateReproducibleUuid(keyInfo.getId() + keyInfo.getDescription()));
155                 keyInfoMap.put(artifactKey, keyInfo);
156             }
157         }
158     }
159
160     /**
161      * {@inheritDoc}.
162      */
163     @Override
164     public AxArtifactKey getKey() {
165         return key;
166     }
167
168     /**
169      * {@inheritDoc}.
170      */
171     @Override
172     public List<AxKey> getKeys() {
173         final List<AxKey> keyList = key.getKeys();
174         keyList.addAll(keyInfoMap.keySet());
175
176         return keyList;
177     }
178
179     /**
180      * Sets the key of this concept.
181      *
182      * @param key the key of this concept
183      */
184     public void setKey(final AxArtifactKey key) {
185         Assertions.argumentNotNull(key, "key may not be null");
186         this.key = key;
187     }
188
189     /**
190      * Gets the key info map of this concept.
191      *
192      * @return the key info map of this concept
193      */
194     public Map<AxArtifactKey, AxKeyInfo> getKeyInfoMap() {
195         return keyInfoMap;
196     }
197
198     /**
199      * Sets the key info map of this concept.
200      *
201      * @param keyInfoMap the key info map of this concept
202      */
203     public void setKeyInfoMap(final Map<AxArtifactKey, AxKeyInfo> keyInfoMap) {
204         Assertions.argumentNotNull(keyInfoMap, "keyInfoMap may not be null");
205         this.keyInfoMap = new TreeMap<>();
206         this.keyInfoMap.putAll(keyInfoMap);
207     }
208
209     /**
210      * {@inheritDoc}.
211      */
212     @Override
213     public AxValidationResult validate(final AxValidationResult resultIn) {
214         AxValidationResult result = resultIn;
215
216         if (key.equals(AxArtifactKey.getNullKey())) {
217             result.addValidationMessage(
218                     new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key"));
219         }
220
221         result = key.validate(result);
222
223         if (keyInfoMap.size() == 0) {
224             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
225                     "keyInfoMap may not be empty"));
226         } else {
227             final Set<UUID> uuidSet = new TreeSet<>();
228
229             for (final Entry<AxArtifactKey, AxKeyInfo> keyInfoEntry : keyInfoMap.entrySet()) {
230                 result = validateKeyInfoEntry(keyInfoEntry, uuidSet, result);
231             }
232         }
233
234         return result;
235     }
236
237     /**
238      * Validate an key information entry.
239      *
240      * @param keyInfoEntry the key information entry
241      * @param uuidSet the set of UUIDs encountered in validation so far, the UUID of this entry is added to the set
242      * @param result the validation result to append to
243      * @return The validation result
244      */
245     private AxValidationResult validateKeyInfoEntry(final Entry<AxArtifactKey, AxKeyInfo> keyInfoEntry,
246             final Set<UUID> uuidSet, AxValidationResult result) {
247         if (keyInfoEntry.getKey().equals(AxArtifactKey.getNullKey())) {
248             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
249                     "key on keyInfoMap entry " + keyInfoEntry.getKey() + " may not be the null key"));
250         } else if (keyInfoEntry.getValue() == null) {
251             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
252                     "value on keyInfoMap entry " + keyInfoEntry.getKey() + " may not be null"));
253         } else {
254             if (!keyInfoEntry.getKey().equals(keyInfoEntry.getValue().getKey())) {
255                 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
256                         "key on keyInfoMap entry " + keyInfoEntry.getKey() + " does not equal entry key "
257                                 + keyInfoEntry.getValue().getKey()));
258             }
259
260             result = keyInfoEntry.getValue().validate(result);
261
262             if (uuidSet.contains(keyInfoEntry.getValue().getUuid())) {
263                 result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
264                         "duplicate UUID found on keyInfoMap entry " + keyInfoEntry.getKey() + ":"
265                                 + keyInfoEntry.getValue().getUuid()));
266             } else {
267                 uuidSet.add(keyInfoEntry.getValue().getUuid());
268             }
269         }
270
271         return result;
272     }
273
274     /**
275      * {@inheritDoc}.
276      */
277     @Override
278     public void clean() {
279         key.clean();
280         for (final Entry<AxArtifactKey, AxKeyInfo> keyInfoEntry : keyInfoMap.entrySet()) {
281             keyInfoEntry.getKey().clean();
282             keyInfoEntry.getValue().clean();
283         }
284     }
285
286     /**
287      * {@inheritDoc}.
288      */
289     @Override
290     public String toString() {
291         final StringBuilder builder = new StringBuilder();
292         builder.append(this.getClass().getSimpleName());
293         builder.append(":(");
294         builder.append("key=");
295         builder.append(key);
296         builder.append(",keyInfoMap=");
297         builder.append(keyInfoMap);
298         builder.append(")");
299         return builder.toString();
300     }
301
302     /**
303      * {@inheritDoc}.
304      */
305     @Override
306     public AxConcept copyTo(final AxConcept target) {
307         Assertions.argumentNotNull(target, "target may not be null");
308
309         final Object copyObject = target;
310         Assertions.instanceOf(copyObject, AxKeyInformation.class);
311
312         final AxKeyInformation copy = ((AxKeyInformation) copyObject);
313         copy.setKey(new AxArtifactKey(key));
314         final Map<AxArtifactKey, AxKeyInfo> newKeyInfoMap = new TreeMap<>();
315         for (final Entry<AxArtifactKey, AxKeyInfo> keyInfoMapEntry : keyInfoMap.entrySet()) {
316             newKeyInfoMap.put(new AxArtifactKey(keyInfoMapEntry.getKey()), new AxKeyInfo(keyInfoMapEntry.getValue()));
317         }
318         copy.setKeyInfoMap(newKeyInfoMap);
319
320         return copy;
321     }
322
323     /**
324      * {@inheritDoc}.
325      */
326     @Override
327     public int hashCode() {
328         final int prime = 31;
329         int result = 1;
330         result = prime * result + key.hashCode();
331         result = prime * result + keyInfoMap.hashCode();
332         return result;
333     }
334
335     /**
336      * {@inheritDoc}.
337      */
338     @Override
339     public boolean equals(final Object obj) {
340         if (obj == null) {
341             return false;
342         }
343         if (this == obj) {
344             return true;
345         }
346
347         if (getClass() != obj.getClass()) {
348             return false;
349         }
350
351         final AxKeyInformation other = (AxKeyInformation) obj;
352         if (!key.equals(other.key)) {
353             return false;
354         }
355         return keyInfoMap.equals(other.keyInfoMap);
356     }
357
358     /**
359      * {@inheritDoc}.
360      */
361     @Override
362     public int compareTo(final AxConcept otherObj) {
363         if (otherObj == null) {
364             return -1;
365         }
366         if (this == otherObj) {
367             return 0;
368         }
369         if (getClass() != otherObj.getClass()) {
370             return this.hashCode() - otherObj.hashCode();
371         }
372
373         final AxKeyInformation other = (AxKeyInformation) otherObj;
374         if (!key.equals(other.key)) {
375             return key.compareTo(other.key);
376         }
377         if (!keyInfoMap.equals(other.keyInfoMap)) {
378             return (keyInfoMap.hashCode() - other.keyInfoMap.hashCode());
379         }
380
381         return 0;
382     }
383
384     /**
385      * {@inheritDoc}.
386      */
387     @Override
388     public AxKeyInfo get(final AxArtifactKey conceptKey) {
389         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).get(conceptKey);
390     }
391
392     /**
393      * {@inheritDoc}.
394      */
395     @Override
396     public AxKeyInfo get(final String conceptKeyName) {
397         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).get(conceptKeyName);
398     }
399
400     /**
401      * {@inheritDoc}.
402      */
403     @Override
404     public AxKeyInfo get(final String conceptKeyName, final String conceptKeyVersion) {
405         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).get(conceptKeyName,
406                 conceptKeyVersion);
407     }
408
409     /**
410      * {@inheritDoc}.
411      */
412     @Override
413     public Set<AxKeyInfo> getAll(final String conceptKeyName) {
414         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).getAll(conceptKeyName);
415     }
416
417     /**
418      * {@inheritDoc}.
419      */
420     @Override
421     public Set<AxKeyInfo> getAll(final String conceptKeyName, final String conceptKeyVersion) {
422         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxKeyInfo>) keyInfoMap).getAll(conceptKeyName,
423                 conceptKeyVersion);
424     }
425 }