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/**
020 * A lifecycle-aware producer for use as a serializer source, providing beans lazily one at a time.
021 *
022 * <p>
023 * Extends {@link Iterable} so that {@code ClassMeta}'s existing {@code ITERABLE} category picks it
024 * up automatically — no new type category is needed in the framework.
025 *
026 * <p>
027 * The serializer drives the full lifecycle:
028 * <ol>
029 *    <li>Calls {@link #begin()} before iteration starts
030 *    <li>Iterates elements via {@link #iterator()}, serializing each
031 *    <li>If an exception occurs during iteration, calls {@link #onError(Exception)}
032 *    <li>Always calls {@link #complete()} after iteration (like {@code finally}) — whether
033 *        serialization succeeded or failed. Use this for resource cleanup (close cursors, connections, etc.)
034 * </ol>
035 *
036 * <p>
037 * For round-trip support (same property used for both serialization and parsing), use
038 * {@link BeanChannel} instead, which extends both {@link BeanSupplier} and {@link BeanConsumer}.
039 *
040 * <p>
041 * If a {@link BeanSupplier} is encountered during parsing (not serialization), the parser will
042 * throw an {@link IllegalArgumentException} with a message recommending {@link BeanConsumer} or
043 * {@link BeanChannel}.
044 *
045 * <h5 class='section'>Example (DB-backed supplier via JDBC cursor):</h5>
046 * <p class='bjava'>
047 *    <ja>@Marshalled</ja>(factory=ItemSupplierFactory.<jk>class</jk>)
048 *    <jk>public class</jk> ItemSupplier <jk>implements</jk> BeanSupplier&lt;Item&gt; {
049 *       <jk>private</jk> Connection <jv>conn</jv>;
050 *       <jk>private</jk> ResultSet <jv>rs</jv>;
051 *
052 *       <ja>@Override</ja> <jk>public void</jk> begin() <jk>throws</jk> Exception {
053 *          <jv>conn</jv> = <jv>ds</jv>.getConnection();
054 *          <jv>rs</jv> = <jv>conn</jv>.prepareStatement(<js>"SELECT * FROM items"</js>).executeQuery();
055 *       }
056 *
057 *       <ja>@Override</ja> <jk>public</jk> Iterator&lt;Item&gt; iterator() {
058 *          <jk>return new</jk> ResultSetIterator&lt;&gt;(<jv>rs</jv>, Item::<jv>fromRow</jv>);
059 *       }
060 *
061 *       <ja>@Override</ja> <jk>public void</jk> onError(Exception <jv>e</jv>) <jk>throws</jk> Exception {
062 *          <jv>rs</jv>.close(); <jk>throw</jk> <jv>e</jv>;
063 *       }
064 *
065 *       <ja>@Override</ja> <jk>public void</jk> complete() <jk>throws</jk> Exception {
066 *          <jv>rs</jv>.close(); <jv>conn</jv>.close();
067 *       }
068 *    }
069 * </p>
070 *
071 * <h5 class='section'>See Also:</h5><ul>
072 *    <li class='jc'>{@link BeanConsumer} - Parse-only lifecycle interface
073 *    <li class='jc'>{@link BeanChannel} - Round-trip lifecycle interface (extends both)
074 *    <li class='jc'>{@link BeanFactory} - Universal factory for DI framework integration
075 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a>
076 * </ul>
077 *
078 * @param <T> The type of bean provided by this supplier.
079 */
080@SuppressWarnings({
081   "java:S112" // throws Exception intentional - lifecycle methods may throw any checked exception
082})
083public interface BeanSupplier<T> extends Iterable<T> {
084
085   /**
086    * Called before iteration starts.
087    *
088    * <p>
089    * Use this to open database connections, execute queries, or perform other setup.
090    *
091    * @throws Exception If setup fails.
092    */
093   default void begin() throws Exception {}
094
095   /**
096    * Always called after iteration ends (like {@code finally}).
097    *
098    * <p>
099    * Use this to close database cursors, connections, or release other resources.
100    * This method is called whether serialization succeeded or {@link #onError(Exception)} rethrew.
101    *
102    * @throws Exception If cleanup fails.
103    */
104   default void complete() throws Exception {}
105
106   /**
107    * Called when an exception occurs during iteration.
108    *
109    * <p>
110    * The default implementation rethrows the exception, stopping serialization immediately.
111    * Note that {@link #complete()} is always called afterward regardless.
112    *
113    * @param e The exception that occurred during iteration.
114    * @throws Exception If the error cannot be recovered from. Rethrow {@code e} to stop serialization.
115    */
116   default void onError(Exception e) throws Exception {
117      throw e;
118   }
119}