Restructure for authorative models
[policy/models.git] / models-tosca / src / main / java / org / onap / policy / models / tosca / simple / serialization / ToscaPropertiesJsonAdapter.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.models.tosca.simple.serialization;
22
23 import com.google.gson.JsonArray;
24 import com.google.gson.JsonElement;
25 import com.google.gson.JsonObject;
26
27 import java.util.Iterator;
28 import java.util.LinkedList;
29 import java.util.List;
30 import java.util.Map.Entry;
31 import javax.ws.rs.core.Response;
32
33 import org.onap.policy.models.base.PfConceptKey;
34 import org.onap.policy.models.base.PfModelRuntimeException;
35 import org.onap.policy.models.base.PfReferenceKey;
36 import org.onap.policy.models.tosca.simple.concepts.JpaToscaConstraint;
37 import org.onap.policy.models.tosca.simple.concepts.JpaToscaConstraintLogical.Operation;
38 import org.onap.policy.models.tosca.simple.concepts.JpaToscaConstraintLogicalString;
39 import org.onap.policy.models.tosca.simple.concepts.JpaToscaConstraintValidValues;
40 import org.onap.policy.models.tosca.simple.concepts.JpaToscaEntrySchema;
41 import org.onap.policy.models.tosca.simple.concepts.JpaToscaProperty;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45
46 /**
47  * GSON type adapter for TOSCA properties.
48  *
49  * @author Chenfei Gao (cgao@research.att.com)
50  */
51 public class ToscaPropertiesJsonAdapter {
52
53     private static final Logger LOGGER = LoggerFactory.getLogger(ToscaPropertiesJsonAdapter.class);
54
55     private static final String DESCRIPTION = "description";
56     private static final String REQUIRED = "required";
57     private static final String DEFAULT = "default";
58     private static final String TYPE = "type";
59     private static final String ENTRY_SCHEMA = "entry_schema";
60     private static final String CONSTRAINTS = "constraints";
61     private static final String EQUAL = "equal";
62     private static final String VALID_VALUES = "valid_values";
63     private static final String DEFAULT_VERSION = "1.0.0";
64
65     /**
66      * Deserializes the properties.
67      *
68      * @param propertiesElement the properties in JsonElement
69      *
70      * @return deserialized ToscaProperty list
71      */
72     public List<JpaToscaProperty> deserializeProperties(JsonElement propertiesElement) {
73
74         final JsonObject propertiesMapObject = propertiesElement.getAsJsonObject();
75         List<JpaToscaProperty> properties = new LinkedList<>();
76
77         for (Entry<String, JsonElement> entry : propertiesMapObject.entrySet()) {
78             final String propertyEntryKey = entry.getKey();
79             final JsonElement propertyEntryVal = entry.getValue();
80
81             // Set property: key and type
82             JpaToscaProperty property = new JpaToscaProperty(
83                     new PfReferenceKey(new PfConceptKey(), propertyEntryKey),
84                     new PfConceptKey(propertyEntryVal.getAsJsonObject().get(TYPE).getAsString(), DEFAULT_VERSION));
85
86             // Set property: description
87             JsonObject propertyJsonObject = propertyEntryVal.getAsJsonObject();
88             if (propertyJsonObject.has(DESCRIPTION)) {
89                 property.setDescription(propertyJsonObject.get(DESCRIPTION).getAsString());
90             }
91
92             // Set property: required
93             if (propertyJsonObject.has(REQUIRED)) {
94                 property.setRequired(propertyJsonObject.get(REQUIRED).getAsBoolean());
95             }
96
97             // Set property: default
98             if (propertyJsonObject.has(DEFAULT)) {
99                 property.setDefaultValue(propertyJsonObject.get(DEFAULT).getAsString());
100             }
101
102             // Set property: entry_schema
103             if (propertyJsonObject.has(ENTRY_SCHEMA)) {
104                 checkEntrySchemaCompatibility(property.getType().getName());
105                 property.setEntrySchema(deserializeEntrySchema(propertyJsonObject.get(ENTRY_SCHEMA)));
106                 property.getEntrySchema().getKey().setParentConceptKey(property.getType());
107                 property.getEntrySchema().getType().setVersion(property.getType().getVersion());
108             }
109
110             // Set property: constraints
111             if (propertyJsonObject.has(CONSTRAINTS)) {
112                 property.setConstraints(deserializeConstraints(propertyJsonObject.get(CONSTRAINTS)));
113                 for (JpaToscaConstraint c : property.getConstraints()) {
114                     c.getKey().setParentConceptKey(property.getType());
115                 }
116             }
117
118             // Add property to properties list
119             properties.add(property);
120         }
121
122         return properties;
123     }
124
125     /**
126      * Serializes the properties.
127      *
128      * @param properties the list of ToscaProperty
129      *
130      * @return serialized JsonElement
131      */
132     public JsonElement serializeProperties(List<JpaToscaProperty> properties) {
133
134         JsonObject propertiesJsonObject = new JsonObject();
135
136         for (JpaToscaProperty property : properties) {
137             JsonObject propertyValJsonObject = new JsonObject();
138
139             // Add type
140             propertyValJsonObject.addProperty(TYPE, property.getType().getName());
141
142             // Add description
143             if (property.getDescription() != null) {
144                 propertyValJsonObject.addProperty(DESCRIPTION, property.getDescription());
145             }
146
147             // Add required
148             propertyValJsonObject.addProperty(REQUIRED, property.isRequired());
149
150             // Add defaultValue
151             if (property.getDefaultValue() != null) {
152                 propertyValJsonObject.addProperty(DEFAULT, property.getDefaultValue());
153             }
154
155             // Add constraints
156             if (property.getConstraints() != null) {
157                 propertyValJsonObject.add(CONSTRAINTS, serializeConstraints(property.getConstraints()));
158             }
159
160             // Add entry_schema
161             if (property.getEntrySchema() != null) {
162                 propertyValJsonObject.add(ENTRY_SCHEMA, serializeEntrySchema(property.getEntrySchema()));
163             }
164
165             propertiesJsonObject.add(property.getKey().getLocalName(), propertyValJsonObject);
166         }
167
168         return propertiesJsonObject;
169     }
170
171     private JsonElement serializeConstraints(List<JpaToscaConstraint> constraints) {
172
173         JsonArray constraintsValJsonArray = new JsonArray();
174
175         for (JpaToscaConstraint c : constraints) {
176             JsonObject constraintJsonObject = new JsonObject();
177
178             // Check which type of constraint it is
179             // TODO: here we only support valid_values and equal
180             if (c instanceof JpaToscaConstraintValidValues) {
181                 JsonArray validValuesJsonArray = new JsonArray();
182                 for (String validValue : ((JpaToscaConstraintValidValues)c).getValidValues()) {
183                     validValuesJsonArray.add(validValue);
184                 }
185                 constraintJsonObject.add(VALID_VALUES, validValuesJsonArray);
186             } else if (c instanceof JpaToscaConstraintLogicalString) {
187                 constraintJsonObject.addProperty(EQUAL, ((JpaToscaConstraintLogicalString)c).getCompareToString());
188             } else {
189                 String errorMessage = "constraint is neither valid_values nor equal";
190                 LOGGER.debug(errorMessage);
191                 throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR, errorMessage);
192             }
193
194             constraintsValJsonArray.add(constraintJsonObject);
195         }
196
197         return constraintsValJsonArray;
198     }
199
200     private JsonElement serializeEntrySchema(JpaToscaEntrySchema entrySchema) {
201
202         JsonObject entrySchemaValJsonObject = new JsonObject();
203
204         // Add type
205         entrySchemaValJsonObject.addProperty(TYPE, entrySchema.getType().getName());
206
207         // Add description
208         if (entrySchema.getDescription() != null) {
209             entrySchemaValJsonObject.addProperty(DESCRIPTION, entrySchema.getDescription());
210         }
211
212         // Add constraints
213         if (entrySchema.getConstraints() != null) {
214             entrySchemaValJsonObject.add(CONSTRAINTS, serializeConstraints(entrySchema.getConstraints()));
215         }
216
217         return entrySchemaValJsonObject;
218     }
219
220     private JpaToscaEntrySchema deserializeEntrySchema(JsonElement entrySchemaElement) {
221
222         JsonObject entrySchemaJsonObject = entrySchemaElement.getAsJsonObject();
223
224         // Set entry_schema: key and type
225         JpaToscaEntrySchema entrySchema = new JpaToscaEntrySchema(
226                 new PfReferenceKey(new PfConceptKey(), ENTRY_SCHEMA),
227                 new PfConceptKey(entrySchemaJsonObject.get(TYPE).getAsString(), DEFAULT_VERSION));
228
229         // Set entry_schema: description
230         if (entrySchemaJsonObject.has(DESCRIPTION)) {
231             entrySchema.setDescription(entrySchemaJsonObject.get(DESCRIPTION).getAsString());
232         }
233
234         // Set entry_schema: constraints
235         if (entrySchemaJsonObject.has(CONSTRAINTS)) {
236             entrySchema.setConstraints(deserializeConstraints(entrySchemaJsonObject.get(CONSTRAINTS)));
237             for (JpaToscaConstraint c : entrySchema.getConstraints()) {
238                 c.getKey().setParentConceptKey(entrySchema.getType());
239             }
240         }
241
242         return entrySchema;
243     }
244
245     private List<JpaToscaConstraint> deserializeConstraints(JsonElement constraintsElement) {
246
247         JsonArray constraintsJsonArray = constraintsElement.getAsJsonArray();
248         List<JpaToscaConstraint> constraints = new LinkedList<>();
249
250         for (Iterator<JsonElement> constraintsIter = constraintsJsonArray.iterator(); constraintsIter.hasNext(); ) {
251             JsonObject constraintJsonObject = constraintsIter.next().getAsJsonObject();
252             // Check which type of constraint it is
253             // TODO: here we only check 'valid_values' and 'equal'
254             if (constraintJsonObject.get(VALID_VALUES) != null) {
255                 List<String> validValues = new LinkedList<>();
256                 for (Iterator<JsonElement> validValuesIter = constraintJsonObject.get(VALID_VALUES).getAsJsonArray()
257                         .iterator(); validValuesIter.hasNext(); ) {
258                     validValues.add(validValuesIter.next().getAsString());
259                 }
260                 JpaToscaConstraint constraint = new JpaToscaConstraintValidValues(
261                         new PfReferenceKey(new PfConceptKey(), VALID_VALUES), validValues);
262                 constraints.add(constraint);
263             } else if (constraintJsonObject.get(EQUAL) != null) {
264                 JpaToscaConstraint constraint = new JpaToscaConstraintLogicalString(new PfReferenceKey(
265                         new PfConceptKey(), EQUAL), Operation.EQ, constraintJsonObject.get(EQUAL).getAsString());
266                 constraints.add(constraint);
267             } else {
268                 String errorMessage = "specified constraint is neither valid_values nor equal";
269                 LOGGER.debug(errorMessage);
270                 throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, errorMessage);
271             }
272         }
273
274         return constraints;
275     }
276
277     private void checkEntrySchemaCompatibility(String type) {
278         if (!("list".equalsIgnoreCase(type)) && !("map".equalsIgnoreCase(type))) {
279             String errorMessage = "entry schema can only be specified for list or map property";
280             LOGGER.debug(errorMessage);
281             throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, errorMessage);
282         }
283     }
284 }