cbd923b6cc40060e097fb2368a6dd2cc86e97629
[policy/apex-pdp.git] / model / context-model / src / main / java / org / onap / policy / apex / model / contextmodel / concepts / AxContextAlbums.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.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      * {@inheritDoc}.
151      */
152     @Override
153     public AxArtifactKey getKey() {
154         return key;
155     }
156
157     /**
158      * {@inheritDoc}.
159      */
160     @Override
161     public List<AxKey> getKeys() {
162         final List<AxKey> keyList = key.getKeys();
163
164         for (final AxContextAlbum contextAlbum : albums.values()) {
165             keyList.addAll(contextAlbum.getKeys());
166         }
167
168         return keyList;
169     }
170
171     /**
172      * Sets the key of the context album container.
173      *
174      * @param key the context album container key
175      */
176     public void setKey(final AxArtifactKey key) {
177         Assertions.argumentNotNull(key, "key may not be null");
178         this.key = key;
179     }
180
181     /**
182      * Gets the map of context albums from the context album container.
183      *
184      * @return the context album map
185      */
186     public Map<AxArtifactKey, AxContextAlbum> getAlbumsMap() {
187         return albums;
188     }
189
190     /**
191      * Sets the map of context albums from the context album container.
192      *
193      * @param albumsMap the map of context albums to place in the container
194      */
195     public void setAlbumsMap(final Map<AxArtifactKey, AxContextAlbum> albumsMap) {
196         Assertions.argumentNotNull(albumsMap, "albums may not be null");
197         this.albums = new TreeMap<>();
198         this.albums.putAll(albumsMap);
199     }
200
201     /**
202      * {@inheritDoc}.
203      */
204     @Override
205     public void clean() {
206         key.clean();
207         for (final Entry<AxArtifactKey, AxContextAlbum> contextAlbumEntry : albums.entrySet()) {
208             contextAlbumEntry.getKey().clean();
209             contextAlbumEntry.getValue().clean();
210         }
211     }
212
213     /**
214      * {@inheritDoc}.
215      */
216     @Override
217     public String toString() {
218         final StringBuilder builder = new StringBuilder();
219         builder.append(this.getClass().getSimpleName());
220         builder.append(":(");
221         builder.append(this.getClass().getSimpleName());
222         builder.append(":(");
223         builder.append("key=");
224         builder.append(key);
225         builder.append(",albums=");
226         builder.append(albums);
227         builder.append(")");
228         return builder.toString();
229     }
230
231     /**
232      * {@inheritDoc}.
233      */
234     @Override
235     public AxValidationResult validate(final AxValidationResult resultIn) {
236         AxValidationResult result = resultIn;
237
238         if (key.equals(AxArtifactKey.getNullKey())) {
239             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
240                             "key is a null key"));
241         }
242
243         result = key.validate(result);
244
245         if (albums.size() == 0) {
246             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.OBSERVATION,
247                             "albums are empty"));
248         } else {
249             for (final Entry<AxArtifactKey, AxContextAlbum> contextAlbumEntry : albums.entrySet()) {
250                 if (contextAlbumEntry.getKey().equals(AxArtifactKey.getNullKey())) {
251                     result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
252                                     "key on context album entry " + contextAlbumEntry.getKey()
253                                                     + " may not be the null key"));
254                 } else if (contextAlbumEntry.getValue() == null) {
255                     result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
256                                     "value on context album entry " + contextAlbumEntry.getKey() + " may not be null"));
257                 } else {
258                     validateContextAlbumKey(result, contextAlbumEntry);
259
260                     result = contextAlbumEntry.getValue().validate(result);
261                 }
262             }
263         }
264
265         return result;
266     }
267
268     private void validateContextAlbumKey(final AxValidationResult result,
269                     final Entry<AxArtifactKey, AxContextAlbum> contextAlbumEntry) {
270         if (!contextAlbumEntry.getKey().equals(contextAlbumEntry.getValue().getKey())) {
271             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
272                             "key on context album entry key " + contextAlbumEntry.getKey()
273                                             + " does not equal context album value key "
274                                             + contextAlbumEntry.getValue().getKey()));
275         }
276     }
277
278     /**
279      * {@inheritDoc}.
280      */
281     @Override
282     public AxConcept copyTo(final AxConcept target) {
283         Assertions.argumentNotNull(target, "target may not be null");
284
285         final Object copyObject = target;
286         Assertions.instanceOf(copyObject, AxContextAlbums.class);
287
288         final AxContextAlbums copy = ((AxContextAlbums) copyObject);
289         copy.setKey(key);
290         final Map<AxArtifactKey, AxContextAlbum> newContextAlbum = new TreeMap<>();
291         for (final Entry<AxArtifactKey, AxContextAlbum> contextAlbumEntry : albums.entrySet()) {
292             newContextAlbum.put(new AxArtifactKey(contextAlbumEntry.getKey()),
293                             new AxContextAlbum(contextAlbumEntry.getValue()));
294         }
295         copy.setAlbumsMap(newContextAlbum);
296
297         return copy;
298     }
299
300     /**
301      * {@inheritDoc}.
302      */
303     @Override
304     public int hashCode() {
305         final int prime = 31;
306         int result = 1;
307         result = prime * result + key.hashCode();
308         result = prime * result + albums.hashCode();
309         return result;
310     }
311
312     /**
313      * {@inheritDoc}.
314      */
315     @Override
316     public boolean equals(final Object obj) {
317         if (obj == null) {
318             return false;
319         }
320         if (this == obj) {
321             return true;
322         }
323
324         if (getClass() != obj.getClass()) {
325             return false;
326         }
327
328         final AxContextAlbums other = (AxContextAlbums) obj;
329         if (!key.equals(other.key)) {
330             return false;
331         }
332         return albums.equals(other.albums);
333     }
334
335     /**
336      * {@inheritDoc}.
337      */
338     @Override
339     public int compareTo(final AxConcept otherObj) {
340         if (otherObj == null) {
341             return -1;
342         }
343         if (this == otherObj) {
344             return 0;
345         }
346         if (getClass() != otherObj.getClass()) {
347             return this.hashCode() - otherObj.hashCode();
348         }
349
350         final AxContextAlbums other = (AxContextAlbums) otherObj;
351         if (!key.equals(other.key)) {
352             return key.compareTo(other.key);
353         }
354         if (!albums.equals(other.albums)) {
355             return (albums.hashCode() - other.albums.hashCode());
356         }
357
358         return 0;
359     }
360
361     /**
362      * {@inheritDoc}.
363      */
364     @Override
365     public AxContextAlbum get(final AxArtifactKey conceptKey) {
366         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextAlbum>) albums).get(conceptKey);
367     }
368
369     /**
370      * {@inheritDoc}.
371      */
372     @Override
373     public AxContextAlbum get(final String conceptKeyName) {
374         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextAlbum>) albums).get(conceptKeyName);
375     }
376
377     /**
378      * {@inheritDoc}.
379      */
380     @Override
381     public AxContextAlbum get(final String conceptKeyName, final String conceptKeyVersion) {
382         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextAlbum>) albums).get(conceptKeyName,
383                         conceptKeyVersion);
384     }
385
386     /**
387      * {@inheritDoc}.
388      */
389     @Override
390     public Set<AxContextAlbum> getAll(final String conceptKeyName) {
391         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextAlbum>) albums).getAll(conceptKeyName);
392     }
393
394     /**
395      * {@inheritDoc}.
396      */
397     @Override
398     public Set<AxContextAlbum> getAll(final String conceptKeyName, final String conceptKeyVersion) {
399         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextAlbum>) albums).getAll(conceptKeyName,
400                         conceptKeyVersion);
401     }
402 }