package org.quickbundle.tools.helper; import java.beans.PropertyDescriptor; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.Serializable; import java.sql.Blob; import java.sql.Clob; import java.sql.Date; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import org.quickbundle.ICoreConstants; import org.quickbundle.base.vo.RmValueObject; import org.quickbundle.config.RmBaseConfig; import org.quickbundle.itf.IPopulateParser; import org.quickbundle.project.serializer.RmObjectMapper; import org.quickbundle.project.serializer.RmPopulateParser; import org.quickbundle.tools.support.log.RmLogHelper; import org.quickbundle.util.RmSequenceMap; import org.slf4j.Logger; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.NotWritablePropertyException; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; public class RmPopulateHelper<E> { static Logger log = RmLogHelper.getLogger(RmPopulateHelper.class); static IPopulateParser parser = new RmPopulateParser(); /** * 功能: * * @param destinationObj 目标对象(RmValueObject, RmCommonVo, Map) * @param sourceObj 来源对象(ServletRequest, ResultSet, RmValueObject, RmCommonVo, Map) * @return */ public static int populate(Object destinationObj, Object sourceObj) { return populate(destinationObj, sourceObj, null, null, null, null); } /** * 功能: * * @param destinationObj 目标对象(ServletRequest, ResultSet, RmValueObject) * @param sourceObj 来源对象 * @param fieldMap field名对应,比如要实现Object.setName(ResultSet.getString("myname")),需提前fieldMap.put("name", "myname") * @param ignoreField 对destinationObj中忽略的field名 * @param iterateObj 自定义 * @param getValue * @return */ public static int populate(Object destinationObj, Object sourceObj, Map fieldMap, String[] ignoreField, IRmIterateObj iterateObj, IRmGetValue getValue) { if(destinationObj == null || sourceObj == null) { return 0; } boolean destination2source = true; if(destinationObj instanceof ResultSet || destinationObj instanceof ServletRequest) { throw new RuntimeException("destinationObj是不支持的注值类型:" + destinationObj.getClass()); } if(destinationObj instanceof Map) {//如果目标是Map类,从右到左 destination2source = false; } else if(sourceObj instanceof ResultSet) { //如果来源是ResultSet,从右到左 destination2source = false; } return populate(destinationObj, sourceObj, fieldMap, ignoreField, iterateObj, getValue, destination2source); } /** * 功能: * * @param destinationObj 目标对象(ServletRequest, ResultSet, RmValueObject) * @param sourceObj 来源对象 * @param fieldMap field名对应,比如要实现Object.setName(ResultSet.getString("myname")),需提前fieldMap.put("name", "myname") * @param ignoreField 对destinationObj中忽略的field名 * @param iterateObj 自定义 * @param getValue * @param destination2source true是从destinationObj取出可能的set方法,再从sourceObj调用get方法 * @return */ @SuppressWarnings("unchecked") public static int populate(Object destinationObj, Object sourceObj, Map fieldMap, String[] ignoreField, IRmIterateObj iterateObj, IRmGetValue getValue, final boolean destination2source) { int sum = 0; if(getValue != null) { //采用自定义的取值 } else if (sourceObj instanceof Map) { getValue = new IRmGetValue() { public Object getValue(Object sourceObj, String key) { return ((Map)sourceObj).get(key); } public boolean containKey(Object sourceObj, String key) { return ((Map)sourceObj).containsKey(key); } public Map getKeyValueMap(Object sourceObj) { return (Map)sourceObj; } }; } else if (sourceObj instanceof ServletRequest) { getValue = new IRmGetValue() { public Object getValue(Object sourceObj, String key) { ServletRequest request = ((ServletRequest)sourceObj); if(request.getParameterValues(key) == null || request.getParameterValues(key).length == 0) { return null; } if(request.getParameterValues(key).length == 1) { return request.getParameter(key); } else { return RmStringHelper.parseToSQLString(request.getParameterValues(key)); } } public boolean containKey(Object sourceObj, String key) { return ((ServletRequest)sourceObj).getParameterMap().containsKey(key); } public Map getKeyValueMap(Object sourceObj) { Map<String, String[]> mRequest = ((ServletRequest)sourceObj).getParameterMap(); Map<String, Object> mReturn = new HashMap<String, Object>(); for(String key: mRequest.keySet()) { mReturn.put(key, RmStringHelper.parseToString(mRequest.get(key))); } return mReturn; } }; } else if (sourceObj instanceof ResultSet) { getValue = new IRmGetValue() { public Object getValue(Object sourceObj, String key) { ResultSet rs = (ResultSet)sourceObj; Object obj = getResultValue(rs, key); return obj; } public boolean containKey(Object sourceObj, String key) { ResultSet rs = (ResultSet)sourceObj; try { ResultSetMetaData rsmd = rs.getMetaData(); for (int i=1; i<=rsmd.getColumnCount(); i++) { if(rsmd.getColumnLabel(i).equalsIgnoreCase(key)) { return true; } } } catch (SQLException e) { throw new RuntimeException("ResultSet containKey('" + key + "') error", e); } return false; } public Map getKeyValueMap(Object sourceObj) { Map<String, Object> m = new RmSequenceMap(); ResultSet rs = (ResultSet)sourceObj; try { ResultSetMetaData rsmd = rs.getMetaData(); for (int i=1; i<=rsmd.getColumnCount(); i++) { String columnLabel = rsmd.getColumnLabel(i); //如果出现小写字母后面紧跟大写字母,则判定为驼峰式规范,保持大小写和sql一致 if(!Pattern.compile("(?<=[a-z])[A-Z]").matcher(columnLabel).find()) { columnLabel = columnLabel.toLowerCase(); } m.put(columnLabel, getResultValue(rs, columnLabel)); } } catch (SQLException e) { throw new RuntimeException("ResultSet getKeyValueMap() error", e); } return m; } }; } else if (sourceObj instanceof RmValueObject) { getValue = new IRmGetValue() { public Object getValue(Object sourceObj, String key) { return RmVoHelper.getVoFieldValue(sourceObj, key); } public boolean containKey(Object sourceObj, String key) { return RmVoHelper.voContainMethod(sourceObj, "get" + RmStringHelper.toFirstUpperCase(key)); } public Map getKeyValueMap(Object sourceObj) { //TODO 实现VO-->Map的转化 return null; } }; } //注值 if(iterateObj == null) { if(destinationObj instanceof Map) { iterateObj = new IRmIterateObj() { public int iterateObj(Object destinationObj, Object sourceObj, Map fieldMap, String[] ignoreField, IRmGetValue getValue) { int sum = 0; Map mDestination = (Map)destinationObj; if(destination2source) { //从RmCommonVo或Map取出所有get方法的值 for(Object key : mDestination.keySet()) { String keyStr = key != null ? key.toString() : null; mDestination.put(key, getValue.getValue(sourceObj, keyStr)); } } else { //一次性从sourceObj取出所有值,赋值给RmCommonVo或Map Map mSource = getValue.getKeyValueMap(sourceObj); for(Object key : mSource.keySet()) { mDestination.put(key, mSource.get(key)); } } return sum; } }; } else if(destinationObj instanceof RmValueObject || destinationObj instanceof Serializable) { iterateObj = new IRmIterateObj() { public int iterateObj(Object destinationObj, Object sourceObj, Map fieldMap, String[] ignoreField, IRmGetValue getValue) { Object vo = destinationObj; int sum = 0; BeanWrapper bw = new BeanWrapperImpl(vo); PropertyDescriptor pd[] = bw.getPropertyDescriptors(); Map mSourceAll = null; if(!destination2source) { //一次性从sourceObj取出所有值,赋值给RmCommonVo或Map mSourceAll = getValue.getKeyValueMap(sourceObj); } for (int i = 0; i < pd.length; i++) { try { String currentKey = pd[i].getName(); if (!"class".equals(currentKey) && !RmStringHelper.arrayContainString(ignoreField, currentKey)) { if(fieldMap != null) { //如果fieldMap只有{"", "$0"},是ajax注值模式 if(fieldMap.size() == 1 && fieldMap.get("") != null) { currentKey = currentKey + fieldMap.get(""); } else if(fieldMap.get(currentKey) != null) { currentKey = fieldMap.get(currentKey).toString(); } } Object value = null; if(destination2source) { value = getValue.getValue(sourceObj, currentKey); } else { if(mSourceAll != null) { value = mSourceAll.get(currentKey); } else { log.warn("从source到destination注值模式下,sourceObj.getKeyValueMap()是null"); } } if(value == null) { continue; } Class propertyType = pd[i].getPropertyType(); Object valueFinal = parser.parse(propertyType, value); if(valueFinal == null) { continue; } bw.setPropertyValue(pd[i].getName(), valueFinal); sum ++; } } catch (NotWritablePropertyException e) { continue; } catch (RuntimeException e) { if(e.getCause() instanceof NoSuchMethodException) { continue; } else { log.warn(e.toString()); throw e; } } } return sum; } }; } else { throw new RuntimeException("destinationObj是不支持的类型:" + destinationObj.getClass().getName()); } } sum = iterateObj.iterateObj(destinationObj, sourceObj, fieldMap, ignoreField, getValue); return sum; } /** * 得到Result值 * * @param resultObj * @return */ public static Object getResultValue(ResultSet rs, String columnName) { try { Object resultObj = rs.getObject(columnName); if(resultObj instanceof Date) { if(ICoreConstants.DatabaseProductType.ORACLE.getDatabaseProductName().equals(RmBaseConfig.getSingleton().getDatabaseProductName())) { resultObj = rs.getTimestamp(columnName); } } else if (resultObj instanceof Clob) { StringBuilder sb = new StringBuilder(); Reader reader = ((Clob) resultObj).getCharacterStream(); BufferedReader br = new BufferedReader(reader); String tempStr = null; while ((tempStr = br.readLine()) != null) { sb.append(tempStr + "\n"); } br.close(); reader.close(); return sb.toString(); } else if (resultObj instanceof Blob) { //Blob输出到byte[]返回 InputStream is = ((Blob) resultObj).getBinaryStream(); BufferedInputStream bis = new BufferedInputStream(is); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int len = 0; while ((len = bis.read(b)) != -1) { baos.write(b, 0, len); } bis.close(); is.close(); return baos.toByteArray(); } return resultObj; } catch (SQLException e) { if(e.toString().indexOf("列名无效") > -1 || e.toString().indexOf("Invalid column name") > -1) { return null; } else { //throw new RmRuntimeException("获取" + columnName + "出错", e); return null; } } catch (IOException e) { throw new RuntimeException("ResultSet获取" + columnName + "出错", e); } } public interface IRmIterateObj { public int iterateObj(Object destinationObj, Object sourceObj, Map fieldMap, String[] ignoreField, IRmGetValue getValue); } public interface IRmGetValue { public Object getValue(Object sourceObj, String key); public boolean containKey(Object sourceObj, String key); public Map getKeyValueMap(Object sourceObj); } /** * ajax注值模式,各vo之间用name$1, name$2区分 * * @param <T> vo泛型 * @param classVo vo的class对象 * @param request 存放form提交数据的request * @return * @throws IOException * @throws JsonMappingException * @throws JsonParseException */ @SuppressWarnings("unchecked") public static<T> List<T> populateAjax(Class<T> classVo, HttpServletRequest request) { List<T> lvo = new ArrayList<T>(); if(RmBaseConfig.getSingleton().isSubmitJson()) { String jsonStr = request.getParameter(ICoreConstants.RM_AJAX_JSON); List vos; try { vos = RmObjectMapper.getInstance().readValue(jsonStr, List.class); } catch (JsonParseException e) { throw new RuntimeException(e); } catch (JsonMappingException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } for (Object vo : vos) { lvo.add(RmObjectMapper.getInstance().convertValue(vo, classVo)); } } else { int rm_record_length = Integer.parseInt(request.getParameter(ICoreConstants.RM_AJAX_RECORD_SIZE)); for(int i=0; i<rm_record_length; i++) { try { T vo = classVo.newInstance(); Map fieldMap = new HashMap(); fieldMap.put("", ICoreConstants.RM_AJAX_SPLIT_KEY + i); populate(vo, request, fieldMap, null, null, null); lvo.add(vo); } catch (Exception e) { log.warn("populateAjax " + classVo.getName() + " " + e.toString()); } } } return lvo; } /** * 针对多个vo,按出现的顺序循环注值 * * @param <T> vo泛型 * @param classVo vo的class对象 * @param request 存放form提交数据的request * @param keyName 某个不为null(可以是""空字符串)的关键字段,此字段的数组length决定注值vo的length * @return */ public static<T> List<T> populateVos(Class<T> classVo, HttpServletRequest request, String keyName) { return populateVos(classVo, request, keyName, ""); } /** * 针对多个vo,按出现的顺序循环注值 * * @param <T> vo泛型 * @param classVo vo的class对象 * @param request 存放form提交数据的request * @param keyName 某个不为null(可以是""空字符串)的关键字段,此字段的数组length决定注值vo的length * @param namespacePrefix 命名空间前缀,从request.getParameter取值时会加上namespacePrefix * @return */ @SuppressWarnings("unchecked") public static<T> List<T> populateVos(Class<T> classVo, HttpServletRequest request, String keyName, String namespacePrefix) { if(namespacePrefix == null) { namespacePrefix = ""; } keyName = namespacePrefix + keyName; List<T> lvo = new ArrayList<T>(); if(request.getParameterValues(keyName) == null) { return lvo; } int rm_record_length = request.getParameterValues(keyName).length; Set<String> sKey = request.getParameterMap().keySet(); Map<String, String>[] mps = new HashMap[rm_record_length]; for(int i=0; i<mps.length; i++) { mps[i] = new HashMap<String, String>(); } for(int i=0; i<rm_record_length; i++) { for(String key : sKey) { String[] values = request.getParameterValues(key); if(!key.startsWith(namespacePrefix)) { continue; } String shortKey = key.substring(namespacePrefix.length()); if(values != null && values.length > i) { mps[i].put(shortKey, values[i]); } } } for(int i=0; i<rm_record_length; i++) { try { T vo = classVo.newInstance(); populate(vo, mps[i], null, null, null, null); lvo.add(vo); } catch (Exception e) { log.warn("populateVos " + classVo.getName() + " " + e.toString()); } } return lvo; } }