All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.microbean.bean.Factory Maven / Gradle / Ivy

There is a newer version: 0.0.9
Show newest version
/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
 *
 * Copyright © 2023–2024 microBean™.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 */
package org.microbean.bean;

import java.lang.constant.Constable;
import java.lang.constant.ConstantDesc;
import java.lang.constant.DynamicConstantDesc;
import java.lang.constant.MethodHandleDesc;

import java.util.Optional;

import static java.lang.constant.ConstantDescs.BSM_INVOKE;

/**
 * A creator and destroyer of contextual instances of a particular type.
 *
 * @param  the type of the contextual instances this {@link Factory} creates and destroys
 *
 * @author Laird Nelson
 */
@FunctionalInterface
public interface Factory extends Aggregate, Constable {

  /**
   * Creates a new contextual instance, possibly using the supplied {@link Request}, if it is non-{@code null}, to
   * acquire its {@linkplain #dependencies() dependencies}.
   *
   * 

Implementations of this method must not call {@link #singleton()}.

* *

Implementations of this method should consider calling {@link Creation#created(Object)} on the supplied {@link * Request} with the contextual instance about to be returned.

* * @param r a {@link Request} responsible for the demand for creation and used for {@linkplain ReferenceSelector * acquiring any needed dependencies}; may be {@code null} in early, uncommon bootstrap-like * situations * * @return a new contextual instance, or {@code null} * * @exception CreationException if an error occurs * * @see Request * * @see ReferenceSelector * * @see Creation */ public I create(final Request r); /** * Returns the sole contextual instance of this {@link Factory}'s type, if there is one, or {@code null} in the very * common case that there is not. * *

The default implementation of this method returns {@code null}.

* *

Overrides of this method should not call {@link #create(Request)}.

* *

Overrides of this method must be idempotent and must return a determinate value.

* * @return the sole contextual instance of this {@link Factory}'s type, or (commonly) {@code null} */ public default I singleton() { return null; } /** * Returns {@code true} if this {@link Factory} implementation destroys its {@linkplain #create(Request) created} * contextual instances in some way, or {@code false} if it does not. * *

The default implementation of this method returns {@code true}.

* *

Overrides of this method must be idempotent and return a determinate value.

* * @return {@code true} if this {@link Factory} implementation destroys its {@linkplain #create(Request) created} * contextual instances in some way; {@code false} otherwise * * @see #destroy(Object, Request) */ public default boolean destroys() { return true; } // MUST be idempotent // If i is an AutoCloseable, MUST be idempotent // // TODO: rename back to destroy() public default void destroy(final I i, final Request creationRequest) { if (i instanceof AutoCloseable ac) { try { ac.close(); } catch (final RuntimeException | Error re) { throw re; } catch (final InterruptedException e) { Thread.currentThread().interrupt(); throw new DestructionException(e.getMessage(), e); } catch (final Exception e) { throw new DestructionException(e.getMessage(), e); } } } /** * Returns an {@link Optional} containing the nominal descriptor for this instance, if one can be constructed, or an * {@linkplain Optional#isEmpty() empty Optional} if one cannot be constructed. * *

The default implementation of this method returns an {@link Optional} that contains a dynamic constant * representing an invocation of the implementation's constructor that takes no arguments. The resolution of * this dynamic constant is undefined if the implementation does not declare such a constructor.

* * @return an {@link Optional} containing the nominal descriptor for this instance, if one can be constructed, or an * {@linkplain Optional#isEmpty() empty Optional} if one cannot be constructed * * @threadsafety This method is safe for concurrent use by multiple threads. * * @idempotency This method is neither idempotent nor deterministic. */ @Override // Constable public default Optional describeConstable() { return this.getClass() .describeConstable() .map(classDesc -> DynamicConstantDesc.of(BSM_INVOKE, MethodHandleDesc.ofConstructor(classDesc))); } }