caf0015ba6dd1ddafd4e3f28075b9fc1ba085001
[ccsdk/sli/core.git] / sli / provider-base / src / main / java / org / onap / ccsdk / sli / core / sli / provider / base / SetNodeExecutor.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : CCSDK
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                      reserved.
7  * ================================================================================
8  * Modifications Copyright (C) 2018 IBM.
9  * ================================================================================
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  * ============LICENSE_END=========================================================
22  */
23
24 package org.onap.ccsdk.sli.core.sli.provider.base;
25
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.LinkedList;
29 import java.util.Map;
30 import java.util.Set;
31 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
32 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
33 import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
34 import org.onap.ccsdk.sli.core.sli.SvcLogicExpressionFactory;
35 import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 public class SetNodeExecutor extends AbstractSvcLogicNodeExecutor {
40
41     private static final Logger LOG = LoggerFactory.getLogger(SetNodeExecutor.class);
42     protected final String arrayPattern = "\\[\\d*\\]";
43
44     @Override
45     public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
46             throws SvcLogicException {
47         execute(node,ctx);
48         return null;
49     }
50
51     public void execute(SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException {
52         String ifunsetStr = SvcLogicExpressionResolver.evaluate(node.getAttribute("only-if-unset"), node, ctx);
53
54         boolean ifunset = "true".equalsIgnoreCase(ifunsetStr);
55
56         Set<Map.Entry<String, SvcLogicExpression>> parameterSet = node.getParameterSet();
57
58         for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = parameterSet.iterator(); iter.hasNext();) {
59             Map.Entry<String, SvcLogicExpression> curEnt = iter.next();
60             String curName = curEnt.getKey();
61             String lhsVarName = curName;
62
63             // Resolve LHS of assignment (could contain index variables)
64             try {
65                 // Backticks symbolize the variable should be handled as an expression instead of as a variable
66                 if (curName.trim().startsWith("`")) {
67                     int lastParen = curName.lastIndexOf("`");
68                     String evalExpr = curName.trim().substring(1, lastParen);
69                     SvcLogicExpression lhsExpr = SvcLogicExpressionFactory.parse(evalExpr);
70                     lhsVarName = SvcLogicExpressionResolver.evaluate(lhsExpr, node, ctx);
71                 } else {
72                     SvcLogicExpression lhsExpr = SvcLogicExpressionFactory.parse(curName);
73                     lhsVarName = SvcLogicExpressionResolver.resolveVariableName(lhsExpr, node, ctx);
74                 }
75             } catch (Exception e) {
76                 LOG.warn("Caught exception trying to resolve variable name (" + curName + ")", e);
77             }
78
79             boolean setValue = true;
80
81             if (curName.endsWith(".")) {
82                 // Copy subtree - value should be a variable name
83                 SvcLogicExpression curValue = curEnt.getValue();
84
85                 if (curValue != null) {
86                     String rhsRoot = curValue.toString();
87
88                     if ((rhsRoot != null) && (rhsRoot.length() > 0)) {
89                         if (rhsRoot.endsWith(".")) {
90                             rhsRoot = rhsRoot.substring(0, rhsRoot.length() - 1);
91                         }
92
93                         // SDNGC-2321 : rhsRoot is variable name, possibly with subscript(s) to be resolved
94                         try {
95                             SvcLogicExpression rhsExpr = SvcLogicExpressionFactory.parse(rhsRoot);
96                             rhsRoot = SvcLogicExpressionResolver.resolveVariableName(rhsExpr, node, ctx);
97                         } catch (Exception e) {
98                             LOG.warn("Caught exception trying to resolve variable name (" + rhsRoot + ")", e);
99                         }
100
101                         // See if the parameters are reversed (copying service-data to input) .. this
102                         // was done as a workaround to earlier issue
103                         if (curName.endsWith("-input.") && rhsRoot.startsWith("service-data")) {
104                             LOG.warn("Arguments appear to be reversed .. will copy input to service-data instead");
105                             lhsVarName = rhsRoot + ".";
106                             rhsRoot = curName.substring(0, curName.length() - 1);
107                         }
108
109                         rhsRoot = rhsRoot + ".";
110                         String lhsPrefix = lhsVarName;
111
112                         if (lhsPrefix.endsWith(".")) {
113                             lhsPrefix = lhsPrefix.substring(0, lhsPrefix.length() - 1);
114                         }
115
116                         HashMap<String, String> parmsToAdd = new HashMap<>();
117
118                         for (String sourceVarName : ctx.getAttributeKeySet()) {
119                             if (sourceVarName.startsWith(rhsRoot)) {
120                                 String targetVar = lhsPrefix + "." + sourceVarName.substring(rhsRoot.length());
121                                 LOG.debug("Copying {} value to {}", sourceVarName, targetVar);
122                                 parmsToAdd.put(targetVar, ctx.getAttribute(sourceVarName));
123                             }
124                         }
125                         for (String newParmName : parmsToAdd.keySet()) {
126                             ctx.setAttribute(newParmName, parmsToAdd.get(newParmName));
127                         }
128                     } else {
129                         // If RHS is empty, unset attributes in LHS
130                         LinkedList<String> parmsToRemove = new LinkedList<>();
131                         String prefix = lhsVarName + ".";
132                         String arrayPrefix = lhsVarName + "[";
133                         //Clear length value in case an array exists with this prefix
134                         String lengthParamName = lhsVarName + "_length";
135                         LOG.debug("Unsetting {} because prefix {} is being cleared.", lengthParamName, prefix);
136
137                         for (String curCtxVarname : ctx.getAttributeKeySet()) {
138                             String curCtxVarnameMatchingValue = curCtxVarname;
139                             //Special handling for reseting array values, strips out brackets and any numbers between the brackets
140                             //when testing if a context memory value starts with a prefix
141                             if(!prefix.contains("[") && curCtxVarnameMatchingValue.contains("[")) {
142                                 curCtxVarnameMatchingValue = curCtxVarname.replaceAll(arrayPattern, "") + ".";
143                             }
144                             if (curCtxVarnameMatchingValue.startsWith(prefix)) {
145                                 LOG.debug("Unsetting {} because matching value {} starts with the prefix {}", curCtxVarname, curCtxVarnameMatchingValue, prefix);
146                                 parmsToRemove.add(curCtxVarname);
147                             }else if (curCtxVarnameMatchingValue.startsWith(lengthParamName)) {
148                                 LOG.debug("Unsetting {} because matching value {} starts with the lengthParamName {}", curCtxVarname, curCtxVarnameMatchingValue, lengthParamName);
149                                 parmsToRemove.add(curCtxVarname);
150                             }else if (curCtxVarnameMatchingValue.startsWith(arrayPrefix)) {
151                                 LOG.debug("Unsetting {} because matching value {} starts with the arrayPrefix {}", curCtxVarname, curCtxVarnameMatchingValue, arrayPrefix);
152                                 parmsToRemove.add(curCtxVarname);
153                             }
154                         }
155                         for (String parmName : parmsToRemove) {
156                             ctx.setAttribute(parmName, null);
157                         }
158                     }
159                 }
160             } else {
161                 if (ifunset) {
162                     String ctxValue = ctx.getAttribute(lhsVarName);
163                     if ((ctxValue != null) && (ctxValue.length() > 0)) {
164                         setValue = false;
165                         LOG.debug("Attribute {} already set and only-if-unset is true, so not overriding", lhsVarName);
166                     }
167                 }
168                 if (setValue) {
169                     String curValue = SvcLogicExpressionResolver.evaluate(curEnt.getValue(), node, ctx);
170
171                     if (LOG.isDebugEnabled()) {
172                         LOG.trace("Parameter value {} resolves to {}", curEnt.getValue().asParsedExpr(), curValue);
173                         LOG.debug("Setting context attribute {} to {}", lhsVarName, curValue);
174                     }
175                     ctx.setAttribute(lhsVarName, curValue);
176                 }
177             }
178         }
179     }
180 }
181