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