2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 ONAP
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.ccsdk.sli.core.sli.provider;
23 import java.util.List;
25 import org.apache.commons.lang.StringUtils;
26 import org.onap.ccsdk.sli.core.sli.SvcLogicAtom;
27 import org.onap.ccsdk.sli.core.sli.SvcLogicBinaryExpression;
28 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
29 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
30 import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
31 import org.onap.ccsdk.sli.core.sli.SvcLogicFunctionCall;
32 import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
33 import org.onap.ccsdk.sli.core.sli.SvcLogicVariableTerm;
34 import org.onap.ccsdk.sli.core.sli.SvcLogicAtom.AtomType;
35 import org.onap.ccsdk.sli.core.sli.SvcLogicBinaryExpression.OperatorType;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 public class SvcLogicExpressionResolver {
41 private static final Logger LOG = LoggerFactory
42 .getLogger(SvcLogicExpressionResolver.class);
44 public static String evaluate(SvcLogicExpression expr, SvcLogicNode node,
45 SvcLogicContext ctx) throws SvcLogicException {
52 if (expr instanceof SvcLogicAtom) {
53 SvcLogicAtom atom = (SvcLogicAtom) expr;
55 AtomType atomType = atom.getAtomType();
59 return (atom.toString());
63 String varName = resolveVariableName(atom, node, ctx);
65 if (atomType == AtomType.CONTEXT_VAR)
67 LOG.trace("Evaluating context variable $"+varName);
69 String varValue = ctx.getAttribute(varName);
71 if (varValue == null) {
72 LOG.trace("Context variable $"+varName+" unset - treating as empty string");
78 SvcLogicExpression parm = node.getParameter(varName);
80 LOG.trace("Evaluating value of parameter "+varName+": "+parm.asParsedExpr());
82 return (evaluate(parm, node, ctx));
92 } else if (expr instanceof SvcLogicBinaryExpression) {
93 SvcLogicBinaryExpression binExpr = (SvcLogicBinaryExpression) expr;
94 List<OperatorType> operators = binExpr.getOperators();
95 if (operators.isEmpty())
97 List<SvcLogicExpression> operands = binExpr.getOperands();
98 if (operands.size() == 1)
100 LOG.trace("SvcLogicBinaryExpression as no operator and one operand - evaluating its operand");
101 return(evaluate(operands.get(0), node, ctx));
105 if (operands.isEmpty())
107 LOG.error("SvcLogicBinaryExpression has no operators and no operands - evaluating value as null");
111 LOG.error("SvcLogicBinaryExpression has no operators and "+operands.size()+" operands - evaluating value as null");
116 switch (operators.get(0)) {
121 return(evalArithExpression(binExpr, node, ctx));
128 return (evalCompareExpression(binExpr, node, ctx));
131 return(evalLogicExpression(binExpr, node, ctx));
137 else if (expr instanceof SvcLogicFunctionCall)
139 return(evalFunctionCall((SvcLogicFunctionCall)expr, node, ctx));
143 throw new SvcLogicException("Unrecognized expression type ["+expr+"]");
147 private static String evalArithExpression(SvcLogicBinaryExpression binExpr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException {
148 List<SvcLogicExpression> operands = binExpr.getOperands();
149 List<OperatorType> operators = binExpr.getOperators();
150 if (operands.size() != (operators.size()+1))
152 throw new SvcLogicException("Invalid expression ("+binExpr+")");
154 String retval = evaluate(operands.get(0), node, ctx);
155 String retsval = retval;
157 boolean valueIsLong = false;
163 if ((retval.length() > 0) && StringUtils.isNumeric(retval))
165 retlval = Long.parseLong(retval);
168 for (OperatorType operator: operators)
170 String curOperandValue = evaluate(operands.get(i++), node, ctx);
173 retsval = retsval + curOperandValue;
176 if ((curOperandValue.length() > 0) && StringUtils.isNumeric(curOperandValue) )
178 retlval = retlval + Long.parseLong(curOperandValue);
187 retlval = retlval - Long.parseLong(curOperandValue);
190 retlval = retlval * Long.parseLong(curOperandValue);
193 retlval = retlval / Long.parseLong(curOperandValue);
199 catch (NumberFormatException e1)
201 throw new SvcLogicException("Illegal value in arithmetic expression", e1);
206 return("" + retlval);
217 private static String evalCompareExpression(SvcLogicBinaryExpression expr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException
220 List<OperatorType> operators = expr.getOperators();
221 List<SvcLogicExpression> operands = expr.getOperands();
223 if ((operators.size() != 1) || (operands.size() != 2))
225 throw new SvcLogicException ("Invalid comparison expression : "+expr);
228 OperatorType operator = operators.get(0);
229 String op1Value = evaluate(operands.get(0), node, ctx);
230 String op2Value = evaluate(operands.get(1), node, ctx);
232 if ((StringUtils.isNotEmpty(op1Value) && StringUtils.isNumeric(op1Value) && StringUtils.isNotEmpty(op2Value) && StringUtils.isNumeric(op2Value)))
236 double op1dbl = Double.parseDouble(op1Value);
237 double op2dbl = Double.parseDouble(op2Value);
242 return(Boolean.toString(op1dbl == op2dbl));
244 return(Boolean.toString(op1dbl != op2dbl));
246 return(Boolean.toString(op1dbl < op2dbl));
248 return(Boolean.toString(op1dbl <= op2dbl));
250 return(Boolean.toString(op1dbl > op2dbl));
252 return(Boolean.toString(op1dbl >= op2dbl));
257 catch (NumberFormatException e)
259 throw new SvcLogicException("Caught exception trying to compare numeric values", e);
267 if (op1Value == null) {
269 } else if (op2Value == null ) {
272 compResult = op1Value.compareToIgnoreCase(op2Value);
278 return(Boolean.toString(compResult == 0));
280 return(Boolean.toString(compResult != 0));
282 return(Boolean.toString(compResult < 0));
284 return(Boolean.toString(compResult <= 0));
286 return(Boolean.toString(compResult > 0));
288 return(Boolean.toString(compResult >= 0));
296 private static String evalLogicExpression(SvcLogicBinaryExpression expr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException
300 List<SvcLogicExpression> operands = expr.getOperands();
301 List<OperatorType> operators = expr.getOperators();
303 if (operands.size() != (operators.size()+1))
305 throw new SvcLogicException("Invalid expression ("+expr+")");
310 retval = Boolean.parseBoolean(evaluate(operands.get(0), node, ctx));
312 for (OperatorType operator : operators)
314 if (operator == OperatorType.andOp)
316 retval = retval && Boolean.parseBoolean(evaluate(operands.get(i++), node, ctx));
321 retval = retval || Boolean.parseBoolean(evaluate(operands.get(i++), node, ctx));
328 throw new SvcLogicException("Invalid expression ("+expr+")");
332 return(Boolean.toString(retval));
335 private static String evalFunctionCall(SvcLogicFunctionCall func, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException
337 String funcName = func.getFunctionName();
338 List<SvcLogicExpression> operands = func.getOperands();
340 if ("length".equalsIgnoreCase(funcName))
343 if (operands.size() == 1)
345 String opValue = evaluate(operands.get(0), node, ctx);
346 return(""+opValue.length());
350 throw new SvcLogicException("Invalid call to length() function");
353 else if ("substr".equalsIgnoreCase(funcName))
355 if (operands.size() == 3)
357 String op1Value = evaluate(operands.get(0), node, ctx);
358 String op2Value = evaluate(operands.get(1), node, ctx);
359 String op3Value = evaluate(operands.get(2), node, ctx);
361 if (!StringUtils.isNumeric(op2Value) || !StringUtils.isNumeric(op3Value))
363 throw new SvcLogicException("Invalid arguments to substr() function");
368 return(op1Value.substring(Integer.parseInt(op2Value), Integer.parseInt(op3Value)));
372 throw new SvcLogicException("Caught exception trying to take substring", e);
378 throw new SvcLogicException("Invalid call to substr() function");
382 else if ("toUpperCase".equalsIgnoreCase(funcName))
384 if (operands.size() == 1)
386 String opValue = evaluate(operands.get(0), node, ctx);
387 if (opValue != null) {
388 return(opValue.toUpperCase());
395 throw new SvcLogicException("Invalid call to toUpperCase() function");
398 else if ("toLowerCase".equalsIgnoreCase(funcName))
400 if (operands.size() == 1)
402 String opValue = evaluate(operands.get(0), node, ctx);
403 if (opValue != null) {
404 return(opValue.toLowerCase());
411 throw new SvcLogicException("Invalid call to toLowerCase() function");
414 else if ("convertBase".equalsIgnoreCase(funcName)) {
417 String srcString = "";
419 if (operands.size() == 2)
422 srcString = evaluate(operands.get(0), node, ctx);
423 toBase = Integer.parseInt(evaluate(operands.get(1), node, ctx));
424 } else if (operands.size() == 3) {
426 srcString = evaluate(operands.get(0), node, ctx);
427 fromBase = Integer.parseInt(evaluate(operands.get(1), node, ctx));
428 toBase = Integer.parseInt(evaluate(operands.get(2), node, ctx));
430 throw new SvcLogicException("Invalid call to convertBase() function");
433 long srcValue = Long.parseLong(srcString, fromBase);
434 return(Long.toString(srcValue, toBase));
438 throw new SvcLogicException("Unrecognized function ("+funcName+")");
443 public static String evaluateAsKey(SvcLogicExpression expr, SvcLogicNode node,
444 SvcLogicContext ctx) throws SvcLogicException {
451 if (expr instanceof SvcLogicAtom) {
452 SvcLogicAtom atom = (SvcLogicAtom) expr;
454 AtomType atomType = atom.getAtomType();
455 StringBuffer varNameBuff = new StringBuffer();
458 return (atom.toString());
460 return("'"+atom.toString()+"'");
463 boolean needDot = false;
464 for (SvcLogicExpression term : atom.getOperands())
468 varNameBuff.append(".");
470 if (term instanceof SvcLogicVariableTerm)
472 SvcLogicVariableTerm vterm = (SvcLogicVariableTerm) term;
473 varNameBuff.append(vterm.getName());
474 if (vterm.numOperands() > 0)
476 varNameBuff.append("[");
477 varNameBuff.append(evaluate(vterm.getSubscript(), node, ctx));
478 varNameBuff.append("]");
484 varNameBuff.append(term.toString());
489 String varName = varNameBuff.toString();
490 LOG.debug("Evaluating context variable $"+varName);
491 String ctxValue = ctx.getAttribute(varName);
492 if (ctxValue == null)
496 if (StringUtils.isNumeric(ctxValue))
502 return("'"+ctxValue+"'");
509 } else if (expr instanceof SvcLogicBinaryExpression) {
510 SvcLogicBinaryExpression binExpr = (SvcLogicBinaryExpression) expr;
511 List<OperatorType> operators = binExpr.getOperators();
512 List<SvcLogicExpression> operands = binExpr.getOperands();
513 if (operators.isEmpty())
515 if (operands.size() == 1)
517 LOG.debug("SvcLogicBinaryExpression as no operator and one operand - evaluating its operand");
518 return(evaluateAsKey(operands.get(0), node, ctx));
522 if (operands.isEmpty())
524 LOG.error("SvcLogicBinaryExpression has no operators and no operands - evaluating value as null");
528 LOG.error("SvcLogicBinaryExpression has no operators and "+operands.size()+" operands - evaluating value as null");
533 StringBuffer sbuff = new StringBuffer();
534 sbuff.append(evaluateAsKey(operands.get(0), node, ctx));
536 for (OperatorType operator : operators)
539 sbuff.append(operator.toString());
541 sbuff.append(evaluateAsKey(operands.get(i++), node,ctx));
543 return(sbuff.toString());
545 else if (expr instanceof SvcLogicFunctionCall)
547 StringBuffer sbuff = new StringBuffer();
548 SvcLogicFunctionCall funcCall = (SvcLogicFunctionCall) expr;
549 sbuff.append(funcCall.getFunctionName());
551 boolean needComma = false;
552 for (SvcLogicExpression operand : funcCall.getOperands())
562 sbuff.append(evaluateAsKey(operand, node, ctx));
565 return(sbuff.toString());
569 throw new SvcLogicException("Unrecognized expression type ["+expr+"]");
573 public static String resolveVariableName(SvcLogicExpression atom, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException
575 StringBuffer varNameBuff = new StringBuffer();
577 boolean needDot = false;
578 for (SvcLogicExpression term : atom.getOperands())
582 varNameBuff.append(".");
584 if (term instanceof SvcLogicVariableTerm)
586 SvcLogicVariableTerm vterm = (SvcLogicVariableTerm) term;
587 varNameBuff.append(vterm.getName());
588 if (vterm.numOperands() > 0)
590 varNameBuff.append("[");
591 varNameBuff.append(evaluate(vterm.getSubscript(), node, ctx));
592 varNameBuff.append("]");
597 varNameBuff.append(term.toString());
601 return(varNameBuff.toString());