/** * Creates a new branch in the tree and returns a builder of that branch. * @return a new builder instance for building the child */ public Builder branch() { if (fragments.isEmpty()) { fragments.add(new PathFragment(new NoopFilter())); } Builder child = new Builder(); child.parent = this; children.add(child); return child; }
/** * Appends the filters as query fragments determined by the last call to {@link #filter()} or {@link #path()}. * * <p>The filters is an array of arrays representing a new set of branches to be created at all the leaves of * the current query tree. * * @param filters the filters to append to the leaves of the query tree * @return this instance */ public SymmetricExtender with(Filter[][] filters) { onLeaves(this.filters, (builder) -> { for (Filter[] fs : filters) { builder.branch().with(queryFragmentSupplier.apply(fs)); } }); return this; }
/** * Proceeds the traversal to the next entities taking into account what parents the next entities should have. * * @param nextEntityType the type of the entities the new context will target * @param parentsType the type of the enum containing the possible parent types * @param currentParent the parent type representing the current position in the traversal * @param parents the parents to proceed to target entities over * @param hopBuilder the producer function that will convert the parent into a filter path to apply to the * traversal * @param <T> the type of the next entity * @param <P> the type of the enum of the possible parents of the target entity * @return a new traversal context */ <T extends Entity<?, ?>, P extends Enum<P> & Parents> TraversalContext<BE, T> proceedWithParents(Class<T> nextEntityType, Class<P> parentsType, P currentParent, P[] parents, BiConsumer<P, Query.SymmetricExtender> hopBuilder) { EnumSet<P> ps = ParentsUtil.convert(parentsType, currentParent, parents); TraversalContext.Builder<BE, E> bld = proceed(); for (P p : ps) { Query.Builder qb = bld.rawQueryBuilder(); qb = qb.branch(); Query.SymmetricExtender extender = qb.symmetricExtender(); hopBuilder.accept(p, extender); qb.done(); } return bld.getting(nextEntityType); }
/** * Builds the <b>whole</b> tree regardless of where in the tree the current builder "operates". * * @return the fully built tree */ public Query build() { Query.Builder root = this; while (true) { if (root.parent == null) { break; } root = root.parent; } root.done(); return root.tree; } }
public Builder with(Filter... filters) { with(converter, queryFragmentSupplier.apply(filters)); return this; }
public static Builder builder() { return new Query.Builder(); }
public Builder path() { queryFragmentSupplier = PathFragment::from; converter = PathFragment::new; if (isFilter != null && isFilter && !this.fragments.isEmpty()) { with(NoopFilter.INSTANCE); } isFilter = false; return this; }
/** * @return a new builder initialized to "contain" this query */ public Builder asBuilder() { Builder b = new Builder(); b.fragments = new ArrayList<>(Arrays.asList(fragments)); for (Query subTree : subTrees) { Builder childBuilder = subTree.asBuilder(); childBuilder.parent = b; b.children.add(childBuilder); } return b; }
/** * Appends the filters as query fragments determined by the last call to {@link #filter()} or {@link #path()}. * * @param filters the filters to append to the leaves of the query tree * @return this instance */ public SymmetricExtender with(Filter... filters) { onLeaves(this.filters, (t) -> t.with(queryFragmentSupplier.apply(filters))); return this; }
/** * Appends the provided query to the leaves of the current query tree, leaving the type of its fragments as they * originally were. * * @param other the query to append * @return this instance */ public SymmetricExtender withExact(Query other) { onLeaves(this.filters, (builder) -> builder.with(other)); return this; }
/** * @return the final query. */ public Query get() { return filters.build(); }
/** * Appends the provided query to the leaves of the current query tree, converting all its fragments to the * current fragment type (determined by the last call to {@link #filter()} or {@link #path()}). * * @param other the query to append * @return this instance */ public SymmetricExtender with(Query other) { onLeaves(this.filters, (builder) -> builder.with(other, converter)); return this; }
public Builder filter() { queryFragmentSupplier = FilterFragment::from; converter = FilterFragment::new; if (isFilter != null && !isFilter && this.fragments.isEmpty()) { with(NoopFilter.INSTANCE); } isFilter = true; return this; }