2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
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
14 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
24 package org.onap.ccsdk.sli.core.sli.provider.base;
26 import java.util.List;
28 import org.apache.commons.lang.StringUtils;
29 import org.onap.ccsdk.sli.core.sli.SvcLogicAtom;
30 import org.onap.ccsdk.sli.core.sli.SvcLogicBinaryExpression;
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.SvcLogicFunctionCall;
35 import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
36 import org.onap.ccsdk.sli.core.sli.SvcLogicVariableTerm;
37 import org.onap.ccsdk.sli.core.sli.SvcLogicAtom.AtomType;
38 import org.onap.ccsdk.sli.core.sli.SvcLogicBinaryExpression.OperatorType;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
42 public class SvcLogicExpressionResolver {
44 private static final Logger LOG = LoggerFactory
45 .getLogger(SvcLogicExpressionResolver.class);
46 private static final String INVALID_EXPRESSION_MSG= "Invalid expression (";
47 private static final String EXPRESSION_DEBUG_PATTERN = "Expression: {} resolves to {}: which has the value {}";
49 public static String evaluate(SvcLogicExpression expr, SvcLogicNode node,
50 SvcLogicContext ctx) throws SvcLogicException {
55 if (expr instanceof SvcLogicAtom) {
56 SvcLogicAtom atom = (SvcLogicAtom) expr;
58 AtomType atomType = atom.getAtomType();
62 return (atom.toString());
66 String varName = resolveVariableName(atom, node, ctx);
68 if (atomType == AtomType.CONTEXT_VAR)
71 String varValue = ctx.getAttribute(varName);
73 if (varValue == null) {
74 LOG.trace("Context variable $"+varName+" unset - treating as empty string");
77 LOG.trace(EXPRESSION_DEBUG_PATTERN,expr.toString(),varName,varValue);
80 SvcLogicExpression parm = node.getParameter(varName);
82 String value = evaluate(parm, node, ctx);
83 LOG.trace(EXPRESSION_DEBUG_PATTERN,expr.toString(),varName,value);
88 LOG.trace(EXPRESSION_DEBUG_PATTERN,expr.toString(),varName,varName);
95 } else if (expr instanceof SvcLogicBinaryExpression) {
96 SvcLogicBinaryExpression binExpr = (SvcLogicBinaryExpression) expr;
97 List<OperatorType> operators = binExpr.getOperators();
98 if (operators.isEmpty())
100 List<SvcLogicExpression> operands = binExpr.getOperands();
101 if (operands.size() == 1)
103 return(evaluate(operands.get(0), node, ctx));
107 if (operands.isEmpty())
109 LOG.error("SvcLogicBinaryExpression has no operators and no operands - evaluating value as null");
113 LOG.error("SvcLogicBinaryExpression has no operators and "+operands.size()+" operands - evaluating value as null");
118 switch (operators.get(0)) {
123 return(evalArithExpression(binExpr, node, ctx));
130 return (evalCompareExpression(binExpr, node, ctx));
133 return(evalLogicExpression(binExpr, node, ctx));
139 else if (expr instanceof SvcLogicFunctionCall)
141 return(evalFunctionCall((SvcLogicFunctionCall)expr, node, ctx));
145 throw new SvcLogicException("Unrecognized expression type ["+expr+"]");
149 private static String evalArithExpression(SvcLogicBinaryExpression binExpr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException {
150 List<SvcLogicExpression> operands = binExpr.getOperands();
151 List<OperatorType> operators = binExpr.getOperators();
152 if (operands.size() != (operators.size()+1))
154 throw new SvcLogicException(INVALID_EXPRESSION_MSG+binExpr+")");
156 String retval = evaluate(operands.get(0), node, ctx);
157 String retsval = retval;
159 boolean valueIsLong = false;
165 if ((retval.length() > 0) && StringUtils.isNumeric(retval))
167 retlval = Long.parseLong(retval);
170 for (OperatorType operator: operators)
172 String curOperandValue = evaluate(operands.get(i++), node, ctx);
175 retsval = retsval + curOperandValue;
178 if ((curOperandValue.length() > 0) && StringUtils.isNumeric(curOperandValue) )
180 retlval = retlval + Long.parseLong(curOperandValue);
189 retlval = retlval - Long.parseLong(curOperandValue);
192 retlval = retlval * Long.parseLong(curOperandValue);
195 retlval = retlval / Long.parseLong(curOperandValue);
201 catch (NumberFormatException e1)
203 throw new SvcLogicException("Illegal value in arithmetic expression", e1);
208 return("" + retlval);
219 private static String evalCompareExpression(SvcLogicBinaryExpression expr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException
222 List<OperatorType> operators = expr.getOperators();
223 List<SvcLogicExpression> operands = expr.getOperands();
225 if ((operators.size() != 1) || (operands.size() != 2))
227 throw new SvcLogicException ("Invalid comparison expression : "+expr);
230 OperatorType operator = operators.get(0);
231 String op1Value = evaluate(operands.get(0), node, ctx);
232 String op2Value = evaluate(operands.get(1), node, ctx);
234 if ((StringUtils.isNotEmpty(op1Value) && StringUtils.isNumeric(op1Value) && StringUtils.isNotEmpty(op2Value) && StringUtils.isNumeric(op2Value)))
238 double op1dbl = Double.parseDouble(op1Value);
239 double op2dbl = Double.parseDouble(op2Value);
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));
254 return(Boolean.toString(op1dbl >= op2dbl));
259 catch (NumberFormatException e)
261 throw new SvcLogicException("Caught exception trying to compare numeric values", e);
269 if (op1Value == null) {
271 } else if (op2Value == null ) {
274 compResult = op1Value.compareToIgnoreCase(op2Value);
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));
290 return(Boolean.toString(compResult >= 0));
298 private static String evalLogicExpression(SvcLogicBinaryExpression expr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException
302 List<SvcLogicExpression> operands = expr.getOperands();
303 List<OperatorType> operators = expr.getOperators();
305 if (operands.size() != (operators.size()+1))
307 throw new SvcLogicException(INVALID_EXPRESSION_MSG+expr+")");
312 retval = Boolean.parseBoolean(evaluate(operands.get(0), node, ctx));
314 for (OperatorType operator : operators)
316 if (operator == OperatorType.andOp)
318 retval = retval && Boolean.parseBoolean(evaluate(operands.get(i++), node, ctx));
323 retval = retval || Boolean.parseBoolean(evaluate(operands.get(i++), node, ctx));
330 throw new SvcLogicException(INVALID_EXPRESSION_MSG+expr+")");
334 return(Boolean.toString(retval));
337 private static String evalFunctionCall(SvcLogicFunctionCall func, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException
339 String funcName = func.getFunctionName();
340 List<SvcLogicExpression> operands = func.getOperands();
342 if ("length".equalsIgnoreCase(funcName))
345 if (operands.size() == 1)
347 String opValue = evaluate(operands.get(0), node, ctx);
348 return(""+opValue.length());
352 throw new SvcLogicException("Invalid call to length() function");
355 else if ("substr".equalsIgnoreCase(funcName))
357 if (operands.size() == 3)
359 String op1Value = evaluate(operands.get(0), node, ctx);
360 String op2Value = evaluate(operands.get(1), node, ctx);
361 String op3Value = evaluate(operands.get(2), node, ctx);
363 if (!StringUtils.isNumeric(op2Value) || !StringUtils.isNumeric(op3Value))
365 throw new SvcLogicException("Invalid arguments to substr() function");
370 return(op1Value.substring(Integer.parseInt(op2Value), Integer.parseInt(op3Value)));
374 throw new SvcLogicException("Caught exception trying to take substring", e);
380 throw new SvcLogicException("Invalid call to substr() function");
384 else if ("toUpperCase".equalsIgnoreCase(funcName))
386 if (operands.size() == 1)
388 String opValue = evaluate(operands.get(0), node, ctx);
389 if (opValue != null) {
390 return(opValue.toUpperCase());
397 throw new SvcLogicException("Invalid call to toUpperCase() function");
400 else if ("toLowerCase".equalsIgnoreCase(funcName))
402 if (operands.size() == 1)
404 String opValue = evaluate(operands.get(0), node, ctx);
405 if (opValue != null) {
406 return(opValue.toLowerCase());
413 throw new SvcLogicException("Invalid call to toLowerCase() function");
416 else if ("convertBase".equalsIgnoreCase(funcName)) {
419 String srcString = "";
421 if (operands.size() == 2)
424 srcString = evaluate(operands.get(0), node, ctx);
425 toBase = Integer.parseInt(evaluate(operands.get(1), node, ctx));
426 } else if (operands.size() == 3) {
428 srcString = evaluate(operands.get(0), node, ctx);
429 fromBase = Integer.parseInt(evaluate(operands.get(1), node, ctx));
430 toBase = Integer.parseInt(evaluate(operands.get(2), node, ctx));
432 throw new SvcLogicException("Invalid call to convertBase() function");
435 long srcValue = Long.parseLong(srcString, fromBase);
436 return(Long.toString(srcValue, toBase));
440 throw new SvcLogicException("Unrecognized function ("+funcName+")");
445 public static String evaluateAsKey(SvcLogicExpression expr, SvcLogicNode node,
446 SvcLogicContext ctx) throws SvcLogicException {
453 if (expr instanceof SvcLogicAtom) {
454 SvcLogicAtom atom = (SvcLogicAtom) expr;
456 AtomType atomType = atom.getAtomType();
457 StringBuffer varNameBuff = new StringBuffer();
460 return (atom.toString());
462 return("'"+atom.toString()+"'");
465 boolean needDot = false;
466 for (SvcLogicExpression term : atom.getOperands())
470 varNameBuff.append(".");
472 if (term instanceof SvcLogicVariableTerm)
474 SvcLogicVariableTerm vterm = (SvcLogicVariableTerm) term;
475 varNameBuff.append(vterm.getName());
476 if (vterm.numOperands() > 0)
478 varNameBuff.append("[");
479 varNameBuff.append(evaluate(vterm.getSubscript(), node, ctx));
480 varNameBuff.append("]");
486 varNameBuff.append(term.toString());
491 String varName = varNameBuff.toString();
492 String ctxValue = ctx.getAttribute(varName);
493 if (ctxValue == null)
497 if (StringUtils.isNumeric(ctxValue))
503 return("'"+ctxValue+"'");
510 } else if (expr instanceof SvcLogicBinaryExpression) {
511 SvcLogicBinaryExpression binExpr = (SvcLogicBinaryExpression) expr;
512 List<OperatorType> operators = binExpr.getOperators();
513 List<SvcLogicExpression> operands = binExpr.getOperands();
514 if (operators.isEmpty())
516 if (operands.size() == 1)
518 LOG.debug("SvcLogicBinaryExpression as no operator and one operand - evaluating its operand");
519 return(evaluateAsKey(operands.get(0), node, ctx));
523 if (operands.isEmpty())
525 LOG.error("SvcLogicBinaryExpression has no operators and no operands - evaluating value as null");
529 LOG.error("SvcLogicBinaryExpression has no operators and "+operands.size()+" operands - evaluating value as null");
534 StringBuffer sbuff = new StringBuffer();
535 sbuff.append(evaluateAsKey(operands.get(0), node, ctx));
537 for (OperatorType operator : operators)
540 sbuff.append(operator.toString());
542 sbuff.append(evaluateAsKey(operands.get(i++), node,ctx));
544 return(sbuff.toString());
546 else if (expr instanceof SvcLogicFunctionCall)
548 StringBuffer sbuff = new StringBuffer();
549 SvcLogicFunctionCall funcCall = (SvcLogicFunctionCall) expr;
550 sbuff.append(funcCall.getFunctionName());
552 boolean needComma = false;
553 for (SvcLogicExpression operand : funcCall.getOperands())
563 sbuff.append(evaluateAsKey(operand, node, ctx));
566 return(sbuff.toString());
570 throw new SvcLogicException("Unrecognized expression type ["+expr+"]");
574 public static String resolveVariableName(SvcLogicExpression atom, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException
576 StringBuffer varNameBuff = new StringBuffer();
578 boolean needDot = false;
579 for (SvcLogicExpression term : atom.getOperands())
583 varNameBuff.append(".");
585 if (term instanceof SvcLogicVariableTerm)
587 SvcLogicVariableTerm vterm = (SvcLogicVariableTerm) term;
588 varNameBuff.append(vterm.getName());
589 if (vterm.numOperands() > 0)
591 varNameBuff.append("[");
592 varNameBuff.append(evaluate(vterm.getSubscript(), node, ctx));
593 varNameBuff.append("]");
598 varNameBuff.append(term.toString());
602 return(varNameBuff.toString());