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