20e43f0b5c2f6049375f26541179939b4548e666
[policy/models.git] / models-pdp / src / main / java / org / onap / policy / models / pdp / persistence / concepts / JpaPdpSubGroup.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP Policy Model
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019 Nordix Foundation.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * SPDX-License-Identifier: Apache-2.0
21  * ============LICENSE_END=========================================================
22  */
23
24 package org.onap.policy.models.pdp.persistence.concepts;
25
26 import java.util.ArrayList;
27 import java.util.LinkedHashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Map.Entry;
31
32 import javax.persistence.CascadeType;
33 import javax.persistence.Column;
34 import javax.persistence.ElementCollection;
35 import javax.persistence.EmbeddedId;
36 import javax.persistence.Entity;
37 import javax.persistence.FetchType;
38 import javax.persistence.Inheritance;
39 import javax.persistence.InheritanceType;
40 import javax.persistence.JoinColumn;
41 import javax.persistence.JoinTable;
42 import javax.persistence.OneToMany;
43 import javax.persistence.Table;
44 import lombok.Data;
45 import lombok.EqualsAndHashCode;
46 import lombok.NonNull;
47
48 import org.onap.policy.common.utils.validation.Assertions;
49 import org.onap.policy.common.utils.validation.ParameterValidationUtils;
50 import org.onap.policy.models.base.PfAuthorative;
51 import org.onap.policy.models.base.PfConcept;
52 import org.onap.policy.models.base.PfConceptKey;
53 import org.onap.policy.models.base.PfKey;
54 import org.onap.policy.models.base.PfKeyUse;
55 import org.onap.policy.models.base.PfReferenceKey;
56 import org.onap.policy.models.base.PfUtils;
57 import org.onap.policy.models.base.PfValidationMessage;
58 import org.onap.policy.models.base.PfValidationResult;
59 import org.onap.policy.models.base.PfValidationResult.ValidationResult;
60 import org.onap.policy.models.pdp.concepts.Pdp;
61 import org.onap.policy.models.pdp.concepts.PdpSubGroup;
62 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
63 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
64
65 /**
66  * Class to represent a PDP subgroup in the database.
67  *
68  * @author Liam Fallon (liam.fallon@est.tech)
69  */
70 @Entity
71 @Table(name = "PdpSubGroup")
72 @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
73 @Data
74 @EqualsAndHashCode(callSuper = false)
75 public class JpaPdpSubGroup extends PfConcept implements PfAuthorative<PdpSubGroup> {
76     private static final long serialVersionUID = -357224425637789775L;
77
78     @EmbeddedId
79     private PfReferenceKey key;
80
81     @ElementCollection
82     private List<PfConceptKey> supportedPolicyTypes;
83
84     @ElementCollection
85     private List<PfConceptKey> policies;
86
87     @Column
88     private int currentInstanceCount;
89
90     @Column
91     private int desiredInstanceCount;
92
93     @ElementCollection
94     private Map<String, String> properties;
95
96     // @formatter:off
97     @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
98     @JoinTable (
99             joinColumns = {
100                 @JoinColumn(name = "pdpParentKeyName",    referencedColumnName = "parentKeyName"),
101                 @JoinColumn(name = "pdpParentKeyVersion", referencedColumnName = "parentKeyVersion"),
102                 @JoinColumn(name = "pdpParentLocalName",  referencedColumnName = "parentLocalName"),
103                 @JoinColumn(name = "pdpLocalName",        referencedColumnName = "localName")
104             }
105         )
106     // formatter:on
107     private List<JpaPdp> pdpInstances;
108
109     /**
110      * The Default Constructor creates a {@link JpaPdpSubGroup} object with a null key.
111      */
112     public JpaPdpSubGroup() {
113         this(new PfReferenceKey());
114     }
115
116     /**
117      * The Key Constructor creates a {@link JpaPdpSubGroup} object with the given concept key.
118      *
119      * @param key the key
120      */
121     public JpaPdpSubGroup(@NonNull final PfReferenceKey key) {
122         this(key, new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
123     }
124
125     /**
126      * The Key Constructor creates a {@link JpaPdpSubGroup} object with all mandatory fields.
127      *
128      * @param key the key
129      * @param supportedPolicyTypes Supported policy types
130      * @param policies policies deployed on this PDP subgroups
131      * @param pdpInstances the PDP instances on this PDP subgroups
132      */
133     public JpaPdpSubGroup(@NonNull final PfReferenceKey key, @NonNull final List<PfConceptKey> supportedPolicyTypes,
134             @NonNull List<PfConceptKey> policies, @NonNull final List<JpaPdp> pdpInstances) {
135         this.key = key;
136         this.supportedPolicyTypes = supportedPolicyTypes;
137         this.policies = policies;
138         this.pdpInstances = pdpInstances;
139     }
140
141     /**
142      * Copy constructor.
143      *
144      * @param copyConcept the concept to copy from
145      */
146     public JpaPdpSubGroup(@NonNull final JpaPdpSubGroup copyConcept) {
147         super(copyConcept);
148     }
149
150     /**
151      * Authorative constructor.
152      *
153      * @param authorativeConcept the authorative concept to copy from
154      */
155     public JpaPdpSubGroup(@NonNull final PdpSubGroup authorativeConcept) {
156         this.fromAuthorative(authorativeConcept);
157     }
158
159     @Override
160     public PdpSubGroup toAuthorative() {
161         PdpSubGroup pdpSubgroup = new PdpSubGroup();
162
163         pdpSubgroup.setPdpType(getKey().getLocalName());
164
165         pdpSubgroup.setSupportedPolicyTypes(new ArrayList<>());
166         for (PfConceptKey supportedPolicyTypeKey : supportedPolicyTypes) {
167             ToscaPolicyTypeIdentifier supportedPolicyTypeIdent = new ToscaPolicyTypeIdentifier(
168                     supportedPolicyTypeKey.getName(), supportedPolicyTypeKey.getVersion());
169             pdpSubgroup.getSupportedPolicyTypes().add(supportedPolicyTypeIdent);
170         }
171
172         pdpSubgroup.setPolicies(new ArrayList<>());
173         for (PfConceptKey policyKey : policies) {
174             ToscaPolicyIdentifier toscaPolicyIdentifier = new ToscaPolicyIdentifier();
175             toscaPolicyIdentifier.setName(policyKey.getName());
176             toscaPolicyIdentifier.setVersion(policyKey.getVersion());
177             pdpSubgroup.getPolicies().add(toscaPolicyIdentifier);
178         }
179
180         pdpSubgroup.setCurrentInstanceCount(currentInstanceCount);
181         pdpSubgroup.setDesiredInstanceCount(desiredInstanceCount);
182         pdpSubgroup.setProperties(properties == null ? null : new LinkedHashMap<>(properties));
183
184         pdpSubgroup.setPdpInstances(new ArrayList<>());
185         for (JpaPdp jpaPdp : pdpInstances) {
186             pdpSubgroup.getPdpInstances().add(jpaPdp.toAuthorative());
187         }
188
189         return pdpSubgroup;
190     }
191
192     @Override
193     public void fromAuthorative(@NonNull final PdpSubGroup pdpSubgroup) {
194         if (this.key == null || this.getKey().isNullKey()) {
195             this.setKey(new PfReferenceKey());
196             getKey().setLocalName(pdpSubgroup.getPdpType());
197         }
198
199         this.supportedPolicyTypes = new ArrayList<>();
200         if (pdpSubgroup.getSupportedPolicyTypes() != null) {
201             for (ToscaPolicyTypeIdentifier supportedPolicyType : pdpSubgroup.getSupportedPolicyTypes()) {
202                 this.supportedPolicyTypes
203                         .add(new PfConceptKey(supportedPolicyType.getName(), supportedPolicyType.getVersion()));
204             }
205         }
206
207         this.policies = new ArrayList<>();
208         if (pdpSubgroup.getPolicies() != null) {
209             for (ToscaPolicyIdentifier toscaPolicyIdentifier : pdpSubgroup.getPolicies()) {
210                 this.policies
211                         .add(new PfConceptKey(toscaPolicyIdentifier.getName(), toscaPolicyIdentifier.getVersion()));
212             }
213         }
214         this.currentInstanceCount = pdpSubgroup.getCurrentInstanceCount();
215         this.desiredInstanceCount = pdpSubgroup.getDesiredInstanceCount();
216         this.properties =
217                 (pdpSubgroup.getProperties() == null ? null : new LinkedHashMap<>(pdpSubgroup.getProperties()));
218
219         this.pdpInstances = new ArrayList<>();
220         if (pdpSubgroup.getPdpInstances() != null) {
221             for (Pdp pdp : pdpSubgroup.getPdpInstances()) {
222                 JpaPdp jpaPdp = new JpaPdp();
223                 jpaPdp.setKey(new PfReferenceKey(getKey(), pdp.getInstanceId()));
224                 jpaPdp.fromAuthorative(pdp);
225                 this.pdpInstances.add(jpaPdp);
226             }
227         }
228     }
229
230     @Override
231     public List<PfKey> getKeys() {
232         List<PfKey> keyList = getKey().getKeys();
233
234         for (PfConceptKey ptkey : supportedPolicyTypes) {
235             keyList.add(new PfKeyUse(ptkey));
236         }
237
238         for (PfConceptKey pkey : policies) {
239             keyList.add(new PfKeyUse(pkey));
240         }
241
242         for (JpaPdp jpaPdp : pdpInstances) {
243             keyList.addAll(jpaPdp.getKeys());
244         }
245
246
247         return keyList;
248     }
249
250     @Override
251     public void clean() {
252         key.clean();
253
254         for (PfConceptKey ptkey : supportedPolicyTypes) {
255             ptkey.clean();
256         }
257
258         for (PfConceptKey pkey : policies) {
259             pkey.clean();
260         }
261
262         if (properties != null) {
263             Map<String, String> cleanedPropertyMap = new LinkedHashMap<>();
264             for (Entry<String, String> propertyEntry : properties.entrySet()) {
265                 cleanedPropertyMap.put(propertyEntry.getKey().trim(), propertyEntry.getValue().trim());
266             }
267             properties = cleanedPropertyMap;
268         }
269
270         for (JpaPdp jpaPdp : pdpInstances) {
271             jpaPdp.clean();
272         }
273     }
274
275     @Override
276     public PfValidationResult validate(@NonNull final PfValidationResult resultIn) {
277         PfValidationResult result = resultIn;
278
279         if (key.isNullKey()) {
280             result.addValidationMessage(
281                     new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key"));
282         }
283
284         result = key.validate(result);
285
286         if (key.getParentConceptKey().isNullKey()) {
287             result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
288                     "parent of key is a null key"));
289         }
290
291         if (currentInstanceCount < 0) {
292             result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
293                     "the current instance count of a PDP group may not be negative"));
294         }
295
296         if (desiredInstanceCount < 0) {
297             result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
298                     "the desired instance count of a PDP group may not be negative"));
299         }
300
301         if (properties != null) {
302             for (Entry<String, String> propertyEntry : properties.entrySet()) {
303                 if (!ParameterValidationUtils.validateStringParameter(propertyEntry.getKey())) {
304                     result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
305                             "a property key may not be null or blank"));
306                 }
307                 if (!ParameterValidationUtils.validateStringParameter(propertyEntry.getValue())) {
308                     result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
309                             "a property value may not be null or blank"));
310                 }
311             }
312         }
313
314
315         return validateSubConcepts(result);
316     }
317
318     /**
319      * Validate collections of sub concepts.
320      *
321      * @param result the result in which to store the validation result
322      * @return the validation result including the results of this method
323      */
324     private PfValidationResult validateSubConcepts(PfValidationResult result) {
325         if (supportedPolicyTypes == null || supportedPolicyTypes.isEmpty()) {
326             result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
327                     "a PDP subgroup must support at least one policy type"));
328         } else {
329             for (PfConceptKey supportedPolicyType : supportedPolicyTypes) {
330                 result = supportedPolicyType.validate(result);
331             }
332         }
333
334         if (policies == null) {
335             result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
336                     "a PDP subgroup must have a list of policies"));
337         } else {
338             for (PfConceptKey policyKey : policies) {
339                 result = policyKey.validate(result);
340             }
341         }
342
343         if (pdpInstances == null) {
344             result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
345                     "a PDP subgroup must have a list of PDPs"));
346         } else {
347             for (JpaPdp jpaPdp : pdpInstances) {
348                 result = jpaPdp.validate(result);
349             }
350         }
351
352         return result;
353     }
354
355     @Override
356     public int compareTo(final PfConcept otherConcept) {
357         if (otherConcept == null) {
358             return -1;
359         }
360         if (this == otherConcept) {
361             return 0;
362         }
363         if (getClass() != otherConcept.getClass()) {
364             return this.hashCode() - otherConcept.hashCode();
365         }
366
367         final JpaPdpSubGroup other = (JpaPdpSubGroup) otherConcept;
368         if (!key.equals(other.key)) {
369             return key.compareTo(other.key);
370         }
371
372         int result = PfUtils.compareObjects(supportedPolicyTypes, other.supportedPolicyTypes);
373         if (result != 0) {
374             return result;
375         }
376
377         result = PfUtils.compareObjects(policies, other.policies);
378         if (result != 0) {
379             return result;
380         }
381
382         if (currentInstanceCount != other.currentInstanceCount) {
383             return currentInstanceCount - other.currentInstanceCount;
384         }
385
386         if (desiredInstanceCount != other.desiredInstanceCount) {
387             return desiredInstanceCount - other.desiredInstanceCount;
388         }
389
390         result = PfUtils.compareObjects(properties, other.properties);
391         if (result != 0) {
392             return result;
393         }
394
395         return PfUtils.compareObjects(pdpInstances, other.pdpInstances);
396     }
397
398     @Override
399     public PfConcept copyTo(@NonNull final PfConcept target) {
400         Assertions.instanceOf(target, JpaPdpSubGroup.class);
401
402         final JpaPdpSubGroup copy = ((JpaPdpSubGroup) target);
403         copy.setKey(new PfReferenceKey(key));
404
405         copy.setSupportedPolicyTypes(PfUtils.mapList(supportedPolicyTypes, PfConceptKey::new));
406         copy.setPolicies(PfUtils.mapList(policies, PfConceptKey::new));
407         copy.setCurrentInstanceCount(currentInstanceCount);
408         copy.setDesiredInstanceCount(desiredInstanceCount);
409         copy.setProperties(properties == null ? null : new LinkedHashMap<>(properties));
410         copy.setPdpInstances(PfUtils.mapList(pdpInstances, JpaPdp::new));
411
412         return copy;
413     }
414 }