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.util;
017
018import com.mybatisflex.core.javassist.ModifyAttrsRecordProxyFactory;
019import com.mybatisflex.core.table.IdInfo;
020import com.mybatisflex.core.table.TableInfo;
021import com.mybatisflex.core.table.TableInfoFactory;
022import org.apache.ibatis.reflection.DefaultReflectorFactory;
023import org.apache.ibatis.reflection.Reflector;
024import org.apache.ibatis.reflection.ReflectorFactory;
025import org.apache.ibatis.reflection.invoker.Invoker;
026
027import java.lang.reflect.Array;
028import java.util.List;
029
030public class UpdateEntity {
031
032    private UpdateEntity() {}
033
034    private static final ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
035
036
037    public static <T> T of(Class<T> clazz) {
038        return ModifyAttrsRecordProxyFactory.getInstance().get(clazz);
039    }
040
041
042    public static <T> T of(Class<T> clazz, Object id) {
043        T newEntity = ModifyAttrsRecordProxyFactory.getInstance().get(clazz);
044        TableInfo tableInfo = TableInfoFactory.ofEntityClass(clazz);
045        List<IdInfo> primaryKeyList = tableInfo.getPrimaryKeyList();
046        Reflector reflector = reflectorFactory.findForClass(clazz);
047
048        if (primaryKeyList != null && !primaryKeyList.isEmpty()) {
049            for (int i = 0; i < primaryKeyList.size(); i++) {
050                IdInfo idInfo = primaryKeyList.get(i);
051                Object idValue = getIdValue(id, i);
052                Invoker setInvoker = reflector.getSetInvoker(idInfo.getProperty());
053                try {
054                    setInvoker.invoke(newEntity, new Object[]{ConvertUtil.convert(idValue, idInfo.getPropertyType())});
055                } catch (Exception e) {
056                    throw new RuntimeException(e.getMessage(), e);
057                }
058            }
059        }
060        return newEntity;
061    }
062
063
064    private static Object getIdValue(Object id, int index) {
065        if (id == null) {
066            return null;
067        }
068        if (ClassUtil.isArray(id.getClass())) {
069            if (index >= Array.getLength(id)) {
070                return null;
071            } else {
072                return Array.get(id, index);
073            }
074        }
075        //not array
076        return index == 0 ? id : null;
077    }
078
079
080    public static <T> T ofNotNull(T entity) {
081        Class<?> usefulClass = ClassUtil.getUsefulClass(entity.getClass());
082
083        T newEntity = (T) of(usefulClass);
084
085        Reflector reflector = reflectorFactory.findForClass(usefulClass);
086        String[] propertyNames = reflector.getGetablePropertyNames();
087
088        for (String propertyName : propertyNames) {
089            try {
090                Object value = reflector.getGetInvoker(propertyName)
091                        .invoke(entity, null);
092                if (value != null) {
093                    reflector.getSetInvoker(propertyName).invoke(newEntity, new Object[]{value});
094                }
095            } catch (Exception e) {
096                //ignore;
097            }
098        }
099
100        return newEntity;
101    }
102
103
104}