/** * Copyright (C) 2006-2017 INRIA and contributors * Spoon - http://spoon.gforge.inria.fr/ * * This software is governed by the CeCILL-C License under French law and * abiding by the rules of distribution of free software. You can use, modify * and/or redistribute the software under the terms of the CeCILL-C license as * circulated by CEA, CNRS and INRIA at http://www.cecill.info. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL-C license and that you accept its terms. */ package spoon.reflect.visitor.chain; import spoon.reflect.declaration.CtElement; import spoon.reflect.factory.Factory; import spoon.reflect.visitor.Filter; import java.util.List; /** * <p>CtQuery represents a query, which can be used to traverse a spoon model and collect * children elements in several ways.</p> * * <p>Creation: A query is created either from a {@link CtElement}, or it can be defined first from {@link Factory#createQuery()} and bound to root elements * afterwards using {@link CtQuery#setInput(Object...)}.</p> * * <p>Chaining: In a query several steps can be chained, by chaining calls to map functions. The non-null outputs of one step * are given as input to the next step. An iterable or array output is considered as a set of different inputs for the next step.</p> * * <p>Evaluation: A CtQuery is lazily evaluated once {@link CtQuery#list()} or {@link CtQuery#forEach(CtConsumer)} are called.</p> * */ public interface CtQuery extends CtQueryable { /** * Recursively scans all children elements of an input element. * The matched child element for which (filter.matches(element)==true) are sent to the next query step. * Essentially the same as {@link CtElement#getElements(Filter)} but more powerful, because it * can be chained with other subsequent queries. * * Note: the input element (the root of the query, `this` if you're in {@link CtElement}) is also checked and may thus be also sent to the next step. * The elements which throw {@link ClassCastException} during {@link Filter#matches(CtElement)} * are considered as **not matching**, ie. are excluded. * * @param filter used to filter scanned children elements of the AST tree. * If null then all children elements pass to next step. * @return this to support fluent API */ @Override <R extends CtElement> CtQuery filterChildren(Filter<R> filter); /** * The matched element for which (filter.matches(element)==true) is sent to the next query step. * * The elements which throw {@link ClassCastException} during {@link Filter#matches(CtElement)} * are considered as **not matching**, ie. are excluded. * * @param filter used to detect if input element can pass to next query step * @return this to support fluent API */ <R extends CtElement> CtQuery select(Filter<R> filter); /** * Query elements based on a function, the behavior depends on the return type of the function. * <table summary=""> * <tr><td><b>Return type of `function`</b><td><b>Behavior</b> * <tr><td>{@link Boolean}<td>Select elements if the returned value of `function` is true (as for {@link Filter}). * <tr><td>? extends {@link Object}<td>Send the returned value of `function` to the next step * <tr><td>{@link Iterable}<td>Send each item of the collection to the next step * <tr><td>{@link Object[]}<td>Send each item of the array to the next step * </table><br> * * @param function a Function with one parameter of type I returning a value of type R * @return this to support fluent API */ @Override <I, R> CtQuery map(CtFunction<I, R> function); /** * Sets (binds) the input of the query. * If the query is created by {@link CtElement#map} or {@link CtElement#filterChildren(Filter)}, * then the query is already bound to this element. * A new call of {@link CtQuery#setInput(Object...)} is always possible, it resets the current binding and sets the new one. * * @param input * @return this to support fluent API */ <T extends CtQuery> T setInput(Object... input); /** * Actually evaluates the query and for each produced output element of the last step, * calls `consumer.accept(outputElement)`. * * This avoids to create useless intermediate lists. * * @param consumer The consumer which accepts the results of the query */ <R> void forEach(CtConsumer<R> consumer); /** * Actually evaluates the query and returns all the elements produced in the last step.<br> * Note: The type R of the list is not checked by the query. So use the type, which matches the results of your query, * otherwise the ClassCastException will be thrown when reading the list. * @return the list of elements collected by the query. * @see #forEach(CtConsumer) for an efficient way of manipulating the elements without creating an intermediate list. */ <R extends Object> List<R> list(); /** * Same as {@link CtQuery#list()}, but with static typing on the return type * and the final filtering, which matches only results, which are assignable from that return type. * * @return the list of elements collected by the query. */ <R> List<R> list(Class<R> itemClass); /** * Actually evaluates the query and returns first elements produced in the last step.<br> * After the first element is found, the query evaluation is terminated. * * Note: The return type R is not checked by the query. So use the type, which matches the results of your query, * otherwise the ClassCastException will be thrown. * @return the first element found by the query. */ <R extends Object> R first(); /** * Same as {@link CtQuery#first()}, but with static typing on the return type * and the final filtering, which matches only the first result, which is assignable from that return type. * * @return the list of elements collected by the query. */ <R> R first(Class<R> itemClass); /** * Defines whether this query will throw {@link ClassCastException} * when the output of the previous step cannot be cast to type of input of next step. * The default value is {@link QueryFailurePolicy#FAIL}, which means than exception is thrown when there is a mismatch<br> * * Note: The {@link CtQueryable#filterChildren(Filter)} step never throws {@link ClassCastException} * * @param policy the policy * @return this to support fluent API */ CtQuery failurePolicy(QueryFailurePolicy policy); /** * Sets the name of current query, to identify the current step during debugging of a query * @param name * @return this to support fluent API */ CtQuery name(String name); /** * Same as {@link CtQuery#map(CtFunction)}, but the returned object is not handled * by java's return statement, but by a call to {@link CtConsumer#accept(Object)}, this * allows efficient and easy to write chained processing, see {@link CtConsumableFunction}. * * @param queryStep * @return this to support fluent API */ @Override <I> CtQuery map(CtConsumableFunction<I> queryStep); /** * Terminates the evaluation of this query. * The query still returns all results collected before termination. * This method should not throw an exception. */ void terminate(); /** * @return true if the evaluation has been terminated. */ boolean isTerminated(); }