Implement serialization/deserialization for TOSCA concepts
[policy/models.git] / models-tosca / src / main / java / org / onap / policy / models / tosca / simple / concepts / ToscaProperty.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.tosca.simple.concepts;
25
26 import com.google.gson.JsonElement;
27 import com.google.gson.annotations.SerializedName;
28
29 import java.util.List;
30
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
39 import lombok.Data;
40 import lombok.EqualsAndHashCode;
41 import lombok.NonNull;
42
43 import org.apache.commons.lang3.ObjectUtils;
44 import org.onap.policy.common.utils.validation.Assertions;
45 import org.onap.policy.models.base.PfConcept;
46 import org.onap.policy.models.base.PfConceptKey;
47 import org.onap.policy.models.base.PfKey;
48 import org.onap.policy.models.base.PfReferenceKey;
49 import org.onap.policy.models.base.PfUtils;
50 import org.onap.policy.models.base.PfValidationMessage;
51 import org.onap.policy.models.base.PfValidationResult;
52 import org.onap.policy.models.base.PfValidationResult.ValidationResult;
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 ToscaProperty extends PfConcept {
66     private static final long serialVersionUID = 1675770231921107988L;
67
68     public enum Status {
69         SUPPORTED, UNSUPPORTED, EXPERIMENTAL, DEPRECATED
70     }
71
72     @EmbeddedId
73     private PfReferenceKey key;
74
75     @Column
76     private PfConceptKey type;
77
78     @Column
79     private String description;
80
81     @Column
82     private boolean required = false;
83
84     @Column(name = "default")
85     @SerializedName("default")
86     private String defaultValue;
87
88     @Column
89     @NonNull
90     private Status status = Status.SUPPORTED;
91
92     @ElementCollection
93     private List<ToscaConstraint> constraints;
94
95     @Column
96     @SerializedName("entry_schema")
97     private ToscaEntrySchema entrySchema;
98
99     /**
100      * The Default Constructor creates a {@link ToscaProperty} object with a null key.
101      */
102     public ToscaProperty() {
103         this(new PfReferenceKey());
104     }
105
106     /**
107      * The Key Constructor creates a {@link ToscaProperty} object with the given concept key.
108      *
109      * @param key the key
110      */
111     public ToscaProperty(@NonNull final PfReferenceKey key) {
112         this(key, new PfConceptKey());
113     }
114
115     /**
116      * The Key Constructor creates a {@link ToscaProperty} object with the given concept key.
117      *
118      * @param key the key
119      * @param type the key of the property type
120      */
121     public ToscaProperty(@NonNull final PfReferenceKey key, @NonNull final PfConceptKey type) {
122         this.key = key;
123         this.type = type;
124     }
125
126     /**
127      * Copy constructor.
128      *
129      * @param copyConcept the concept to copy from
130      */
131     public ToscaProperty(final ToscaProperty copyConcept) {
132         super(copyConcept);
133     }
134
135     @Override
136     public List<PfKey> getKeys() {
137         final List<PfKey> keyList = getKey().getKeys();
138
139         keyList.addAll(type.getKeys());
140
141         if (constraints != null) {
142             for (ToscaConstraint constraint : constraints) {
143                 keyList.addAll(constraint.getKeys());
144             }
145         }
146
147         if (entrySchema != null) {
148             keyList.addAll(entrySchema.getKeys());
149         }
150
151         return keyList;
152     }
153
154     @Override
155     public void clean() {
156         key.clean();
157
158         type.clean();
159
160         if (description != null) {
161             description = description.trim();
162         }
163
164         if (defaultValue != null) {
165             defaultValue = defaultValue.trim();
166         }
167
168         if (constraints != null) {
169             for (ToscaConstraint constraint : constraints) {
170                 constraint.clean();
171             }
172         }
173
174         if (entrySchema != null) {
175             entrySchema.clean();
176         }
177     }
178
179     @Override
180     public PfValidationResult validate(final PfValidationResult resultIn) {
181         PfValidationResult result = resultIn;
182
183         if (key.isNullKey()) {
184             result.addValidationMessage(
185                     new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key"));
186         }
187
188         result = key.validate(result);
189
190         if (type == null || type.isNullKey()) {
191             result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
192                     "property type may not be null"));
193         }
194
195         return validateFields(result);
196     }
197
198     /**
199      * Validate the property fields.
200      *
201      * @param resultIn the incoming validation results so far
202      * @return the validation results including this validation
203      */
204     private PfValidationResult validateFields(final PfValidationResult resultIn) {
205         PfValidationResult result = resultIn;
206
207         if (description != null && description.trim().length() == 0) {
208             result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
209                     "property description may not be blank"));
210         }
211
212         if (defaultValue != null && defaultValue.trim().length() == 0) {
213             result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
214                     "property default value may not be null"));
215         }
216
217         if (constraints != null) {
218             for (ToscaConstraint constraint : constraints) {
219                 if (constraint == null) {
220                     result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
221                             "property constraint may not be null "));
222                 } else {
223                     result = constraint.validate(result);
224                 }
225             }
226         }
227         return (entrySchema != null ? entrySchema.validate(result) : result);
228     }
229
230     @Override
231     public int compareTo(final PfConcept otherConcept) {
232         if (otherConcept == null) {
233             return -1;
234         }
235         if (this == otherConcept) {
236             return 0;
237         }
238         if (getClass() != otherConcept.getClass()) {
239             return this.hashCode() - otherConcept.hashCode();
240         }
241
242         final ToscaProperty other = (ToscaProperty) otherConcept;
243         if (!key.equals(other.key)) {
244             return key.compareTo(other.key);
245         }
246
247         return compareFields(other);
248     }
249
250     /**
251      * Compare the fields of this ToscaProperty object with the fields of the other ToscaProperty
252      * object.
253      *
254      * @param other the other ToscaProperty object
255      */
256     private int compareFields(final ToscaProperty other) {
257         if (!type.equals(other.type)) {
258             return type.compareTo(other.type);
259         }
260
261         int result = ObjectUtils.compare(description, other.description);
262         if (result != 0) {
263             return result;
264         }
265
266         result = ObjectUtils.compare(required, other.required);
267         if (result != 0) {
268             return result;
269         }
270
271         result = ObjectUtils.compare(defaultValue, other.defaultValue);
272         if (result != 0) {
273             return result;
274         }
275
276         result = ObjectUtils.compare(status, other.status);
277         if (result != 0) {
278             return result;
279         }
280
281         result = PfUtils.compareObjects(constraints, other.constraints);
282         if (result != 0) {
283             return result;
284         }
285
286         return entrySchema.compareTo(other.entrySchema);
287     }
288
289     @Override
290     public PfConcept copyTo(@NonNull final PfConcept target) {
291         Assertions.instanceOf(target, ToscaProperty.class);
292
293         final ToscaProperty copy = ((ToscaProperty) target);
294         copy.setKey(new PfReferenceKey(key));
295         copy.setType(new PfConceptKey(type));
296         copy.setDescription(description);
297         copy.setRequired(required);
298         copy.setDefaultValue(defaultValue);
299         copy.setStatus(status);
300         copy.constraints = constraints; // Constraints are immutable
301         copy.setEntrySchema(entrySchema != null ? new ToscaEntrySchema(entrySchema) : null);
302
303         return copy;
304     }
305 }