001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2023–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 016import java.util.SequencedSet; 017 018/** 019 * An interface whose implementations {@linkplain #produce(Request) produce} possibly uninitialized contextual 020 * instances. 021 * 022 * <p>{@link Producer}s are used to implement {@link Factory} instances' {@link Factory#create(Request) create(Request)} 023 * and {@link Factory#destroy(Object, Request) destroy(Object, Request)} methods. Values returned from the {@link 024 * #produce(Request)} method are often supplied to {@link Initializer}s.</p> 025 * 026 * @param <I> the type of contextual instance 027 * 028 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 029 * 030 * @see #produce(Request) 031 * 032 * @see Factory#create(Request) 033 */ 034// Subordinate to Factory<I> (really to Initializer<I>) 035// Akin to CDI's Producer. 036// Handles instance production and disposal, *including intercepted production*. 037// 038// Does NOT handle initialization; see for example 039// https://github.com/search?q=repo%3Aweld%2Fcore+%22.produce%28%29%22+language%3AJava&type=code. Obviously it may 040// acquire dependencies and supply them during production, but the point is it doesn't do field injection or initializer 041// method invocation. 042// 043// Does NOT handle post-initialization. 044// Does NOT handle business method interception. 045// Does NOT handle pre-disposal. 046// See also: InterceptingProducer 047@FunctionalInterface 048public interface Producer<I> extends Aggregate { 049 050 /** 051 * Disposes of the supplied contextual instance. 052 * 053 * <p>The default implementation of this method checks to see if {@code i} is an instance of {@link AutoCloseable}, 054 * and, if so, calls {@link AutoCloseable#close() close()} on it, throwing any resulting exception as a {@link 055 * DestructionException}.</p> 056 * 057 * @param i a contextual instance {@linkplain #produce(Request) produced} by this {@link Producer}; may be {@code 058 * null} 059 * 060 * @param r the {@link Request} that was {@linkplain #produce(Request) present at production time}; must not be {@code 061 * null} 062 * 063 * @exception NullPointerException if {@code r} is {@code null} 064 * 065 * @exception DestructionException if {@code i} is an {@link AutoCloseable} instance, and if its {@link 066 * AutoCloseable#close() close()} method throws a checked exception 067 */ 068 public default void dispose(final I i, final Request<I> r) { 069 if (i instanceof AutoCloseable ac) { 070 try { 071 ac.close(); 072 } catch (final RuntimeException | Error e) { 073 throw e; 074 } catch (final InterruptedException e) { 075 Thread.currentThread().interrupt(); 076 throw new DestructionException(e.getMessage(), e); 077 } catch (final Exception e) { 078 throw new DestructionException(e.getMessage(), e); 079 } 080 } 081 } 082 083 /** 084 * Produces a new contextual instance and returns it by calling the {@link #produce(SequencedSet)} method with the 085 * return value of an invocation of the {@link #assign(Request)} method with the supplied {@link Request}. 086 * 087 * @param r a {@link Request}; must not be {@code null} 088 * 089 * @return a new contextual instance, or {@code null} 090 * 091 * @exception NullPointerException if {@code r} is {@code null} 092 * 093 * @see #produce(SequencedSet) 094 * 095 * @see #assign(Request) 096 */ 097 public default I produce(final Request<?> r) { 098 return this.produce(this.assign(r)); 099 } 100 101 /** 102 * Produces a new contextual instance and returns it, possibly (often) making use of the supplied, dependent, 103 * contextual references. 104 * 105 * <p>Implementations of this method must not call {@link #produce(Request)} or an infinite loop may result.</p> 106 * 107 * @param assignments a {@link SequencedSet} of {@link Assignment}s this {@link Producer} needs to create the 108 * contextual instance; must not be {@code null} 109 * 110 * @return a new contextual instance, or {@code null} 111 * 112 * @exception NullPointerException if {@code dependentContextualReferences} is {@code null} 113 */ 114 public I produce(final SequencedSet<? extends Assignment<?>> assignments); 115 116}