Fix the new tosca converter
[clamp.git] / src / main / java / org / onap / clamp / policy / operational / OperationalPolicy.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP CLAMP
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights
6  *                             reserved.
7  * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END============================================
21  * ===================================================================
22  *
23  */
24
25 package org.onap.clamp.policy.operational;
26
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import com.google.gson.Gson;
30 import com.google.gson.GsonBuilder;
31 import com.google.gson.JsonArray;
32 import com.google.gson.JsonElement;
33 import com.google.gson.JsonObject;
34 import com.google.gson.JsonSyntaxException;
35 import com.google.gson.annotations.Expose;
36 import java.io.IOException;
37 import java.io.Serializable;
38 import java.io.UnsupportedEncodingException;
39 import java.net.URLEncoder;
40 import java.nio.charset.StandardCharsets;
41 import java.util.HashMap;
42 import java.util.Map;
43 import javax.persistence.Column;
44 import javax.persistence.Entity;
45 import javax.persistence.FetchType;
46 import javax.persistence.Id;
47 import javax.persistence.JoinColumn;
48 import javax.persistence.ManyToOne;
49 import javax.persistence.Table;
50 import javax.persistence.Transient;
51 import org.apache.commons.lang3.RandomStringUtils;
52 import org.hibernate.annotations.TypeDef;
53 import org.hibernate.annotations.TypeDefs;
54 import org.onap.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
55 import org.onap.clamp.dao.model.jsontype.StringJsonUserType;
56 import org.onap.clamp.loop.Loop;
57 import org.onap.clamp.loop.service.Service;
58 import org.onap.clamp.loop.template.LoopElementModel;
59 import org.onap.clamp.loop.template.PolicyModel;
60 import org.onap.clamp.policy.Policy;
61 import org.yaml.snakeyaml.DumperOptions;
62 import org.yaml.snakeyaml.Yaml;
63
64 @Entity
65 @Table(name = "operational_policies")
66 @TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
67 public class OperationalPolicy extends Policy implements Serializable {
68     /**
69      * The serial version ID.
70      */
71     private static final long serialVersionUID = 6117076450841538255L;
72
73     @Transient
74     private static final EELFLogger logger = EELFManager.getInstance().getLogger(OperationalPolicy.class);
75
76     @Id
77     @Expose
78     @Column(nullable = false, name = "name", unique = true)
79     private String name;
80
81     @ManyToOne(fetch = FetchType.LAZY)
82     @JoinColumn(name = "loop_id", nullable = false)
83     private Loop loop;
84
85     /**
86      * Constructor for serialization.
87      */
88     public OperationalPolicy() {
89     }
90
91     /**
92      * The constructor.
93      *
94      * @param name               The name of the operational policy
95      * @param configurationsJson The operational policy property in the format of
96      *                           json
97      * @param jsonRepresentation The jsonObject defining the json schema
98      * @param policyModel        The policy model associated if any, can be null
99      * @param loopElementModel   The loop element from which this instance is supposed to be created
100      * @param pdpGroup           The Pdp Group info
101      * @param pdpSubgroup        The Pdp Subgroup info
102      */
103     public OperationalPolicy(String name, JsonObject configurationsJson,
104                              JsonObject jsonRepresentation, PolicyModel policyModel,
105                              LoopElementModel loopElementModel, String pdpGroup, String pdpSubgroup) {
106         this.name = name;
107         this.setPolicyModel(policyModel);
108         this.setConfigurationsJson(configurationsJson);
109         this.setPdpGroup(pdpGroup);
110         this.setPdpSubgroup(pdpSubgroup);
111         this.setLoopElementModel(loopElementModel);
112         this.setJsonRepresentation(jsonRepresentation);
113
114     }
115
116     /**
117      * Create an operational policy from a loop element model.
118      *
119      * @param loop             The parent loop
120      * @param service          The loop service
121      * @param loopElementModel The loop element model
122      * @param toscaConverter   The tosca converter that must be used to create the Json representation
123      * @throws IOException In case of issues with the legacy files (generated from resource files
124      */
125     public OperationalPolicy(Loop loop, Service service, LoopElementModel loopElementModel,
126                              ToscaConverterWithDictionarySupport toscaConverter) throws IOException {
127         this(Policy.generatePolicyName("OPERATIONAL", service.getName(), service.getVersion(),
128                 RandomStringUtils.randomAlphanumeric(3), RandomStringUtils.randomAlphanumeric(3)), new JsonObject(),
129                 new JsonObject(), loopElementModel.getPolicyModels().first(), loopElementModel, null, null);
130         this.setLoop(loop);
131         this.setJsonRepresentation(generateJsonRepresentation(this, toscaConverter));
132     }
133
134     /**
135      * Create an operational policy from a policy model.
136      *
137      * @param loop             The parent loop
138      * @param service          The loop service
139      * @param policyModel       The policy model
140      * @param toscaConverter   The tosca converter that must be used to create the Json representation
141      * @throws IOException In case of issues with the legacy files (generated from resource files
142      */
143     public OperationalPolicy(Loop loop, Service service, PolicyModel policyModel,
144                              ToscaConverterWithDictionarySupport toscaConverter) throws IOException {
145         this(Policy.generatePolicyName("OPERATIONAL", service.getName(), service.getVersion(),
146                 RandomStringUtils.randomAlphanumeric(3), RandomStringUtils.randomAlphanumeric(3)), new JsonObject(),
147                 new JsonObject(), policyModel, null, null, null);
148         this.setLoop(loop);
149         this.setJsonRepresentation(generateJsonRepresentation(this, toscaConverter));
150     }
151
152     /**
153      * This method can generate a Json representation (json schema) for an operational policy.
154      * This is mainly to support a legacy case and a generic case.
155      *
156      * @param operationalPolicy The operational policy
157      * @param toscaConverter    The tosca converter
158      * @return The Json Object with Json schema
159      */
160     public static JsonObject generateJsonRepresentation(OperationalPolicy operationalPolicy,
161                                                         ToscaConverterWithDictionarySupport toscaConverter)
162             throws IOException {
163         JsonObject jsonReturned = new JsonObject();
164         if (operationalPolicy.getPolicyModel() == null) {
165             return new JsonObject();
166         }
167         if (operationalPolicy.isLegacy()) {
168             // Op policy Legacy case
169             LegacyOperationalPolicy.preloadConfiguration(jsonReturned, operationalPolicy.loop);
170             jsonReturned = OperationalPolicyRepresentationBuilder
171                     .generateOperationalPolicySchema(operationalPolicy.loop.getModelService());
172         }
173         else {
174             // Generic Case
175             jsonReturned = toscaConverter.convertToscaToJsonSchemaObject(
176                     operationalPolicy.getPolicyModel().getPolicyModelTosca(),
177                     operationalPolicy.getPolicyModel().getPolicyModelType());
178         }
179
180         return jsonReturned;
181     }
182
183     public void setLoop(Loop loopName) {
184         this.loop = loopName;
185     }
186
187     public Loop getLoop() {
188         return loop;
189     }
190
191     @Override
192     public String getName() {
193         return name;
194     }
195
196     /**
197      * name setter.
198      *
199      * @param name the name to set
200      */
201     @Override
202     public void setName(String name) {
203         this.name = name;
204     }
205
206     @Override
207     public int hashCode() {
208         final int prime = 31;
209         int result = 1;
210         result = prime * result + ((name == null) ? 0 : name.hashCode());
211         return result;
212     }
213
214     @Override
215     public boolean equals(Object obj) {
216         if (this == obj) {
217             return true;
218         }
219         if (obj == null) {
220             return false;
221         }
222         if (getClass() != obj.getClass()) {
223             return false;
224         }
225         OperationalPolicy other = (OperationalPolicy) obj;
226         if (name == null) {
227             if (other.name != null) {
228                 return false;
229             }
230         }
231         else if (!name.equals(other.name)) {
232             return false;
233         }
234         return true;
235     }
236
237     public Boolean isLegacy() {
238         return (this.getPolicyModel() != null) && this.getPolicyModel().getPolicyModelType().contains("legacy");
239     }
240
241     /**
242      * Create policy Yaml from json defined here.
243      *
244      * @return A string containing Yaml
245      */
246     public String createPolicyPayloadYaml() {
247         JsonObject policyPayloadResult = new JsonObject();
248
249         policyPayloadResult.addProperty("tosca_definitions_version", "tosca_simple_yaml_1_0_0");
250
251         JsonObject topologyTemplateNode = new JsonObject();
252         policyPayloadResult.add("topology_template", topologyTemplateNode);
253
254         JsonArray policiesArray = new JsonArray();
255         topologyTemplateNode.add("policies", policiesArray);
256
257         JsonObject operationalPolicy = new JsonObject();
258         policiesArray.add(operationalPolicy);
259
260         JsonObject operationalPolicyDetails = new JsonObject();
261         operationalPolicy.add(this.name, operationalPolicyDetails);
262         operationalPolicyDetails.addProperty("type", "onap.policies.controlloop.Operational");
263         operationalPolicyDetails.addProperty("version", "1.0.0");
264
265         JsonObject metadata = new JsonObject();
266         operationalPolicyDetails.add("metadata", metadata);
267         metadata.addProperty("policy-id", this.name);
268
269         operationalPolicyDetails.add("properties", LegacyOperationalPolicy
270                 .reworkActorAttributes(this.getConfigurationsJson().get("operational_policy").deepCopy()));
271
272         DumperOptions options = new DumperOptions();
273         options.setIndent(2);
274         options.setPrettyFlow(true);
275         options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
276         Gson gson = new GsonBuilder().create();
277
278         return (new Yaml(options)).dump(gson.fromJson(gson.toJson(policyPayloadResult), Map.class));
279     }
280
281     @Override
282     public String createPolicyPayload() throws UnsupportedEncodingException {
283         if (isLegacy()) {
284             // Now using the legacy payload fo Dublin
285             JsonObject payload = new JsonObject();
286             payload.addProperty("policy-id", this.getName());
287             payload.addProperty("content",
288                     URLEncoder.encode(
289                             LegacyOperationalPolicy
290                                     .createPolicyPayloadYamlLegacy(
291                                             this.getConfigurationsJson().get("operational_policy")),
292                             StandardCharsets.UTF_8.toString()));
293             String opPayload = new GsonBuilder().setPrettyPrinting().create().toJson(payload);
294             logger.info("Operational policy payload: " + opPayload);
295             return opPayload;
296         }
297         else {
298             return super.createPolicyPayload();
299         }
300     }
301
302     /**
303      * Return a map containing all Guard policies indexed by Guard policy Name.
304      *
305      * @return The Guards map
306      */
307     public Map<String, String> createGuardPolicyPayloads() {
308         Map<String, String> result = new HashMap<>();
309
310         if (this.getConfigurationsJson() != null) {
311             JsonElement guardsList = this.getConfigurationsJson().get("guard_policies");
312             if (guardsList != null) {
313                 for (JsonElement guardElem : guardsList.getAsJsonArray()) {
314                     result.put(guardElem.getAsJsonObject().get("policy-id").getAsString(),
315                             new GsonBuilder().create().toJson(guardElem));
316                 }
317             }
318         }
319         logger.info("Guard policy payload: " + result);
320         return result;
321     }
322
323     /**
324      * Regenerate the Operational Policy Json Representation.
325      */
326     public void updateJsonRepresentation() {
327         try {
328             this.setJsonRepresentation(
329                     OperationalPolicyRepresentationBuilder.generateOperationalPolicySchema(loop.getModelService()));
330         } catch (JsonSyntaxException | IOException | NullPointerException e) {
331             logger.error("Unable to generate the operational policy Schema ... ", e);
332             this.setJsonRepresentation(new JsonObject());
333         }
334     }
335 }