All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.obhen233.util.ExpressionUtil Maven / Gradle / Ivy

The newest version!
package com.github.obhen233.util;

import java.lang.reflect.Field;
import java.util.*;
import java.util.Map.Entry;


import com.github.obhen233.annotation.application.IfNull;
import com.github.obhen233.element.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.obhen233.annotation.framework.NoBase;
import com.github.obhen233.annotation.framework.NoParam;
import com.github.obhen233.annotation.framework.RuleBase;
import com.github.obhen233.annotation.framework.RuleParam;
import com.github.obhen233.attribute.Nrule;
import com.github.obhen233.attribute.Rule;

import com.github.obhen233.exception.ExpressionFormatException;
import com.github.obhen233.producer.RuleProducer;



/**
 * 1.元素:一组[]表示是元素,元素分为Node和Leaf Node是包含元素的单元,可以包含Node,也可以包含Leaf.Leaf 下面只能包含函数
 * 2.规则:元素与元素之间的关系是"与"或者"或",做以下限定 如果一个元素完全是由Node组成,那么这些Node之间的关系是"或",
 *         如果本元素既有Node又有Leaf,或者完全是Leaf 那么这些元素之间的关系是"与",Leaf下函数之间的关系是"与".
 * 3.特殊元素:Bud 是一个只会返回True的Leaf 表示成[] 这个是为了处理元素内的完全是由Node组成, 但是Node之间又必须用"与"相连的情况,
 *         root 元素是根元素,所有元素的起点,root 元素有 一个 unid 表示唯一root
 * 4.函数:$加函数名称表示一个函数,函数的实现是由第三方语言实现
 * 5. 函数参数:分为参数值与基准值,参数值在前,基准值在后,参数值由##把key包裹,调用之时用方法名.参数的方式调用.值与值之间用,隔开 如果
 * 			没有参数或使用默认参数,参数值请置空。当没有参数的时候,需要在对应的Rule上用@NoParam注解 默认参数是param 如果有新增维护的
 * 			字段请用@RuleParam注解value是本字段对应表达式的参数,默认是字段名称,请实现get,set方法 。
 *            基准值由{}包裹,{key:value}形式,参数与基准值有两个默认参数可以不加,如果参数 不加的话,默认使用基准值,有且仅有一个,如果只有key 冒号不能省略。
 * 6.参数使用:正常传值,列表或者是数组,用逗号隔开,字典值用| 每个值之间用逗号隔开
 * 7.@format格式化完成不允许出现的参数有 [ ] $ # ( ) { } 
 * 8. 对于冒号 : 冒号只对时间格式做了兼容,如果没有自定义参数,格式化时间里面带有冒号,必须前面加上: 例:{:2019-08-17 00:00:00}
 * **/


public class ExpressionUtil {
	
	private static Logger logger = LoggerFactory.getLogger(ExpressionUtil.class);

	public static boolean testExpression(String expression) throws Exception{
		Node node = formatNode(expression);
		return node != null;
	}
	
	public static Root expression2Root(String expression) throws Exception{
		
		Node node = formatNode(expression);
		Root root = new Root();
		if(node == null)
			throw new ExpressionFormatException("expression exchange error");
		List elements = node.getElements();
		if(elements != null && elements.size() > 0){
			root.setElements(elements);
		}else{
			throw new ExpressionFormatException("expression exchange error");
		}
		return root;	
	}
	
	private static String formatErrorExp(String expression){
		int firstIndex = indexOfAlphabet(expression);
		int lastIndex = lastIndexOfAlphabet(expression);
		if(firstIndex == -1 || lastIndex == -1)
			return "";
		return expression.substring(firstIndex,lastIndex+1);	
	}
	
