001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2025–2026 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 016import javax.lang.model.AnnotatedConstruct; 017 018import org.microbean.assign.Annotated; 019 020import org.microbean.construct.Domain; 021 022/** 023 * A supplier of {@link References} objects. 024 * 025 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 026 * 027 * @see #references(Annotated) 028 * 029 * @see #reference(Annotated) 030 * 031 * @see References 032 */ 033// TODO: not crazy about the circular dependencies, but they're no worse than, say, a sealed class 034public interface ReferencesSelector { 035 036 /** 037 * Destroys the supplied contextual reference if and only if it meets the conditions for destruction. 038 * 039 * @param r a contextual reference; may be {@code null} in which case {@code false} will be returned 040 * 041 * @return {@code true} if and only if destruction occurred 042 * 043 * @exception DestructionException if an error occurs 044 */ 045 public boolean destroy(final Object r); // e.g. CDI's Instance#destroy(Object); works only on normal- and @Dependent-scoped objects 046 047 // I don't like this at all. But you need something that can make, e.g., AnnotatedConstructs, so that you can call the other 048 // methods in this interface. Every other type can be acquired at runtime via a ReferencesSelector, but you need a 049 // Domain to kick start the process. 050 /** 051 * Returns a non-{@code null} {@link Domain} that can be used to furnish {@link javax.lang.model.AnnotatedConstruct}s. 052 * 053 * <p>Implementations of this method must be safe for concurrent use by multiple threads.</p> 054 * 055 * <h4>Design Note</h4> 056 * 057 * <p>Without this method, componenents using a {@link ReferencesSelector} will have to arrange to have their own 058 * {@link Domain} somehow. Inconveniently, this is the only type in the system that cannot be acquired by an 059 * invocation of the {@link #references(Annotated)} method, since you need a {@link Domain} to make an {@link 060 * Annotated Annotated<? extends AnnotatedConstruct>}.</p> 061 * 062 * @return a non-{@code null} {@link Domain} 063 * 064 * @see Domain 065 */ 066 public Domain domain(); 067 068 /** 069 * Returns a non-{@code null}, determinate, contextual reference appropriate for the supplied {@link Bean}. 070 * 071 * <p>Implementations of this method must be safe for concurrent use by multiple threads.</p> 072 * 073 * <p>Implementations of this method must, directly or indirectly, must ensure that ultimately the supplied {@link 074 * Bean}'s {@linkplain Bean#factory() affiliated <code>Factory</code>} is the mechanism used, and no other is used, to 075 * {@linkplain Factory#create(Creation) create} any contextual instance underlying the contextual reference to be 076 * returned.</p> 077 * 078 * @param <R> the contextual reference type 079 * 080 * @param bean a non-{@code null} {@link Bean} 081 * 082 * @return a non-{@code null}, determinate, contextual reference appropriate for the supplied {@link Bean} 083 * 084 * @exception NullPointerException if {@code bean} is {@code null} 085 * 086 * @exception IllegalArgumentException if {@code bean} is unsuitable in any way 087 */ 088 // Experimental. Needed because you might grab a pile of Beans, then filter them yourself according to external 089 // criteria, and then want references for them. I'm slightly sour on this because up to this point you don't need 090 // Beans to implement ReferencesSelector at all. Maybe this needs to be a different interface, but then you're still 091 // faced with the issue that fundamentally this method returns a contextual reference, and that *is* the domain of 092 // ReferencesSelector. 093 // 094 // You could do reference(Predicate) but that's TOO generic. 095 public <R> R reference(final Bean<R> bean); 096 097 /** 098 * Returns a non-{@code null}, determinate {@link References} capable of locating contextual references compatible 099 * with the supplied {@link Annotated Annotated<? extends AnnotatedConstruct>}. 100 * 101 * @param <R> the contextual reference type 102 * 103 * @param aac a non-{@code null} {@link Annotated Annotated<? extends AnnotatedConstruct>} describing the 104 * putative contextual reference; must represent {@code <R>} 105 * 106 * @return a non-{@code null}, determinate {@link References} 107 * 108 * @exception NullPointerException if {@code aac} is {@code null} 109 * 110 * @exception IllegalArgumentException if {@code aac} is unsuitable in any way 111 * 112 * @see References 113 * 114 * @see Annotated#of(AnnotatedConstruct) 115 */ 116 public <R> References<R> references(final Annotated<? extends AnnotatedConstruct> aac); 117 118 /** 119 * Returns a non-{@code null}, determinate {@link References} capable of locating contextual references compatible 120 * with the supplied {@link AnnotatedConstruct}. 121 * 122 * @param <R> the contextual reference type 123 * 124 * @param ac a non-{@code null} {@link AnnotatedConstruct} describing the putative contextual reference; must represent 125 * {@code <R>} 126 * 127 * @return a non-{@code null}, determinate {@link References} 128 * 129 * @exception NullPointerException if {@code ac} is {@code null} 130 * 131 * @exception IllegalArgumentException if {@code ac} is unsuitable in any way 132 * 133 * @see References 134 * 135 * @see Annotated#of(AnnotatedConstruct) 136 * 137 * @deprecated Please use the {@link #references(Annotated)} method instead. 138 */ 139 @Deprecated 140 public default <R> References<R> references(final AnnotatedConstruct ac) { 141 return references(Annotated.of(ac)); 142 } 143 144 /** 145 * A convenience method that acquires and returns what is presumed, possibly incorrectly, to be the sole contextual 146 * reference compatible with the supplied {@link AnnotatedConstruct}. 147 * 148 * @param <R> the contextual reference type 149 * 150 * @param ac a non-{@code null} {@link AnnotatedConstruct} describing the putative contextual reference; must 151 * represent {@code <R>} 152 * 153 * @return a non-{@code null}, determinate contextual reference 154 * 155 * @exception NullPointerException if {@code ac} is {@code null} 156 * 157 * @exception UnsatisfiedResolutionException if there is no compatible contextual reference 158 * 159 * @exception AmbiguousResolutionException if there is more than one compatible contextual reference 160 * 161 * @see #references(Annotated) 162 * 163 * @see Annotated#of(AnnotatedConstruct) 164 * 165 * @see References#get() 166 * 167 * @deprecated Please use the {@link #reference(Annotated)} method instead. 168 */ 169 @Deprecated 170 public default <R> R reference(final AnnotatedConstruct ac) { 171 return this.<R>reference(Annotated.of(ac)); 172 } 173 174 /** 175 * A convenience method that acquires and returns what is presumed, possibly incorrectly, to be the sole contextual 176 * reference compatible with the supplied {@link Annotated Annotated<? extends AnnotatedConstruct>}. 177 * 178 * @param <R> the contextual reference type 179 * 180 * @param aac a non-{@code null} {@link Annotated Annotated<? extends AnnotatedConstruct>} describing the 181 * putative contextual reference; must represent {@code <R>} 182 * 183 * @return a non-{@code null}, determinate contextual reference 184 * 185 * @exception NullPointerException if {@code aac} is {@code null} 186 * 187 * @exception UnsatisfiedResolutionException if there is no compatible contextual reference 188 * 189 * @exception AmbiguousResolutionException if there is more than one compatible contextual reference 190 * 191 * @see #references(Annotated) 192 * 193 * @see References#get() 194 */ 195 public default <R> R reference(final Annotated<? extends AnnotatedConstruct> aac) { 196 return this.<R>references(aac).get(); 197 } 198 199}