1fa0cf57a721a134004639b3895c37cf153894b0
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2019-2021 Nordix Foundation.
5  *  Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.apex.model.contextmodel.concepts;
24
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Map.Entry;
28 import java.util.NavigableMap;
29 import java.util.Set;
30 import java.util.TreeMap;
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.ManyToMany;
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 import lombok.AccessLevel;
44 import lombok.EqualsAndHashCode;
45 import lombok.Getter;
46 import lombok.ToString;
47 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
48 import org.onap.policy.apex.model.basicmodel.concepts.AxConcept;
49 import org.onap.policy.apex.model.basicmodel.concepts.AxConceptGetter;
50 import org.onap.policy.apex.model.basicmodel.concepts.AxConceptGetterImpl;
51 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
52 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationMessage;
53 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult;
54 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult;
55 import org.onap.policy.common.utils.validation.Assertions;
56
57 /**
58  * This class is a context schema container and holds a map of the context schemas for an entire Apex model. All Apex
59  * models that use context schemas must have an {@link AxContextSchemas} field. The {@link AxContextSchemas} class
60  * implements the helper methods of the {@link AxConceptGetter} interface to allow {@link AxContextSchema} instances to
61  * be retrieved by calling methods directly on this class without referencing the contained map.
62  *
63  * <p>Validation checks that the container key is not null. An error is issued if no context schemas are defined in the
64  * container. Each context schema entry is checked to ensure that its key and value are not null and that the key
65  * matches the key in the map value. Each context schema entry is then validated individually.
66  */
67 @Entity
68 @Table(name = "AxContextSchemas")
69
70 @Getter
71 @ToString
72 @EqualsAndHashCode(callSuper = false)
73
74 @XmlAccessorType(XmlAccessType.FIELD)
75 @XmlType(name = "AxContextSchemas", namespace = "http://www.onap.org/policy/apex-pdp", propOrder =
76     { "key", "schemas" })
77
78 public class AxContextSchemas extends AxConcept implements AxConceptGetter<AxContextSchema> {
79     private static final long serialVersionUID = -3203734282886453582L;
80
81     @EmbeddedId
82     @XmlElement(name = "key", required = true)
83     private AxArtifactKey key;
84
85     // @formatter:off
86     @ManyToMany(cascade = CascadeType.ALL)
87     @JoinTable(
88             joinColumns = {@JoinColumn(name = "contextSchemasName", referencedColumnName = "name"),
89                 @JoinColumn(name = "contextSchemasVersion", referencedColumnName = "version")},
90             inverseJoinColumns = {@JoinColumn(name = "contextSchemaName", referencedColumnName = "name"),
91                 @JoinColumn(name = "contextSchemaVersion", referencedColumnName = "version")})
92     @XmlElement(name = "schemas", required = true)
93     @Getter(AccessLevel.NONE)
94     private Map<AxArtifactKey, AxContextSchema> schemas;
95     // @formatter:on
96
97     /**
98      * The Default Constructor creates a {@link AxContextSchemas} object with a null artifact key and creates an empty
99      * context schemas map.
100      */
101     public AxContextSchemas() {
102         this(new AxArtifactKey());
103     }
104
105     /**
106      * Copy constructor.
107      *
108      * @param copyConcept the concept to copy from
109      */
110     public AxContextSchemas(final AxContextSchemas copyConcept) {
111         super(copyConcept);
112     }
113
114     /**
115      * The Key Constructor creates a {@link AxContextSchemas} object with the given artifact key and creates an empty
116      * context schemas map.
117      *
118      * @param key the key of the context album container
119      */
120     public AxContextSchemas(final AxArtifactKey key) {
121         this(key, new TreeMap<>());
122     }
123
124     /**
125      * This Constructor creates a {@link AxContextSchemas} object with all its fields defined.
126      *
127      * @param key the key of the context schema container
128      * @param schemas a map of the schemas to insert in the context schema container
129      */
130     public AxContextSchemas(final AxArtifactKey key, final Map<AxArtifactKey, AxContextSchema> schemas) {
131         super();
132         Assertions.argumentNotNull(key, "key may not be null");
133         Assertions.argumentNotNull(schemas, "schemas may not be null");
134
135         this.key = key;
136         this.schemas = new TreeMap<>();
137         this.schemas.putAll(schemas);
138     }
139
140     /**
141      * When a model is unmarshalled from disk or from the database, the context schema map is returned as a raw hash
142      * map. This method is called by JAXB after unmarshaling and is used to convert the hash map to a
143      * {@link NavigableMap} so that it will work with the {@link AxConceptGetter} interface.
144      *
145      * @param unmarshaller the unmarshaler that is unmarshaling the model
146      * @param parent the parent object of this object in the unmarshaler
147      */
148     public void afterUnmarshal(final Unmarshaller unmarshaller, final Object parent) {
149         // The map must be navigable to allow name and version searching, unmarshaling returns a
150         // hash map
151         final NavigableMap<AxArtifactKey, AxContextSchema> navigableContextSchemas = new TreeMap<>();
152         navigableContextSchemas.putAll(schemas);
153         schemas = navigableContextSchemas;
154     }
155
156     /**
157      * {@inheritDoc}.
158      */
159     @Override
160     public List<AxKey> getKeys() {
161         final List<AxKey> keyList = key.getKeys();
162         keyList.addAll(schemas.keySet());
163
164         return keyList;
165     }
166
167     /**
168      * Sets the key of the context schema container.
169      *
170      * @param key the key of the container
171      */
172     public void setKey(final AxArtifactKey key) {
173         Assertions.argumentNotNull(key, "key may not be null");
174         this.key = key;
175     }
176
177     /**
178      * Gets the map of context schemas in this container.
179      *
180      * @return the map of schemas
181      */
182     public Map<AxArtifactKey, AxContextSchema> getSchemasMap() {
183         return schemas;
184     }
185
186     /**
187      * Sets the map of context schemas in this container.
188      *
189      * @param schemasMap the map of schemas
190      */
191     public void setSchemasMap(final Map<AxArtifactKey, AxContextSchema> schemasMap) {
192         Assertions.argumentNotNull(schemasMap, "schemasMap may not be null");
193
194         this.schemas = new TreeMap<>();
195         this.schemas.putAll(schemasMap);
196     }
197
198     /**
199      * {@inheritDoc}.
200      */
201     @Override
202     public AxValidationResult validate(final AxValidationResult resultIn) {
203         AxValidationResult result = resultIn;
204
205         if (key.equals(AxArtifactKey.getNullKey())) {
206             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
207                             "key is a null key"));
208         }
209
210         result = key.validate(result);
211
212         if (schemas.size() == 0) {
213             result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
214                             "contextSchemas may not be empty"));
215         } else {
216             for (final Entry<AxArtifactKey, AxContextSchema> contextSchemaEntry : schemas.entrySet()) {
217                 if (contextSchemaEntry.getKey().equals(AxArtifactKey.getNullKey())) {
218                     result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
219                                     "key on schemas entry " + contextSchemaEntry.getKey()
220                                                     + " may not be the null key"));
221                 } else if (contextSchemaEntry.getValue() == null) {
222                     result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
223                                     "value on schemas entry " + contextSchemaEntry.getKey() + " may not be null"));
224                 } else {
225                     if (!contextSchemaEntry.getKey().equals(contextSchemaEntry.getValue().getKey())) {
226                         result.addValidationMessage(
227                                         new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID,
228                                                         "key on schemas entry " + contextSchemaEntry.getKey()
229                                                                         + " does not equal entry key "
230                                                                         + contextSchemaEntry.getValue().getKey()));
231                     }
232
233                     result = contextSchemaEntry.getValue().validate(result);
234                 }
235             }
236         }
237
238         return result;
239     }
240
241     /**
242      * {@inheritDoc}.
243      */
244     @Override
245     public void clean() {
246         key.clean();
247         for (final Entry<AxArtifactKey, AxContextSchema> contextSchemaEntry : schemas.entrySet()) {
248             contextSchemaEntry.getKey().clean();
249             contextSchemaEntry.getValue().clean();
250         }
251     }
252
253     /**
254      * {@inheritDoc}.
255      */
256     @Override
257     public AxConcept copyTo(final AxConcept target) {
258         Assertions.argumentNotNull(target, "target may not be null");
259
260         final Object copyObject = target;
261         Assertions.instanceOf(copyObject, AxContextSchemas.class);
262
263         final AxContextSchemas copy = ((AxContextSchemas) copyObject);
264         copy.setKey(new AxArtifactKey(key));
265
266         final Map<AxArtifactKey, AxContextSchema> newcontextSchemas = new TreeMap<>();
267         for (final Entry<AxArtifactKey, AxContextSchema> contextSchemasEntry : schemas.entrySet()) {
268             newcontextSchemas.put(new AxArtifactKey(contextSchemasEntry.getKey()),
269                             new AxContextSchema(contextSchemasEntry.getValue()));
270         }
271         copy.setSchemasMap(newcontextSchemas);
272
273         return copy;
274     }
275
276     /**
277      * {@inheritDoc}.
278      */
279     @Override
280     public int compareTo(final AxConcept otherObj) {
281         if (otherObj == null) {
282             return -1;
283         }
284         if (this == otherObj) {
285             return 0;
286         }
287         if (getClass() != otherObj.getClass()) {
288             return this.hashCode() - otherObj.hashCode();
289         }
290
291         final AxContextSchemas other = (AxContextSchemas) otherObj;
292         if (!key.equals(other.key)) {
293             return key.compareTo(other.key);
294         }
295         if (!schemas.equals(other.schemas)) {
296             return (schemas.hashCode() - other.schemas.hashCode());
297         }
298
299         return 0;
300     }
301
302     /**
303      * {@inheritDoc}.
304      */
305     @Override
306     public AxContextSchema get(final AxArtifactKey conceptKey) {
307         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextSchema>) schemas).get(conceptKey);
308     }
309
310     /**
311      * {@inheritDoc}.
312      */
313     @Override
314     public AxContextSchema get(final String conceptKeyName) {
315         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextSchema>) schemas).get(conceptKeyName);
316     }
317
318     /**
319      * {@inheritDoc}.
320      */
321     @Override
322     public AxContextSchema get(final String conceptKeyName, final String conceptKeyVersion) {
323         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextSchema>) schemas).get(conceptKeyName,
324                         conceptKeyVersion);
325     }
326
327     /**
328      * {@inheritDoc}.
329      */
330     @Override
331     public Set<AxContextSchema> getAll(final String conceptKeyName) {
332         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextSchema>) schemas).getAll(conceptKeyName);
333     }
334
335     /**
336      * {@inheritDoc}.
337      */
338     @Override
339     public Set<AxContextSchema> getAll(final String conceptKeyName, final String conceptKeyVersion) {
340         return new AxConceptGetterImpl<>((NavigableMap<AxArtifactKey, AxContextSchema>) schemas).getAll(conceptKeyName,
341                         conceptKeyVersion);
342     }
343 }