2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
22 package org.onap.ccsdk.sli.core.sli;
26 import com.google.gson.*;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.w3c.dom.Document;
30 import org.w3c.dom.Element;
31 import org.w3c.dom.Node;
32 import org.w3c.dom.NodeList;
33 import org.w3c.dom.Text;
36 public class SvcLogicContext {
38 private static final Logger LOG = LoggerFactory.getLogger(SvcLogicContext.class);
39 private final SecurePrinter securePrinter = new SecurePrinter();
40 public static final String CTX_NULL_VALUE="";
41 private static final String LENGTH="_length";
43 private HashMap<String, String> attributes;
45 private String status = SvcLogicConstants.SUCCESS;
47 public SvcLogicContext() {
48 this.attributes = new HashMap<>();
52 public SvcLogicContext(Properties props) {
53 this.attributes = new HashMap<>();
55 if (props.containsKey(CommonConstants.SERVICE_LOGIC_STATUS)) {
56 this.status = props.getProperty(CommonConstants.SERVICE_LOGIC_STATUS);
59 for (Object nameObj : props.keySet()) {
60 String propName = (String) nameObj;
61 attributes.put(propName, props.getProperty(propName));
65 public String getAttribute(String name) {
66 if (attributes.containsKey(name)) {
67 return attributes.get(name);
73 public void setAttribute(String name, String value) {
75 if (attributes.containsKey(name)) {
76 attributes.remove(name);
79 attributes.put(name, value);
83 public Set<String> getAttributeKeySet() {
84 return attributes.keySet();
87 public Boolean isSuccess() {
88 return status.equals(SvcLogicConstants.SUCCESS);
92 public String getStatus() {
97 public void setStatus(String status) {
101 public void markFailed() {
102 this.status = SvcLogicConstants.FAILURE;
105 public void markSuccess() {
106 this.status = SvcLogicConstants.SUCCESS;
109 public Properties toProperties() {
110 Properties props = new Properties();
112 if (status != null) {
113 props.setProperty(CommonConstants.SERVICE_LOGIC_STATUS, status);
118 for (Map.Entry<String, String> entry : attributes.entrySet()) {
119 attrName = entry.getKey();
120 attrVal = entry.getValue();
121 if (attrVal == null) {
122 LOG.warn("attribute {} value is null - setting to empty string", attrName);
123 props.setProperty(attrName, "");
125 props.setProperty(attrName, attrVal);
132 public void mergeDocument(String pfx, Document doc) {
139 Element root = doc.getDocumentElement();
141 mergeElement(prefix, root, null);
144 public void mergeElement(String pfx, Element element, Map<String, Integer> nodeMap) {
146 // In XML, cannot tell the difference between containers and lists.
147 // So, have to treat each element as both (ugly but necessary).
148 // We do this by passing a nodeMap to be used to count instance of each tag,
149 // which will be used to set _length and to set index
151 LOG.trace("mergeElement({},{},{})", pfx, element.getTagName(), nodeMap);
153 String curTagName = element.getTagName();
154 String prefix = curTagName;
157 prefix = pfx + "." + prefix;
162 if (nodeMap != null) {
163 if (nodeMap.containsKey(curTagName)) {
164 myIdx = nodeMap.get(curTagName);
167 nodeMap.put(curTagName, myIdx + 1);
168 this.setAttribute(prefix + "_length", Integer.toString(myIdx + 1));
171 NodeList children = element.getChildNodes();
173 int numChildren = children.getLength();
175 Map<String, Integer> childMap = new HashMap<>();
176 Map<String, Integer> idxChildMap = new HashMap<>();
178 for (int i = 0; i < numChildren; i++) {
179 Node curNode = children.item(i);
181 if (curNode instanceof Text) {
182 Text curText = (Text) curNode;
183 String curTextValue = curText.getTextContent();
184 LOG.trace("Setting ctx variable {} = {}", prefix, curTextValue);
185 this.setAttribute(prefix, curText.getTextContent());
188 } else if (curNode instanceof Element) {
189 mergeElement(prefix, (Element) curNode, childMap);
190 if (nodeMap != null) {
192 mergeElement(prefix + "[" + myIdx + "]", (Element) curNode, idxChildMap);
200 public void mergeJson(String pfx, String jsonString) {
202 JsonParser jp = new JsonParser();
203 JsonElement element = jp.parse(jsonString);
205 if ((pfx != null) && (pfx.length() > 0)) {
208 if (element.isJsonObject()) {
209 writeJsonObject(element.getAsJsonObject(), root);
210 } else if (element.isJsonArray()) {
211 handleJsonArray("", element.getAsJsonArray(), root);
216 protected void writeJsonObject(JsonObject obj, String root) {
217 for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
218 String key = entry.getKey();
219 if (entry.getValue().isJsonObject()) {
220 writeJsonObject(entry.getValue().getAsJsonObject(), root + key + ".");
221 } else if (entry.getValue().isJsonArray()) {
222 JsonArray array = entry.getValue().getAsJsonArray();
223 handleJsonArray(key, array, root);
225 //Handles when a JSON obj is nested within a JSON obj
226 if(!root.endsWith(".")){
229 if(entry.getValue().isJsonNull()) {
230 this.setAttribute(root + key, CTX_NULL_VALUE);
232 this.setAttribute(root + key, entry.getValue().getAsString());
238 protected void handleJsonArray(String key, JsonArray array, String root) {
239 this.setAttribute(root + key + LENGTH, String.valueOf(array.size()));
240 Integer arrayIdx = 0;
241 for (JsonElement element : array) {
242 String prefix = root + key + "[" + arrayIdx + "]";
244 if (element.isJsonArray()) {
245 handleJsonArray(key, element.getAsJsonArray(), prefix);
246 } else if (element.isJsonObject()) {
247 writeJsonObject(element.getAsJsonObject(), prefix + ".");
248 } else if (element.isJsonNull()) {
249 this.setAttribute(prefix, CTX_NULL_VALUE);
250 } else if (element.isJsonPrimitive()) {
251 this.setAttribute(prefix, element.getAsString());
258 public String resolve(String ctxVarName) {
260 if (ctxVarName.indexOf('[') == -1) {
261 // Ctx variable contains no arrays
262 return getAttribute(ctxVarName);
265 // Resolve any array references
266 StringBuilder sbuff = new StringBuilder();
267 String[] ctxVarParts = ctxVarName.split("\\[");
268 sbuff.append(ctxVarParts[0]);
269 for (int i = 1; i < ctxVarParts.length; i++) {
270 if (ctxVarParts[i].startsWith("$")) {
271 int endBracketLoc = ctxVarParts[i].indexOf(']');
272 if (endBracketLoc == -1) {
273 // Missing end bracket ... give up parsing
274 LOG.warn("Variable reference {} seems to be missing a ']'", ctxVarName);
275 return getAttribute(ctxVarName);
278 String idxVarName = ctxVarParts[i].substring(1, endBracketLoc);
279 String remainder = ctxVarParts[i].substring(endBracketLoc);
282 sbuff.append(this.getAttribute(idxVarName));
283 sbuff.append(remainder);
286 // Index is not a variable reference
288 sbuff.append(ctxVarParts[i]);
292 return getAttribute(sbuff.toString());
295 public String toJsonString(String pfx) {
296 JsonParser jp = new JsonParser();
298 String jsonString = this.toJsonString();
299 JsonObject jsonRoot = (JsonObject) jp.parse(jsonString);
300 JsonObject targetJson = jsonRoot.getAsJsonObject(pfx);
301 if (targetJson == null) {
304 return(targetJson.toString());
308 public String toJsonString() {
309 JsonObject root = new JsonObject();
310 JsonElement lastJsonObject = root;
311 JsonElement currJsonLeaf = root;
313 String attrName = null;
314 String attrVal = null;
316 // Sort properties so that arrays will be reconstructed in proper order
317 TreeMap<String, String> sortedAttributes = new TreeMap<>();
318 sortedAttributes.putAll(attributes);
320 // Loop through properties, sorted by key
321 for (Map.Entry<String, String> entry : sortedAttributes.entrySet()) {
322 attrName = entry.getKey();
323 attrVal = entry.getValue();
326 String curFieldName = null;
327 JsonArray curArray = null;
328 lastJsonObject = null;
329 boolean addNeeded = false;
331 // Split property names by period and iterate through parts
332 for (String attrNamePart : attrName.split("\\.")) {
334 // Add last object found to JSON tree. Need to handle
335 // this way because last element found (leaf) needs to be
336 // assigned the property value.
337 if (lastJsonObject != null) {
339 if (currJsonLeaf.isJsonArray()) {
340 ((JsonArray) currJsonLeaf).add(lastJsonObject);
342 ((JsonObject) currJsonLeaf).add(curFieldName, lastJsonObject);
345 currJsonLeaf = (JsonObject) lastJsonObject;
348 // See if current level should be a JsonArray or JsonObject based on
349 // whether name part contains square brackets.
350 if (!attrNamePart.contains("[")) {
351 // This level should be inserted as a JsonObject
352 curFieldName = attrNamePart;
353 lastJsonObject = ((JsonObject) currJsonLeaf).get(curFieldName);
354 if (lastJsonObject == null) {
355 lastJsonObject = new JsonObject();
357 } else if (!lastJsonObject.isJsonObject()) {
358 LOG.error("Unexpected condition - expecting to find JsonObject, but found " + lastJsonObject.getClass().getName());
359 lastJsonObject = new JsonObject();
363 // This level should be inserted as a JsonArray.
365 String[] curFieldNameParts = attrNamePart.split("[\\[\\]]");
366 curFieldName = curFieldNameParts[0];
367 int curIndex = Integer.parseInt(curFieldNameParts[1]);
370 curArray = ((JsonObject) currJsonLeaf).getAsJsonArray(curFieldName);
372 if (curArray == null) {
373 // This is the first time we see this array.
374 // Create a new JsonArray and add it to current
376 curArray = new JsonArray();
377 ((JsonObject) currJsonLeaf).add(curFieldName, curArray);
380 // Current leaf should point to the JsonArray for this level.
381 // lastJsonObject should point to the array item entry to append
382 // the next level to - which is a new one if the index value
383 // isn't the end of the current array.
384 currJsonLeaf = curArray;
385 if (curArray.size() == curIndex + 1) {
386 lastJsonObject = curArray.get(curArray.size() - 1);
388 lastJsonObject = new JsonObject();
394 // Done parsing property name. Add the value of this
395 // property to the current json leaf, either as a property
396 // or as a string (if the current leaf is a JsonArray)
398 if (!curFieldName.endsWith("_length")) {
399 if (currJsonLeaf.isJsonArray()) {
400 if ("true".equals(attrVal) || "false".equals(attrVal)) {
401 ((JsonArray) currJsonLeaf).add(Boolean.valueOf(attrVal));
402 } else if ("null".equals(attrVal)) {
403 ((JsonArray) currJsonLeaf).add(new JsonNull());
405 ((JsonArray) currJsonLeaf).add(attrVal);
408 if (("true".equals(attrVal) || "false".equals(attrVal))) {
409 ((JsonObject) currJsonLeaf).addProperty(curFieldName, Boolean.valueOf(attrVal));
410 } else if ("null".equals(attrVal)){
412 ((JsonObject) currJsonLeaf).add(curFieldName, new JsonNull());
414 ((JsonObject) currJsonLeaf).addProperty(curFieldName, attrVal);
420 return (root.toString());
423 public void printProperties(Properties props) {
424 securePrinter.printProperties(props);
427 public void printAttributes() {
428 securePrinter.printAttributes(attributes);
431 public void printProperties(Properties props, String subpath) {
432 securePrinter.printProperties(props, subpath);
435 public void printAttributes(String subpath) {
436 securePrinter.printAttributes(attributes, subpath);