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.relation;
017
018import com.mybatisflex.core.query.QueryWrapper;
019import com.mybatisflex.core.row.Row;
020import com.mybatisflex.core.util.*;
021
022import java.lang.reflect.Field;
023import java.util.*;
024
025class ToManyRelation<SelfEntity> extends AbstractRelation<SelfEntity> {
026
027    protected String mapKeyField;
028    protected FieldWrapper mapKeyFieldWrapper;
029    protected String orderBy;
030    protected int limit = 0;
031
032
033    public ToManyRelation(String selfField, String targetSchema, String targetTable, String targetField,
034                          String joinTable, String joinSelfColumn, String joinTargetColumn,
035                          String dataSource, Class<SelfEntity> selfEntityClass, Field relationField,
036                          String extraCondition) {
037        super(selfField, targetSchema, targetTable, targetField,
038            joinTable, joinSelfColumn, joinTargetColumn,
039            dataSource, selfEntityClass, relationField,
040            extraCondition
041        );
042    }
043
044
045    @Override
046    public void customizeQueryWrapper(QueryWrapper queryWrapper) {
047        if (StringUtil.isNotBlank(orderBy)) {
048            queryWrapper.orderBy(orderBy);
049        }
050
051        if (limit > 0) {
052            queryWrapper.limit(limit);
053        }
054    }
055
056    @SuppressWarnings("rawtypes")
057    @Override
058    public void join(List<SelfEntity> selfEntities, List<?> targetObjectList, List<Row> mappingRows) {
059        selfEntities.forEach(selfEntity -> {
060            Object selfValue = selfFieldWrapper.get(selfEntity);
061            if (selfValue != null) {
062                selfValue = selfValue.toString();
063                Set<String> targetMappingValues = new HashSet<>();
064                if (mappingRows != null) {
065                    for (Row mappingRow : mappingRows) {
066                        if (selfValue.equals(String.valueOf(mappingRow.getIgnoreCase(joinSelfColumn)))) {
067                            Object joinValue = mappingRow.getIgnoreCase(joinTargetColumn);
068                            if (joinValue != null) {
069                                targetMappingValues.add(joinValue.toString());
070                            }
071                        }
072                    }
073                } else {
074                    targetMappingValues.add((String) selfValue);
075                }
076
077                if (targetMappingValues.isEmpty()) {
078                    return;
079                }
080
081                Class<?> fieldType = relationFieldWrapper.getFieldType();
082                //map
083                if (Map.class.isAssignableFrom(fieldType)) {
084                    Class<?> wrapType = getMapWrapType(fieldType);
085                    Map map = (Map) ClassUtil.newInstance(wrapType);
086                    for (Object targetObject : targetObjectList) {
087                        Object targetValue = targetFieldWrapper.get(targetObject);
088                        if (targetValue != null && targetMappingValues.contains(targetValue.toString())) {
089                            Object keyValue = mapKeyFieldWrapper.get(targetObject);
090                            Object needKeyValue = ConvertUtil.convert(keyValue, relationFieldWrapper.getKeyType());
091                            map.put(needKeyValue, targetObject);
092                        }
093                    }
094                    relationFieldWrapper.set(map, selfEntity);
095                }
096                //集合
097                else {
098                    Class<?> wrapType = MapperUtil.getCollectionWrapType(fieldType);
099                    Collection collection = (Collection) ClassUtil.newInstance(wrapType);
100                    for (Object targetObject : targetObjectList) {
101                        Object targetValue = targetFieldWrapper.get(targetObject);
102                        if (targetValue != null && targetMappingValues.contains(targetValue.toString())) {
103                            collection.add(targetObject);
104                        }
105                    }
106                    relationFieldWrapper.set(collection, selfEntity);
107                }
108            }
109        });
110    }
111
112    public void setMapKeyField(String mapKeyField) {
113        this.mapKeyField = mapKeyField;
114        if (StringUtil.isNotBlank(mapKeyField)) {
115            this.mapKeyFieldWrapper = FieldWrapper.of(targetEntityClass, mapKeyField);
116        }
117    }
118
119    public static Class<? extends Map> getMapWrapType(Class<?> type) {
120        if (ClassUtil.canInstance(type.getModifiers())) {
121            return (Class<? extends Map>) type;
122        }
123
124        return HashMap.class;
125    }
126
127}