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

com.github.obhen233.producer.RootProducer Maven / Gradle / Ivy

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

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.*;
import java.util.Map.Entry;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import com.github.obhen233.annotation.application.Leaf;
import com.github.obhen233.annotation.application.Node;
import com.github.obhen233.annotation.application.Root;
import com.github.obhen233.annotation.application.Rule;
import com.github.obhen233.annotation.framework.Function;
import com.github.obhen233.annotation.framework.NoBase;
import com.github.obhen233.element.Bud;
import com.github.obhen233.element.Element;
import com.github.obhen233.out.FeildInfo;
import com.github.obhen233.out.FieldType;
import com.github.obhen233.out.RootParam;
import com.github.obhen233.plugin.AsyncStorePlugin;
import com.github.obhen233.plugin.StorePlugin;
import com.github.obhen233.plugin.SynchStorePlugin;
import com.github.obhen233.util.CodingUtil;
import com.github.obhen233.util.PackageScanner;
import com.github.obhen233.util.ReflectionUtil;
import com.github.obhen233.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import com.github.obhen233.annotation.application.IfNull;
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.exception.ClassRepeatsException;
import com.github.obhen233.exception.ClassUnregisteredException;
import com.github.obhen233.exception.NoFindRootException;
import com.github.obhen233.exception.UnidNullException;

public class RootProducer {

	private static Logger logger = LoggerFactory.getLogger(RootProducer.class);

	private static Map engineMap = new HashMap();
	private static final String defaultRuleXmlPath = "ruleengine-commom.xml";
	private static final int defaultSaveRootSec = 5000;
	private static RootProducer instance;
	private static StorePlugin storePlugin;

	private RootProducer() {
	}

	public static synchronized RootProducer getInstance() {
		if (instance == null) {
			instance = new RootProducer();
		}
		return instance;
	}

	public boolean inntProducer(String xmlPath) throws Exception {
		ClassLoader classLoader = RootProducer.class.getClassLoader();
		InputStream in = classLoader.getResourceAsStream(xmlPath);
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document doc = builder.parse(in);
		NodeList nodeList = doc.getElementsByTagName("element-scan");
		if (nodeList != null) {
			org.w3c.dom.Element scanElement = (org.w3c.dom.Element) nodeList.item(0);
			String annotationPath = scanElement.getAttribute("base-package");
			inntAnnotation(annotationPath);
		}

		return true;
	}

	public static boolean inntProducer(StorePlugin storePlugin,int SaveRootSec) throws Exception {
		RootProducer.storePlugin = storePlugin;
		if(storePlugin != null && AsyncStorePlugin.class.isInstance(storePlugin)) {
			List roots = storePlugin.getRoots();
			for (com.github.obhen233.element.Root root : roots) {
				getKeyFromRoot(deepClone(root));
			}
			saveRootsTimers(SaveRootSec);
		}
		return true;
	}

	public static boolean inntProducer(StorePlugin storePlugin) throws Exception {
		return inntProducer(storePlugin,defaultSaveRootSec);
	}

	private static void inntAnnotation(String annotationPath) throws Exception {
		if (StringUtil.isNotBlank(annotationPath)) {
			PackageScanner scanner = new PackageScanner(annotationPath);
			List scannerClassList = scanner.getFullyQualifiedClassNameList();
			for (String elementClass : scannerClassList) {
				Class anonClass = Class.forName(elementClass);
				Root rootAnno = (Root) anonClass.getDeclaredAnnotation(Root.class);
				if (rootAnno != null) {
					String unid = rootAnno.unid();
					if (StringUtil.isBlank(unid))
						throw new UnidNullException("the " + elementClass + " root element unid is null.");
					com.github.obhen233.element.Root root = new com.github.obhen233.element.Root();
					root.setUnid(unid);
					Node nodeAnno = (Node) anonClass.getAnnotation(Node.class);
					if (nodeAnno == null) {
						logger.info(elementClass + "has not Nodes.");
						continue;
					}
					Class[] elements = nodeAnno.elements();
					List es = formatAnnotation(elements);
					root.setElements(es);
					getKeyFromRoot(root);
				}
			}
		}
	}

	private static List formatAnnotation(Class[] es) throws Exception {
		List elements = new ArrayList();
		if (es != null && es.length > 0) {
			for (Class ec : es) {
				com.github.obhen233.element.Node node = null;
				com.github.obhen233.element.Leaf leaf = null;
				Bud bud = null;
				Node n = ec.getAnnotation(Node.class);
				Leaf l = ec.getAnnotation(Leaf.class);
				if (n!= null) {
					List list = formatAnnotation(n.elements());
					if (list != null && list.size() > 0) {
						node = new com.github.obhen233.element.Node();
						node.setElements(list);
					}
				}
				if (ec.equals(Bud.class)) {
					bud = new Bud();
				}
				if (l!= null) {
					leaf = new com.github.obhen233.element.Leaf();
					List rules = new ArrayList();
					leaf.setRules(rules);

					Rule[] ruleAnnos = l.value();
					if (ruleAnnos != null && ruleAnnos.length > 0) {
						for (Rule anno : ruleAnnos) {
							Class ruleClass = anno.rule();
							boolean not = anno.not();
							com.github.obhen233.attribute.Rule rule = ruleClass.newInstance();
							Field[] fields = StringUtil.getAllFields(ruleClass);
							for (Field f : fields) {
								f.setAccessible(true);
								String name = f.getName();
								//param不用初始化
								//RuleParam ruleParam = f.getAnnotation(RuleParam.class);
								RuleBase ruleBase = f.getAnnotation(RuleBase.class);
								if (ruleBase != null) {
									String base = ruleBase.base();
									Object o = StringUtil.StringToField(base, f);
									ReflectionUtil.invokeSet(rule, name, o);
								}
							}
							if (not) {
								Nrule nRule = new Nrule(rule);
								rules.add(nRule);
							} else {
								rules.add(rule);
							}
						}
					} else {
						IfNull ifNullAnno = ec.getAnnotation(IfNull.class);
						boolean ifNull = ifNullAnno == null ? false : ifNullAnno.value();
						leaf = new com.github.obhen233.element.Leaf();
						leaf.setRules(null, ifNull);
					}
				}

				if (node == null && leaf != null && bud == null) {
					elements.add(leaf);
				}
				if (node != null && leaf == null && bud == null) {
					elements.add(node);
				}
				if (node == null && leaf == null && bud != null) {
					elements.add(bud);
				}
			}
			return elements;
		} else {
			return null;
		}
	}

	public static boolean inntProducer(Properties properties) throws Exception {
		String annotationPath = properties.getProperty("element-scan");
		inntAnnotation(annotationPath);
		return true;
	}


	private static void getKeyFromRoot(com.github.obhen233.element.Root root) throws Exception {
		StringBuilder sb = new StringBuilder();
		String unid = root.getUnid();
		if (StringUtil.isBlank(unid))
			throw new UnidNullException("the  root element unid is null.");
		sb.append(unid);
		List elements = root.getElements();
		SortedSet sortSet = new TreeSet();
		getElementsStr(elements, sortSet);
		for (String key : sortSet) {
			sb.append("&").append(key);
		}
		engineMap.put(CodingUtil.MD5(sb.toString()), root);
	}


	private static void getElementsStr(List elements, SortedSet sortSet) {
		if (elements != null && elements.size() > 0)
			for (Element element : elements) {
				if ("Node".equals(element.getClass().getSimpleName())) {
					com.github.obhen233.element.Node n = (com.github.obhen233.element.Node) element;
					getElementsStr(n.getElements(), sortSet);
				} else if ("Leaf".equals(element.getClass().getSimpleName())) {
					com.github.obhen233.element.Leaf l = (com.github.obhen233.element.Leaf) element;
					List rules = l.getRules();
					if (rules != null && rules.size() > 0) {
						for (com.github.obhen233.attribute.Rule r : rules) {
							if (Nrule.class.isInstance(r)) {
								com.github.obhen233.attribute.Rule nr = ((Nrule) r).getRule();
								getParamFields(nr, sortSet);
							} else {
								getParamFields(r, sortSet);
							}
						}
					}
				}
			}
	}

	private static void getParamFields(com.github.obhen233.attribute.Rule rule, SortedSet sortSet) {
		Class clazz = rule.getClass();
		Field[] fields = StringUtil.getAllFields(clazz);
		StringBuilder s = null;
		String preKey = RuleProducer.getKeyByClassName(clazz.getName());
		if (StringUtil.isBlank(preKey))
			throw new ClassUnregisteredException("Rule Class \"" + clazz.getName() + "\" unregistered");
		NoParam noParam = clazz.getAnnotation(NoParam.class);
		NoBase noBase = clazz.getAnnotation(NoBase.class);
		boolean isNoParam = noParam != null;
		boolean isNoBase = noBase != null;
		boolean hasCustomizeParam = false;
		boolean hasCustomizeBase = false;
		for (Field f : fields) {
			f.setAccessible(true);
			String name = f.getName();
			Object o = ReflectionUtil.invokeGet(rule, name);
			if (o == null) {
				RuleParam ruleParam = f.getDeclaredAnnotation(RuleParam.class);
				RuleBase ruleBase = f.getDeclaredAnnotation(RuleBase.class);
				if (ruleParam != null && !isNoParam) {
					hasCustomizeParam = true;
					String value = ruleParam.value();
					String key = StringUtil.isNotBlank(value) ? value : name;
					s = new StringBuilder();
					sortSet.add(s.append(preKey).append(".").append(key).toString());
				} else if (ruleBase != null && !isNoBase) {
					hasCustomizeBase = true;
					String value = ruleBase.value();
					String key = StringUtil.isNotBlank(value) ? value : name;
					s = new StringBuilder();
					sortSet.add(s.append(preKey).append(".").append(key).toString());
				}
			}else{
				hasCustomizeBase = true;
			}
		}
		if (!hasCustomizeParam && !isNoParam) {
			Object o = ReflectionUtil.invokeGet(rule, "param");
			if (o == null) {
				s = new StringBuilder();
				sortSet.add(s.append(preKey).append(".").append("param").toString());
			}
		}

		if (!hasCustomizeBase && !isNoBase) {
			Object o = ReflectionUtil.invokeGet(rule, "base");
			if (o == null) {
				s = new StringBuilder();
				sortSet.add(s.append(preKey).append(".").append("base").toString());
			}
		}
	}

	public static com.github.obhen233.element.Root getRootByKey(String key) throws Exception {
		if(storePlugin != null && SynchStorePlugin.class.isInstance(storePlugin)){
			for(com.github.obhen233.element.Root root :((SynchStorePlugin)storePlugin).getRoots()){
				String tempKey = getKeyStrFromRoot(root);
				if(tempKey.equals(key))
					return root;
			}
			throw new NoFindRootException();
		}else {
			com.github.obhen233.element.Root root = engineMap.get(key);
			if (root == null) {
				throw new NoFindRootException();
			}
			return deepClone(root);
		}
	}

	public static String getKeyStrFromRoot(com.github.obhen233.element.Root root) throws Exception {
		StringBuilder sb = new StringBuilder();
		String unid = root.getUnid();
		if (StringUtil.isBlank(unid))
			throw new UnidNullException("the root element unid is null.");
		sb.append(unid);
		List elements = root.getElements();
		SortedSet sortSet = new TreeSet();
		getElementsStr(elements, sortSet);
		for (String key : sortSet) {
			sb.append("&").append(key);
		}
		return CodingUtil.MD5(sb.toString());
	}

	public static boolean insertRoot(com.github.obhen233.element.Root root, boolean updateFlag) throws Exception {
		if (storePlugin != null && SynchStorePlugin.class.isInstance(storePlugin))
			return ((SynchStorePlugin) storePlugin).saveRoot(root,updateFlag);
		String unid = root.getUnid();
		if (StringUtil.isBlank(unid)) {
			throw new UnidNullException("insert Root error");
		}
		String key = getKeyStrFromRoot(root);
		if (engineMap.containsKey(key)) {
			if (!updateFlag)
				throw new ClassRepeatsException("root already have.");
		}

		engineMap.put(key, root);
		return true;
	}

	public static boolean insertRoot(com.github.obhen233.element.Root root) throws Exception {
		return insertRoot(root, false);
	}

	public static boolean deleteRoot(String key) throws Exception {

		if (storePlugin != null && SynchStorePlugin.class.isInstance(storePlugin)) {
			return ((SynchStorePlugin) storePlugin).deleteRoot(getRootByKey(key));
		}else {
			if (StringUtil.isBlank(key))
				return true;
			com.github.obhen233.element.Root root = engineMap.remove(key.toUpperCase());
			return root != null;
		}
	}

