package org.crazycake.formSqlBuilder.utils; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.ObjectMapper; import org.crazycake.formSqlBuilder.FormSqlBuilder; import org.crazycake.formSqlBuilder.exception.FormSqlBuilderParseException; import org.crazycake.formSqlBuilder.model.Rule; import org.crazycake.formSqlBuilder.model.enums.Operator; import org.crazycake.formSqlBuilder.model.enums.Relation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 配置加载工具类 * @author alex.yang * */ public class PropertiesUtils { private static Logger logger = LoggerFactory.getLogger(PropertiesUtils.class); /** * 加载hqlbuilder.properties的配置文件 */ public static Properties loadProperties() { /** * 初始化加载配置文件 */ Properties hqlprop = new Properties(); hqlprop.setProperty("rules_folder", "formSqlRules"); InputStream in = FormSqlBuilder.class.getClassLoader().getResourceAsStream("formSqlBuilder.properties"); try { hqlprop.load(in); in.close(); } catch (Throwable e){ logger.debug("no formSqlBuilder.properties"); } return hqlprop; } /** * 加载配置的json文件 * @throws FormSqlBuilderParseException */ public static Hashtable<String, Map<String,Rule>> loadJson(String rulesFolder) throws FormSqlBuilderParseException { Hashtable<String, Map<String,Rule>> queryRules = new Hashtable<String, Map<String,Rule>>(); /** * 初始化加载json映射文件 * 通过配置获取映射文件所在文件夹 */ if(rulesFolder != null){ URL dirUrl = FormSqlBuilder.class.getClassLoader().getResource(rulesFolder); if (dirUrl != null && dirUrl.getProtocol().equals("file")) { //获取到映射文件夹 try { File rulesFolderFile = new File(dirUrl.toURI()); //获取映射文件列表 File[] jsonFiles = rulesFolderFile.listFiles(); ObjectMapper jacksonMapper = new ObjectMapper(); for (int i = 0; i < jsonFiles.length; i++) { parseJsonFile(queryRules, jsonFiles, jacksonMapper, i); } } catch (URISyntaxException e) { logger.error("resolve json folder error",e); } } } return queryRules; } /** * 解析单个文件 * @param queryRules * @param jsonFiles * @param jacksonMapper * @param i * @throws FormSqlBuilderParseException */ private static void parseJsonFile(Hashtable<String, Map<String, Rule>> queryRules, File[] jsonFiles, ObjectMapper jacksonMapper, int i) throws FormSqlBuilderParseException { File jsonFile = jsonFiles[i]; //使用jackson来解析这些文件 try { /* * 获取到整个json文件 */ Map<String, Object> rawData = jacksonMapper.readValue(jsonFile, Map.class); Iterator<String> it = rawData.keySet().iterator(); while(it.hasNext()){ //解析一个rule scheme parseRuleScheme(queryRules, rawData, it); } } catch (JsonParseException e) { logger.error("parse json file error",e); } catch (JsonMappingException e) { logger.error("parse json file error",e); } catch (IOException e) { logger.error("parse json file error",e); } } /** * 解析rule scheme * @param queryRules * @param rawData * @param it * @throws FormSqlBuilderParseException */ private static void parseRuleScheme(Hashtable<String, Map<String, Rule>> queryRules, Map<String, Object> rawData, Iterator<String> it) throws FormSqlBuilderParseException { String queryRuleId = it.next(); /* * 单个解析节点,对应的是一组解析规则 */ List<Map<String, Object>> parseRules = (List<Map<String, Object>>)rawData.get(queryRuleId); /** * 对应这组解析规则的Rule列表 * 此处用LinkedHashMap是为了让hql的拼接顺序是按照配置文件来的 */ Map<String,Rule> rules = new LinkedHashMap<String, Rule>(); //group counter int groupCounter = 0; for (int j = 0; j < parseRules.size(); j++) { //解析单个rule节点 /** * 获取出单个解析规则 */ Map<String, Object> ruleMap = parseRules.get(j); Rule r = null; if(ruleMap.get("field") != null && !"".equals((String)ruleMap.get("field"))){ //it should be a rule node r = parseOneRule(ruleMap); }else if(ruleMap.get("members") != null && !"".equals(ruleMap.get("members"))){ //it should be a group r = parseOneGroup(ruleMap,groupCounter); groupCounter++; }else{ return; } /** * 添加到解析规则组 */ rules.put(r.getField(),r); } /** * 将这组Rule规则加入到全局Rule规则表 */ queryRules.put(queryRuleId, rules); } /** * 解析单个rule * @return * @throws FormSqlBuilderParseException */ private static Rule parseOneRule(Map<String, Object> ruleMap) throws FormSqlBuilderParseException{ Rule r = new Rule(); String field = (String)ruleMap.get("field"); //validate some field error validateFieldExpr(field); r.setField(field); r.setTargetField((String)ruleMap.get("targetField")); r.setOp(Operator.find((String)ruleMap.get("op"))); r.setRel(Relation.find((String)ruleMap.get("rel"))); //wildcardTargetField is optional Object wildcardTargetField = ruleMap.get("wildcardTargetField"); if(wildcardTargetField != null){ r.setWildcardTargetField((Boolean)wildcardTargetField); } return r; } /** * validate some obvious errors * @param field * @throws FormSqlBuilderParseException */ private static void validateFieldExpr(String field) throws FormSqlBuilderParseException { if(field.startsWith("int:")){ throw new FormSqlBuilderParseException("Use Integer instead of int! field: "+field); }else if(field.startsWith("boolean:")){ throw new FormSqlBuilderParseException("Use Integer Boolean of boolean! field: "+field); }else if(field.startsWith("double:")){ throw new FormSqlBuilderParseException("Use Integer Double of double! field: "+field); } } /** * 解析一个组 * @param ruleMap * @param groupCounter * @return * @throws FormSqlBuilderParseException */ private static Rule parseOneGroup(Map<String, Object> ruleMap, int groupCounter) throws FormSqlBuilderParseException{ Rule r = new Rule(); r.setField("_group"+groupCounter); r.setRel(Relation.find((String)ruleMap.get("rel"))); List<Rule> memberList = new ArrayList<Rule>(); List<Map<String, Object>> members = (List<Map<String, Object>>)ruleMap.get("members"); for(Map<String, Object> member:members){ memberList.add(parseOneRule(member)); } r.setMembers(memberList); return r; } }