| /* |
| * 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. |
| */ |
| |
| // ---------------------------------------------------------------------------- |
| // This class is largely adapted from "com.google.common.base.Preconditions", |
| // which is part of the "Guava" library. |
| // |
| // Because of frequent issues with dependency conflicts, this class was |
| // added to the Flink code base to reduce dependency on Guava. |
| // ---------------------------------------------------------------------------- |
| |
| package org.apache.flink.util; |
| |
| import org.apache.flink.annotation.Internal; |
| |
| import javax.annotation.Nullable; |
| |
| import java.util.concurrent.CompletableFuture; |
| import java.util.concurrent.ExecutionException; |
| |
| /** |
| * A collection of static utility methods to validate input. |
| * |
| * <p>This class is modelled after Google Guava's Preconditions class, and partly takes code from |
| * that class. We add this code to the Flink code base in order to reduce external dependencies. |
| */ |
| @Internal |
| public final class Preconditions { |
| |
| // ------------------------------------------------------------------------ |
| // Null checks |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Ensures that the given object reference is not null. Upon violation, a {@code |
| * NullPointerException} with no message is thrown. |
| * |
| * @param reference The object reference |
| * @return The object reference itself (generically typed). |
| * @throws NullPointerException Thrown, if the passed reference was null. |
| */ |
| public static <T> T checkNotNull(@Nullable T reference) { |
| if (reference == null) { |
| throw new NullPointerException(); |
| } |
| return reference; |
| } |
| |
| /** |
| * Ensures that the given object reference is not null. Upon violation, a {@code |
| * NullPointerException} with the given message is thrown. |
| * |
| * @param reference The object reference |
| * @param errorMessage The message for the {@code NullPointerException} that is thrown if the |
| * check fails. |
| * @return The object reference itself (generically typed). |
| * @throws NullPointerException Thrown, if the passed reference was null. |
| */ |
| public static <T> T checkNotNull(@Nullable T reference, @Nullable String errorMessage) { |
| if (reference == null) { |
| throw new NullPointerException(String.valueOf(errorMessage)); |
| } |
| return reference; |
| } |
| |
| /** |
| * Ensures that the given object reference is not null. Upon violation, a {@code |
| * NullPointerException} with the given message is thrown. |
| * |
| * <p>The error message is constructed from a template and an arguments array, after a similar |
| * fashion as {@link String#format(String, Object...)}, but supporting only {@code %s} as a |
| * placeholder. |
| * |
| * @param reference The object reference |
| * @param errorMessageTemplate The message template for the {@code NullPointerException} that is |
| * thrown if the check fails. The template substitutes its {@code %s} placeholders with the |
| * error message arguments. |
| * @param errorMessageArgs The arguments for the error message, to be inserted into the message |
| * template for the {@code %s} placeholders. |
| * @return The object reference itself (generically typed). |
| * @throws NullPointerException Thrown, if the passed reference was null. |
| */ |
| public static <T> T checkNotNull( |
| T reference, |
| @Nullable String errorMessageTemplate, |
| @Nullable Object... errorMessageArgs) { |
| |
| if (reference == null) { |
| throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs)); |
| } |
| return reference; |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Boolean Condition Checking (Argument) |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Checks the given boolean condition, and throws an {@code IllegalArgumentException} if the |
| * condition is not met (evaluates to {@code false}). |
| * |
| * @param condition The condition to check |
| * @throws IllegalArgumentException Thrown, if the condition is violated. |
| */ |
| public static void checkArgument(boolean condition) { |
| if (!condition) { |
| throw new IllegalArgumentException(); |
| } |
| } |
| |
| /** |
| * Checks the given boolean condition, and throws an {@code IllegalArgumentException} if the |
| * condition is not met (evaluates to {@code false}). The exception will have the given error |
| * message. |
| * |
| * @param condition The condition to check |
| * @param errorMessage The message for the {@code IllegalArgumentException} that is thrown if |
| * the check fails. |
| * @throws IllegalArgumentException Thrown, if the condition is violated. |
| */ |
| public static void checkArgument(boolean condition, @Nullable Object errorMessage) { |
| if (!condition) { |
| throw new IllegalArgumentException(String.valueOf(errorMessage)); |
| } |
| } |
| |
| /** |
| * Checks the given boolean condition, and throws an {@code IllegalArgumentException} if the |
| * condition is not met (evaluates to {@code false}). |
| * |
| * @param condition The condition to check |
| * @param errorMessageTemplate The message template for the {@code IllegalArgumentException} |
| * that is thrown if the check fails. The template substitutes its {@code %s} placeholders |
| * with the error message arguments. |
| * @param errorMessageArgs The arguments for the error message, to be inserted into the message |
| * template for the {@code %s} placeholders. |
| * @throws IllegalArgumentException Thrown, if the condition is violated. |
| */ |
| public static void checkArgument( |
| boolean condition, |
| @Nullable String errorMessageTemplate, |
| @Nullable Object... errorMessageArgs) { |
| |
| if (!condition) { |
| throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs)); |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Boolean Condition Checking (State) |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Checks the given boolean condition, and throws an {@code IllegalStateException} if the |
| * condition is not met (evaluates to {@code false}). |
| * |
| * @param condition The condition to check |
| * @throws IllegalStateException Thrown, if the condition is violated. |
| */ |
| public static void checkState(boolean condition) { |
| if (!condition) { |
| throw new IllegalStateException(); |
| } |
| } |
| |
| /** |
| * Checks the given boolean condition, and throws an {@code IllegalStateException} if the |
| * condition is not met (evaluates to {@code false}). The exception will have the given error |
| * message. |
| * |
| * @param condition The condition to check |
| * @param errorMessage The message for the {@code IllegalStateException} that is thrown if the |
| * check fails. |
| * @throws IllegalStateException Thrown, if the condition is violated. |
| */ |
| public static void checkState(boolean condition, @Nullable Object errorMessage) { |
| if (!condition) { |
| throw new IllegalStateException(String.valueOf(errorMessage)); |
| } |
| } |
| |
| /** |
| * Checks the given boolean condition, and throws an {@code IllegalStateException} if the |
| * condition is not met (evaluates to {@code false}). |
| * |
| * @param condition The condition to check |
| * @param errorMessageTemplate The message template for the {@code IllegalStateException} that |
| * is thrown if the check fails. The template substitutes its {@code %s} placeholders with |
| * the error message arguments. |
| * @param errorMessageArgs The arguments for the error message, to be inserted into the message |
| * template for the {@code %s} placeholders. |
| * @throws IllegalStateException Thrown, if the condition is violated. |
| */ |
| public static void checkState( |
| boolean condition, |
| @Nullable String errorMessageTemplate, |
| @Nullable Object... errorMessageArgs) { |
| |
| if (!condition) { |
| throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs)); |
| } |
| } |
| |
| /** |
| * Ensures that the given index is valid for an array, list or string of the given size. |
| * |
| * @param index index to check |
| * @param size size of the array, list or string |
| * @throws IllegalArgumentException Thrown, if size is negative. |
| * @throws IndexOutOfBoundsException Thrown, if the index negative or greater than or equal to |
| * size |
| */ |
| public static void checkElementIndex(int index, int size) { |
| checkArgument(size >= 0, "Size was negative."); |
| if (index < 0 || index >= size) { |
| throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); |
| } |
| } |
| |
| /** |
| * Ensures that the given index is valid for an array, list or string of the given size. |
| * |
| * @param index index to check |
| * @param size size of the array, list or string |
| * @param errorMessage The message for the {@code IndexOutOfBoundsException} that is thrown if |
| * the check fails. |
| * @throws IllegalArgumentException Thrown, if size is negative. |
| * @throws IndexOutOfBoundsException Thrown, if the index negative or greater than or equal to |
| * size |
| */ |
| public static void checkElementIndex(int index, int size, @Nullable String errorMessage) { |
| checkArgument(size >= 0, "Size was negative."); |
| if (index < 0 || index >= size) { |
| throw new IndexOutOfBoundsException( |
| String.valueOf(errorMessage) + " Index: " + index + ", Size: " + size); |
| } |
| } |
| |
| /** |
| * Ensures that future has completed normally. |
| * |
| * @throws IllegalStateException Thrown, if future has not completed or it has completed |
| * exceptionally. |
| */ |
| public static void checkCompletedNormally(CompletableFuture<?> future) { |
| checkState(future.isDone()); |
| if (future.isCompletedExceptionally()) { |
| try { |
| future.get(); |
| } catch (InterruptedException | ExecutionException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Utilities |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * A simplified formatting method. Similar to {@link String#format(String, Object...)}, but with |
| * lower overhead (only String parameters, no locale, no format validation). |
| * |
| * <p>This method is taken quasi verbatim from the Guava Preconditions class. |
| */ |
| private static String format(@Nullable String template, @Nullable Object... args) { |
| final int numArgs = args == null ? 0 : args.length; |
| template = String.valueOf(template); // null -> "null" |
| |
| // start substituting the arguments into the '%s' placeholders |
| StringBuilder builder = new StringBuilder(template.length() + 16 * numArgs); |
| int templateStart = 0; |
| int i = 0; |
| while (i < numArgs) { |
| int placeholderStart = template.indexOf("%s", templateStart); |
| if (placeholderStart == -1) { |
| break; |
| } |
| builder.append(template.substring(templateStart, placeholderStart)); |
| builder.append(args[i++]); |
| templateStart = placeholderStart + 2; |
| } |
| builder.append(template.substring(templateStart)); |
| |
| // if we run out of placeholders, append the extra args in square braces |
| if (i < numArgs) { |
| builder.append(" ["); |
| builder.append(args[i++]); |
| while (i < numArgs) { |
| builder.append(", "); |
| builder.append(args[i++]); |
| } |
| builder.append(']'); |
| } |
| |
| return builder.toString(); |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| /** Private constructor to prevent instantiation. */ |
| private Preconditions() {} |
| } |