	public static boolean deleteRoot(com.github.obhen233.element.Root root) throws Exception {
		String unid = root.getUnid();
		if (StringUtil.isBlank(unid)) {
			throw new UnidNullException("insert Root error");
		}
		String key = getKeyStrFromRoot(root);
		return deleteRoot(key);
	}

	public static List getRootsParam(String lang) {
		List rootParams = new ArrayList();
		if (storePlugin != null && SynchStorePlugin.class.isInstance(storePlugin)) {
			for (com.github.obhen233.element.Root r : ((SynchStorePlugin)storePlugin).getRoots()) {
				RootParam rootParam = new RootParam();
				TreeSet feildInfos = new TreeSet();
				rootParam.setFeilds(feildInfos);
				rootParam.setUnid(r.getUnid());
				getFeildInfo(r.getElements(), feildInfos, lang);
				rootParams.add(rootParam);
			}
		}else {
			for (String key : engineMap.keySet()) {
				com.github.obhen233.element.Root r = engineMap.get(key);
				RootParam rootParam = new RootParam();
				TreeSet feildInfos = new TreeSet();
				rootParam.setFeilds(feildInfos);
				rootParam.setUnid(r.getUnid());
				getFeildInfo(r.getElements(), feildInfos, lang);
				rootParams.add(rootParam);
			}
		}
		return rootParams;
	}

	public static List getRootsParam() {
		return getRootsParam("zh_cn");
	}

	private static void getFeildInfo(List elements, TreeSet feildInfos, String lang) {
		if (elements == null || elements.size() <= 0)
			return;
		for (Element e : elements) {
			if (Bud.class.equals(e.getClass()))
				continue;
			else if (com.github.obhen233.element.Node.class.equals(e.getClass()))
				getFeildInfo(((com.github.obhen233.element.Node) e).getElements(), feildInfos, lang);
			else if (com.github.obhen233.element.Leaf.class.equals(e.getClass())) {
				com.github.obhen233.element.Leaf leaf = (com.github.obhen233.element.Leaf) e;
				List rules = leaf.getRules();
				if (rules == null || rules.size() <= 0)
					return;

				for (com.github.obhen233.attribute.Rule rule : rules) {
					TreeSet infos = getFeildInfo(rule, lang);
					if (feildInfos == null)
						feildInfos = new TreeSet();
						feildInfos.addAll(infos);
				}
			}
		}
	}

	private static TreeSet getFeildInfo(com.github.obhen233.attribute.Rule rule, String lang) {

		com.github.obhen233.attribute.Rule ru = rule;
		if (Nrule.class.equals(rule.getClass()))
			ru = ((Nrule) rule).getRule();
		if (ru != null) {
			Function function = ru.getClass().getDeclaredAnnotation(Function.class);
			String ruleFunctionName = null;
			if (function != null)
				ruleFunctionName = function.name();
			NoParam noParam = ru.getClass().getDeclaredAnnotation(NoParam.class);
			NoBase noBase = ru.getClass().getDeclaredAnnotation(NoBase.class);
			String ruleClassName = ru.getClass().getSimpleName();
			StringBuilder sb = new StringBuilder();
			sb.append(ruleClassName.substring(0, 1).toLowerCase());
			sb.append(ruleClassName.substring(1));
			String className = (StringUtil.isNotBlank(ruleFunctionName)) ? ruleFunctionName : sb.toString();
			TreeSet feildInfos = new TreeSet();
			Field[] fields = StringUtil.getAllFields(ru.getClass());
			for (Field field :fields) {
				Object objValue = ReflectionUtil.invokeGet(ru, field.getName());
				if (objValue != null)
					continue;
				String fieldName = null;
				if (field != null) {
					FeildInfo feildInfo = new FeildInfo();
					field.setAccessible(true);
					if("base".equals(field.getName()) && (!needBase(fields) || noBase != null))
						continue;
					if("param".equals(field.getName()) && (!needParam(fields) || noParam != null))
						continue;

					String fieldValue = null;
					RuleBase ruleBase = field.getDeclaredAnnotation(RuleBase.class);
					RuleParam ruleParam = field.getDeclaredAnnotation(RuleParam.class);
					if (ruleBase != null) {
						if (noBase != null)
							continue;
						if (StringUtil.isNotBlank(ruleBase.base()))
							continue;
						feildInfo.setFieldType(FieldType.base);
						fieldValue = ruleBase.value();
					} else if (ruleParam != null) {
						if (noParam != null)
							continue;
						feildInfo.setFieldType(FieldType.param);
						fieldValue = ruleParam.value();
					}
					fieldName = StringUtil.isNotBlank(fieldValue) ? fieldValue : field.getName();
					StringBuilder fieldSb = new StringBuilder();
					feildInfo.setName(fieldSb.append(className).append(".").append(fieldName).toString());
					feildInfo.setSimpleName(fieldName);
					feildInfo.setLang(lang);
					feildInfo.setDesc(StringUtil.getDescription(ru.getClass(), field, lang));
					feildInfos.add(feildInfo);
				}
			}
			return feildInfos;
		}
		return null;
	}