	private static int indexOfAlphabet(String s){
		if(s == null || s.length() <= 0)
			return -1;
		for(int i = 0;i c)||('a'< c && 'z' > c) ||('0'c)){
				return i;
			}
		}
		return -1;
	}
	private static int lastIndexOfAlphabet(String s){
		if(s == null || s.length() <= 0)
			return -1;
		for(int i = 0;i c)||('a'< c && 'z' > c) ||('0'c)){
				return index;
			}
		}
		return -1;
	}
	//关键字 [ ] $ # ( ) { } :
	private static Leaf formatLeaf(String leafStr) throws Exception{
		Leaf leaf = new Leaf();
		
		if(StringUtil.isNotBlank(leafStr)){
			if(leafStr.startsWith("[") && leafStr.endsWith("]")){
				List rules = new ArrayList();
				String rulesStr =  leafStr.substring(1,leafStr.length()-1);
				while(true){
					if(StringUtil.isBlank(rulesStr)){
						break;
					}
					int index = rulesStr.indexOf(")");
					if( index != -1){
						String rulestr = rulesStr.substring(0,index+1);
						if(!StringUtil.isBlank(rulestr)){
							int funStartIndex = rulestr.indexOf("$");
							boolean isNot = false;
							if(funStartIndex != 0 && funStartIndex != -1){
								String exclStr = rulestr.substring(funStartIndex-1,funStartIndex);
								isNot = "!".equals(exclStr);
							}
							int funEndIndex = rulestr.indexOf("(");
							if(funStartIndex != -1 && funEndIndex != -1){
								String funcStr = rulestr.substring(funStartIndex+1,funEndIndex);
								Rule rule = RuleProducer.getRuleInstanceByKey(funcStr);
								if(rule == null)
									throw new ExpressionFormatException("innt Rule instance error "+funcStr);
								if(rulestr.contains("#")){
									NoParam noParam = rule.getClass().getAnnotation(NoParam.class);
									if(noParam != null)
										throw new ExpressionFormatException("this is a no param function "+funcStr);
									int lastPoundIndex = rulestr.lastIndexOf("#");
									int firstPoundIndex = rulestr.indexOf("#");
									if(lastPoundIndex != firstPoundIndex){
										String targets = rulestr.substring(firstPoundIndex,lastPoundIndex+1);
										if("##".endsWith(targets))
											throw new ExpressionFormatException("param is null:"+rulestr);
										checkTarget(targets,rule);		
									}else{
										throw new ExpressionFormatException("only have one # :"+rulestr);
									}
								}
								int leftIndexBrace = rulestr.indexOf("{");
								int reghtIndexBrace = rulestr.indexOf(")")-1;
								if(leftIndexBrace != -1 && reghtIndexBrace != -1){
									NoBase noBase = rule.getClass().getAnnotation(NoBase.class);
									if(noBase != null)
										throw new ExpressionFormatException("this is a no base function "+funcStr);
									 String baseStr = rulesStr.substring(leftIndexBrace,reghtIndexBrace+1);
									 setBase(baseStr,rule);
								}
								rules.add(ObjectUtil.deepClone(isNot?new Nrule(rule):rule));
							}else{
								throw new ExpressionFormatException("function name is illegal :"+rulestr);
							}
							rulesStr =  rulesStr.substring(index+1,rulesStr.length());
						}else{
							throw new ExpressionFormatException("format rule error "+rulestr);
						}
					}else{
						throw new ExpressionFormatException("The rule is not closed. rule string is :"+rulesStr);
					}
				}
				leaf.setRules(rules);
			}else{
				throw new ExpressionFormatException("The Leaf is illegal");
			}
		}else{
			throw new ExpressionFormatException("rule in Leaf is null");
		}
		return leaf;
	}	
	
	private static void checkTarget(String targetStr,Rule rule){
		List managelist = new ArrayList();
		List paramList = getParamFromRule(rule.getClass());
		while(true){
			if(StringUtil.isBlank(targetStr)){
				break;
			}
			if(!targetStr.startsWith("#"))
				throw new ExpressionFormatException("The param has some error"+targetStr);
			String tmpTargetStr = targetStr.substring(1,targetStr.length());
			int nextPoundIndex = tmpTargetStr.indexOf("#");
			if(nextPoundIndex != -1){
				String param = tmpTargetStr.substring(0,nextPoundIndex);
				targetStr = targetStr.substring(nextPoundIndex+3 >targetStr.length() ?targetStr.length():nextPoundIndex+3 ,targetStr.length());
				if(StringUtil.isBlank(param))
					throw new ExpressionFormatException("The param is null");
				if(!paramList.contains(param))
					throw new ExpressionFormatException("param "+param+" not in "+rule.getClass().getSimpleName());
				managelist.add(param);
			}else{
				throw new ExpressionFormatException("The param has some error"+targetStr);
			}
			
		}
		if(managelist.size() != paramList.size()){
			StringBuilder sb = new StringBuilder();
			for(String s :managelist){
				sb.append(sb.length() > 0?",":"");
				sb.append(s);
			}
			throw new ExpressionFormatException("Please check "+ (sb.length() > 0 ? sb.toString():"null")+ ", the parameters are different from " + rule.getClass().getSimpleName()+" parameters");
		}
	}
	
	private static List getParamFromRule(Class ruleClass){
		NoParam noParam = ruleClass.getAnnotation(NoParam.class);
		List list = new ArrayList();
		if(noParam != null)
			return list;
		
		Field[] fields = StringUtil.getAllFields(ruleClass);
		for(Field f:fields){
			f.setAccessible(true);
			String name = f.getName();
			RuleParam ruleParam = f.getAnnotation(RuleParam.class);
			if(ruleParam != null){
				String value = ruleParam.value();
				if(StringUtil.isBlank(value))
					list.add(name);
				else
					list.add(value);
			}
			
		}
		if(list.size() <= 0)
			list.add("param");
		return list;
	}
	private static void setBase(String baseStr,Rule rule){
		Map manageMap =new HashMap();
		List baseList = getBaseFromRule(rule.getClass());
		while(true){
			if(StringUtil.isBlank(baseStr)){
				break;
			}
			if(!baseStr.startsWith("{") && !baseStr.endsWith("}") )
				throw new ExpressionFormatException("The base has some error"+baseStr);
			int leftIndexBrace = baseStr.indexOf("{");
			int reghtIndexBrace = baseStr.indexOf("}");
			String kAndv = baseStr.substring(leftIndexBrace+1,reghtIndexBrace);
			if(kAndv.indexOf("{") != -1 || kAndv.indexOf("}") != -1  )
				throw new ExpressionFormatException("base format error, around "+kAndv);
			
			if(StringUtil.isNotBlank(kAndv)){
				if(baseList.size() <= 0)
					throw new ExpressionFormatException("is a no base Rule "+rule.getClass().getSimpleName());
				if(!kAndv.contains(":")){
					manageMap.put("base",kAndv);
				}else{
					List arr = new ArrayList();
					int indexOFColon = kAndv.indexOf(":");
					String pre = kAndv.substring(0,indexOFColon);
					String suf = kAndv.substring(indexOFColon+1);
					if(StringUtil.isNotBlank(pre) && StringUtil.isNotBlank(suf)){
						manageMap.put(pre,suf);
					}else if(StringUtil.isBlank(pre) && StringUtil.isNotBlank(suf)){
						if(baseList.size() != 1)
							throw new ExpressionFormatException("base size not match " + rule.getClass().getSimpleName() + " has " +baseList.size() + "but expression has more.");
						manageMap.put("base",suf);
					}else if(StringUtil.isNotBlank(pre) && StringUtil.isBlank(suf)){
						manageMap.put(pre,null);
					}else{
						if(baseList.size() >= 0)
							throw new ExpressionFormatException("base size not match " + rule.getClass().getSimpleName() + " has " +baseList.size() + "but expression has null.");
					}
				}
				baseStr = baseStr.substring((baseStr.length() >= reghtIndexBrace+2)?reghtIndexBrace+2:baseStr.length(),baseStr.length());
			}else{
				if(baseList.size() > 0) {
					if (baseList.size() != 1) {
						throw new ExpressionFormatException("base size not match " + rule.getClass().getSimpleName() + " has " + baseList.size() + "but expression has null.");
					} else if (!"base".equals(baseList.get(0))) {
						throw new ExpressionFormatException(rule.getClass().getSimpleName() + " need base by find " + baseList.get(0));
					}
				}
				manageMap.put("base",null);
				break;
			}
			
		}
		if(manageMap.keySet().size() != baseList.size()){
			StringBuilder sb = new StringBuilder();
			for(String key :manageMap.keySet()){
				sb.append(sb.length() > 0?",":"");
				sb.append(key);
			}
			throw new ExpressionFormatException("Please check "+ (sb.length() > 0 ? sb.toString():"null")+ ", the bases are different from " + rule.getClass().getSimpleName()+" bases");
		}
		if(manageMap != null ){
			for(Entry baseEntry: manageMap.entrySet()){
				String key = baseEntry.getKey();
				String value = baseEntry.getValue();
				setRuleValue(rule,key,value);
			}
		}
	}
	private static void setRuleValue(Rule rule,String key,String value) {
		Class ruleClass = rule.getClass();
		if(ruleClass.getAnnotation(NoBase.class) != null ){
			return;
		}
		Field[] fields = StringUtil.getAllFields(ruleClass);
		boolean managed = false;
		for(Field f:fields){
			f.setAccessible(true);
			RuleBase ruleBase = f.getAnnotation(RuleBase.class);
			if(ruleBase == null)
				continue;
			managed = true;
			String paramValue = ruleBase.value();
			String base = ruleBase.base();
			String name = f.getName();
			if(key.equals(StringUtil.isNotBlank(paramValue)?paramValue:name)){
				if(StringUtil.isNotBlank(value))
					ReflectionUtil.invokeSet(rule, name, StringUtil.StringToField(value, f));
				else{
					if(StringUtil.isNotBlank(base))
						ReflectionUtil.invokeSet(rule, name, StringUtil.StringToField(base, f));
				}

			}
		}
		if(!managed){
			if("base".equals(key))
				try {
					ReflectionUtil.invokeSet(rule, "base", StringUtil.StringToField(value, ruleClass.getSuperclass().getDeclaredField("base")));
				} catch (Exception e) {
					try {
						throw e;
					} catch (Exception e1) {
						logger.error("throw e error");
					}
				}
			else
				throw new ExpressionFormatException("please check,The base key "+key +"not find in "+ruleClass.getSimpleName());
		}
	}
	private static List getBaseFromRule(Class ruleClass){
		List list = new ArrayList();
		NoBase noBase = ruleClass.getAnnotation(NoBase.class);
		if(noBase != null)
			return list;
		Field[] fields = StringUtil.getAllFields(ruleClass);
		for(Field f:fields){
			f.setAccessible(true);
			String name = f.getName();
			RuleBase ruleBase = f.getAnnotation(RuleBase.class);
			if(ruleBase != null){
				String value = ruleBase.value();
				if(StringUtil.isBlank(value))
					list.add(name);
				else
					list.add(value);
			}
			
		}
		if(list.size() <= 0)
			list.add("base");
		return list;
	}
	
	
	private static int indexOfRightSquareBracket(int indexOfLeftSquareBracket,String expression){
		if(indexOfLeftSquareBracket == -1)
			return -1;
		String bracketCharacter = expression.substring(indexOfLeftSquareBracket,indexOfLeftSquareBracket+1);
		if(!"[".equals(bracketCharacter))
			return -1;
		if((indexOfLeftSquareBracket+2) > expression.length())
			return -1;
		Stack leftSquareBracketstack = new Stack();
		leftSquareBracketstack.add("[");
		for(int i = indexOfLeftSquareBracket+1;i elements = new ArrayList();
			expression = expression.substring(1,expression.length()-1);
			while(StringUtil.isNotBlank(expression)){
				int indexOfLeftSquareBracket = expression.indexOf("[");
				if(indexOfLeftSquareBracket == -1)
					throw new ExpressionFormatException("expression format error  around "+expression);
				int indexOfRightSquareBracket = indexOfRightSquareBracket(indexOfLeftSquareBracket,expression);
				if(indexOfRightSquareBracket == -1)
					throw new ExpressionFormatException("expression format error not find the right square bracket. around "+expression);
				String preExp = expression.substring(indexOfLeftSquareBracket,indexOfRightSquareBracket+1);
				String sufExp = expression.substring(indexOfRightSquareBracket+1);
				if(StringUtil.isNotBlank(preExp)){
					if("[]".equals(preExp)){
						elements.add(new Bud());
					}else{
						if(preExp.startsWith("[") && preExp.endsWith("]")){
							String tmpExp = preExp.substring(1,preExp.length()-1);
							if(tmpExp.contains("[") && tmpExp.contains("]")){
								elements.add(formatNode(preExp));
							}else if(!tmpExp.contains("[") && !tmpExp.contains("]") && tmpExp.contains("$")){
								elements.add(formatLeaf(preExp));
							}
						}else{
							throw new ExpressionFormatException("expression format error  around "+preExp);
						}
					}
				}else{
					throw new ExpressionFormatException("expression format error not find the element.around "+expression);
				}
				expression = sufExp;
			}
			node.setElements(elements);
			return node;
		}else{
			throw new ExpressionFormatException("expression not start with [ or not end with ]");
		}
	}
	
	public static Root  expression2Root(Class clazz) throws Exception{
		Root root = new Root();
		com.github.obhen233.annotation.application.Root rootAnno = (com.github.obhen233.annotation.application.Root)
				clazz.getDeclaredAnnotation(com.github.obhen233.annotation.application.Root.class);
		if(rootAnno == null)
			throw new ExpressionFormatException("not have Root Annotation.");
		String unid = rootAnno.unid();
		if(StringUtil.isBlank(unid))
			throw new ExpressionFormatException("unid is null");
		root.setUnid(unid);
		com.github.obhen233.annotation.application.Node nodeAnno = (com.github.obhen233.annotation.application.Node)
				clazz.getDeclaredAnnotation(com.github.obhen233.annotation.application.Node.class);
		if(nodeAnno == null)
			throw new ExpressionFormatException("not have Node Annotation.");
		Class[] elementClasses = nodeAnno.elements();
		root.setElements(formatAnnoElement(elementClasses));
		return root;
	}
	
	private static List formatAnnoElement(Class[] elementClasses) throws Exception{
		if(elementClasses == null || elementClasses.length <= 0)
			throw new ExpressionFormatException("elementClasses is null");
		List elements = new ArrayList();
		for(int i = 0;i < elementClasses.length ; i++){
			Class elementClass = elementClasses[i];
			if(Bud.class.equals(elementClass)){
				elements.add(new Bud());
			}else {
				com.github.obhen233.annotation.application.Node nodeAnno = (com.github.obhen233.annotation.application.Node)
						elementClass.getDeclaredAnnotation(com.github.obhen233.annotation.application.Node.class);
				com.github.obhen233.annotation.application.Leaf leafAnno = (com.github.obhen233.annotation.application.Leaf)
						elementClass.getDeclaredAnnotation(com.github.obhen233.annotation.application.Leaf.class);
				if(nodeAnno == null && leafAnno == null){
					throw new ExpressionFormatException(elementClass.getSimpleName()+" not have Node Annotation OR Leaf Annotation");
				}
				if(nodeAnno != null){
					Class[] eleClasses = nodeAnno.elements();
					List es = formatAnnoElement(eleClasses);
					if(es != null && es.size() > 0){
						Node node = new Node();
						node.setElements(es);
						elements.add(node);
					}	
				}
				if(leafAnno != null){
					com.github.obhen233.annotation.application.Rule[] rules = leafAnno.value();
					if(rules != null && rules.length > 0){
						Leaf leaf = new Leaf();
						List rs = new ArrayList();
						for(com.github.obhen233.annotation.application.Rule rule:rules){
							boolean not = rule.not();
							Class ruleClass = rule.rule();
							if(not){
								rs.add(new Nrule((Rule)ruleClass.newInstance()));
							}else{
								rs.add((Rule)ruleClass.newInstance());
							}
						}
						IfNull ifNullAnno = (IfNull)
								elementClass.getDeclaredAnnotation(IfNull.class);
						boolean ifnull = ifNullAnno== null?false:ifNullAnno.value();
						leaf.setRules(rs,ifnull);
						elements.add(leaf);
					}else{
						throw new ExpressionFormatException(elementClass.getSimpleName()+" not have Rules");
					}
				}
				
			}
		}
		return elements;
	}
	public static void main(String[] args) throws Exception {
		Properties properties = new Properties();
		properties.setProperty("rule-scan","com.github.obhen233.util");
		RuleProducer.inntProducer(properties);
		String ex = "[[[$strEuqal({})]]]";
		System.out.println(ExpressionUtil.expression2Root(ex));
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy