Java tutorial
/* * JasperReports - Free Java Reporting Library. * Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved. * http://www.jaspersoft.com * * Unless you have purchased a commercial license agreement from Jaspersoft, * the following license terms apply: * * This program is part of JasperReports. * * JasperReports is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JasperReports is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with JasperReports. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.jasperreports.engine.json.expression.filter.evaluation; import java.math.BigDecimal; import net.sf.jasperreports.engine.json.JRJsonNode; import net.sf.jasperreports.engine.json.JsonNodeContainer; import net.sf.jasperreports.engine.json.expression.EvaluationContext; import net.sf.jasperreports.engine.json.expression.filter.BasicFilterExpression; import net.sf.jasperreports.engine.json.expression.filter.FilterExpression; import net.sf.jasperreports.engine.json.expression.filter.ValueDescriptor; import net.sf.jasperreports.engine.json.expression.member.MemberExpression; import net.sf.jasperreports.engine.type.JsonOperatorEnum; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.fasterxml.jackson.databind.JsonNode; /** * @author Narcis Marcu (narcism@users.sourceforge.net) */ public class BasicFilterExpressionEvaluator implements FilterExpressionEvaluator { private static final Log log = LogFactory.getLog(BasicFilterExpressionEvaluator.class); private EvaluationContext evaluationContext; private BasicFilterExpression expression; public BasicFilterExpressionEvaluator(EvaluationContext evaluationContext, BasicFilterExpression expression) { this.evaluationContext = evaluationContext; this.expression = expression; } @Override public boolean evaluate(JRJsonNode jsonNode) { JsonNodeContainer memberEval = new JsonNodeContainer(jsonNode); boolean result = false; if (log.isDebugEnabled()) { log.debug("filtering (" + this.expression + ") to: " + jsonNode); } // traverse the members outer: for (MemberExpression me : expression.getMemberExpressionList()) { memberEval = me.evaluate(memberEval, evaluationContext.getMemberExpressionEvaluatorVisitorForFilter()); // exit on first null if (memberEval == null) { if (log.isDebugEnabled()) { log.debug("result is null"); } return false; } // break when hitting a missing node; this will allow filtering for missing keys if (memberEval.getSize() == 1 && memberEval.getFirst().getDataNode().isMissingNode()) { if (log.isDebugEnabled()) { log.debug("hit missing node"); } break outer; } } if (log.isDebugEnabled()) { log.debug("done filter members' eval => node with (size: " + memberEval.getSize() + ", cSize: " + memberEval.getContainerSize() + ")"); } // check for null first if (expression.isNullFunction()) { if (log.isDebugEnabled()) { log.debug("expression isNullFunction"); } if (memberEval.getSize() == 1 && (memberEval.getFirst().getDataNode().isNull() || memberEval.getFirst().getDataNode().isMissingNode())) { result = true; } } // check for not null on everything except null and missing nodes else if (expression.isNotNullFunction()) { if (log.isDebugEnabled()) { log.debug("expression isNotNullFunction"); } if (memberEval.getSize() > 1 || memberEval.getSize() == 1 && !(memberEval.getFirst().getDataNode().isNull() || memberEval.getFirst().getDataNode().isMissingNode())) { result = true; } } else if (expression.isArrayFunction()) { if (log.isDebugEnabled()) { log.debug("expression isArrayFunction"); } if (memberEval.getSize() > 1 || memberEval.getSize() == 1 && memberEval.getFirst().getDataNode().isArray()) { return true; } } else if (expression.isObjectFunction()) { if (log.isDebugEnabled()) { log.debug("expression isObjectFunction"); } if (memberEval.getSize() == 1 && memberEval.getFirst().getDataNode().isObject()) { return true; } } else if (expression.isValueFunction()) { if (log.isDebugEnabled()) { log.debug("expression isValueFunction"); } if (memberEval.getSize() == 1 && memberEval.getFirst().getDataNode().isValueNode()) { return true; } } // the size is only checked on an array object else if (expression.isSizeFunction()) { if (log.isDebugEnabled()) { log.debug("expression isSizeFunction"); } if (memberEval.getSize() > 1 || memberEval.getSize() == 1 && memberEval.getFirst().getDataNode().isArray()) { result = applySizeOperator(memberEval.getContainerSize()); } } // else perform the filtering only for value/missing nodes else if (memberEval.getSize() == 1 && (memberEval.getFirst().getDataNode().isValueNode() || memberEval.getFirst().getDataNode().isMissingNode())) { result = applyOperator(memberEval.getFirst().getDataNode()); } if (log.isDebugEnabled()) { log.debug("filter result is: " + result); } return result; } protected boolean applySizeOperator(int size) { if (expression.getValueDescriptor().getType() == FilterExpression.VALUE_TYPE.INTEGER) { int operand = Integer.parseInt(expression.getValueDescriptor().getValue()); switch (expression.getOperator()) { case EQ: return size == operand; case NE: return size != operand; case GT: return size > operand; case GE: return size >= operand; case LT: return size < operand; case LE: return size <= operand; } } return false; } protected boolean applyOperator(JsonNode valueNode) { ValueDescriptor valueDescriptor = expression.getValueDescriptor(); JsonOperatorEnum operator = expression.getOperator(); FilterExpression.VALUE_TYPE type = valueDescriptor.getType(); // do null comparison first if (FilterExpression.VALUE_TYPE.NULL.equals(type)) { switch (operator) { case EQ: return valueNode.isNull() || valueNode.isMissingNode(); case NE: return !(valueNode.isNull() || valueNode.isMissingNode()); } } else { // compare numbers with numbers if (valueNode.isNumber() && (FilterExpression.VALUE_TYPE.INTEGER.equals(type) || FilterExpression.VALUE_TYPE.DOUBLE.equals(type))) { BigDecimal opRight = new BigDecimal(valueDescriptor.getValue()); BigDecimal opLeft; if (valueNode.isBigDecimal()) { opLeft = valueNode.decimalValue(); } else { opLeft = new BigDecimal(valueNode.asText()); } switch (operator) { case EQ: return opLeft.compareTo(opRight) == 0; case NE: return opLeft.compareTo(opRight) != 0; case GT: return opLeft.compareTo(opRight) > 0; case GE: return opLeft.compareTo(opRight) >= 0; case LT: return opLeft.compareTo(opRight) < 0; case LE: return opLeft.compareTo(opRight) <= 0; } } // compare strings with strings else if (valueNode.isTextual() && FilterExpression.VALUE_TYPE.STRING.equals(type)) { switch (operator) { case EQ: return valueNode.textValue().equals(valueDescriptor.getValue()); case NE: return !valueNode.textValue().equals(valueDescriptor.getValue()); case CONTAINS: return valueNode.textValue().contains(valueDescriptor.getValue()); } } // compare booleans with booleans else if (valueNode.isBoolean() && FilterExpression.VALUE_TYPE.BOOLEAN.equals(type)) { switch (operator) { case EQ: return valueNode.booleanValue() == Boolean.parseBoolean(valueDescriptor.getValue()); case NE: return valueNode.booleanValue() != Boolean.parseBoolean(valueDescriptor.getValue()); } } } return false; } }