60e2fa05a34f58ac4472ee084f4462b89a4724e5
[policy/models.git] / models-tosca / src / main / java / org / onap / policy / models / tosca / simple / concepts / JpaToscaProperty.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-2020 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.tosca.simple.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.Column;
32 import javax.persistence.ElementCollection;
33 import javax.persistence.EmbeddedId;
34 import javax.persistence.Entity;
35 import javax.persistence.Inheritance;
36 import javax.persistence.InheritanceType;
37 import javax.persistence.Table;
38 import javax.ws.rs.core.Response;
39 import lombok.Data;
40 import lombok.EqualsAndHashCode;
41 import lombok.NonNull;
42 import org.apache.commons.lang3.ObjectUtils;
43 import org.onap.policy.common.utils.coder.CoderException;
44 import org.onap.policy.common.utils.coder.StandardCoder;
45 import org.onap.policy.common.utils.coder.YamlJsonTranslator;
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.PfModelRuntimeException;
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.tosca.authorative.concepts.ToscaConstraint;
57 import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
58 import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty.Status;
59
60 /**
61  * Class to represent the property in TOSCA definition.
62  *
63  * @author Chenfei Gao (cgao@research.att.com)
64  * @author Liam Fallon (liam.fallon@est.tech)
65  */
66 @Entity
67 @Table(name = "ToscaProperty")
68 @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
69 @Data
70 @EqualsAndHashCode(callSuper = false)
71 public class JpaToscaProperty extends PfConcept implements PfAuthorative<ToscaProperty> {
72     private static final long serialVersionUID = 1675770231921107988L;
73
74     @EmbeddedId
75     private PfReferenceKey key;
76
77     @Column
78     private PfConceptKey type;
79
80     @Column
81     private String description;
82
83     @Column
84     private boolean required = false;
85
86     @Column(name = "default")
87     private String defaultValue;
88
89     @Column
90     private Status status = Status.SUPPORTED;
91
92     @ElementCollection
93     private List<JpaToscaConstraint> constraints = new ArrayList<>();
94
95     @Column
96     private JpaToscaEntrySchema entrySchema;
97
98     @ElementCollection
99     private Map<String, String> metadata = new LinkedHashMap<>();
100
101     /**
102      * The Default Constructor creates a {@link JpaToscaProperty} object with a null key.
103      */
104     public JpaToscaProperty() {
105         this(new PfReferenceKey());
106     }
107
108     /**
109      * The Key Constructor creates a {@link JpaToscaProperty} object with the given concept key.
110      *
111      * @param key the key
112      */
113     public JpaToscaProperty(@NonNull final PfReferenceKey key) {
114         this(key, new PfConceptKey());
115     }
116
117     /**
118      * The Key Constructor creates a {@link JpaToscaProperty} object with the given concept key.
119      *
120      * @param key  the key
121      * @param type the key of the property type
122      */
123     public JpaToscaProperty(@NonNull final PfReferenceKey key, @NonNull final PfConceptKey type) {
124         this.key = key;
125         this.type = type;
126     }
127
128     /**
129      * Copy constructor.
130      *
131      * @param copyConcept the concept to copy from
132      */
133     public JpaToscaProperty(final JpaToscaProperty copyConcept) {
134         super(copyConcept);
135         this.key = new PfReferenceKey(copyConcept.key);
136         this.type = new PfConceptKey(copyConcept.type);
137         this.description = copyConcept.description;
138         this.required = copyConcept.required;
139         this.defaultValue = copyConcept.defaultValue;
140         this.status = copyConcept.status;
141         // Constraints are immutable
142         this.constraints = (copyConcept.constraints != null ? new ArrayList<>(copyConcept.constraints) : null);
143         this.entrySchema = (copyConcept.entrySchema != null ? new JpaToscaEntrySchema(copyConcept.entrySchema) : null);
144         this.metadata = (copyConcept.metadata != null ? new LinkedHashMap<>(copyConcept.metadata) : null);
145     }
146
147     /**
148      * Authorative constructor.
149      *
150      * @param authorativeConcept the authorative concept to copy from
151      */
152     public JpaToscaProperty(final ToscaProperty authorativeConcept) {
153         this.fromAuthorative(authorativeConcept);
154     }
155
156     @Override
157     public ToscaProperty toAuthorative() {
158         ToscaProperty toscaProperty = new ToscaProperty();
159
160         toscaProperty.setName(key.getLocalName());
161
162         toscaProperty.setType(type.getName());
163         toscaProperty.setTypeVersion(type.getVersion());
164
165         toscaProperty.setDescription(description);
166         toscaProperty.setRequired(required);
167         toscaProperty.setStatus(status);
168
169         if (defaultValue != null) {
170             toscaProperty.setDefaultValue(new YamlJsonTranslator().fromYaml(defaultValue, Object.class));
171         }
172
173         if (constraints != null) {
174             List<ToscaConstraint> toscaConstraints = new ArrayList<>();
175
176             for (JpaToscaConstraint constraint : constraints) {
177                 toscaConstraints.add(constraint.toAuthorative());
178             }
179
180             toscaProperty.setConstraints(toscaConstraints);
181         }
182
183         if (entrySchema != null) {
184             toscaProperty.setEntrySchema(entrySchema.toAuthorative());
185         }
186
187         if (metadata != null) {
188             toscaProperty.setMetadata(new LinkedHashMap<>(metadata));
189         }
190
191         return toscaProperty;
192     }
193
194     @Override
195     public void fromAuthorative(ToscaProperty toscaProperty) {
196         this.setKey(new PfReferenceKey());
197         getKey().setLocalName(toscaProperty.getName());
198
199         if (toscaProperty.getTypeVersion() != null) {
200             type = new PfConceptKey(toscaProperty.getType(), toscaProperty.getTypeVersion());
201         } else {
202             type = new PfConceptKey(toscaProperty.getType(), PfKey.NULL_KEY_VERSION);
203         }
204
205         description = toscaProperty.getDescription();
206         required = toscaProperty.isRequired();
207         status = toscaProperty.getStatus();
208
209         if (toscaProperty.getDefaultValue() != null) {
210             defaultValue = new YamlJsonTranslator().toYaml(toscaProperty.getDefaultValue()).trim();
211         } else {
212             defaultValue = null;
213         }
214
215         if (toscaProperty.getConstraints() != null) {
216             constraints = new ArrayList<>();
217
218             for (ToscaConstraint toscaConstraint : toscaProperty.getConstraints()) {
219                 constraints.add(JpaToscaConstraint.newInstance(toscaConstraint));
220             }
221         }
222
223         if (toscaProperty.getEntrySchema() != null) {
224             entrySchema = new JpaToscaEntrySchema(toscaProperty.getEntrySchema());
225         }
226
227         // Add the property metadata if it doesn't exist already
228         if (toscaProperty.getMetadata() != null) {
229             metadata = new LinkedHashMap<>(toscaProperty.getMetadata());
230         }
231
232     }
233
234     @Override
235     public List<PfKey> getKeys() {
236         final List<PfKey> keyList = getKey().getKeys();
237
238         keyList.addAll(type.getKeys());
239
240         if (entrySchema != null) {
241             keyList.addAll(entrySchema.getKeys());
242         }
243
244         return keyList;
245     }
246
247     @Override
248     public void clean() {
249         key.clean();
250
251         type.clean();
252
253         if (description != null) {
254             description = description.trim();
255         }
256
257         if (defaultValue != null) {
258             defaultValue = defaultValue.trim();
259         }
260
261         if (entrySchema != null) {
262             entrySchema.clean();
263         }
264
265         if (metadata != null) {
266             for (Entry<String, String> metadataEntry : metadata.entrySet()) {
267                 metadataEntry.setValue(metadataEntry.getValue().trim());
268             }
269         }
270     }
271
272     @Override
273     public PfValidationResult validate(final PfValidationResult resultIn) {
274         PfValidationResult result = resultIn;
275
276         if (key.isNullKey()) {
277             result.addValidationMessage(
278                 new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key"));
279         }
280
281         result = key.validate(result);
282
283         if (type == null || type.isNullKey()) {
284             result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
285                 "property type may not be null"));
286         }
287
288         return validateFields(result);
289     }
290
291     /**
292      * Validate the property fields.
293      *
294      * @param resultIn the incoming validation results so far
295      * @return the validation results including this validation
296      */
297     private PfValidationResult validateFields(final PfValidationResult resultIn) {
298         PfValidationResult result = resultIn;
299
300         if (description != null && description.trim().length() == 0) {
301             result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
302                 "property description may not be blank"));
303         }
304
305         if (defaultValue != null && defaultValue.trim().length() == 0) {
306             result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
307                 "property default value may not be null"));
308         }
309
310         if (constraints != null) {
311             for (JpaToscaConstraint constraint : constraints) {
312                 if (constraint == null) {
313                     result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
314                         "property constraint may not be null "));
315                 }
316             }
317         }
318         return (entrySchema != null ? entrySchema.validate(result) : result);
319     }
320
321     @Override
322     public int compareTo(final PfConcept otherConcept) {
323         if (otherConcept == null) {
324             return -1;
325         }
326         if (this == otherConcept) {
327             return 0;
328         }
329         if (getClass() != otherConcept.getClass()) {
330             return getClass().getName().compareTo(otherConcept.getClass().getName());
331         }
332
333         final JpaToscaProperty other = (JpaToscaProperty) otherConcept;
334         if (!key.equals(other.key)) {
335             return key.compareTo(other.key);
336         }
337
338         return compareFields(other);
339     }
340
341     /**
342      * Compare the fields of this ToscaProperty object with the fields of the other ToscaProperty object.
343      *
344      * @param other the other ToscaProperty object
345      */
346     private int compareFields(final JpaToscaProperty other) {
347         if (!type.equals(other.type)) {
348             return type.compareTo(other.type);
349         }
350
351         int result = ObjectUtils.compare(description, other.description);
352         if (result != 0) {
353             return result;
354         }
355
356         result = ObjectUtils.compare(required, other.required);
357         if (result != 0) {
358             return result;
359         }
360
361         result = ObjectUtils.compare(defaultValue, other.defaultValue);
362         if (result != 0) {
363             return result;
364         }
365
366         result = ObjectUtils.compare(status, other.status);
367         if (result != 0) {
368             return result;
369         }
370
371         result = PfUtils.compareObjects(constraints, other.constraints);
372         if (result != 0) {
373             return result;
374         }
375
376         return entrySchema.compareTo(other.entrySchema);
377     }
378 }