package com.hotent.runtime.utils; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; import com.hotent.base.util.BeanUtils; import com.hotent.base.util.JsonUtil; import com.hotent.base.util.StringUtil; import com.hotent.base.util.string.StringPool; import java.math.BigDecimal; /** * @author moka * */ public class SubCalcUtils { private final static String OP_EQUALS = "1"; private final static String OP_NOT_EQUALS = "2"; private final static String OP_GREAT_THAN = "3"; private final static String OP_LESS_THAN = "4"; private final static String OP_GREAT_EQUALS = "7"; private final static String OP_LESS_EQUALS = "8"; private final static String OP_CONTAINS = "9"; private final static String OP_ISNULL = "11"; private final static String OP_NOTNULL = "12"; /** * 判断子表中某一行满足某个条件, 默认为false * * 若令条件为A,B,C为符合条件,包含则是A || B || C,即其中一个条件(如A)不满足,则直接返回true * */ public static boolean subFieldContain(JsonNode subArray, String field, String op, Object value, String dataType) { //默认为false if(!(subArray instanceof ArrayNode)){ return false; } ArrayNode arrayNode = (ArrayNode) subArray; if (arrayNode.isEmpty()) { return false; } for (JsonNode node : arrayNode) { ObjectNode row = (ObjectNode) node; boolean rowResult = SubCalcUtils.subRowCalc(row, field, op, value, dataType); if (rowResult) { return true; } } return false; } /** * 判断子表中是否全部不满足条件的 * * 不包含正 等价于 全为反 * 若令条件为A,B,C为符合条件,不包含则是!A and !B and !C,即其中一个条件(如!A)不满足,则直接返回false * */ public static boolean subFieldNotContain(JsonNode subArray, String field, String op, Object value, String dateType) { if(!(subArray instanceof ArrayNode)){ return false; } ArrayNode arrayNode = (ArrayNode) subArray; if (arrayNode.isEmpty()) { return false; } for (JsonNode node : arrayNode) { ObjectNode row = (ObjectNode) node; boolean rowResult = SubCalcUtils.subRowCalc(row, field, op, value, dateType); if (rowResult) { return false; } } return true; } private static boolean subRowCalc(ObjectNode row, String field, String op, Object value, String dateType) { switch (dateType) { case "string": return subRowStringCalc(row, field, op, BeanUtils.isEmpty(value) ? "" : value.toString()); case "number": return subRowNumberCalc(row, field, op, BeanUtils.isEmpty(value) ? BigDecimal.ZERO : value); case "date": return subRowDateCalc(row, field, op, BeanUtils.isEmpty(value) ? "" : value.toString()); default: throw new IllegalArgumentException("unknown date type"); } } /** * 1: == * 2: != * 3: > * 4: < * 7: >= * 8: <= * 9: belong to(value split by comma and length is 2) * */ private static boolean subRowDateCalc(ObjectNode row, String field, String op, String value) { String dateValue = JsonUtil.getString(row, field, StringPool.EMPTY); if (OP_ISNULL.equals(op)){ return BeanUtils.isEmpty(dateValue); }else if (OP_NOTNULL.equals(op)){ return BeanUtils.isNotEmpty(dateValue); } if (OP_CONTAINS.equals(op)) { return subRowDateRegionCalc(dateValue, value); } int diff = dateValue.compareTo(value); return getSubRowCalcResult(diff, op); } private static boolean subRowDateRegionCalc(String dateValue, String dateRegion) { if (StringUtil.isEmpty(dateRegion) || StringUtil.isEmpty(dateValue)) { return false; } String[] split = dateRegion.split(StringPool.COMMA); if (2 == split.length) { return (dateValue.compareTo(split[0]) >= 0 && dateValue.compareTo(split[1]) <= 0); } throw new IllegalArgumentException("illegal date argument, the date region must contains one comma"); } /** * 1: == * 2: != * 3: > * 4: < * 7: >= * 8: <= * 9: belong to(value split by comma) * */ private static boolean subRowNumberCalc(ObjectNode row, String field, String op, Object value) { JsonNode fieldNode = row.get(field); if (OP_ISNULL.equals(op)){ return BeanUtils.isEmpty(fieldNode); }else if (OP_NOTNULL.equals(op)){ return BeanUtils.isNotEmpty(fieldNode); } BigDecimal decimalValue; if (value instanceof BigDecimal) { decimalValue = ((BigDecimal) value); } else if (value instanceof Integer) { decimalValue = BigDecimal.valueOf((Integer) value); } else if (value instanceof Long) { decimalValue = BigDecimal.valueOf(((Long) value)); } else if (value instanceof Double) { decimalValue = BigDecimal.valueOf(((Double) value)); } else if (value instanceof String && OP_CONTAINS.equals(op)) { return calcNumberContains(value.toString(), row.get(field)); } else { throw new IllegalArgumentException("unknown value type"); } // numberValue 可能为 TextNode 则直接读取数据 if (fieldNode instanceof TextNode ){ int diff = new BigDecimal(fieldNode.asInt()).compareTo(decimalValue); return getSubRowCalcResult(diff, op); } // numberValue 可能为BigDecimal或Int BigDecimal curValue; try { curValue = fieldNode.decimalValue(); } catch (Exception e) { curValue = BigDecimal.ZERO; } int diff = curValue.compareTo(decimalValue); return getSubRowCalcResult(diff, op); } private static boolean getSubRowCalcResult(int diff, String op) { switch (op) { case OP_EQUALS: return diff == 0; case OP_NOT_EQUALS: return diff != 0; case OP_GREAT_THAN: return diff > 0; case OP_LESS_THAN: return diff < 0; case OP_GREAT_EQUALS: return diff >= 0; case OP_LESS_EQUALS: return diff <= 0; default: throw new IllegalArgumentException("unknown operation type"); } } private static boolean calcNumberContains(String valueStr, JsonNode node) { String[] split = valueStr.split(StringPool.COMMA); BigDecimal curValue; try { curValue = node.decimalValue(); } catch (Exception e) { curValue = BigDecimal.ZERO; } for (String numberStr : split) { BigDecimal decimal = BigDecimal.valueOf(Long.parseLong(numberStr)); if (curValue.compareTo(decimal) == 0) { return true; } } return false; } /** * 1: == * 2: != * 9: contains(split by comma) * */ private static boolean subRowStringCalc(ObjectNode row, String field, String op, String value) { String fieldValue = JsonUtil.getString(row, field, StringPool.EMPTY); switch (op) { case OP_EQUALS: return fieldValue.equals(value); case OP_NOT_EQUALS: return !fieldValue.equals(value); case OP_CONTAINS: String[] split = value.split(StringPool.COMMA); for (String s : split) { if (fieldValue.equals(s)) { return true; } } return false; case OP_ISNULL: return StringUtil.isEmpty(fieldValue); case OP_NOTNULL: return StringUtil.isNotEmpty(fieldValue); default: throw new IllegalArgumentException("unknown operation type"); } } }