001/**
002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (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 io.jboot.service;
017
018import com.jfinal.kit.StrKit;
019import com.jfinal.plugin.activerecord.Page;
020import com.jfinal.plugin.activerecord.Record;
021import io.jboot.db.JbootDb;
022import io.jboot.db.model.Columns;
023import io.jboot.db.model.JbootModel;
024import io.jboot.utils.ArrayUtil;
025import io.jboot.utils.ObjectFunc;
026import io.jboot.utils.StrUtil;
027
028import java.util.ArrayList;
029import java.util.List;
030
031
032public abstract class JbootServiceJoinerImpl implements JbootServiceJoiner {
033
034
035    @Override
036    public <M extends JbootModel> Page<M> join(Page<M> page, String columnName) {
037        join(page.getList(), columnName);
038        return page;
039    }
040
041    @Override
042    public <M extends JbootModel> Page<M> join(Page<M> page, String columnName, String[] attrs) {
043        join(page.getList(), columnName, attrs);
044        return page;
045    }
046
047
048    @Override
049    public <M extends JbootModel> Page<M> join(Page<M> page, String columnName, String joinName) {
050        join(page.getList(), columnName, joinName);
051        return page;
052    }
053
054
055    @Override
056    public <M extends JbootModel> Page<M> join(Page<M> page, String columnName, String joinName, String[] attrs) {
057        join(page.getList(), columnName, joinName, attrs);
058        return page;
059    }
060
061
062    @Override
063    public <M extends JbootModel> List<M> join(List<M> models, String columnName) {
064        if (ArrayUtil.isNotEmpty(models)) {
065            for (JbootModel m : models) {
066                join(m, columnName);
067            }
068        }
069        return models;
070    }
071
072
073    @Override
074    public <M extends JbootModel> List<M> join(List<M> models, String columnName, String[] attrs) {
075        if (ArrayUtil.isNotEmpty(models)) {
076            for (JbootModel m : models) {
077                join(m, columnName, attrs);
078            }
079        }
080        return models;
081    }
082
083
084    @Override
085    public <M extends JbootModel> List<M> join(List<M> models, String columnName, String joinName) {
086        if (ArrayUtil.isNotEmpty(models)) {
087            for (JbootModel m : models) {
088                join(m, columnName, joinName);
089            }
090        }
091        return models;
092    }
093
094
095    @Override
096    public <M extends JbootModel> List<M> join(List<M> models, String columnName, String joinName, String[] attrs) {
097        if (ArrayUtil.isNotEmpty(models)) {
098            for (JbootModel m : models) {
099                join(m, columnName, joinName, attrs);
100            }
101        }
102        return models;
103    }
104
105
106    /**
107     * 添加关联数据到某个model中去,避免关联查询,提高性能。
108     *
109     * @param model      要添加到的model
110     * @param columnName model对于的关联字段
111     */
112    @Override
113    public <M extends JbootModel> M join(M model, String columnName) {
114        return join(model, columnName, null, null);
115    }
116
117    /**
118     * 添加关联数据到某个model中去,避免关联查询,提高性能。
119     *
120     * @param model
121     * @param columnName
122     * @param attrs
123     */
124    @Override
125    public <M extends JbootModel> M join(M model, String columnName, String[] attrs) {
126        return join(model, columnName, null, attrs);
127    }
128
129
130    /**
131     * 添加关联数据到某个model中去,避免关联查询,提高性能。
132     *
133     * @param model
134     * @param columnName
135     * @param joinName
136     */
137    @Override
138    public <M extends JbootModel> M join(M model, String columnName, String joinName) {
139        return join(model, columnName, joinName, null);
140    }
141
142
143    /**
144     * 添加关联数据到某个model中去,避免关联查询,提高性能。
145     *
146     * @param model
147     * @param columnName
148     * @param joinName
149     * @param attrs
150     */
151    @Override
152    public <M extends JbootModel> M join(M model, String columnName, String joinName, String[] attrs) {
153        if (model == null) {
154            return null;
155        }
156        Object value = model.get(columnName);
157        if (value == null) {
158            return model;
159        }
160        JbootModel m = joinByValue(value, model);
161        if (m != null) {
162            joinName = StrUtil.isNotBlank(joinName) ? joinName : StrKit.firstCharToLowerCase(m.getClass().getSimpleName());
163            model.put(joinName, ArrayUtil.isNotEmpty(attrs) ? m.copy().keep(attrs) : m);
164        }
165        return model;
166    }
167
168
169    /**
170     * 可以让子类去复写 joinByColumnValue ,比如默认只 join 部分字段等,或者不是根据主键进行查询等
171     * 一般情况下,传入的 columnValue 是主键的值,但是也有可能不是,要看场景,如果不是的情况下可以通过 sourceModel 来进行判断
172     *
173     * @param columnValue
174     * @return
175     */
176    protected abstract JbootModel joinByValue(Object columnValue, JbootModel sourceModel);
177
178
179/////////////////joinMany start/////////////////////////////
180
181
182    @Override
183    public <M extends JbootModel> Page<M> joinMany(Page<M> page, String targetColumnName) {
184        joinMany(page.getList(), targetColumnName);
185        return page;
186    }
187
188    @Override
189    public <M extends JbootModel> Page<M> joinMany(Page<M> page, String targetColumnName, String[] attrs) {
190        joinMany(page.getList(), targetColumnName, attrs);
191        return page;
192    }
193
194
195    @Override
196    public <M extends JbootModel> Page<M> joinMany(Page<M> page, String targetColumnName, String joinName) {
197        joinMany(page.getList(), targetColumnName, joinName);
198        return page;
199    }
200
201
202    @Override
203    public <M extends JbootModel> Page<M> joinMany(Page<M> page, String targetColumnName, String joinName, String[] attrs) {
204        joinMany(page.getList(), targetColumnName, joinName, attrs);
205        return page;
206    }
207
208
209    @Override
210    public <M extends JbootModel> List<M> joinMany(List<M> models, String targetColumnName) {
211        if (ArrayUtil.isNotEmpty(models)) {
212            for (M m : models) {
213                joinMany(m, targetColumnName);
214            }
215        }
216        return models;
217    }
218
219
220    @Override
221    public <M extends JbootModel> List<M> joinMany(List<M> models, String targetColumnName, String[] attrs) {
222        if (ArrayUtil.isNotEmpty(models)) {
223            for (M m : models) {
224                joinMany(m, targetColumnName, attrs);
225            }
226        }
227        return models;
228    }
229
230
231    @Override
232    public <M extends JbootModel> List<M> joinMany(List<M> models, String targetColumnName, String joinName) {
233        if (ArrayUtil.isNotEmpty(models)) {
234            for (M m : models) {
235                joinMany(m, targetColumnName, joinName);
236            }
237        }
238        return models;
239    }
240
241
242    @Override
243    public <M extends JbootModel> List<M> joinMany(List<M> models, String targetColumnName, String joinName, String[] attrs) {
244        if (ArrayUtil.isNotEmpty(models)) {
245            for (M m : models) {
246                joinMany(m, targetColumnName, joinName, attrs);
247            }
248        }
249        return models;
250    }
251
252
253    @Override
254    public <M extends JbootModel> M joinMany(M model, String targetColumnName) {
255        return joinMany(model, null, targetColumnName, null, null);
256    }
257
258    @Override
259    public <M extends JbootModel> M joinMany(M model, String targetColumnName, String[] attrs) {
260        return joinMany(model, null, targetColumnName, null, attrs);
261    }
262
263    @Override
264    public <M extends JbootModel> M joinMany(M model, String targetColumnName, String joinName) {
265        return joinMany(model, null, targetColumnName, joinName, null);
266    }
267
268
269    @Override
270    public <M extends JbootModel> M joinMany(M model, String targetColumnName, String joinName, String[] attrs) {
271        return joinMany(model, null, targetColumnName, joinName, attrs);
272    }
273
274
275    @Override
276    public <M extends JbootModel> Page<M> joinMany(Page<M> page, ObjectFunc<M> modelValueGetter, String targetColumnName) {
277        joinMany(page.getList(), modelValueGetter, targetColumnName);
278        return page;
279    }
280
281    @Override
282    public <M extends JbootModel> Page<M> joinMany(Page<M> page, ObjectFunc<M> modelValueGetter, String targetColumnName, String[] attrs) {
283        joinMany(page.getList(), modelValueGetter, targetColumnName, attrs);
284        return page;
285    }
286
287
288    @Override
289    public <M extends JbootModel> Page<M> joinMany(Page<M> page, ObjectFunc<M> modelValueGetter, String targetColumnName, String joinName) {
290        joinMany(page.getList(), modelValueGetter, targetColumnName, joinName);
291        return page;
292    }
293
294
295    @Override
296    public <M extends JbootModel> Page<M> joinMany(Page<M> page, ObjectFunc<M> modelValueGetter, String targetColumnName, String joinName, String[] attrs) {
297        joinMany(page.getList(), modelValueGetter, targetColumnName, joinName, attrs);
298        return page;
299    }
300
301
302    @Override
303    public <M extends JbootModel> List<M> joinMany(List<M> models, ObjectFunc<M> modelValueGetter, String targetColumnName) {
304        if (ArrayUtil.isNotEmpty(models)) {
305            for (M m : models) {
306                joinMany(m, modelValueGetter, targetColumnName);
307            }
308        }
309        return models;
310    }
311
312
313    @Override
314    public <M extends JbootModel> List<M> joinMany(List<M> models, ObjectFunc<M> modelValueGetter, String targetColumnName, String[] attrs) {
315        if (ArrayUtil.isNotEmpty(models)) {
316            for (M m : models) {
317                joinMany(m, modelValueGetter, targetColumnName, attrs);
318            }
319        }
320        return models;
321    }
322
323
324    @Override
325    public <M extends JbootModel> List<M> joinMany(List<M> models, ObjectFunc<M> modelValueGetter, String targetColumnName, String joinName) {
326        if (ArrayUtil.isNotEmpty(models)) {
327            for (M m : models) {
328                joinMany(m, modelValueGetter, targetColumnName, joinName);
329            }
330        }
331        return models;
332    }
333
334
335    @Override
336    public <M extends JbootModel> List<M> joinMany(List<M> models, ObjectFunc<M> modelValueGetter, String targetColumnName, String joinName, String[] attrs) {
337        if (ArrayUtil.isNotEmpty(models)) {
338            for (M m : models) {
339                joinMany(m, modelValueGetter, targetColumnName, joinName, attrs);
340            }
341        }
342        return models;
343    }
344
345
346    @Override
347    public <M extends JbootModel> M joinMany(M model, ObjectFunc<M> modelValueGetter, String targetColumnName) {
348        return joinMany(model, modelValueGetter, targetColumnName, null, null);
349    }
350
351    @Override
352    public <M extends JbootModel> M joinMany(M model, ObjectFunc<M> modelValueGetter, String targetColumnName, String[] attrs) {
353        return joinMany(model, modelValueGetter, targetColumnName, null, attrs);
354    }
355
356
357    @Override
358    public <M extends JbootModel> M joinMany(M model, ObjectFunc<M> modelValueGetter, String targetColumnName, String joinName) {
359        return joinMany(model, modelValueGetter, targetColumnName, joinName, null);
360    }
361
362
363    @Override
364    public <M extends JbootModel> M joinMany(M model, ObjectFunc<M> modelValueGetter, String targetColumnName, String joinName, String[] attrs) {
365        if (model == null) {
366            return null;
367        }
368        Object value = modelValueGetter != null ? modelValueGetter.get(model) : model._getIdValue();
369        if (value == null) {
370            return model;
371        }
372
373        List<M> list = joinManyByValue(targetColumnName, value, model);
374        if (list != null && !list.isEmpty()) {
375            joinName = StrUtil.isNotBlank(joinName) ? joinName : StrKit.firstCharToLowerCase(list.get(0).getClass().getSimpleName()) + "List";
376            model.put(joinName, ArrayUtil.isNotEmpty(attrs) ? keepModelListAttrs(list, attrs) : list);
377        }
378
379        return model;
380    }
381
382
383    protected <M extends JbootModel> List<M> keepModelListAttrs(List<M> list, String[] attrs) {
384        if (list == null || list.isEmpty()) {
385            return null;
386        }
387        List<M> retList = new ArrayList<>(list.size());
388        for (M model : list) {
389            retList.add((M) model.copy().keep(attrs));
390        }
391        return retList;
392    }
393
394
395    protected abstract <M extends JbootModel> List<M> joinManyByValue(String columnName, Object value, M sourceModel);
396
397
398/////////////////joinMany end/////////////////////////////
399
400
401/////////////////joinManyByTable start/////////////////////////////
402
403    @Override
404    public <M extends JbootModel> Page<M> joinManyByTable(Page<M> page, String tableName, String columnName, String targetColumnName) {
405        joinManyByTable(page.getList(), tableName, columnName, targetColumnName);
406        return page;
407    }
408
409    @Override
410    public <M extends JbootModel> Page<M> joinManyByTable(Page<M> page, String tableName, String columnName, String targetColumnName, String[] attrs) {
411        joinManyByTable(page.getList(), tableName, columnName, targetColumnName, attrs);
412        return page;
413    }
414
415    @Override
416    public <M extends JbootModel> Page<M> joinManyByTable(Page<M> page, String tableName, String columnName, String targetColumnName, String joinName) {
417        joinManyByTable(page.getList(), tableName, columnName, targetColumnName, joinName);
418        return page;
419    }
420
421
422    @Override
423    public <M extends JbootModel> Page<M> joinManyByTable(Page<M> page, String tableName, String columnName, String targetColumnName, String joinName, String[] attrs) {
424        joinManyByTable(page.getList(), tableName, columnName, targetColumnName, joinName, attrs);
425        return page;
426    }
427
428
429    @Override
430    public <M extends JbootModel> List<M> joinManyByTable(List<M> models, String tableName, String columnName, String targetColumnName) {
431        if (ArrayUtil.isNotEmpty(models)) {
432            for (M m : models) {
433                joinManyByTable(m, tableName, columnName, targetColumnName);
434            }
435        }
436        return models;
437    }
438
439    @Override
440    public <M extends JbootModel> List<M> joinManyByTable(List<M> models, String tableName, String columnName, String targetColumnName, String[] attrs) {
441        if (ArrayUtil.isNotEmpty(models)) {
442            for (M m : models) {
443                joinManyByTable(m, tableName, columnName, targetColumnName, attrs);
444            }
445        }
446        return models;
447    }
448
449    @Override
450    public <M extends JbootModel> List<M> joinManyByTable(List<M> models, String tableName, String columnName, String targetColumnName, String joinName) {
451        if (ArrayUtil.isNotEmpty(models)) {
452            for (M m : models) {
453                joinManyByTable(m, tableName, columnName, targetColumnName, joinName);
454            }
455        }
456        return models;
457    }
458
459
460    @Override
461    public <M extends JbootModel> List<M> joinManyByTable(List<M> models, String tableName, String columnName, String targetColumnName, String joinName, String[] attrs) {
462        if (ArrayUtil.isNotEmpty(models)) {
463            for (M m : models) {
464                joinManyByTable(m, tableName, columnName, targetColumnName, joinName, attrs);
465            }
466        }
467        return models;
468    }
469
470
471    @Override
472    public <M extends JbootModel> M joinManyByTable(M model, String tableName, String columnName, String targetColumnName) {
473        return joinManyByTable(model, tableName, columnName, targetColumnName, null, null);
474    }
475
476    @Override
477    public <M extends JbootModel> M joinManyByTable(M model, String tableName, String columnName, String targetColumnName, String[] attrs) {
478        return joinManyByTable(model, tableName, columnName, targetColumnName, null, attrs);
479    }
480
481    @Override
482    public <M extends JbootModel> M joinManyByTable(M model, String tableName, String columnName, String targetColumnName, String joinName) {
483        return joinManyByTable(model, tableName, columnName, targetColumnName, joinName, null);
484    }
485
486    @Override
487    public <M extends JbootModel> M joinManyByTable(M model, String tableName, String columnName, String targetColumnName, String joinName, String[] attrs) {
488        return joinManyByTable(model, null, tableName, columnName, targetColumnName, joinName, attrs);
489    }
490
491
492    @Override
493    public <M extends JbootModel> Page<M> joinManyByTable(Page<M> page, ObjectFunc<M> modelValueGetter, String tableName, String columnName, String targetColumnName) {
494        joinManyByTable(page.getList(), modelValueGetter, tableName, columnName, targetColumnName);
495        return page;
496    }
497
498    @Override
499    public <M extends JbootModel> Page<M> joinManyByTable(Page<M> page, ObjectFunc<M> modelValueGetter, String tableName, String columnName, String targetColumnName, String[] attrs) {
500        joinManyByTable(page.getList(), modelValueGetter, tableName, columnName, targetColumnName, attrs);
501        return page;
502    }
503
504    @Override
505    public <M extends JbootModel> Page<M> joinManyByTable(Page<M> page, ObjectFunc<M> modelValueGetter, String tableName, String columnName, String targetColumnName, String joinName) {
506        joinManyByTable(page.getList(), modelValueGetter, tableName, columnName, targetColumnName, joinName);
507        return page;
508    }
509
510
511    @Override
512    public <M extends JbootModel> Page<M> joinManyByTable(Page<M> page, ObjectFunc<M> modelValueGetter, String tableName, String columnName, String targetColumnName, String joinName, String[] attrs) {
513        joinManyByTable(page.getList(), modelValueGetter, tableName, columnName, targetColumnName, joinName, attrs);
514        return page;
515    }
516
517
518    @Override
519    public <M extends JbootModel> List<M> joinManyByTable(List<M> models, ObjectFunc<M> modelValueGetter, String tableName, String columnName, String targetColumnName) {
520        if (ArrayUtil.isNotEmpty(models)) {
521            for (M m : models) {
522                joinManyByTable(m, modelValueGetter, tableName, columnName, targetColumnName);
523            }
524        }
525        return models;
526    }
527
528    @Override
529    public <M extends JbootModel> List<M> joinManyByTable(List<M> models, ObjectFunc<M> modelValueGetter, String tableName, String columnName, String targetColumnName, String[] attrs) {
530        if (ArrayUtil.isNotEmpty(models)) {
531            for (M m : models) {
532                joinManyByTable(m, modelValueGetter, tableName, columnName, targetColumnName, attrs);
533            }
534        }
535        return models;
536    }
537
538    @Override
539    public <M extends JbootModel> List<M> joinManyByTable(List<M> models, ObjectFunc<M> modelValueGetter, String tableName, String columnName, String targetColumnName, String joinName) {
540        if (ArrayUtil.isNotEmpty(models)) {
541            for (M m : models) {
542                joinManyByTable(m, modelValueGetter, tableName, columnName, targetColumnName, joinName);
543            }
544        }
545        return models;
546    }
547
548
549    @Override
550    public <M extends JbootModel> List<M> joinManyByTable(List<M> models, ObjectFunc<M> modelValueGetter, String tableName, String columnName, String targetColumnName, String joinName, String[] attrs) {
551        if (ArrayUtil.isNotEmpty(models)) {
552            for (M m : models) {
553                joinManyByTable(m, modelValueGetter, tableName, columnName, targetColumnName, joinName, attrs);
554            }
555        }
556        return models;
557    }
558
559
560    @Override
561    public <M extends JbootModel> M joinManyByTable(M model, ObjectFunc<M> modelValueGetter, String tableName, String columnName, String targetColumnName) {
562        return joinManyByTable(model, modelValueGetter, tableName, columnName, targetColumnName, null, null);
563    }
564
565    @Override
566    public <M extends JbootModel> M joinManyByTable(M model, ObjectFunc<M> modelValueGetter, String tableName, String columnName, String targetColumnName, String[] attrs) {
567        return joinManyByTable(model, modelValueGetter, tableName, columnName, targetColumnName, null, attrs);
568    }
569
570    @Override
571    public <M extends JbootModel> M joinManyByTable(M model, ObjectFunc<M> modelValueGetter, String tableName, String columnName, String targetColumnName, String joinName) {
572        return joinManyByTable(model, modelValueGetter, tableName, columnName, targetColumnName, joinName, null);
573    }
574
575    @Override
576    public <M extends JbootModel> M joinManyByTable(M model, ObjectFunc<M> modelValueGetter, String tableName, String columnName, String targetColumnName, String joinName, String[] attrs) {
577        if (model == null) {
578            return null;
579        }
580
581        Object columnValue = modelValueGetter != null ? modelValueGetter.get(model) : model._getIdValue();
582        if (columnValue == null) {
583            return model;
584        }
585
586        List<Record> middleTableRecords = findMiddleTableRecords(tableName, columnName, columnValue);
587        if (middleTableRecords == null || middleTableRecords.isEmpty()) {
588            return model;
589        }
590
591        List<M> list = new ArrayList();
592        for (Record record : middleTableRecords) {
593            Object targetTableValue = record.get(targetColumnName);
594            if (targetTableValue != null) {
595                M data = (M) joinByValue(targetTableValue, model);
596                if (data != null) {
597                    list.add(data);
598                }
599            }
600        }
601
602        if (!list.isEmpty()) {
603            joinName = StrUtil.isNotBlank(joinName) ? joinName : StrKit.firstCharToLowerCase(list.get(0).getClass().getSimpleName()) + "List";
604            model.put(joinName, ArrayUtil.isNotEmpty(attrs) ? keepModelListAttrs(list, attrs) : list);
605        }
606
607        return model;
608    }
609
610
611    /**
612     * 查询中间表数据,方便子类复写,比如:通过缓存获取等
613     * @param tableName
614     * @param columnName
615     * @param columnValue
616     * @return
617     */
618    protected List<Record> findMiddleTableRecords(String tableName, String columnName, Object columnValue) {
619        return JbootDb.find(tableName, Columns.create(columnName, columnValue));
620    }
621
622
623/////////////////joinManyByTable end/////////////////////////////
624
625}