	public static List getRootParamByUnid(String unid, String lang) {
		if (StringUtil.isBlank(unid))
			return null;
		List rootParams = new ArrayList();
		if (storePlugin != null && SynchStorePlugin.class.isInstance(storePlugin)) {
			for (com.github.obhen233.element.Root root : ((SynchStorePlugin) storePlugin).getRoots()) {
				if (root != null) {
					String rootUnid = root.getUnid();
					if (!unid.equals(rootUnid))
						continue;
					RootParam rootParam = new RootParam();
					TreeSet feildInfos = new TreeSet();
					rootParam.setFeilds(feildInfos);
					rootParam.setUnid(root.getUnid());
					getFeildInfo(root.getElements(), feildInfos, lang);
					rootParams.add(rootParam);
				}
			}
		}else {

			for (Entry entry : engineMap.entrySet()) {
				com.github.obhen233.element.Root root = entry.getValue();
				if (root != null) {
					String rootUnid = root.getUnid();
					if (!unid.equals(rootUnid))
						continue;
					RootParam rootParam = new RootParam();
					TreeSet feildInfos = new TreeSet();
					rootParam.setFeilds(feildInfos);
					rootParam.setUnid(root.getUnid());
					getFeildInfo(root.getElements(), feildInfos, lang);
					rootParams.add(rootParam);
				}
			}
		}
		return rootParams;
	}

	public static List getRootParamByUnid(String unid) {
		return getRootParamByUnid(unid, "zh_cn");
	}


	private static  T deepClone(T object) {
		T temp = null;
		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(baos);
			oos.writeObject(object);
			ByteArrayInputStream bis = new ByteArrayInputStream(baos.toByteArray());
			ObjectInputStream ois = new ObjectInputStream(bis);
			temp = (T) ois.readObject();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return temp;
	}

	public static boolean saveRoots() {
		if (storePlugin != null && AsyncStorePlugin.class.isInstance(storePlugin)) {
			List list = new ArrayList();
			for (String key : engineMap.keySet()) {
				com.github.obhen233.element.Root root = engineMap.get(key);
				if (root != null)
					list.add(deepClone(root));
			}
			return ((AsyncStorePlugin) storePlugin).saveRoots(list);
		}
		return false;
	}

	private static void saveRootsTimers(int saveSec){
		Timer saveTimer = new Timer();
		saveTimer.schedule(new TimerTask() {
			@Override
			public void run () {
				RootProducer.saveRoots();
			}
		},1000,saveSec);
	}

	public static List getRoots(){
		if (storePlugin != null) {
			return storePlugin.getRoots();
		}
		List roots = new ArrayList(engineMap.size());
		for(Entry entry:engineMap.entrySet()){
			roots.add(deepClone(entry.getValue()));
		}
		return roots;
	}


	private static boolean needBase(Field[] fields){
		for(Field field:fields) {
			RuleBase ruleBase = field.getDeclaredAnnotation(RuleBase.class);
			if (ruleBase != null)
				return false;
		}
		return true;
	}
	private static boolean needParam(Field[] fields) {
		for (Field field : fields) {
			RuleParam ruleParam = field.getDeclaredAnnotation(RuleParam.class);
			if (ruleParam != null)
				return false;
		}
		return true;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy