All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.cloud.dataflow.sdk.coders.CoderProviders Maven / Gradle / Ivy

Go to download

Google Cloud Dataflow Java SDK provides a simple, Java-based interface for processing virtually any size data using Google cloud resources. This artifact includes entire Dataflow Java SDK.

There is a newer version: 2.5.0
Show newest version
/*
 * 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 static com.google.common.base.Preconditions.checkArgument;

import com.google.cloud.dataflow.sdk.util.InstanceBuilder;
import com.google.cloud.dataflow.sdk.values.TypeDescriptor;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

import java.lang.reflect.InvocationTargetException;
import java.util.List;

/**
 * Static utility methods for working with {@link CoderProvider CoderProviders}.
 */
public final class CoderProviders {

  // Static utility class
  private CoderProviders() { }

  /**
   * Creates a {@link CoderProvider} built from particular static methods of a class that
   * implements {@link Coder}. The requirements for this method are precisely the requirements
   * for a {@link Coder} class to be usable with {@link DefaultCoder} annotations.
   *
   * 

The class must have the following static method: * *

{@code
   * public static Coder of(TypeDescriptor type)
   * }
   * 
*/ public static CoderProvider fromStaticMethods(Class clazz) { return new CoderProviderFromStaticMethods(clazz); } /** * Returns a {@link CoderProvider} that consults each of the provider {@code coderProviders} * and returns the first {@link Coder} provided. * *

Note that the order in which the providers are listed matters: While the set of types * handled will be the union of those handled by all of the providers in the list, the actual * {@link Coder} provided by the first successful provider may differ, and may have inferior * properties. For example, not all {@link Coder Coders} are deterministic, handle {@code null} * values, or have comparable performance. */ public static CoderProvider firstOf(CoderProvider... coderProviders) { return new FirstOf(ImmutableList.copyOf(coderProviders)); } /////////////////////////////////////////////////////////////////////////////////////////////// /** * @see #firstOf */ private static class FirstOf implements CoderProvider { private Iterable providers; public FirstOf(Iterable providers) { this.providers = providers; } @Override public Coder getCoder(TypeDescriptor type) throws CannotProvideCoderException { List messages = Lists.newArrayList(); for (CoderProvider provider : providers) { try { return provider.getCoder(type); } catch (CannotProvideCoderException exc) { messages.add(String.format("%s could not provide a Coder for type %s: %s", provider, type, exc.getMessage())); } } throw new CannotProvideCoderException( String.format("Cannot provide coder for type %s: %s.", type, Joiner.on("; ").join(messages))); } } private static class CoderProviderFromStaticMethods implements CoderProvider { /** If true, then clazz has {@code of(TypeDescriptor)}. If false, {@code of(Class)}. */ private final boolean takesTypeDescriptor; private final Class clazz; public CoderProviderFromStaticMethods(Class clazz) { // Note that the second condition supports older classes, which only needed to provide // of(Class), not of(TypeDescriptor). Our own classes have updated to accept a // TypeDescriptor. Hence the error message points only to the current specification, // not both acceptable conditions. checkArgument(classTakesTypeDescriptor(clazz) || classTakesClass(clazz), "Class " + clazz.getCanonicalName() + " is missing required static method of(TypeDescriptor)."); this.takesTypeDescriptor = classTakesTypeDescriptor(clazz); this.clazz = clazz; } @Override public Coder getCoder(TypeDescriptor type) throws CannotProvideCoderException { try { if (takesTypeDescriptor) { @SuppressWarnings("unchecked") Coder result = InstanceBuilder.ofType(Coder.class) .fromClass(clazz) .fromFactoryMethod("of") .withArg(TypeDescriptor.class, type) .build(); return result; } else { @SuppressWarnings("unchecked") Coder result = InstanceBuilder.ofType(Coder.class) .fromClass(clazz) .fromFactoryMethod("of") .withArg(Class.class, type.getRawType()) .build(); return result; } } catch (RuntimeException exc) { if (exc.getCause() instanceof InvocationTargetException) { throw new CannotProvideCoderException(exc.getCause().getCause()); } throw exc; } } private boolean classTakesTypeDescriptor(Class clazz) { try { clazz.getDeclaredMethod("of", TypeDescriptor.class); return true; } catch (NoSuchMethodException | SecurityException exc) { return false; } } private boolean classTakesClass(Class clazz) { try { clazz.getDeclaredMethod("of", Class.class); return true; } catch (NoSuchMethodException | SecurityException exc) { return false; } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy