001package io.ebean;
002
003import io.ebean.service.SpiFetchGroupQuery;
004
005import javax.annotation.Nonnull;
006
007/**
008 * Defines what part of the object graph to load (select and fetch clauses).
009 * <p>
010 * Using a FetchGroup effectively sets the select() and fetch() clauses for a query. It is alternative
011 * to specifying the select() and fetch() clauses on the query allowing for more re-use of "what to load"
012 * that can be defined separately from the query and combined with other FetchGroups.
013 * </p>
014 *
015 * <h3>Select example</h3>
016 * <pre>{@code
017 *
018 * FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class, "name, status");
019 *
020 * Customer.query()
021 *   .select(fetchGroup)
022 *   .findList();
023 *
024 * }</pre>
025 *
026 * <h3>Select and fetch example</h3>
027 * <pre>{@code
028 *
029 * FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class)
030 *   .select("name, status")
031 *   .fetch("contacts", "firstName, lastName, email")
032 *   .build();
033 *
034 * Customer.query()
035 *   .select(fetchGroup)
036 *   .findList();
037 *
038 * }</pre>
039 *
040 * <h3>Combining FetchGroups</h3>
041 * <p>
042 *   FetchGroups can be combined together to form another FetchGroup.
043 * </p>
044 * <pre>{@code
045 *
046 *  FetchGroup<Address> FG_ADDRESS = FetchGroup.of(Address.class)
047 *    .select("line1, line2, city")
048 *    .fetch("country", "name")
049 *    .build();
050 *
051 *  FetchGroup<Customer> FG_CUSTOMER = FetchGroup.of(Customer.class)
052 *    .select("name, version")
053 *    .fetch("billingAddress", FG_ADDRESS)
054 *    .build();
055 *
056 *
057 *  Customer.query()
058 *    .select(FG_CUSTOMER)
059 *    .findList();
060 *
061 * }</pre>
062 *
063 * @param <T> The bean type the Fetch group can be applied to
064 */
065public interface FetchGroup<T> {
066
067  /**
068   * Return the FetchGroup with the given select clause.
069   * <p>
070   *   We use this for simple FetchGroup that only select() properties and do not have additional fetch() clause.
071   * </p>
072   * <pre>{@code
073   *
074   * FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class, "name, status");
075   *
076   * Customer.query()
077   *   .select(fetchGroup)
078   *   .findList();
079   *
080   * }</pre>
081   *
082   * @param select The select clause of the FetchGroup
083   *
084   * @return The FetchGroup with the given select clause
085   */
086  @Nonnull
087  static <T> FetchGroup<T> of(Class<T> cls, String select) {
088    return XServiceProvider.fetchGroupOf(cls, select);
089  }
090
091  /**
092   * Return the FetchGroupBuilder with the given select clause that we can add fetch clauses to.
093   * <p>
094   * We chain select() with one or more fetch() clauses to define the object graph to load.
095   * </p>
096   * <pre>{@code
097   *
098   * FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class)
099   *   .select("name, status")
100   *   .fetch("contacts", "firstName, lastName, email")
101   *   .build();
102   *
103   * Customer.query()
104   *   .select(fetchGroup)
105   *   .findList();
106   *
107   * }</pre>
108   *
109   * @return The FetchGroupBuilder with the given select clause which we will add fetch clauses to
110   */
111  @Nonnull
112  static <T> FetchGroupBuilder<T> of(Class<T> cls) {
113    return XServiceProvider.fetchGroupOf(cls);
114  }
115
116  /**
117   * Return a query to be used by query beans for constructing FetchGroup.
118   */
119  static <T> SpiFetchGroupQuery<T> queryFor(Class<T> beanType) {
120    return XServiceProvider.fetchGroupQueryFor(beanType);
121  }
122
123}