001/** 002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core.row; 017 018import com.mybatisflex.core.table.TableInfo; 019import com.mybatisflex.core.table.TableInfoFactory; 020import com.mybatisflex.core.util.ClassUtil; 021import com.mybatisflex.core.util.ConvertUtil; 022import com.mybatisflex.core.util.StringUtil; 023import org.apache.ibatis.util.MapUtil; 024 025import java.lang.reflect.Method; 026import java.lang.reflect.Modifier; 027import java.util.*; 028import java.util.concurrent.ConcurrentHashMap; 029 030public class RowUtil { 031 032 private static final Map<Class<?>, Map<String, Method>> classGettersMapping = new ConcurrentHashMap<>(); 033 034 public static <T> T toObject(Row row, Class<T> objectClass) { 035 T instance = ClassUtil.newInstance(objectClass); 036 Map<String, Method> setterMethods = getSetterMethods(objectClass); 037 row.forEach((column, columnValue) -> { 038 Method setter = setterMethods.get(column.toLowerCase()); 039 try { 040 if (setter != null) { 041 Object value = ConvertUtil.convert(columnValue, setter.getParameterTypes()[0]); 042 setter.invoke(instance, value); 043 } 044 } catch (Exception e) { 045 throw new RuntimeException("Can not invoke method: " + setter); 046 } 047 }); 048 return instance; 049 } 050 051 052 public static <T> List<T> toObjectList(List<Row> rows, Class<T> objectClass) { 053 if (rows == null || rows.isEmpty()) { 054 return Collections.emptyList(); 055 } else { 056 List<T> objectList = new ArrayList<>(); 057 for (Row row : rows) { 058 objectList.add(toObject(row, objectClass)); 059 } 060 return objectList; 061 } 062 } 063 064 065 public static <T> T toEntity(Row row, Class<T> entityClass) { 066 TableInfo tableInfo = TableInfoFactory.ofEntityClass(entityClass); 067 return tableInfo.newInstanceByRow(row); 068 } 069 070 071 public static <T> List<T> toEntityList(List<Row> rows, Class<T> entityClass) { 072 if (rows == null || rows.isEmpty()) { 073 return Collections.emptyList(); 074 } else { 075 TableInfo tableInfo = TableInfoFactory.ofEntityClass(entityClass); 076 List<T> entityList = new ArrayList<>(); 077 for (Row row : rows) { 078 T entity = tableInfo.newInstanceByRow(row); 079 entityList.add(entity); 080 } 081 return entityList; 082 } 083 } 084 085 086 public static void registerMapping(Class<?> clazz, Map<String, Method> columnSetterMapping) { 087 classGettersMapping.put(clazz, columnSetterMapping); 088 } 089 090 091 private static Map<String, Method> getSetterMethods(Class<?> aClass) { 092 return MapUtil.computeIfAbsent(classGettersMapping, aClass, aClass1 -> { 093 Map<String, Method> columnSetterMapping = new HashMap<>(); 094 List<Method> setters = ClassUtil.getAllMethods(aClass1, 095 method -> method.getName().startsWith("set") 096 && method.getParameterCount() == 1 097 && Modifier.isPublic(method.getModifiers()) 098 ); 099 for (Method setter : setters) { 100 String column = setter.getName().substring(3); 101 columnSetterMapping.put(column.toLowerCase(), setter); 102 columnSetterMapping.put(StringUtil.camelToUnderline(column).toLowerCase(), setter); 103 columnSetterMapping.put(StringUtil.underlineToCamel(column).toUpperCase(), setter); 104 } 105 return columnSetterMapping; 106 }); 107 } 108}