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