001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2023–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.scopelet; 015 016import java.lang.System.Logger; 017 018import java.lang.constant.Constable; 019import java.lang.constant.ConstantDesc; 020import java.lang.constant.DynamicConstantDesc; 021 022import java.util.Optional; 023 024import org.microbean.bean.Creation; 025import org.microbean.bean.Destruction; 026import org.microbean.bean.Factory; 027 028import org.microbean.reference.DestructorRegistry; 029 030import static java.lang.constant.ConstantDescs.BSM_INVOKE; 031 032import static java.lang.constant.MethodHandleDesc.ofConstructor; 033 034import static java.lang.System.getLogger; 035 036import static java.lang.System.Logger.Level.WARNING; 037 038/** 039 * A {@link Scopelet} implementation that does not cache objects at all. 040 * 041 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 042 */ 043public class NoneScopelet extends Scopelet<NoneScopelet> implements Constable { 044 045 046 /* 047 * Static fields. 048 */ 049 050 051 private static final Logger LOGGER = getLogger(NoneScopelet.class.getName()); 052 053 054 /* 055 * Constructors. 056 */ 057 058 059 /** 060 * Creates a new {@link NoneScopelet}. 061 */ 062 public NoneScopelet() { 063 super(); 064 } 065 066 067 /* 068 * Instance methods. 069 */ 070 071 072 /** 073 * Checks to see if this {@link Scopelet} {@linkplain #active() is active} and then returns a contextual instance 074 * {@linkplain Factory#create(Creation) created by the supplied <code>Factory</code>}. 075 * 076 * <p>This method (and its overrides) may return {@code null}.</p> 077 * 078 * <p>If the supplied {@link Factory} is {@code null}, this method will (and its overrides must) return {@code null}. 079 * 080 * @param ignoredBeanId an identifier; ignored by the default implementation; may be {@code null} 081 * 082 * @param factory a {@link Factory}; may be {@code null} in which case {@code null} will and must be returned 083 * 084 * @param creation a {@link Creation}, typically the one in effect that is causing this method to be invoked in the 085 * first place; may be {@code null}; most commonly also an instance of {@link DestructorRegistry} 086 * 087 * @return a contextual instance, or {@code null} 088 * 089 * @exception InactiveScopeletException if this {@link Scopelet} {@linkplain #active() is not active} 090 * 091 * @exception ClassCastException if destruction is called for, {@code creation} is non-{@code null}, and {@code 092 * creation} does not implement {@link Destruction}, a requirement of its contract 093 * 094 * @see DestructorRegistry 095 * 096 * @see Creation 097 * 098 * @see Destruction 099 * 100 * @see Factory#destroys() 101 */ 102 // All parameters are nullable. 103 // Non-final to permit subclasses to, e.g., add logging. 104 @Override // Scopelet<NoneScopelet> 105 public <I> I instance(final Object ignoredBeanId, final Factory<I> factory, final Creation<I> creation) { 106 if (!this.active()) { 107 throw new InactiveScopeletException(); 108 } else if (factory == null) { 109 return null; 110 } 111 final I returnValue = factory.create(creation); 112 if (factory.destroys()) { 113 if (creation instanceof DestructorRegistry dr && creation instanceof Destruction d) { 114 dr.register(returnValue, () -> factory.destroy(returnValue, d)); 115 } else if (LOGGER.isLoggable(WARNING)) { 116 LOGGER.log(WARNING, "Dependent objects will not be destroyed"); 117 } 118 } 119 return returnValue; 120 } 121 122 @Override // Constable 123 public Optional<? extends ConstantDesc> describeConstable() { 124 return Optional.of(DynamicConstantDesc.of(BSM_INVOKE, ofConstructor(this.getClass().describeConstable().orElseThrow()))); 125 } 126 127}