com.google.cloud.dataflow.sdk.coders.CoderFactories Maven / Gradle / Ivy
Show all versions of google-cloud-dataflow-java-sdk-all Show documentation
/*
* Copyright (C) 2014 Google Inc.
*
* Licensed 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 com.google.cloud.dataflow.sdk.coders;
import com.google.cloud.dataflow.sdk.values.TypeDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Static utility methods for creating and working with {@link Coder}s.
*/
public final class CoderFactories {
private CoderFactories() { } // Static utility class
/**
* Creates a {@link CoderFactory} built from particular static methods of a class that
* implements {@link Coder}.
*
* The class must have the following static methods:
*
*
* - {@code
* public static Coder
of(Coder argCoder1, Coder argCoder2, ...)
* }
* - {@code
* public static List
*
* The {@code of(...)} method will be used to construct a
* {@code Coder} from component {@link Coder}s.
* It must accept one {@link Coder} argument for each
* generic type parameter of {@code T}. If {@code T} takes no generic
* type parameters, then the {@code of()} factory method should take
* no arguments.
*
* The {@code getInstanceComponents} method will be used to
* decompose a value during the {@link Coder} inference process,
* to automatically choose coders for the components.
*
*
Note that the class {@code T} to be coded may be a
* not-yet-specialized generic class.
* For a generic class {@code MyClass} and an actual type parameter
* {@code Foo}, the {@link CoderFactoryFromStaticMethods} will
* accept any {@code Coder} and produce a {@code Coder>}.
*
* For example, the {@link CoderFactory} returned by
* {@code fromStaticMethods(ListCoder.class)}
* will produce a {@code Coder>} for any {@code Coder Coder}.
*/
public static CoderFactory fromStaticMethods(Class clazz) {
return new CoderFactoryFromStaticMethods(clazz);
}
/**
* Creates a {@link CoderFactory} that always returns the
* given coder.
*
* The {@code getInstanceComponents} method of this
* {@link CoderFactory} always returns an empty list.
*/
public static CoderFactory forCoder(Coder coder) {
return new CoderFactoryForCoder<>(coder);
}
/**
* See {@link #fromStaticMethods} for a detailed description
* of the characteristics of this {@link CoderFactory}.
*/
private static class CoderFactoryFromStaticMethods implements CoderFactory {
@Override
@SuppressWarnings("rawtypes")
public Coder create(List> componentCoders) {
try {
return (Coder) factoryMethod.invoke(
null /* static */, componentCoders.toArray());
} catch (IllegalAccessException
| IllegalArgumentException
| InvocationTargetException
| NullPointerException
| ExceptionInInitializerError exn) {
throw new IllegalStateException(
"error when invoking Coder factory method " + factoryMethod,
exn);
}
}
@Override
public List