dd156d8f37f42646eb513a6485d2847212358f41
[clamp.git] / src / main / java / org / onap / clamp / policy / operational / LegacyOperationalPolicy.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP CLAMP
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights
6  *                             reserved.
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  * ============LICENSE_END============================================
20  * ===================================================================
21  *
22  */
23
24 package org.onap.clamp.policy.operational;
25
26 import com.google.gson.GsonBuilder;
27 import com.google.gson.JsonElement;
28 import com.google.gson.JsonObject;
29
30 import java.util.ArrayList;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Map.Entry;
34 import java.util.TreeMap;
35
36 import org.apache.commons.lang3.math.NumberUtils;
37 import org.onap.clamp.loop.Loop;
38 import org.yaml.snakeyaml.DumperOptions;
39 import org.yaml.snakeyaml.DumperOptions.ScalarStyle;
40 import org.yaml.snakeyaml.Yaml;
41
42 /**
43  * This class contains the code required to support the sending of Legacy
44  * operational payload to policy engine. This will probably disappear in El
45  * Alto.
46  */
47 public class LegacyOperationalPolicy {
48
49     private LegacyOperationalPolicy() {
50
51     }
52
53     private static void translateStringValues(String jsonKey, String stringValue, JsonElement parentJsonElement) {
54         if (stringValue.equalsIgnoreCase("true") || stringValue.equalsIgnoreCase("false")) {
55             parentJsonElement.getAsJsonObject().addProperty(jsonKey, Boolean.valueOf(stringValue));
56
57         } else if (NumberUtils.isParsable(stringValue)) {
58             parentJsonElement.getAsJsonObject().addProperty(jsonKey, Long.parseLong(stringValue));
59         }
60     }
61
62     private static JsonElement removeAllQuotes(JsonElement jsonElement) {
63         if (jsonElement.isJsonArray()) {
64             for (JsonElement element : jsonElement.getAsJsonArray()) {
65                 removeAllQuotes(element);
66             }
67         } else if (jsonElement.isJsonObject()) {
68             for (Entry<String, JsonElement> entry : jsonElement.getAsJsonObject().entrySet()) {
69                 if (entry.getValue().isJsonPrimitive() && entry.getValue().getAsJsonPrimitive().isString()) {
70                     translateStringValues(entry.getKey(), entry.getValue().getAsString(), jsonElement);
71                 } else {
72                     removeAllQuotes(entry.getValue());
73                 }
74             }
75         }
76         return jsonElement;
77     }
78
79     /**
80      * This method rework the payload attribute (yaml) that is normally wrapped in a
81      * string when coming from the UI.
82      * 
83      * @param policyJson The operational policy json config
84      * @return The same object reference but modified
85      */
86     public static JsonElement reworkPayloadAttributes(JsonElement policyJson) {
87         for (JsonElement policy : policyJson.getAsJsonObject().get("policies").getAsJsonArray()) {
88             JsonElement payloadElem = policy.getAsJsonObject().get("payload");
89             String payloadString = payloadElem != null ? payloadElem.getAsString() : "";
90             if (!payloadString.isEmpty()) {
91                 Map<String, String> testMap = new Yaml().load(payloadString);
92                 String json = new GsonBuilder().create().toJson(testMap);
93                 policy.getAsJsonObject().add("payload", new GsonBuilder().create().fromJson(json, JsonElement.class));
94             }
95         }
96         return policyJson;
97     }
98
99     private static void replacePropertiesIfEmpty(JsonElement policy, String key, String valueIfEmpty) {
100         JsonElement payloadElem = policy.getAsJsonObject().get(key);
101         String payloadString = payloadElem != null ? payloadElem.getAsString() : "";
102         if (payloadString.isEmpty()) {
103             policy.getAsJsonObject().addProperty(key, valueIfEmpty);
104         }
105     }
106
107     private static JsonElement fulfillPoliciesTreeField(JsonElement policyJson) {
108         for (JsonElement policy : policyJson.getAsJsonObject().get("policies").getAsJsonArray()) {
109             replacePropertiesIfEmpty(policy, "success", "final_success");
110             replacePropertiesIfEmpty(policy, "failure", "final_failure");
111             replacePropertiesIfEmpty(policy, "failure_timeout", "final_failure_timeout");
112             replacePropertiesIfEmpty(policy, "failure_retries", "final_failure_retries");
113             replacePropertiesIfEmpty(policy, "failure_exception", "final_failure_exception");
114             replacePropertiesIfEmpty(policy, "failure_guard", "final_failure_guard");
115         }
116         return policyJson;
117     }
118
119     private static Map<String, Object> createMap(JsonElement jsonElement) {
120         Map<String, Object> mapResult = new TreeMap<>();
121
122         if (jsonElement.isJsonObject()) {
123             for (Entry<String, JsonElement> entry : jsonElement.getAsJsonObject().entrySet()) {
124                 if (entry.getValue().isJsonPrimitive() && entry.getValue().getAsJsonPrimitive().isString()) {
125                     mapResult.put(entry.getKey(), entry.getValue().getAsString());
126                 } else if (entry.getValue().isJsonPrimitive() && entry.getValue().getAsJsonPrimitive().isBoolean()) {
127                     mapResult.put(entry.getKey(), entry.getValue().getAsBoolean());
128                 } else if (entry.getValue().isJsonPrimitive() && entry.getValue().getAsJsonPrimitive().isNumber()) {
129                     // Only int ro long normally, we don't need float here
130                     mapResult.put(entry.getKey(), entry.getValue().getAsLong());
131                 } else if (entry.getValue().isJsonArray()) {
132                     List<Map<String, Object>> newArray = new ArrayList<>();
133                     mapResult.put(entry.getKey(), newArray);
134                     for (JsonElement element : entry.getValue().getAsJsonArray()) {
135                         newArray.add(createMap(element));
136                     }
137                 } else if (entry.getValue().isJsonObject()) {
138                     mapResult.put(entry.getKey(), createMap(entry.getValue()));
139                 }
140             }
141         }
142         return mapResult;
143     }
144
145     /**
146      * This method transforms the configuration json to a Yaml format.
147      * 
148      * @param operationalPolicyJsonElement The operational policy json config
149      * @return The Yaml as string
150      */
151     public static String createPolicyPayloadYamlLegacy(JsonElement operationalPolicyJsonElement) {
152         JsonElement opPolicy = fulfillPoliciesTreeField(
153                 removeAllQuotes(reworkPayloadAttributes(operationalPolicyJsonElement.getAsJsonObject().deepCopy())));
154         Map<?, ?> jsonMap = createMap(opPolicy);
155         DumperOptions options = new DumperOptions();
156         options.setDefaultScalarStyle(ScalarStyle.PLAIN);
157         options.setIndent(2);
158         options.setPrettyFlow(true);
159         // Policy can't support { } in the yaml
160         options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
161         return (new Yaml(options)).dump(jsonMap);
162     }
163
164     /**
165      * This method load mandatory field in the operational policy configuration
166      * JSON.
167      * 
168      * @param configurationsJson The operational policy JSON
169      * @param loop               The parent loop object
170      */
171     public static void preloadConfiguration(JsonObject configurationsJson, Loop loop) {
172         if (configurationsJson.entrySet().isEmpty()) {
173             JsonObject controlLoopName = new JsonObject();
174             controlLoopName.addProperty("controlLoopName",
175                     loop != null ? loop.getName() : "Empty (NO loop loaded yet)");
176             JsonObject controlLoop = new JsonObject();
177             controlLoop.add("controlLoop", controlLoopName);
178             configurationsJson.add("operational_policy", controlLoop);
179         }
180     }
181 }