• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018, OpenCensus Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.opencensus.internal;
18 
19 import java.util.List;
20 import java.util.Map;
21 
22 /*>>>
23 import org.checkerframework.checker.nullness.qual.NonNull;
24 */
25 
26 /** General internal utility methods. */
27 public final class Utils {
28 
Utils()29   private Utils() {}
30 
31   /**
32    * Throws an {@link IllegalArgumentException} if the argument is false. This method is similar to
33    * {@code Preconditions.checkArgument(boolean, Object)} from Guava.
34    *
35    * @param isValid whether the argument check passed.
36    * @param errorMessage the message to use for the exception. Will be converted to a string using
37    *     {@link String#valueOf(Object)}.
38    */
checkArgument( boolean isValid, @javax.annotation.Nullable Object errorMessage)39   public static void checkArgument(
40       boolean isValid, @javax.annotation.Nullable Object errorMessage) {
41     if (!isValid) {
42       throw new IllegalArgumentException(String.valueOf(errorMessage));
43     }
44   }
45 
46   /**
47    * Throws an {@link IllegalArgumentException} if the argument is false. This method is similar to
48    * {@code Preconditions.checkArgument(boolean, Object)} from Guava.
49    *
50    * @param expression a boolean expression
51    * @param errorMessageTemplate a template for the exception message should the check fail. The
52    *     message is formed by replacing each {@code %s} placeholder in the template with an
53    *     argument. These are matched by position - the first {@code %s} gets {@code
54    *     errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message in
55    *     square braces. Unmatched placeholders will be left as-is.
56    * @param errorMessageArgs the arguments to be substituted into the message template. Arguments
57    *     are converted to strings using {@link String#valueOf(Object)}.
58    * @throws IllegalArgumentException if {@code expression} is false
59    * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or
60    *     {@code errorMessageArgs} is null (don't let this happen)
61    */
checkArgument( boolean expression, String errorMessageTemplate, @javax.annotation.Nullable Object... errorMessageArgs)62   public static void checkArgument(
63       boolean expression,
64       String errorMessageTemplate,
65       @javax.annotation.Nullable Object... errorMessageArgs) {
66     if (!expression) {
67       throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs));
68     }
69   }
70 
71   /**
72    * Throws an {@link IllegalStateException} if the argument is false. This method is similar to
73    * {@code Preconditions.checkState(boolean, Object)} from Guava.
74    *
75    * @param isValid whether the state check passed.
76    * @param errorMessage the message to use for the exception. Will be converted to a string using
77    *     {@link String#valueOf(Object)}.
78    */
checkState(boolean isValid, @javax.annotation.Nullable Object errorMessage)79   public static void checkState(boolean isValid, @javax.annotation.Nullable Object errorMessage) {
80     if (!isValid) {
81       throw new IllegalStateException(String.valueOf(errorMessage));
82     }
83   }
84 
85   /**
86    * Validates an index in an array or other container. This method throws an {@link
87    * IllegalArgumentException} if the size is negative and throws an {@link
88    * IndexOutOfBoundsException} if the index is negative or greater than or equal to the size. This
89    * method is similar to {@code Preconditions.checkElementIndex(int, int)} from Guava.
90    *
91    * @param index the index to validate.
92    * @param size the size of the array or container.
93    */
checkIndex(int index, int size)94   public static void checkIndex(int index, int size) {
95     if (size < 0) {
96       throw new IllegalArgumentException("Negative size: " + size);
97     }
98     if (index < 0 || index >= size) {
99       throw new IndexOutOfBoundsException("Index out of bounds: size=" + size + ", index=" + index);
100     }
101   }
102 
103   /**
104    * Throws a {@link NullPointerException} if the argument is null. This method is similar to {@code
105    * Preconditions.checkNotNull(Object, Object)} from Guava.
106    *
107    * @param arg the argument to check for null.
108    * @param errorMessage the message to use for the exception. Will be converted to a string using
109    *     {@link String#valueOf(Object)}.
110    * @return the argument, if it passes the null check.
111    */
checkNotNull( T arg, @javax.annotation.Nullable Object errorMessage)112   public static <T /*>>> extends @NonNull Object*/> T checkNotNull(
113       T arg, @javax.annotation.Nullable Object errorMessage) {
114     if (arg == null) {
115       throw new NullPointerException(String.valueOf(errorMessage));
116     }
117     return arg;
118   }
119 
120   /**
121    * Throws a {@link NullPointerException} if any of the list elements is null.
122    *
123    * @param list the argument list to check for null.
124    * @param errorMessage the message to use for the exception. Will be converted to a string using
125    *     {@link String#valueOf(Object)}.
126    */
checkListElementNotNull( List<T> list, @javax.annotation.Nullable Object errorMessage)127   public static <T /*>>> extends @NonNull Object*/> void checkListElementNotNull(
128       List<T> list, @javax.annotation.Nullable Object errorMessage) {
129     for (T element : list) {
130       if (element == null) {
131         throw new NullPointerException(String.valueOf(errorMessage));
132       }
133     }
134   }
135 
136   /**
137    * Throws a {@link NullPointerException} if any of the map elements is null.
138    *
139    * @param map the argument map to check for null.
140    * @param errorMessage the message to use for the exception. Will be converted to a string using
141    *     {@link String#valueOf(Object)}.
142    */
143   public static <K /*>>> extends @NonNull Object*/, V /*>>> extends @NonNull Object*/>
checkMapElementNotNull(Map<K, V> map, @javax.annotation.Nullable Object errorMessage)144       void checkMapElementNotNull(Map<K, V> map, @javax.annotation.Nullable Object errorMessage) {
145     for (Map.Entry<K, V> entry : map.entrySet()) {
146       if (entry.getKey() == null || entry.getValue() == null) {
147         throw new NullPointerException(String.valueOf(errorMessage));
148       }
149     }
150   }
151 
152   /**
153    * Compares two Objects for equality. This functionality is provided by {@code
154    * Objects.equal(Object, Object)} in Java 7.
155    */
equalsObjects( @avax.annotation.Nullable Object x, @javax.annotation.Nullable Object y)156   public static boolean equalsObjects(
157       @javax.annotation.Nullable Object x, @javax.annotation.Nullable Object y) {
158     return x == null ? y == null : x.equals(y);
159   }
160 
161   /**
162    * Substitutes each {@code %s} in {@code template} with an argument. These are matched by
163    * position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than
164    * placeholders, the unmatched arguments will be appended to the end of the formatted message in
165    * square braces.
166    *
167    * <p>Copied from {@code Preconditions.format(String, Object...)} from Guava
168    *
169    * @param template a non-null string containing 0 or more {@code %s} placeholders.
170    * @param args the arguments to be substituted into the message template. Arguments are converted
171    *     to strings using {@link String#valueOf(Object)}. Arguments can be null.
172    */
173   // Note that this is somewhat-improperly used from Verify.java as well.
format(String template, @javax.annotation.Nullable Object... args)174   private static String format(String template, @javax.annotation.Nullable Object... args) {
175     // If no arguments return the template.
176     if (args == null) {
177       return template;
178     }
179 
180     // start substituting the arguments into the '%s' placeholders
181     StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
182     int templateStart = 0;
183     int i = 0;
184     while (i < args.length) {
185       int placeholderStart = template.indexOf("%s", templateStart);
186       if (placeholderStart == -1) {
187         break;
188       }
189       builder.append(template, templateStart, placeholderStart);
190       builder.append(args[i++]);
191       templateStart = placeholderStart + 2;
192     }
193     builder.append(template, templateStart, template.length());
194 
195     // if we run out of placeholders, append the extra args in square braces
196     if (i < args.length) {
197       builder.append(" [");
198       builder.append(args[i++]);
199       while (i < args.length) {
200         builder.append(", ");
201         builder.append(args[i++]);
202       }
203       builder.append(']');
204     }
205 
206     return builder.toString();
207   }
208 }
209