001/**
002 * Copyright (C) 2006-2026 Talend Inc. - www.talend.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * 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
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.talend.sdk.component.api.processor;
017
018import java.util.Iterator;
019
020/**
021 * Allows a processor to stream records lazily to multiple output connections
022 * without buffering, supporting two mutually exclusive modes per invocation:
023 *
024 * <ul>
025 * <li><b>Split mode</b> ({@link #setIterator(Iterator)}): a single tagged iterator
026 * routes each record to a specific output connection via {@link TaggedOutput}.
027 * Use when records come from one shared source and must be split between outputs.</li>
028 * <li><b>Independent mode</b> ({@link #setIterator(String, Iterator)}): each output
029 * connection gets its own independent lazy iterator, consumed in parallel by the drain
030 * loop. Use when each output has its own self-contained lazy source.</li>
031 * </ul>
032 *
033 * <p>
034 * Both modes can be selected at runtime from the same fixed method parameter,
035 * so the component does not need separate parameters per output.
036 *
037 * <p>
038 * It is equally valid to use it with a <b>single</b> output: the point is then to stream records lazily
039 * instead of pushing them through an {@link OutputEmitter}, which avoids buffering. In that case the
040 * branch is named as usual with {@code @Output("FLOW")}; {@code @Output(branches = ...)} is only needed
041 * when the parameter feeds several branches, to declare them to the design layer.
042 *
043 * <p>
044 * <b>Important:</b> This interface is supported only in the Studio DI runtime.
045 *
046 * <p>
047 * <b>Split mode example</b> (one source, per-record routing):
048 *
049 * <pre>
050 * {@code
051 * 
052 * &#64;ElementListener
053 * public void process(&#64;Input Record input,
054 *         &#64;Output(branches = { "MAIN", "REJECT" }) MultiOutputIterator<Record> out) {
055 *     out.setIterator(
056 *             mySource.stream()
057 *                     .map(r -> isValid(r)
058 *                             ? TaggedOutput.of("MAIN", transform(r))
059 *                             : TaggedOutput.of("REJECT", r))
060 *                     .iterator());
061 * }
062 * }
063 * </pre>
064 *
065 * <p>
066 * <b>Independent mode example</b> (each output has its own lazy source):
067 *
068 * <pre>
069 * {@code
070 * 
071 * &#64;AfterGroup
072 * public void afterGroup(&#64;Output(branches = { "MAIN", "REJECT" }) MultiOutputIterator<Record> out) {
073 *     out.setIterator("MAIN", mainDatabase.lazyQuery());
074 *     out.setIterator("REJECT", errorLog.lazyRead());
075 * }
076 * }
077 * </pre>
078 *
079 * @param <T> the record type
080 * @see TaggedOutput
081 */
082public interface MultiOutputIterator<T> {
083
084    /**
085     * <b>Split mode</b>: sets a single lazy iterator whose elements are tagged with
086     * the target output connection name via {@link TaggedOutput}.
087     * The runtime reads one record at a time and routes it to the matching connection.
088     *
089     * <p>
090     * Mutually exclusive with {@link #setIterator(String, Iterator)} within one invocation.
091     *
092     * @param iterator the tagged iterator routing records to their named outputs
093     */
094    void setIterator(Iterator<TaggedOutput<T>> iterator);
095
096    /**
097     * <b>Independent mode</b>: assigns a lazy iterator to a specific named output connection.
098     * Call once per output that needs a dedicated lazy source; connections without an
099     * assigned iterator fall back to the push-mode queue as usual.
100     *
101     * <p>
102     * Mutually exclusive with {@link #setIterator(Iterator)} within one invocation.
103     *
104     * @param outputName the output connection name (e.g. {@code "MAIN"}, {@code "REJECT"})
105     * @param iterator the lazy iterator producing records for that connection
106     */
107    void setIterator(String outputName, Iterator<T> iterator);
108}