package com.hg.ecommerce.util; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.json.JSONArray; import org.json.JSONObject; import com.hg.ecommerce.config.ProjectConfig; import com.hg.ecommerce.model.support.EntityObject; /** * Utilizer class: contain several helper methods * * @author apple * */ public class Util { private static SimpleDateFormat dateFormat = new SimpleDateFormat( ProjectConfig.getProperty("format.date")); private static Pattern pattern = Pattern.compile("(:([a-zA-Z0-9\\-_\\$]+))"); /** * 将java.util.Date对象转换为string,格式规定为project.properties文件中 * * @param date * @return */ public static String dateToString(Date date) { if (date == null) { date = new Date(); } return dateFormat.format(date); } /** * 将string转换为java.util.Date,格式规定为project.properties文件中 * * @param string * @return */ public static Date stringToDate(String string) { try { return dateFormat.parse(string); } catch (ParseException e) { e.printStackTrace(); return new Date(); } } public static final String SETTER_PREFIX = "set"; public static final String GETTER_PREFIX = "get"; public static final String IS_PREFIX = "is"; /** * 此方法用于快速映射两个对象的相同字段,方法会创建一个与pojo对象对应的dto对象, * 用于从pojo对象中复制字段值到dto对象,这些字段必须是pojo对象与dto对象都共同存在的。 * * 需要借用project.properties指定的dto所在的package 使用此转换规则需要遵循一定的条件: * 1.类命名条件:pojo类命名为:Area,对应dto类命名为:AreaDto * 2.字段命名规则:想要快速映射的字段,在Area与AreaDto中应该具有一样的名字和getter与setter方法 * * @param pojo * @return */ @SuppressWarnings("rawtypes") public static Object pojoToDto(Object pojo) { try { Class pojoCls = pojo.getClass(); Class dtoCls = Class.forName(ProjectConfig .getProperty("package.dto") + "." + pojoCls.getSimpleName() + "Dto"); Method[] pojoMethods = pojoCls.getDeclaredMethods(); Method[] dtoMethods = dtoCls.getDeclaredMethods(); Object dto = dtoCls.newInstance(); for (Method dtoMethod : dtoMethods) { String methodName = dtoMethod.getName(); if (!methodName.startsWith(SETTER_PREFIX)) { continue; } Method pojoMethod = endsSameMethod(methodName, pojoMethods); if (pojoMethod == null) { continue; } dtoMethod.invoke(dto, pojoMethod.invoke(pojo, (Object[]) null)); } return dto; } catch (Exception exception) { exception.printStackTrace(); return null; } } /** * 此方法用于快速映射两个对象的相同字段,方法会创建一个与dto对象对应的pojo对象, * 用于从dto对象中复制字段值到pojo对象,这些字段必须是pojo对象与dto对象都共同存在的。 * 需要借用project.properties指定的dto所在的package 使用此转换规则需要遵循一定的条件: * 1.类命名条件:pojo类命名为:Area,对应dto类命名为:AreaDto * 2.字段命名规则:想要快速映射的字段,在Area与AreaDto中应该具有一样的名字和getter与setter方法 * * @param dto * @return */ @SuppressWarnings("rawtypes") public static Object dtoToPojo(Object dto) { try { Class dtoCls = dto.getClass(); Class pojoCls = Class.forName(ProjectConfig .getProperty("package.pojo") + "." + dtoCls.getSimpleName().substring(0, dtoCls.getSimpleName().indexOf("Dto"))); Method[] pojoMethods = pojoCls.getDeclaredMethods(); Method[] dtoMethods = dtoCls.getDeclaredMethods(); Object pojo = pojoCls.newInstance(); for (Method pojoMethod : pojoMethods) { String methodName = pojoMethod.getName(); if (!methodName.startsWith(SETTER_PREFIX)) { continue; } Method dtoMethod = endsSameMethod(methodName, dtoMethods); if (dtoMethod == null) { continue; } pojoMethod.invoke(pojo, dtoMethod.invoke(dto, (Object[]) null)); } return pojo; } catch (Exception exception) { exception.printStackTrace(); return null; } } /** * 查看两个方法是否一个为setter,一个getter,并且是针对同样名称的字段操作 * * @param method1 * @param method2 * @return */ private static boolean endsSame(String method1, String method2) { String affix1 = null; String affix2 = null; if (method1.startsWith(SETTER_PREFIX) && !method2.startsWith(SETTER_PREFIX)) { affix1 = method1.substring(SETTER_PREFIX.length()); if (method2.startsWith(GETTER_PREFIX)) { affix2 = method2.substring(GETTER_PREFIX.length()); } else if (method2.startsWith(IS_PREFIX)) { affix2 = method2.substring(IS_PREFIX.length()); } } else if (method2.startsWith(SETTER_PREFIX) && !method1.startsWith(SETTER_PREFIX)) { affix2 = method2.substring(SETTER_PREFIX.length()); if (method1.startsWith(GETTER_PREFIX)) { affix1 = method1.substring(GETTER_PREFIX.length()); } else if (method1.startsWith(IS_PREFIX)) { affix1 = method1.substring(IS_PREFIX.length()); } } if (affix1 == null || affix2 == null) { return false; } else { return affix1.equals(affix2); } } /** * 根据endsSame提供的boolean返回值,获取合适的method对象 * * @param method1 * @param methods * @return */ private static Method endsSameMethod(String method1, Method[] methods) { for (Method method : methods) { if (endsSame(method1, method.getName())) { return method; } else { continue; } } return null; } /** * 转换为JSON化对象,可序列化。 * * @param object * 要转化的对象 * @return 返回JSONObject */ @SuppressWarnings("rawtypes") public static Object getJsonObject(Object object) { if (object == null) { return null; } if (object instanceof EntityObject) { // 字段对象为EntityObject object = ((EntityObject) object).toJSON(); } else if (object instanceof Date) { // 字段对象为Date // object = ((Date) object).getTime(); object = Util.dateToString((Date)object); } else if (object instanceof Map) { JSONObject jsonObject = new JSONObject(); for (Object obj : ((Map) object).entrySet()) { Entry entry = (Entry) obj; // 如果为map,必须保证key为String if (!(entry.getKey() instanceof String)) { throw new RuntimeException( "java.util.Map has Non-String Key, not allowed!"); } jsonObject.put(entry.getKey().toString(), getJsonObject(entry.getValue())); } object = jsonObject; } else if (object instanceof Collection) { JSONArray jsonArray = new JSONArray(); for (Object obj : (Collection) object) { jsonArray.put(getJsonObject(obj)); } object = jsonArray; } return object; } /** * 以某种token连接字符串数组 * * @param token * @param parts * @return */ public static String join(char token, String... parts) { StringBuilder sb = new StringBuilder(); if (parts.length < 1) return ""; sb.append(parts[0]); for (int i = 1; i < parts.length; ++i) { sb.append(token); sb.append(parts[i]); } return sb.toString(); } /** * 类似于模板引擎,将render mustache模板文件 * * @param reader * @param writer * @param object * @throws IOException */ public static void render(List<String> mustache, PrintWriter writer, JSONObject jsonObject) { String line; Pattern pattern = Pattern.compile( "\\{\\{([#/]?)([a-zA-Z0-9\\-_$\\.]+)\\}\\}", Pattern.MULTILINE); ListIterator<String> iterator = mustache.listIterator(); while (iterator.hasNext()) { boolean shouldPrint = true; String mstr = iterator.next(); Matcher matcher = pattern.matcher(mstr); int sequenceIndex = 0; boolean shouldContinue = true; while (matcher.find(sequenceIndex)) { // 更新下标,避免死循环 sequenceIndex = matcher.end(0); if (!shouldContinue) break; // System.err.println(matcher.group(0)); // System.err.println(matcher.group(1)); // System.err.println(matcher.group(2)); // System.err.println(); String prefix = matcher.group(1); String token = matcher.group(2); if (prefix == null || prefix.trim().equals("")) { Object replacement = ""; try { replacement = jsonObject.get(token); } catch (Exception exception) { System.err.println("Has no property named \"" + token + "\""); } // 直接覆盖mstr应当不影响Matcher对象 mstr = mstr.replace("{{" + token + "}}", replacement.toString()); } else { mstr = mstr.replace("{{" + prefix + token + "}}", ""); // 递归判定开始 if ("#".equals(prefix)) { Object subObject = null; try { subObject = jsonObject.get(token); } catch (Exception exception) { System.err.println("Has no property named \"" + token + "\""); // continue; } // 判定递归成功,不应再让Matcher查找下去 shouldContinue = false; // 我的策略是如果用户在模板中指定的集合字段或boolean字段不存在,标签体中的一切都要放弃掉 if (subObject != null) { //创建list,收集标签体中的语句 List<String> subList = new ArrayList<String>(); subList.add(mstr); while (iterator.hasNext()) { line = iterator.next(); // 添加行数,知道遇到结束标签 if (line.contains("{{/" + token + "}}")) { iterator.previous(); break; } else { subList.add(line); } } //收集完成后,判断对象类型,决定处理手段,如果是array,遍历array,多次递归调用render,如果是boolean。。。见下面的else if (subObject instanceof JSONArray) { // 转型为 JSONArray JSONArray array = (JSONArray) subObject; for (int i = 0; i < array.length(); ++i) { // JSONArray中的不一定是JSONObject 需要分情况讨论 Object inner = array.get(i); JSONObject innerJsonObject = null; if (inner instanceof JSONObject) { innerJsonObject = (JSONObject) inner; } else if (inner instanceof JSONArray) { } else { innerJsonObject = new JSONObject(); innerJsonObject.put(".", inner); } render(subList, writer, innerJsonObject); } } else { boolean dealFlag = true; // 除了JSONArray之外,其他相似标签一律作true or false判定 if(subObject.getClass().getName().equals("boolean")||subObject instanceof Boolean){ if(!(Boolean)subObject){ //设置不作处理 dealFlag = false; } } //判断是否处理 if(dealFlag){ render(subList, writer, jsonObject); } } } else { // 空找结束标签,抛弃体中的一切东西 while (iterator.hasNext()) { line = iterator.next(); // 添加行数,知道遇到结束标签 if (line.contains("{{/" + token + "}}")) { iterator.previous(); break; } } } } else { shouldPrint = false; continue; } } } // System.err.println(mstr); if(shouldPrint&&!mstr.trim().equals("")) writer.println(mstr); } } /** * 格式化字段名称 * * @param mappedFieldName * @return */ public static String qualifyFieldName(String mappedFieldName) { StringBuilder sb = new StringBuilder(); String[] parts = mappedFieldName.split("_"); sb.append(parts[0]); for (int i = 1; i < parts.length; i++) { sb.append(repairName(parts[i])); } return sb.toString(); } /** * 格式化实体名称 * * @param tableName * @return */ public static String qualifyModelName(String tableName) { StringBuilder sb = new StringBuilder(); String[] parts = tableName.split("_"); for (int i = 0; i < parts.length; i++) { sb.append(repairName(parts[i])); } return sb.toString(); } /** * 保证首字母大写 * * @param name * @return */ public static String repairName(String name) { if (name.length() < 1) return ""; return Character.toUpperCase(name.charAt(0)) + name.substring(1); } /** * 如果入参为空,返回默认值 */ public static <T> T conditionedGet(T in, T defaultVal) { if (in == null) return defaultVal; if (in instanceof CharSequence) { if (in.toString().equals("")) return defaultVal; } return in; } /** * 通过传入对象和fieldName来获取该FieldName上的值 */ public static <T> Object getFieldValue(Field field, T data){ Class<?> cls = field.getDeclaringClass(); String rFieldName = repairName(field.getName()); Method method = null; try{ method = cls.getDeclaredMethod("get"+rFieldName, (Class<?>[])null); } catch(Exception exception){ try{ method = cls.getDeclaredMethod("is"+rFieldName, (Class<?>[])null); }catch(Exception exception2){ } } if(method!=null){ try { Object obj = method.invoke(data, (Object[])null); if(obj!=null) return obj; } catch (Exception e) { } } return ""; } /** * render sql with named param * @param rawSQL raw sql * @param params map params * @return sql string */ public static String renderSQL(String rawSQL, Map<String, String> params){ StringBuilder builder = new StringBuilder(); Matcher matcher = pattern.matcher(rawSQL); int endIndex = 0; int start; while (matcher.find(endIndex)){ start = endIndex; endIndex = matcher.end(); builder.append(rawSQL.substring(start, matcher.start())); builder.append("'").append(params.get(matcher.group(2))).append("'"); } if(endIndex!=rawSQL.length()){ builder.append(rawSQL.substring(endIndex,rawSQL.length())); } return builder.toString(); } /** * render sql with named param * @param rawSQL raw sql * @param object entity object * @return */ public static <T extends EntityObject> String renderSQL(String rawSQL, T object){ JSONObject jsonObject = ((EntityObject)object).toJSON(); StringBuilder builder = new StringBuilder(); Matcher matcher = pattern.matcher(rawSQL); int endIndex = 0; int start; while (matcher.find(endIndex)){ start = endIndex; endIndex = matcher.end(); builder.append(rawSQL.substring(start,matcher.start())); builder.append("'").append(jsonObject.get(matcher.group(2))).append("'"); } if(endIndex!=rawSQL.length()){ builder.append(rawSQL.substring(endIndex,rawSQL.length())); } return builder.toString(); } }