class Joiner {
            private final List<Term> terms;

            private final List<Term> joinTerms = new ArrayList<>();

            public Joiner(List<Term> terms) {
                this.terms = terms;
                prepare(terms);
            }

            public void prepare(List<Term> terms) {<FILL_FUNCTION_BODY>}


            private Function<Flux<R>, Flux<R>> buildHandler(JoinConditionalSpecImpl join,
                                                            ColumnMapping.All<R, ?> mapping) {
                if (joinTerms.size() == 1) {
                    return buildBatchHandler(join, mapping);
                }
                return flux -> flux
                    .flatMap(data -> {
                        QueryParamEntity param = new QueryParamEntity();
                        param.setTerms(refactorTerms(data));
                        return parent
                            .select(join.mainClassSafe())
                            .all(join.mainClass)
                            .from(join.mainClass)
                            .where(param.noPaging())
                            .fetch()
                            .collectList()
                            .map(list -> FastBeanCopier.copy(Collections.singletonMap(mapping.targetProperty, list), data));
                    }, 16);
            }

            private List<Term> refactorTerms(R main) {
                return refactorTerms(terms.stream().map(Term::clone).collect(Collectors.toList()), main);
            }

            private List<Term> refactorTerms(List<Term> terms, R main) {
                for (Term term : terms) {
                    refactorTerms(main, term);
                    if (CollectionUtils.isNotEmpty(term.getTerms())) {
                        refactorTerms(term.getTerms(), main);
                    }
                }
                return terms;
            }

            private void refactorTerms(R main, Term term) {
                if (term.getValue() instanceof JoinConditionalSpecImpl.ColumnRef) {
                    JoinConditionalSpecImpl.ColumnRef ref = (JoinConditionalSpecImpl.ColumnRef) term.getValue();
                    String mainProperty = ref.getColumn().getAlias();

                    Object value = FastBeanCopier.getProperty(main, mainProperty);
                    if (value == null) {
                        term.setTermType(TermType.isnull);
                        term.setValue(1);
                    } else {
                        term.setValue(value);
                    }
                }
            }

            private Function<Flux<R>, Flux<R>> buildBatchHandler(JoinConditionalSpecImpl join,
                                                                 ColumnMapping.All<R, ?> mapping) {
                Term term = joinTerms.get(0);
                JoinConditionalSpecImpl.ColumnRef ref = (JoinConditionalSpecImpl.ColumnRef) term.getValue();

                String joinProperty = term.getColumn();
                String mainProperty = ref.getColumn().getAlias();

                return flux -> QueryHelper
                    .combineOneToMany(
                        flux,
                        t -> FastBeanCopier.getProperty(t, mainProperty),
                        idList -> {
                            term.setColumn(joinProperty);
                            term.setTermType(TermType.in);
                            term.setValue(idList);

                            QueryParamEntity param = new QueryParamEntity();
                            param.setTerms(terms);
                            return parent
                                .select(join.mainClassSafe())
                                .all(join.mainClass)
                                .from(join.mainClass)
                                .where(param.noPaging())
                                .fetch();
                        },
                        r -> FastBeanCopier.getProperty(r, joinProperty),
                        (t, list) -> FastBeanCopier.copy(Collections.singletonMap(mapping.targetProperty, list), t)
                    );
            }

        }

                for (Term term : terms) {
                    if (Objects.equals(TermType.eq, term.getTermType())
                        && term.getValue() instanceof JoinConditionalSpecImpl.ColumnRef) {
                        joinTerms.add(term);
                    }
                    if (term.getTerms() != null) {
                        prepare(term.getTerms());
                    }
                }
            
<no_super_class>