528d695c3d7c1bb5f364dbbd8119cec993f32beb
[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      * For the legacy case the operational policy given is modified (configurationJson).
156      *
157      * @param operationalPolicy The operational policy
158      * @param toscaConverter    The tosca converter
159      * @return The Json Object with Json schema
160      */
161     public static JsonObject generateJsonRepresentation(OperationalPolicy operationalPolicy,
162                                                         ToscaConverterWithDictionarySupport toscaConverter)
163             throws IOException {
164         JsonObject jsonReturned = new JsonObject();
165         if (operationalPolicy.getPolicyModel() == null) {
166             return new JsonObject();
167         }
168         if (operationalPolicy.isLegacy()) {
169             // Op policy Legacy case
170             LegacyOperationalPolicy.preloadConfiguration(operationalPolicy.getConfigurationsJson(), operationalPolicy.loop);
171             jsonReturned = OperationalPolicyRepresentationBuilder
172                     .generateOperationalPolicySchema(operationalPolicy.loop.getModelService());
173         }
174         else {
175             // Generic Case
176             jsonReturned = toscaConverter.convertToscaToJsonSchemaObject(
177                     operationalPolicy.getPolicyModel().getPolicyModelTosca(),
178                     operationalPolicy.getPolicyModel().getPolicyModelType());
179         }
180
181         return jsonReturned;
182     }
183
184     public void setLoop(Loop loopName) {
185         this.loop = loopName;
186     }
187
188     public Loop getLoop() {
189         return loop;
190     }
191
192     @Override
193     public String getName() {
194         return name;
195     }
196
197     /**
198      * name setter.
199      *
200      * @param name the name to set
201      */
202     @Override
203     public void setName(String name) {
204         this.name = name;
205     }
206
207     @Override
208     public int hashCode() {
209         final int prime = 31;
210         int result = 1;
211         result = prime * result + ((name == null) ? 0 : name.hashCode());
212         return result;
213     }
214
215     @Override
216     public boolean equals(Object obj) {
217         if (this == obj) {
218             return true;
219         }
220         if (obj == null) {
221             return false;
222         }
223         if (getClass() != obj.getClass()) {
224             return false;
225         }
226         OperationalPolicy other = (OperationalPolicy) obj;
227         if (name == null) {
228             if (other.name != null) {
229                 return false;
230             }
231         }
232         else if (!name.equals(other.name)) {
233             return false;
234         }
235         return true;
236     }
237
238     public Boolean isLegacy() {
239         return (this.getPolicyModel() != null) && this.getPolicyModel().getPolicyModelType().contains("legacy");
240     }
241
242     /**
243      * Create policy Yaml from json defined here.
244      *
245      * @return A string containing Yaml
246      */
247     public String createPolicyPayloadYaml() {
248         JsonObject policyPayloadResult = new JsonObject();
249
250         policyPayloadResult.addProperty("tosca_definitions_version", "tosca_simple_yaml_1_0_0");
251
252         JsonObject topologyTemplateNode = new JsonObject();
253         policyPayloadResult.add("topology_template", topologyTemplateNode);
254
255         JsonArray policiesArray = new JsonArray();
256         topologyTemplateNode.add("policies", policiesArray);
257
258         JsonObject operationalPolicy = new JsonObject();
259         policiesArray.add(operationalPolicy);
260
261         JsonObject operationalPolicyDetails = new JsonObject();
262         operationalPolicy.add(this.name, operationalPolicyDetails);
263         operationalPolicyDetails.addProperty("type", "onap.policies.controlloop.Operational");
264         operationalPolicyDetails.addProperty("version", "1.0.0");
265
266         JsonObject metadata = new JsonObject();
267         operationalPolicyDetails.add("metadata", metadata);
268         metadata.addProperty("policy-id", this.name);
269
270         operationalPolicyDetails.add("properties", LegacyOperationalPolicy
271                 .reworkActorAttributes(this.getConfigurationsJson().get("operational_policy").deepCopy()));
272
273         DumperOptions options = new DumperOptions();
274         options.setIndent(2);
275         options.setPrettyFlow(true);
276         options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
277         Gson gson = new GsonBuilder().create();
278
279         return (new Yaml(options)).dump(gson.fromJson(gson.toJson(policyPayloadResult), Map.class));
280     }
281
282     @Override
283     public String createPolicyPayload() throws UnsupportedEncodingException {
284         if (isLegacy()) {
285             // Now using the legacy payload fo Dublin
286             JsonObject payload = new JsonObject();
287             payload.addProperty("policy-id", this.getName());
288             payload.addProperty("content",
289                     URLEncoder.encode(
290                             LegacyOperationalPolicy
291                                     .createPolicyPayloadYamlLegacy(
292                                             this.getConfigurationsJson().get("operational_policy")),
293                             StandardCharsets.UTF_8.toString()));
294             String opPayload = new GsonBuilder().setPrettyPrinting().create().toJson(payload);
295             logger.info("Operational policy payload: " + opPayload);
296             return opPayload;
297         }
298         else {
299             return super.createPolicyPayload();
300         }
301     }
302
303     /**
304      * Return a map containing all Guard policies indexed by Guard policy Name.
305      *
306      * @return The Guards map
307      */
308     public Map<String, String> createGuardPolicyPayloads() {
309         Map<String, String> result = new HashMap<>();
310
311         if (this.getConfigurationsJson() != null) {
312             JsonElement guardsList = this.getConfigurationsJson().get("guard_policies");
313             if (guardsList != null) {
314                 for (JsonElement guardElem : guardsList.getAsJsonArray()) {
315                     result.put(guardElem.getAsJsonObject().get("policy-id").getAsString(),
316                             new GsonBuilder().create().toJson(guardElem));
317                 }
318             }
319         }
320         logger.info("Guard policy payload: " + result);
321         return result;
322     }
323
324     /**
325      * Regenerate the Operational Policy Json Representation.
326      */
327     public void updateJsonRepresentation() {
328         try {
329             this.setJsonRepresentation(
330                     OperationalPolicyRepresentationBuilder.generateOperationalPolicySchema(loop.getModelService()));
331         } catch (JsonSyntaxException | IOException | NullPointerException e) {
332             logger.error("Unable to generate the operational policy Schema ... ", e);
333             this.setJsonRepresentation(new JsonObject());
334         }
335     }
336 }