/* * 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.runners.core; import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import org.apache.beam.sdk.coders.Coder; import org.apache.beam.sdk.transforms.windowing.BoundedWindow; import org.apache.beam.sdk.util.WindowedValue; import org.apache.beam.sdk.values.TupleTag; /** * Base class for implementations of {@link ExecutionContext}. * * <p>A concrete subclass should implement {@link #createStepContext} to create the appropriate * {@link StepContext} implementation. Any {@code StepContext} created will * be cached for the lifetime of this {@link ExecutionContext}. * * <p>BaseExecutionContext is generic to allow implementing subclasses to return a concrete subclass * of {@link StepContext} from {@link #getOrCreateStepContext(String, String)} and * {@link #getAllStepContexts()} without forcing each subclass to override the method, e.g. * <pre>{@code * {@literal @}Override * StreamingModeExecutionContext.StepContext getOrCreateStepContext(...) { * return (StreamingModeExecutionContext.StepContext) super.getOrCreateStepContext(...); * } * }</pre> * * <p>When a subclass of {@code BaseExecutionContext} has been downcast, the return types of * {@link #createStepContext(String, String)}, * {@link #getOrCreateStepContext(String, String)}, and {@link #getAllStepContexts()} * will be appropriately specialized. */ public abstract class BaseExecutionContext<T extends ExecutionContext.StepContext> implements ExecutionContext { private Map<String, T> cachedStepContexts = new LinkedHashMap<>(); /** * Implementations should override this to create the specific type * of {@link StepContext} they need. */ protected abstract T createStepContext(String stepName, String transformName); /** * Returns the {@link StepContext} associated with the given step. */ @Override public T getOrCreateStepContext(String stepName, String transformName) { final String finalStepName = stepName; final String finalTransformName = transformName; return getOrCreateStepContext( stepName, new CreateStepContextFunction<T>() { @Override public T create() { return createStepContext(finalStepName, finalTransformName); } }); } /** * Factory method interface to create an execution context if none exists during * {@link #getOrCreateStepContext(String, CreateStepContextFunction)}. */ protected interface CreateStepContextFunction<T extends ExecutionContext.StepContext> { T create(); } protected final T getOrCreateStepContext(String stepName, CreateStepContextFunction<T> createContextFunc) { T context = cachedStepContexts.get(stepName); if (context == null) { context = createContextFunc.create(); cachedStepContexts.put(stepName, context); } return context; } /** * Returns a collection view of all of the {@link StepContext}s. */ @Override public Collection<? extends T> getAllStepContexts() { return Collections.unmodifiableCollection(cachedStepContexts.values()); } @Override public void noteOutput(WindowedValue<?> output) {} @Override public void noteOutput(TupleTag<?> tag, WindowedValue<?> output) {} /** * Base class for implementations of {@link ExecutionContext.StepContext}. * * <p>To complete a concrete subclass, implement {@link #timerInternals} and * {@link #stateInternals}. */ public abstract static class StepContext implements ExecutionContext.StepContext { private final ExecutionContext executionContext; private final String stepName; private final String transformName; public StepContext(ExecutionContext executionContext, String stepName, String transformName) { this.executionContext = executionContext; this.stepName = stepName; this.transformName = transformName; } @Override public String getStepName() { return stepName; } @Override public String getTransformName() { return transformName; } @Override public void noteOutput(WindowedValue<?> output) { executionContext.noteOutput(output); } @Override public void noteOutput(TupleTag<?> tag, WindowedValue<?> output) { executionContext.noteOutput(tag, output); } @Override public <T, W extends BoundedWindow> void writePCollectionViewData( TupleTag<?> tag, Iterable<WindowedValue<T>> data, Coder<Iterable<WindowedValue<T>>> dataCoder, W window, Coder<W> windowCoder) throws IOException { throw new UnsupportedOperationException("Not implemented."); } @Override public abstract StateInternals stateInternals(); @Override public abstract TimerInternals timerInternals(); } }