/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.beam.sdk.transforms;
import org.apache.beam.sdk.PipelineRunner;
import org.apache.beam.sdk.options.PipelineOptions;
import org.apache.beam.sdk.transforms.Combine.CombineFn;
import org.apache.beam.sdk.values.PCollectionView;
/**
* This class contains combine functions that have access to {@code PipelineOptions} and side inputs
* through {@code CombineWithContext.Context}.
*
* <p>{@link CombineFnWithContext} is for users to extend.
*/
public class CombineWithContext {
/**
* Information accessible to all methods in {@code CombineFnWithContext}
* and {@code KeyedCombineFnWithContext}.
*/
public abstract static class Context {
/**
* Returns the {@code PipelineOptions} specified with the
* {@link PipelineRunner}
* invoking this {@code KeyedCombineFn}.
*/
public abstract PipelineOptions getPipelineOptions();
/**
* Returns the value of the side input for the window corresponding to the
* main input's window in which values are being combined.
*/
public abstract <T> T sideInput(PCollectionView<T> view);
}
/**
* An internal interface for signaling that a {@code GloballyCombineFn}
* or a {@code PerKeyCombineFn} needs to access {@code CombineWithContext.Context}.
*
* <p>For internal use only.
*/
public interface RequiresContextInternal {}
/**
* A combine function that has access to {@code PipelineOptions} and side inputs through
* {@code CombineWithContext.Context}.
*
* <p>See the equivalent {@link CombineFn} for details about combine functions.
*/
public abstract static class CombineFnWithContext<InputT, AccumT, OutputT>
extends CombineFnBase.AbstractGlobalCombineFn<InputT, AccumT, OutputT>
implements RequiresContextInternal {
/**
* Returns a new, mutable accumulator value, representing the accumulation of zero input values.
*
* <p>It is equivalent to {@link CombineFn#createAccumulator}, but it has additional access to
* {@code CombineWithContext.Context}.
*/
public abstract AccumT createAccumulator(Context c);
/**
* Adds the given input value to the given accumulator, returning the
* new accumulator value.
*
* <p>It is equivalent to {@link CombineFn#addInput}, but it has additional access to
* {@code CombineWithContext.Context}.
*/
public abstract AccumT addInput(AccumT accumulator, InputT input, Context c);
/**
* Returns an accumulator representing the accumulation of all the
* input values accumulated in the merging accumulators.
*
* <p>It is equivalent to {@link CombineFn#mergeAccumulators}, but it has additional access to
* {@code CombineWithContext.Context}.
*/
public abstract AccumT mergeAccumulators(Iterable<AccumT> accumulators, Context c);
/**
* Returns the output value that is the result of combining all
* the input values represented by the given accumulator.
*
* <p>It is equivalent to {@link CombineFn#extractOutput}, but it has additional access to
* {@code CombineWithContext.Context}.
*/
public abstract OutputT extractOutput(AccumT accumulator, Context c);
/**
* Returns an accumulator that represents the same logical value as the
* input accumulator, but may have a more compact representation.
*
* <p>It is equivalent to {@link CombineFn#compact}, but it has additional access to
* {@code CombineWithContext.Context}.
*/
public AccumT compact(AccumT accumulator, Context c) {
return accumulator;
}
/**
* Applies this {@code CombineFnWithContext} to a collection of input values to produce a
* combined output value.
*/
public OutputT apply(Iterable<? extends InputT> inputs, Context c) {
AccumT accum = createAccumulator(c);
for (InputT input : inputs) {
accum = addInput(accum, input, c);
}
return extractOutput(accum, c);
}
@Override
public OutputT defaultValue() {
throw new UnsupportedOperationException(
"Override this function to provide the default value.");
}
}
}