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