Merge "Add impl of more PDP persistence"
[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.CollectionTable;
33 import javax.persistence.Column;
34 import javax.persistence.ElementCollection;
35 import javax.persistence.EmbeddedId;
36 import javax.persistence.Entity;
37 import javax.persistence.Inheritance;
38 import javax.persistence.InheritanceType;
39 import javax.persistence.JoinColumn;
40 import javax.persistence.OneToMany;
41 import javax.persistence.Table;
42
43 import lombok.Data;
44 import lombok.EqualsAndHashCode;
45 import lombok.NonNull;
46
47 import org.onap.policy.common.utils.validation.Assertions;
48 import org.onap.policy.common.utils.validation.ParameterValidationUtils;
49 import org.onap.policy.models.base.PfAuthorative;
50 import org.onap.policy.models.base.PfConcept;
51 import org.onap.policy.models.base.PfConceptKey;
52 import org.onap.policy.models.base.PfKey;
53 import org.onap.policy.models.base.PfKeyUse;
54 import org.onap.policy.models.base.PfReferenceKey;
55 import org.onap.policy.models.base.PfUtils;
56 import org.onap.policy.models.base.PfValidationMessage;
57 import org.onap.policy.models.base.PfValidationResult;
58 import org.onap.policy.models.base.PfValidationResult.ValidationResult;
59 import org.onap.policy.models.pdp.concepts.Pdp;
60 import org.onap.policy.models.pdp.concepts.PdpSubGroup;
61 import org.onap.policy.models.pdp.concepts.ToscaPolicyIdentifier;
62 import org.onap.policy.models.pdp.concepts.ToscaPolicyTypeIdentifier;
63 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
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
98     @CollectionTable(joinColumns = {
99             @JoinColumn(name = "pdpSubGroupParentKeyName",    referencedColumnName = "parentKeyName"),
100             @JoinColumn(name = "pdpSubGroupParentKeyVersion", referencedColumnName = "parentKeyVersion"),
101             @JoinColumn(name = "pdpSubGroupParentLocalName",  referencedColumnName = "parentLocalName"),
102             @JoinColumn(name = "pdpSubGroupLocalName",        referencedColumnName = "localName")
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<PfConceptKey> 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(final JpaPdpSubGroup copyConcept) {
145         super(copyConcept);
146     }
147
148     /**
149      * Authorative constructor.
150      *
151      * @param authorativeConcept the authorative concept to copy from
152      */
153     public JpaPdpSubGroup(final PdpSubGroup authorativeConcept) {
154         this.fromAuthorative(authorativeConcept);
155     }
156
157     @Override
158     public PdpSubGroup toAuthorative() {
159         PdpSubGroup pdpSubgroup = new PdpSubGroup();
160
161         pdpSubgroup.setPdpType(getKey().getLocalName());
162
163         pdpSubgroup.setSupportedPolicyTypes(new ArrayList<>());
164         for (PfConceptKey supportedPolicyTypeKey : supportedPolicyTypes) {
165             ToscaPolicyTypeIdentifier supportedPolicyTypeIdent = new ToscaPolicyTypeIdentifier(
166                     supportedPolicyTypeKey.getName(), supportedPolicyTypeKey.getVersion());
167             pdpSubgroup.getSupportedPolicyTypes().add(supportedPolicyTypeIdent);
168         }
169
170         pdpSubgroup.setPolicies(new ArrayList<>());
171         for (PfConceptKey policyKey : policies) {
172             ToscaPolicyIdentifier toscaPolicyIdentifier = new ToscaPolicyIdentifier();
173             toscaPolicyIdentifier.setName(policyKey.getName());
174             toscaPolicyIdentifier.setVersion(policyKey.getVersion());
175             pdpSubgroup.getPolicies().add(toscaPolicyIdentifier);
176         }
177
178         pdpSubgroup.setCurrentInstanceCount(currentInstanceCount);
179         pdpSubgroup.setDesiredInstanceCount(desiredInstanceCount);
180         pdpSubgroup.setProperties(properties == null ? null : new LinkedHashMap<>(properties));
181
182         pdpSubgroup.setPdpInstances(new ArrayList<>());
183         for (JpaPdp jpaPdp : pdpInstances) {
184             pdpSubgroup.getPdpInstances().add(jpaPdp.toAuthorative());
185         }
186
187         return pdpSubgroup;
188     }
189
190     @Override
191     public void fromAuthorative(final PdpSubGroup pdpSubgroup) {
192         if (this.getKey().isNullKey()) {
193             this.setKey(new PfReferenceKey());
194             getKey().setLocalName(pdpSubgroup.getPdpType());
195         }
196
197         this.supportedPolicyTypes = new ArrayList<>();
198         for (ToscaPolicyTypeIdentifier supportedPolicyType : pdpSubgroup.getSupportedPolicyTypes()) {
199             this.supportedPolicyTypes
200                     .add(new PfConceptKey(supportedPolicyType.getName(), supportedPolicyType.getVersion()));
201         }
202
203
204         this.policies = new ArrayList<>();
205         for (ToscaPolicyIdentifier toscaPolicyIdentifier : pdpSubgroup.getPolicies()) {
206             this.policies.add(new PfConceptKey(toscaPolicyIdentifier.getName(), toscaPolicyIdentifier.getVersion()));
207         }
208
209         this.currentInstanceCount = pdpSubgroup.getCurrentInstanceCount();
210         this.desiredInstanceCount = pdpSubgroup.getDesiredInstanceCount();
211         this.properties =
212                 (pdpSubgroup.getProperties() == null ? null : new LinkedHashMap<>(pdpSubgroup.getProperties()));
213
214         this.pdpInstances = new ArrayList<>();
215         for (Pdp pdp : pdpSubgroup.getPdpInstances()) {
216             JpaPdp jpaPdp = new JpaPdp();
217             jpaPdp.setKey(new PfReferenceKey(getKey(), pdp.getInstanceId()));
218             jpaPdp.fromAuthorative(pdp);
219             this.pdpInstances.add(jpaPdp);
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(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 }