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