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