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}