| /*- |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.sling.query; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.function.Function; |
| import java.util.function.Predicate; |
| import java.util.stream.Stream; |
| import java.util.stream.StreamSupport; |
| |
| import org.apache.sling.query.api.SearchStrategy; |
| import org.apache.sling.query.api.internal.IteratorToIteratorFunction; |
| import org.apache.sling.query.api.internal.Option; |
| import org.apache.sling.query.api.internal.TreeProvider; |
| import org.apache.sling.query.impl.function.AddFunction; |
| import org.apache.sling.query.impl.function.ChildrenFunction; |
| import org.apache.sling.query.impl.function.ClosestFunction; |
| import org.apache.sling.query.impl.function.CompositeFunction; |
| import org.apache.sling.query.impl.function.DescendantFunction; |
| import org.apache.sling.query.impl.function.FilterFunction; |
| import org.apache.sling.query.impl.function.FindFunction; |
| import org.apache.sling.query.impl.function.HasFunction; |
| import org.apache.sling.query.impl.function.IdentityFunction; |
| import org.apache.sling.query.impl.function.LastFunction; |
| import org.apache.sling.query.impl.function.NextFunction; |
| import org.apache.sling.query.impl.function.NotFunction; |
| import org.apache.sling.query.impl.function.ParentFunction; |
| import org.apache.sling.query.impl.function.ParentsFunction; |
| import org.apache.sling.query.impl.function.PrevFunction; |
| import org.apache.sling.query.impl.function.SiblingsFunction; |
| import org.apache.sling.query.impl.function.SliceFunction; |
| import org.apache.sling.query.impl.function.UniqueFunction; |
| import org.apache.sling.query.impl.iterator.EmptyElementFilter; |
| import org.apache.sling.query.impl.iterator.OptionDecoratingIterator; |
| import org.apache.sling.query.impl.iterator.OptionStrippingIterator; |
| import org.apache.sling.query.impl.predicate.IterableContainsPredicate; |
| import org.apache.sling.query.impl.predicate.RejectingPredicate; |
| import org.apache.sling.query.impl.selector.SelectorFunction; |
| import org.apache.sling.query.impl.util.LazyList; |
| import org.osgi.annotation.versioning.ProviderType; |
| |
| @ProviderType |
| public abstract class AbstractQuery<T, Q extends AbstractQuery<T, Q>> implements Iterable<T> { |
| |
| protected final List<Function<?, ?>> functions = new ArrayList<>(); |
| |
| private final List<T> initialCollection; |
| |
| private final SearchStrategy searchStrategy; |
| |
| private final TreeProvider<T> provider; |
| |
| AbstractQuery(TreeProvider<T> provider, T[] initialCollection, SearchStrategy strategy) { |
| this.provider = provider; |
| this.initialCollection = new ArrayList<>(Arrays.asList(initialCollection)); |
| this.searchStrategy = strategy; |
| } |
| |
| protected AbstractQuery(AbstractQuery<T, Q> original, SearchStrategy searchStrategy) { |
| this.functions.addAll(original.functions); |
| this.initialCollection = new ArrayList<>(original.initialCollection); |
| this.searchStrategy = searchStrategy; |
| this.provider = original.provider; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Iterator<T> iterator() { |
| IteratorToIteratorFunction<T> f = new CompositeFunction<>(functions); |
| Iterator<Option<T>> iterator = f.apply(new OptionDecoratingIterator<>(initialCollection.iterator())); |
| iterator = new EmptyElementFilter<>(iterator); |
| return new OptionStrippingIterator<>(iterator); |
| } |
| |
| public Stream<T> stream() { |
| return StreamSupport.stream(this.spliterator(), false); |
| } |
| |
| /** |
| * Include resources to the collection. |
| * |
| * @param resources |
| * Resources to include |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q add(T... resources) { |
| return function(new AddFunction<>(Arrays.asList(resources))); |
| } |
| |
| /** |
| * Include resources to the collection. |
| * |
| * @param iterable |
| * Resources to include |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q add(Iterable<T> iterable) { |
| return function(new AddFunction<>(iterable)); |
| } |
| |
| /** |
| * Transform SlingQuery collection into a lazy list. |
| * |
| * @return List containing all elements from the collection. |
| */ |
| public List<T> asList() { |
| return new LazyList<>(iterator()); |
| } |
| |
| /** |
| * Get list of the children for each Resource in the collection. |
| * |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q children() { |
| return function(new ChildrenFunction<>(provider)); |
| } |
| |
| /** |
| * Get list of the children for each Resource in the collection. |
| * |
| * @param filter |
| * Children filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q children(String filter) { |
| return function(new ChildrenFunction<>(provider), filter); |
| } |
| |
| /** |
| * Get list of the children for each Resource in the collection. |
| * |
| * @param filter |
| * Children filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q children(Predicate<T> filter) { |
| return function(new ChildrenFunction<>(provider), filter); |
| } |
| |
| /** |
| * Get list of the children for each Resource in the collection. |
| * |
| * @param filter |
| * Children filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q children(Iterable<T> filter) { |
| return function(new ChildrenFunction<>(provider), filter); |
| } |
| |
| /** |
| * For each Resource in the collection, return the first element matching the |
| * selector testing the Resource itself and traversing up its ancestors. |
| * |
| * @param selector |
| * Ancestor filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q closest(String selector) { |
| return closest(parse(selector)); |
| } |
| |
| /** |
| * For each Resource in the collection, return the first element matching the |
| * selector testing the Resource itself and traversing up its ancestors. |
| * |
| * @param iterable |
| * Ancestor filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q closest(Iterable<T> iterable) { |
| return closest(new IterableContainsPredicate<>(iterable, provider)); |
| } |
| |
| /** |
| * For each Resource in the collection, return the first element matching the |
| * selector testing the Resource itself and traversing up its ancestors. |
| * |
| * @param predicate |
| * Ancestor filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q closest(Predicate<T> predicate) { |
| return function(new ClosestFunction<>(predicate, provider)); |
| } |
| |
| /** |
| * Reduce Resource collection to the one Resource at the given 0-based index. |
| * |
| * @param index |
| * 0-based index |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q eq(int index) { |
| return slice(index, index); |
| } |
| |
| /** |
| * Filter Resource collection using given selector. |
| * |
| * @param selector |
| * Selector |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q filter(String selector) { |
| return function(new IdentityFunction<T>(), selector); |
| } |
| |
| /** |
| * Filter Resource collection using given predicate object. |
| * |
| * @param predicate |
| * Collection filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q filter(Predicate<T> predicate) { |
| return function(new FilterFunction<>(predicate)); |
| } |
| |
| /** |
| * Filter Resource collection using given iterable. |
| * |
| * @param iterable |
| * Collection filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q filter(Iterable<T> iterable) { |
| return function(new FilterFunction<>(new IterableContainsPredicate<>(iterable, provider))); |
| } |
| |
| /** |
| * For each Resource in collection use depth-first search to return all its |
| * descendants. Please notice that invoking this method on a Resource being a |
| * root of a large subtree may and will cause performance problems. |
| * |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q find() { |
| return function(new FindFunction<>(searchStrategy, provider, "")); |
| } |
| |
| /** |
| * For each Resource in collection use breadth-first search to return all its |
| * descendants. Please notice that invoking this method on a Resource being a |
| * root of a large subtree may and will cause performance problems. |
| * |
| * @param selector |
| * descendants filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q find(String selector) { |
| return function(new FindFunction<>(searchStrategy, provider, selector), selector); |
| } |
| |
| /** |
| * For each Resource in collection use breadth-first search to return all its |
| * descendants. Please notice that invoking this method on a Resource being a |
| * root of a large subtree may and will cause performance problems. |
| * |
| * @param predicate |
| * descendants filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q find(Predicate<T> predicate) { |
| return function(new FindFunction<>(searchStrategy, provider, ""), predicate); |
| } |
| |
| /** |
| * For each Resource in collection use breadth-first search to return all its |
| * descendants. Please notice that invoking this method on a Resource being a |
| * root of a large subtree may and will cause performance problems. |
| * |
| * @param iterable |
| * descendants filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q find(Iterable<T> iterable) { |
| return function(new DescendantFunction<>(new LazyList<>(iterable.iterator()), provider)); |
| } |
| |
| /** |
| * Filter Resource collection to the first element. Equivalent to {@code eq(0)} |
| * or {@code slice(0, 0)}. |
| * |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q first() { |
| return eq(0); |
| } |
| |
| /** |
| * Pick such Resources from the collection that have descendant matching the |
| * selector. |
| * |
| * @param selector |
| * Descendant selector |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q has(String selector) { |
| return function(new HasFunction<>(selector, searchStrategy, provider)); |
| } |
| |
| /** |
| * Pick such Resources from the collection that have descendant matching the |
| * selector. |
| * |
| * @param predicate |
| * Descendant selector |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q has(Predicate<T> predicate) { |
| return function(new HasFunction<>(predicate, searchStrategy, provider)); |
| } |
| |
| /** |
| * Pick such Resources from the collection that have descendant matching the |
| * selector. |
| * |
| * @param iterable |
| * Descendant selector |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q has(Iterable<T> iterable) { |
| return function(new HasFunction<>(iterable, provider)); |
| } |
| |
| /** |
| * Filter Resource collection to the last element. |
| * |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q last() { |
| return function(new LastFunction<T>()); |
| } |
| |
| /** |
| * Return the next sibling for each Resource in the collection. |
| * |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q next() { |
| return function(new NextFunction<>(provider)); |
| } |
| |
| /** |
| * Return the next sibling for each Resource in the collection and filter it by |
| * a selector. If the next sibling doesn't match it, empty collection will be |
| * returned. |
| * |
| * @param selector |
| * Next sibling filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q next(String selector) { |
| return function(new NextFunction<>(provider), selector); |
| } |
| |
| /** |
| * Return the next sibling for each Resource in the collection and filter it by |
| * a selector. If the next sibling doesn't match it, empty collection will be |
| * returned. |
| * |
| * @param predicate |
| * Next sibling filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q next(Predicate<T> predicate) { |
| return function(new NextFunction<>(provider), predicate); |
| } |
| |
| /** |
| * Return the next sibling for each Resource in the collection and filter it by |
| * a selector. If the next sibling doesn't match it, empty collection will be |
| * returned. |
| * |
| * @param iterable |
| * Next sibling filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q next(Iterable<T> iterable) { |
| return function(new NextFunction<>(provider), iterable); |
| } |
| |
| /** |
| * Return all following siblings for each Resource in the collection. |
| * |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q nextAll() { |
| return function(new NextFunction<>(new RejectingPredicate<>(), provider)); |
| } |
| |
| /** |
| * Return all following siblings for each Resource in the collection, filtering |
| * them by a selector. |
| * |
| * @param selector |
| * Following siblings filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q nextAll(String selector) { |
| return function(new NextFunction<>(new RejectingPredicate<>(), provider), selector); |
| } |
| |
| /** |
| * Return all following siblings for each Resource in the collection, filtering |
| * them by a selector. |
| * |
| * @param predicate |
| * Following siblings filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q nextAll(Predicate<T> predicate) { |
| return function(new NextFunction<>(new RejectingPredicate<>(), provider), predicate); |
| } |
| |
| /** |
| * Return all following siblings for each Resource in the collection, filtering |
| * them by a selector. |
| * |
| * @param iterable |
| * Following siblings filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q nextAll(Iterable<T> iterable) { |
| return function(new NextFunction<>(new RejectingPredicate<>(), provider), iterable); |
| } |
| |
| /** |
| * Return all following siblings for each Resource in the collection up to, but |
| * not including, Resource matched by a selector. |
| * |
| * @param until |
| * Selector marking when the operation should stop |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q nextUntil(String until) { |
| return function(new NextFunction<>(parse(until), provider)); |
| } |
| |
| /** |
| * Return all following siblings for each Resource in the collection up to, but |
| * not including, Resource matched by a selector. |
| * |
| * @param predicate |
| * Selector marking when the operation should stop |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q nextUntil(Predicate<T> predicate) { |
| return function(new NextFunction<>(predicate, provider)); |
| } |
| |
| /** |
| * Return all following siblings for each Resource in the collection up to, but |
| * not including, Resource matched by a selector. |
| * |
| * @param iterable |
| * Selector marking when the operation should stop |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q nextUntil(Iterable<T> iterable) { |
| return nextUntil(new IterableContainsPredicate<>(iterable, provider)); |
| } |
| |
| /** |
| * Remove elements from the collection. |
| * |
| * @param selector |
| * Selector used to remove Resources |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q not(String selector) { |
| return function(new NotFunction<>(parse(selector))); |
| } |
| |
| /** |
| * Remove elements from the collection. |
| * |
| * @param predicate |
| * Selector used to remove Resources |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q not(Predicate<T> predicate) { |
| return function(new FilterFunction<>(new RejectingPredicate<>(predicate))); |
| } |
| |
| /** |
| * Remove elements from the collection. |
| * |
| * @param iterable |
| * Selector used to remove Resources |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q not(Iterable<T> iterable) { |
| return not(new IterableContainsPredicate<>(iterable, provider)); |
| } |
| |
| /** |
| * Replace each element in the collection with its parent. |
| * |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q parent() { |
| return function(new ParentFunction<>(provider)); |
| } |
| |
| /** |
| * For each element in the collection find its all ancestor. |
| * |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q parents() { |
| return function(new ParentsFunction<>(new RejectingPredicate<>(), provider)); |
| } |
| |
| /** |
| * For each element in the collection find its all ancestor, filtered by a |
| * selector. |
| * |
| * @param selector |
| * Parents filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q parents(String selector) { |
| return function(new ParentsFunction<>(new RejectingPredicate<>(), provider), selector); |
| } |
| |
| /** |
| * For each element in the collection find its all ancestor, filtered by a |
| * selector. |
| * |
| * @param predicate |
| * Parents filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q parents(Predicate<T> predicate) { |
| return function(new ParentsFunction<>(new RejectingPredicate<>(), provider), predicate); |
| } |
| |
| /** |
| * For each element in the collection find its all ancestor, filtered by a |
| * selector. |
| * |
| * @param iterable |
| * Parents filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q parents(Iterable<T> iterable) { |
| return function(new ParentsFunction<>(new RejectingPredicate<>(), provider), iterable); |
| } |
| |
| /** |
| * For each element in the collection find all of its ancestors until the |
| * predicate is met. |
| * |
| * @param until |
| * Selector marking when the operation should stop |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q parentsUntil(String until) { |
| return function(new ParentsFunction<>(parse(until), provider)); |
| } |
| |
| /** |
| * For each element in the collection find all of its ancestors until the |
| * predicate is met. |
| * |
| * @param predicate |
| * Selector marking when the operation should stop |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q parentsUntil(Predicate<T> predicate) { |
| return function(new ParentsFunction<>(predicate, provider)); |
| } |
| |
| /** |
| * For each element in the collection find all of its ancestors until the |
| * predicate is met. |
| * |
| * @param iterable |
| * Selector marking when the operation should stop |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q parentsUntil(Iterable<T> iterable) { |
| return parentsUntil(new IterableContainsPredicate<>(iterable, provider)); |
| } |
| |
| /** |
| * Return the previous sibling for each Resource in the collection. |
| * |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q prev() { |
| return function(new PrevFunction<>(provider)); |
| } |
| |
| /** |
| * Return the previous sibling for each Resource in the collection and filter it |
| * by a selector. If the previous sibling doesn't match it, empty collection |
| * will be returned. |
| * |
| * @param selector |
| * Previous sibling filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q prev(String selector) { |
| return function(new PrevFunction<>(null, provider), selector); |
| } |
| |
| /** |
| * Return the previous sibling for each Resource in the collection and filter it |
| * by a selector. If the previous sibling doesn't match it, empty collection |
| * will be returned. |
| * |
| * @param predicate |
| * Previous sibling filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q prev(Predicate<T> predicate) { |
| return function(new PrevFunction<>(null, provider), predicate); |
| } |
| |
| /** |
| * Return the previous sibling for each Resource in the collection and filter it |
| * by a selector. If the previous sibling doesn't match it, empty collection |
| * will be returned. |
| * |
| * @param iterable |
| * Previous sibling filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q prev(Iterable<T> iterable) { |
| return function(new PrevFunction<>(null, provider), iterable); |
| } |
| |
| /** |
| * Return all previous siblings for each Resource in the collection. |
| * |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q prevAll() { |
| return function(new PrevFunction<>(new RejectingPredicate<>(), provider)); |
| } |
| |
| /** |
| * Return all previous siblings for each Resource in the collection, filtering |
| * them by a selector. |
| * |
| * @param selector |
| * Previous siblings filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q prevAll(String selector) { |
| return function(new PrevFunction<>(new RejectingPredicate<>(), provider), selector); |
| } |
| |
| /** |
| * Return all previous siblings for each Resource in the collection, filtering |
| * them by a selector. |
| * |
| * @param predicate |
| * Previous siblings filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q prevAll(Predicate<T> predicate) { |
| return function(new PrevFunction<>(new RejectingPredicate<>(), provider), predicate); |
| } |
| |
| /** |
| * Return all previous siblings for each Resource in the collection, filtering |
| * them by a selector. |
| * |
| * @param iterable |
| * Previous siblings filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q prevAll(Iterable<T> iterable) { |
| return function(new PrevFunction<>(new RejectingPredicate<>(), provider), iterable); |
| } |
| |
| /** |
| * Return all previous siblings for each Resource in the collection up to, but |
| * not including, Resource matched by a selector. |
| * |
| * @param until |
| * Selector marking when the operation should stop |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q prevUntil(String until) { |
| return function(new PrevFunction<>(parse(until), provider)); |
| } |
| |
| /** |
| * Return all previous siblings for each Resource in the collection up to, but |
| * not including, Resource matched by a selector. |
| * |
| * @param predicate |
| * Selector marking when the operation should stop |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q prevUntil(Predicate<T> predicate) { |
| return function(new PrevFunction<>(predicate, provider)); |
| } |
| |
| /** |
| * Return all previous siblings for each Resource in the collection up to, but |
| * not including, Resource matched by a selector. |
| * |
| * @param iterable |
| * Selector marking when the operation should stop |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q prevUntil(Iterable<T> iterable) { |
| return prevUntil(new IterableContainsPredicate<>(iterable, provider)); |
| } |
| |
| /** |
| * Set new search strategy, which will be used in {@link AbstractQuery#find()} |
| * and {@link AbstractQuery#has(String)} functions. |
| * |
| * @param strategy |
| * Search strategy type |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q searchStrategy(SearchStrategy strategy) { |
| return clone(this, strategy); |
| } |
| |
| /** |
| * Return siblings for the given Ts. |
| * |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q siblings() { |
| return siblings(""); |
| } |
| |
| /** |
| * Return siblings for the given Resources filtered by a selector. |
| * |
| * @param selector |
| * Siblings filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q siblings(String selector) { |
| return function(new SiblingsFunction<>(provider), selector); |
| } |
| |
| /** |
| * Return siblings for the given Resources filtered by a selector. |
| * |
| * @param predicate |
| * Siblings filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q siblings(Predicate<T> predicate) { |
| return function(new SiblingsFunction<>(provider), predicate); |
| } |
| |
| /** |
| * Return siblings for the given Resources filtered by a selector. |
| * |
| * @param iterable |
| * Siblings filter |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q siblings(Iterable<T> iterable) { |
| return function(new SiblingsFunction<>(provider), iterable); |
| } |
| |
| /** |
| * Filter out first {@code from} Resources from the collection. |
| * |
| * @param from |
| * How many Resources to cut out |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q slice(int from) { |
| if (from < 0) { |
| throw new IndexOutOfBoundsException(); |
| } |
| return function(new SliceFunction<T>(from)); |
| } |
| |
| /** |
| * Reduce the collection to a subcollection specified by a given range. Both |
| * from and to are inclusive, 0-based indices. |
| * |
| * @param from |
| * Low endpoint (inclusive) of the subcollection |
| * @param to |
| * High endpoint (inclusive) of the subcollection |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q slice(int from, int to) { |
| if (from < 0) { |
| throw new IndexOutOfBoundsException(); |
| } |
| if (from > to) { |
| throw new IllegalArgumentException(); |
| } |
| return function(new SliceFunction<T>(from, to)); |
| } |
| |
| /** |
| * Filter out repeated resources. The implementation of this method uses a |
| * {@link HashSet} to store the processed elements, which may result in an |
| * increased memory usage for the big collections. |
| * |
| * @return new SlingQuery object transformed by this operation |
| */ |
| public Q unique() { |
| return function(new UniqueFunction<>()); |
| } |
| |
| private Q function(Function<?, ?> function, Iterable<T> iterable) { |
| Q newQuery = clone(this, this.searchStrategy); |
| newQuery.functions.add(function); |
| newQuery.functions.add(new FilterFunction<>(new IterableContainsPredicate<>(iterable, provider))); |
| return newQuery; |
| } |
| |
| private Q function(Function<?, ?> function, Predicate<T> predicate) { |
| Q newQuery = clone(this, this.searchStrategy); |
| newQuery.functions.add(function); |
| newQuery.functions.add(new FilterFunction<>(predicate)); |
| return newQuery; |
| } |
| |
| private Q function(Function<?, ?> function, String selector) { |
| Q newQuery = clone(this, this.searchStrategy); |
| newQuery.functions.add(function); |
| newQuery.functions.add(new SelectorFunction<>(selector, provider, searchStrategy)); |
| return newQuery; |
| } |
| |
| private Q function(Function<?, ?> function) { |
| Q newQuery = clone(this, this.searchStrategy); |
| newQuery.functions.add(function); |
| return newQuery; |
| } |
| |
| private SelectorFunction<T> parse(String selector) { |
| return new SelectorFunction<>(selector, provider, searchStrategy); |
| } |
| |
| protected abstract Q clone(AbstractQuery<T, Q> original, SearchStrategy strategy); |
| |
| @Override |
| public String toString() { |
| StringBuilder builder = new StringBuilder(); |
| builder.append("$("); |
| Iterator<T> iterator = this.iterator(); |
| while (iterator.hasNext()) { |
| builder.append('['); |
| builder.append(iterator.next()); |
| builder.append(']'); |
| if (iterator.hasNext()) { |
| builder.append(", "); |
| } |
| } |
| builder.append(")"); |
| return builder.toString(); |
| } |
| } |