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