001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.commons.function;
018/**
019 * A universal factory interface used with <ja>@Marshalled</ja><c>(factory=X.class)</c> for any bean type the
020 * framework needs to instantiate.
021 *
022 * <p>
023 * This interface provides a single DI hook for all framework-managed classes including
024 * {@link BeanConsumer}, {@link BeanSupplier}, {@link BeanChannel}, {@code ObjectSwap} subclasses,
025 * and any ordinary bean class parsed from JSON/XML/etc.
026 *
027 * <p>
028 * When a class annotated with <ja>@Marshalled</ja><c>(factory=MyFactory.class)</c> needs to be instantiated,
029 * the framework resolves the factory as follows:
030 * <ol>
031 *    <li>Look up the factory class in the {@code BeanStore} (e.g. Spring {@code ApplicationContext})
032 *    <li>If not found in the store, attempt to instantiate the factory directly via no-arg constructor
033 *        or {@code getInstance()} static method
034 *    <li>If both fail, throw {@link IllegalArgumentException}
035 * </ol>
036 *
037 * <h5 class='section'>Example (Spring integration):</h5>
038 * <p class='bjava'>
039 *    <jc>// Spring singleton factory that creates per-request ItemChannel instances</jc>
040 *    <ja>@Component</ja>
041 *    <jk>public class</jk> ItemChannelFactory <jk>implements</jk> BeanFactory&lt;ItemChannel&gt; {
042 *       <ja>@Autowired</ja> DataSource <jv>ds</jv>;
043 *
044 *       <ja>@Override</ja>
045 *       <jk>public</jk> ItemChannel create() {
046 *          <jk>return new</jk> ItemChannel(<jv>ds</jv>);
047 *       }
048 *    }
049 *
050 *    <jc>// The target class declares which factory creates it</jc>
051 *    <ja>@Marshalled</ja>(factory=ItemChannelFactory.<jk>class</jk>)
052 *    <jk>public class</jk> ItemChannel <jk>implements</jk> BeanChannel&lt;Item&gt; { ... }
053 * </p>
054 *
055 * <h5 class='section'>See Also:</h5><ul>
056 *    <li class='jc'>{@link BeanConsumer} - Parse-only lifecycle interface
057 *    <li class='jc'>{@link BeanSupplier} - Serialize-only lifecycle interface
058 *    <li class='jc'>{@link BeanChannel} - Round-trip lifecycle interface
059 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
060 * </ul>
061 *
062 * @param <T> The type of bean this factory creates.
063 */
064@FunctionalInterface
065public interface BeanFactory<T> {
066
067   /**
068    * Creates a new instance of the bean.
069    *
070    * @return A new bean instance.
071    * @throws Exception If the bean cannot be created.
072    */
073   @SuppressWarnings({
074      "java:S112" // Functional-interface factory hook: implementations (e.g. Spring factory methods) must be free to throw any checked exception.
075   })
076   T create() throws Exception;
077
078   /**
079    * Sentinel class used as the default value for {@code @BeanType(factory=...)} and
080    * {@code @BeanProp(factory=...)} when no factory is specified.
081    */
082   @SuppressWarnings({
083      "java:S9398", // Public API annotation-default sentinel; moving it breaks adopters.
084      "rawtypes" // Raw type required for use as annotation sentinel
085   })
086   final class Void implements BeanFactory {
087      private Void() {}
088
089      @Override
090      public Object create() {
091         throw new UnsupportedOperationException("BeanFactory.Void is a sentinel and cannot be instantiated.");
092      }
093   }
094}