From 7f8fd751c9272c33be0b74f02cd962dd615b63d3 Mon Sep 17 00:00:00 2001 From: "Smokowski, Kevin (ks6305)" Date: Fri, 30 Nov 2018 18:00:42 +0000 Subject: refactor sli-provider split sli-provider into sli-provider and sli-provider-base Change-Id: I7b7edb767c04c9a6caf72a9172f49518655e33b7 Issue-ID: CCSDK-778 Signed-off-by: Smokowski, Kevin (ks6305) --- .../provider/base/SvcLogicExpressionResolver.java | 605 +++++++++++++++++++++ 1 file changed, 605 insertions(+) create mode 100644 sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolver.java (limited to 'sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolver.java') diff --git a/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolver.java b/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolver.java new file mode 100644 index 00000000..779be9e9 --- /dev/null +++ b/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolver.java @@ -0,0 +1,605 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.core.sli.provider.base; + +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.onap.ccsdk.sli.core.sli.SvcLogicAtom; +import org.onap.ccsdk.sli.core.sli.SvcLogicBinaryExpression; +import org.onap.ccsdk.sli.core.sli.SvcLogicContext; +import org.onap.ccsdk.sli.core.sli.SvcLogicException; +import org.onap.ccsdk.sli.core.sli.SvcLogicExpression; +import org.onap.ccsdk.sli.core.sli.SvcLogicFunctionCall; +import org.onap.ccsdk.sli.core.sli.SvcLogicNode; +import org.onap.ccsdk.sli.core.sli.SvcLogicVariableTerm; +import org.onap.ccsdk.sli.core.sli.SvcLogicAtom.AtomType; +import org.onap.ccsdk.sli.core.sli.SvcLogicBinaryExpression.OperatorType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SvcLogicExpressionResolver { + + private static final Logger LOG = LoggerFactory + .getLogger(SvcLogicExpressionResolver.class); + + public static String evaluate(SvcLogicExpression expr, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + if (expr == null) { + return (null); + } + + + + if (expr instanceof SvcLogicAtom) { + SvcLogicAtom atom = (SvcLogicAtom) expr; + + AtomType atomType = atom.getAtomType(); + switch (atomType) { + case NUMBER: + case STRING: + return (atom.toString()); + case CONTEXT_VAR: + case IDENTIFIER: + + String varName = resolveVariableName(atom, node, ctx); + + if (atomType == AtomType.CONTEXT_VAR) + { + LOG.trace("Evaluating context variable $"+varName); + + String varValue = ctx.getAttribute(varName); + + if (varValue == null) { + LOG.trace("Context variable $"+varName+" unset - treating as empty string"); + varValue = ""; + } + + return (varValue); + } + SvcLogicExpression parm = node.getParameter(varName); + if (parm != null) { + LOG.trace("Evaluating value of parameter "+varName+": "+parm.asParsedExpr()); + + return (evaluate(parm, node, ctx)); + } + else + { + return(varName); + } + default: + return(null); + } + + } else if (expr instanceof SvcLogicBinaryExpression) { + SvcLogicBinaryExpression binExpr = (SvcLogicBinaryExpression) expr; + List operators = binExpr.getOperators(); + if (operators.isEmpty()) + { + List operands = binExpr.getOperands(); + if (operands.size() == 1) + { + LOG.trace("SvcLogicBinaryExpression as no operator and one operand - evaluating its operand"); + return(evaluate(operands.get(0), node, ctx)); + } + else + { + if (operands.isEmpty()) + { + LOG.error("SvcLogicBinaryExpression has no operators and no operands - evaluating value as null"); + } + else + { + LOG.error("SvcLogicBinaryExpression has no operators and "+operands.size()+" operands - evaluating value as null"); + } + return(null); + } + } + switch (operators.get(0)) { + case addOp: + case subOp: + case multOp: + case divOp: + return(evalArithExpression(binExpr, node, ctx)); + case equalOp: + case neOp: + case ltOp: + case leOp: + case gtOp: + case geOp: + return (evalCompareExpression(binExpr, node, ctx)); + case andOp: + case orOp: + return(evalLogicExpression(binExpr, node, ctx)); + + default: + return(null); + } + } + else if (expr instanceof SvcLogicFunctionCall) + { + return(evalFunctionCall((SvcLogicFunctionCall)expr, node, ctx)); + } + else + { + throw new SvcLogicException("Unrecognized expression type ["+expr+"]"); + } + } + + private static String evalArithExpression(SvcLogicBinaryExpression binExpr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException { + List operands = binExpr.getOperands(); + List operators = binExpr.getOperators(); + if (operands.size() != (operators.size()+1)) + { + throw new SvcLogicException("Invalid expression ("+binExpr+")"); + } + String retval = evaluate(operands.get(0), node, ctx); + String retsval = retval; + long retlval = 0; + boolean valueIsLong = false; + + int i = 1; + try + { + + if ((retval.length() > 0) && StringUtils.isNumeric(retval)) + { + retlval = Long.parseLong(retval); + valueIsLong = true; + } + for (OperatorType operator: operators) + { + String curOperandValue = evaluate(operands.get(i++), node, ctx); + switch(operator) { + case addOp: + retsval = retsval + curOperandValue; + if (valueIsLong) + { + if ((curOperandValue.length() > 0) && StringUtils.isNumeric(curOperandValue) ) + { + retlval = retlval + Long.parseLong(curOperandValue); + } + else + { + valueIsLong = false; + } + } + break; + case subOp: + retlval = retlval - Long.parseLong(curOperandValue); + break; + case multOp: + retlval = retlval * Long.parseLong(curOperandValue); + break; + case divOp: + retlval = retlval / Long.parseLong(curOperandValue); + break; + } + + } + } + catch (NumberFormatException e1) + { + throw new SvcLogicException("Illegal value in arithmetic expression", e1); + } + + if (valueIsLong) + { + return("" + retlval); + } + else + { + return(retsval); + } + + } + + + + private static String evalCompareExpression(SvcLogicBinaryExpression expr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException + { + + List operators = expr.getOperators(); + List operands = expr.getOperands(); + + if ((operators.size() != 1) || (operands.size() != 2)) + { + throw new SvcLogicException ("Invalid comparison expression : "+expr); + } + + OperatorType operator = operators.get(0); + String op1Value = evaluate(operands.get(0), node, ctx); + String op2Value = evaluate(operands.get(1), node, ctx); + + if ((StringUtils.isNotEmpty(op1Value) && StringUtils.isNumeric(op1Value) && StringUtils.isNotEmpty(op2Value) && StringUtils.isNumeric(op2Value))) + { + try + { + double op1dbl = Double.parseDouble(op1Value); + double op2dbl = Double.parseDouble(op2Value); + + switch(operator) + { + case equalOp: + return(Boolean.toString(op1dbl == op2dbl)); + case neOp: + return(Boolean.toString(op1dbl != op2dbl)); + case ltOp: + return(Boolean.toString(op1dbl < op2dbl)); + case leOp: + return(Boolean.toString(op1dbl <= op2dbl)); + case gtOp: + return(Boolean.toString(op1dbl > op2dbl)); + case geOp: + return(Boolean.toString(op1dbl >= op2dbl)); + default: + return(null); + } + } + catch (NumberFormatException e) + { + throw new SvcLogicException("Caught exception trying to compare numeric values", e); + } + } + else + { + + int compResult = 0; + + if (op1Value == null) { + compResult = -1; + } else if (op2Value == null ) { + compResult = 1; + } else { + compResult = op1Value.compareToIgnoreCase(op2Value); + } + + switch(operator) + { + case equalOp: + return(Boolean.toString(compResult == 0)); + case neOp: + return(Boolean.toString(compResult != 0)); + case ltOp: + return(Boolean.toString(compResult < 0)); + case leOp: + return(Boolean.toString(compResult <= 0)); + case gtOp: + return(Boolean.toString(compResult > 0)); + case geOp: + return(Boolean.toString(compResult >= 0)); + default: + return(null); + } + } + + } + + private static String evalLogicExpression(SvcLogicBinaryExpression expr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException + { + boolean retval; + + List operands = expr.getOperands(); + List operators = expr.getOperators(); + + if (operands.size() != (operators.size()+1)) + { + throw new SvcLogicException("Invalid expression ("+expr+")"); + } + + try + { + retval = Boolean.parseBoolean(evaluate(operands.get(0), node, ctx)); + int i = 1; + for (OperatorType operator : operators) + { + if (operator == OperatorType.andOp) + { + retval = retval && Boolean.parseBoolean(evaluate(operands.get(i++), node, ctx)); + } + else + { + + retval = retval || Boolean.parseBoolean(evaluate(operands.get(i++), node, ctx)); + } + + } + } + catch (Exception e) + { + throw new SvcLogicException("Invalid expression ("+expr+")"); + } + + + return(Boolean.toString(retval)); + } + + private static String evalFunctionCall(SvcLogicFunctionCall func, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException + { + String funcName = func.getFunctionName(); + List operands = func.getOperands(); + + if ("length".equalsIgnoreCase(funcName)) + { + + if (operands.size() == 1) + { + String opValue = evaluate(operands.get(0), node, ctx); + return(""+opValue.length()); + } + else + { + throw new SvcLogicException("Invalid call to length() function"); + } + } + else if ("substr".equalsIgnoreCase(funcName)) + { + if (operands.size() == 3) + { + String op1Value = evaluate(operands.get(0), node, ctx); + String op2Value = evaluate(operands.get(1), node, ctx); + String op3Value = evaluate(operands.get(2), node, ctx); + + if (!StringUtils.isNumeric(op2Value) || !StringUtils.isNumeric(op3Value)) + { + throw new SvcLogicException("Invalid arguments to substr() function"); + } + + try + { + return(op1Value.substring(Integer.parseInt(op2Value), Integer.parseInt(op3Value))); + } + catch (Exception e) + { + throw new SvcLogicException("Caught exception trying to take substring", e); + } + } + else + { + + throw new SvcLogicException("Invalid call to substr() function"); + } + + } + else if ("toUpperCase".equalsIgnoreCase(funcName)) + { + if (operands.size() == 1) + { + String opValue = evaluate(operands.get(0), node, ctx); + if (opValue != null) { + return(opValue.toUpperCase()); + } else { + return(""); + } + } + else + { + throw new SvcLogicException("Invalid call to toUpperCase() function"); + } + } + else if ("toLowerCase".equalsIgnoreCase(funcName)) + { + if (operands.size() == 1) + { + String opValue = evaluate(operands.get(0), node, ctx); + if (opValue != null) { + return(opValue.toLowerCase()); + } else { + return(""); + } + } + else + { + throw new SvcLogicException("Invalid call to toLowerCase() function"); + } + } + else if ("convertBase".equalsIgnoreCase(funcName)) { + int fromBase = 10; + int toBase = 10; + String srcString = ""; + + if (operands.size() == 2) + { + fromBase = 10; + srcString = evaluate(operands.get(0), node, ctx); + toBase = Integer.parseInt(evaluate(operands.get(1), node, ctx)); + } else if (operands.size() == 3) { + + srcString = evaluate(operands.get(0), node, ctx); + fromBase = Integer.parseInt(evaluate(operands.get(1), node, ctx)); + toBase = Integer.parseInt(evaluate(operands.get(2), node, ctx)); + } else { + throw new SvcLogicException("Invalid call to convertBase() function"); + } + + long srcValue = Long.parseLong(srcString, fromBase); + return(Long.toString(srcValue, toBase)); + } + else + { + throw new SvcLogicException("Unrecognized function ("+funcName+")"); + } + + } + + public static String evaluateAsKey(SvcLogicExpression expr, SvcLogicNode node, + SvcLogicContext ctx) throws SvcLogicException { + if (expr == null) { + return (null); + } + + + + if (expr instanceof SvcLogicAtom) { + SvcLogicAtom atom = (SvcLogicAtom) expr; + + AtomType atomType = atom.getAtomType(); + StringBuffer varNameBuff = new StringBuffer(); + switch (atomType) { + case NUMBER: + return (atom.toString()); + case STRING: + return("'"+atom.toString()+"'"); + case CONTEXT_VAR: + case IDENTIFIER: + boolean needDot = false; + for (SvcLogicExpression term : atom.getOperands()) + { + if (needDot) + { + varNameBuff.append("."); + } + if (term instanceof SvcLogicVariableTerm) + { + SvcLogicVariableTerm vterm = (SvcLogicVariableTerm) term; + varNameBuff.append(vterm.getName()); + if (vterm.numOperands() > 0) + { + varNameBuff.append("["); + varNameBuff.append(evaluate(vterm.getSubscript(), node, ctx)); + varNameBuff.append("]"); + + } + } + else + { + varNameBuff.append(term.toString()); + } + needDot = true; + } + + String varName = varNameBuff.toString(); + LOG.debug("Evaluating context variable $"+varName); + String ctxValue = ctx.getAttribute(varName); + if (ctxValue == null) + { + return(null); + } + if (StringUtils.isNumeric(ctxValue)) + { + return(ctxValue); + } + else + { + return("'"+ctxValue+"'"); + } + + default: + return(null); + } + + } else if (expr instanceof SvcLogicBinaryExpression) { + SvcLogicBinaryExpression binExpr = (SvcLogicBinaryExpression) expr; + List operators = binExpr.getOperators(); + List operands = binExpr.getOperands(); + if (operators.isEmpty()) + { + if (operands.size() == 1) + { + LOG.debug("SvcLogicBinaryExpression as no operator and one operand - evaluating its operand"); + return(evaluateAsKey(operands.get(0), node, ctx)); + } + else + { + if (operands.isEmpty()) + { + LOG.error("SvcLogicBinaryExpression has no operators and no operands - evaluating value as null"); + } + else + { + LOG.error("SvcLogicBinaryExpression has no operators and "+operands.size()+" operands - evaluating value as null"); + } + return(null); + } + } + StringBuffer sbuff = new StringBuffer(); + sbuff.append(evaluateAsKey(operands.get(0), node, ctx)); + int i = 1; + for (OperatorType operator : operators) + { + sbuff.append(" "); + sbuff.append(operator.toString()); + sbuff.append(" "); + sbuff.append(evaluateAsKey(operands.get(i++), node,ctx)); + } + return(sbuff.toString()); + } + else if (expr instanceof SvcLogicFunctionCall) + { + StringBuffer sbuff = new StringBuffer(); + SvcLogicFunctionCall funcCall = (SvcLogicFunctionCall) expr; + sbuff.append(funcCall.getFunctionName()); + sbuff.append("("); + boolean needComma = false; + for (SvcLogicExpression operand : funcCall.getOperands()) + { + if (needComma) + { + sbuff.append(","); + } + else + { + needComma = true; + } + sbuff.append(evaluateAsKey(operand, node, ctx)); + } + sbuff.append(")"); + return(sbuff.toString()); + } + else + { + throw new SvcLogicException("Unrecognized expression type ["+expr+"]"); + } + } + + public static String resolveVariableName(SvcLogicExpression atom, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException + { + StringBuffer varNameBuff = new StringBuffer(); + + boolean needDot = false; + for (SvcLogicExpression term : atom.getOperands()) + { + if (needDot) + { + varNameBuff.append("."); + } + if (term instanceof SvcLogicVariableTerm) + { + SvcLogicVariableTerm vterm = (SvcLogicVariableTerm) term; + varNameBuff.append(vterm.getName()); + if (vterm.numOperands() > 0) + { + varNameBuff.append("["); + varNameBuff.append(evaluate(vterm.getSubscript(), node, ctx)); + varNameBuff.append("]"); + } + } + else + { + varNameBuff.append(term.toString()); + } + needDot = true; + } + return(varNameBuff.toString()); + } + +} -- cgit 1.2.3-korg