001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2024–2025 microBean™.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
006 * the License. You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
011 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
012 * specific language governing permissions and limitations under the License.
013 */
014package org.microbean.bean;
015
016/**
017 * A request for a contextual reference of a particular attributed type, along with functionality to help fulfil the
018 * request.
019 *
020 * @param <I> the type of the contextual reference
021 *
022 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a>
023 *
024 * @see #beanReduction()
025 *
026 * @see ReferenceSelector
027 *
028 * @see Creation
029 */
030public interface Request<I> extends Creation<I>, ReferenceSelector {
031
032  /**
033   * Returns the {@link BeanReduction} describing this {@link Request} in progress.
034   *
035   * @return the {@link BeanReduction} describing this {@link Request} in progress, or {@code null} if this is the
036   * <dfn>primordial request</dfn>
037   *
038   * @microbean.idempotency Implementations of this method must be idempotent and deterministic.
039   *
040   * @microbean.nullability Implementations of this method may return {@code null}, but only to represent the
041   * <dfn>primordial request</dfn>.
042   *
043   * @microbean.threadsafety Implementations of this method must be safe for concurrent use by multiple threads.
044   *
045   * @see BeanReduction
046   */
047  public BeanReduction<I> beanReduction();
048
049  /**
050   * Returns a {@link Request} that is conceptually a <dfn>child</dfn> of this {@link Request} and that represents a
051   * request for a contextual reference satisfying the supplied {@link BeanReduction}.
052   *
053   * <p>If the supplied {@link BeanReduction} {@linkplain BeanReduction#equals(Object) is equal to} the return value of
054   * an invocation of this {@link Request}'s {@link #beanReduction()} method, it is permissible for this {@link Request}
055   * to be returned instead of a new child.</p>
056   *
057   * @param <J> the type of contextual reference returned by the child {@link Request}
058   *
059   * @param beanReduction a {@link BeanReduction}; must not be {@code null}
060   *
061   * @return a {@link Request} that is conceptually a <dfn>child</dfn> of this {@link Request} and that represents a
062   * request for a contextual reference satisfying the supplied {@link BeanReduction}; never {@code null}
063   *
064   * @exception NullPointerException if {@code beanReduction} is {@code null}
065   */
066  // Returns a "child" Request, where "childness" means "in the service of the parent". So a request for a
067  // CoffeeMaker is the logical parent of a request for its Heater, which is the new child.
068  //
069  // If the supplied BeanReduction is equal to this Request's current beanReduction(), it is permissible for this
070  // Request to be returned instead.
071  //
072  // It is very common for a Request implementation to *also* be (or house) an AutoCloseableRegistry implementation. So
073  // if the Heater object is in "none"/dependent scope, it should get added to the CoffeeMaker parent's set of
074  // AutoCloseables to be closed when the parent goes out of scope, and if a child request for a Fuse object gets
075  // created, then the Fuse should be added to the Heater child's set of AutoCloseables, and so on.
076  //
077  // See AutoCloseableRegistry#newChild() for how that part works.
078  //
079  // Note that the semantics of this child(BeanReduction) method don't have the same "tree node"-like quality as
080  // AutoCloseableRegistry#newChild(). That is, there's no requirement that a child Request retain a reference to its
081  // parent Request.
082  public <J> Request<J> child(final BeanReduction<J> beanReduction);
083
084  /**
085   * Returns {@code true} if and only if this {@link Request} implementation is the <dfn>primordial request</dfn>.
086   *
087   * <p>The default implementation of this method returns {@code true} if and only if the return value of an invocation
088   * of the {@link #beanReduction()} method is {@code null}.</p>
089   *
090   * @return {@code true} if and only if this {@link Request} is the <dfn>primordial request</dfn>
091   */
092  public default boolean primordial() {
093    return this.beanReduction() == null;
094  }
095
096  /**
097   * Acquires a contextual reference that matches the supplied {@link AttributedType} and returns it.
098   *
099   * @param <R> the type of contextual reference
100   *
101   * @param attributedType an {@link AttributedType}; must not be {@code null}
102   *
103   * @return a contextual reference, which may be {@code null}
104   *
105   * @exception NullPointerException if {@code attributedtype} is {@code null}
106   */
107  @SuppressWarnings("unchecked")
108  public default <R> R reference(final AttributedType attributedType) {
109    return this.reference(attributedType, (Creation<R>)this);
110  }
111
112}