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