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
016import java.lang.constant.ClassDesc;
017import java.lang.constant.Constable;
018import java.lang.constant.DynamicConstantDesc;
019
020import java.util.Optional;
021
022import org.microbean.constant.Constables;
023
024import static java.lang.constant.ConstantDescs.BSM_INVOKE;
025import static java.lang.constant.ConstantDescs.CD_Object;
026
027import static java.lang.constant.MethodHandleDesc.ofConstructor;
028
029import static java.util.Objects.requireNonNull;
030
031/**
032 * A {@link Factory} that returns its singleton from its {@link #create(Request)} method.
033 *
034 * @param <I> the singleton type
035 *
036 * @param singleton the singleton
037 *
038 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a>
039 *
040 * @see #singleton()
041 *
042 * @see #create(Request)
043 */
044public final record Constant<I>(I singleton) implements Constable, Factory<I> {
045
046  /**
047   * Creates a new {@link Constant}.
048   *
049   * @param singleton an object; must not be {@code null}
050   *
051   * @exception NullPointerException if {@code singleton} is {@code null}
052   */
053  public Constant {
054    requireNonNull(singleton, "singleton");
055  }
056
057  /**
058   * Invokes the {@link #singleton()} method and returns its result.
059   *
060   * @param creation a {@link Creation}; may be {@code null}; ignored
061   *
062   * @return the result of invoking the {@link #singleton()} method
063   *
064   * @see #singleton()
065   */
066  @Override // Factory<I>
067  public final I create(final Creation<I> creation) {
068    return this.singleton;
069  }
070
071  /**
072   * Returns {@code true} if and only if the return value of an invocation of the {@link #singleton()} method is {@link
073   * AutoCloseable}.
074   *
075   * @return {@code true} if and only if the return value of an invocation of the {@link #singleton()} method is {@link
076   * AutoCloseable}
077   */
078  @Override // Factory<I>
079  public final boolean destroys() {
080    return this.singleton instanceof AutoCloseable;
081  }
082
083  @Override // Factory<I>
084  public final void destroy(final I i, final Destruction creation) {
085    Factory.super.destroy(i, creation);
086  }
087
088  @Override // Constable
089  public final Optional<DynamicConstantDesc<I>> describeConstable() {
090    return Constables.describeConstable(this.singleton())
091      .map(iDesc -> DynamicConstantDesc.of(BSM_INVOKE,
092                                           ofConstructor(this.getClass().describeConstable().orElseThrow(),
093                                                         CD_Object),
094                                           iDesc));
095  }
096
097
098}