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