001/*
002 * Copyright (C) 2014 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015package com.google.common.base;
016
017import static com.google.common.base.Preconditions.checkNotNull;
018
019import com.google.common.annotations.GwtCompatible;
020import com.google.errorprone.annotations.CanIgnoreReturnValue;
021import java.lang.reflect.Array;
022import java.util.Arrays;
023import java.util.Collection;
024import java.util.Map;
025import javax.annotation.CheckForNull;
026
027/**
028 * Helper functions that operate on any {@code Object}, and are not already provided in {@link
029 * java.util.Objects}.
030 *
031 * <p>See the Guava User Guide on <a
032 * href="https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained">writing {@code Object}
033 * methods with {@code MoreObjects}</a>.
034 *
035 * @author Laurence Gonsalves
036 * @since 18.0 (since 2.0 as {@code Objects})
037 */
038@GwtCompatible
039@ElementTypesAreNonnullByDefault
040public final class MoreObjects {
041  /**
042   * Returns the first of two given parameters that is not {@code null}, if either is, or otherwise
043   * throws a {@link NullPointerException}.
044   *
045   * <p>To find the first non-null element in an iterable, use {@code Iterables.find(iterable,
046   * Predicates.notNull())}. For varargs, use {@code Iterables.find(Arrays.asList(a, b, c, ...),
047   * Predicates.notNull())}, static importing as necessary.
048   *
049   * <p><b>Note:</b> if {@code first} is represented as an {@link Optional}, this can be
050   * accomplished with {@link Optional#or(Object) first.or(second)}. That approach also allows for
051   * lazy evaluation of the fallback instance, using {@link Optional#or(Supplier)
052   * first.or(supplier)}.
053   *
054   * <p><b>Java 9 users:</b> use {@code java.util.Objects.requireNonNullElse(first, second)}
055   * instead.
056   *
057   * @return {@code first} if it is non-null; otherwise {@code second} if it is non-null
058   * @throws NullPointerException if both {@code first} and {@code second} are null
059   * @since 18.0 (since 3.0 as {@code Objects.firstNonNull()}).
060   */
061  /*
062   * We annotate firstNonNull in a way that protects against NullPointerException at the cost of
063   * forbidding some reasonable calls.
064   *
065   * The more permissive signature would be to accept (@CheckForNull T first, @CheckForNull T
066   * second), since it's OK for `second` to be null as long as `first` is not also null. But we
067   * expect for that flexibility to be useful relatively rarely: The more common use case is to
068   * supply a clearly non-null default, like `firstNonNull(someString, "")`. And users who really
069   * know that `first` is guaranteed non-null when `second` is null can write the logic out
070   * longhand, including a requireNonNull call, which calls attention to the fact that the static
071   * analyzer can't prove that the operation is safe.
072   *
073   * This matches the signature we currently have for requireNonNullElse in our own checker. (And
074   * that in turn matches that method's signature under the Checker Framework.) As always, we could
075   * consider the more flexible signature if we judge it worth the risks. If we do, we would likely
076   * update both methods so that they continue to match.
077   */
078  public static <T> T firstNonNull(@CheckForNull T first, T second) {
079    if (first != null) {
080      return first;
081    }
082    if (second != null) {
083      return second;
084    }
085    throw new NullPointerException("Both parameters are null");
086  }
087
088  /**
089   * Creates an instance of {@link ToStringHelper}.
090   *
091   * <p>This is helpful for implementing {@link Object#toString()}. Specification by example:
092   *
093   * <pre>{@code
094   * // Returns "ClassName{}"
095   * MoreObjects.toStringHelper(this)
096   *     .toString();
097   *
098   * // Returns "ClassName{x=1}"
099   * MoreObjects.toStringHelper(this)
100   *     .add("x", 1)
101   *     .toString();
102   *
103   * // Returns "MyObject{x=1}"
104   * MoreObjects.toStringHelper("MyObject")
105   *     .add("x", 1)
106   *     .toString();
107   *
108   * // Returns "ClassName{x=1, y=foo}"
109   * MoreObjects.toStringHelper(this)
110   *     .add("x", 1)
111   *     .add("y", "foo")
112   *     .toString();
113   *
114   * // Returns "ClassName{x=1}"
115   * MoreObjects.toStringHelper(this)
116   *     .omitNullValues()
117   *     .add("x", 1)
118   *     .add("y", null)
119   *     .toString();
120   * }</pre>
121   *
122   * <p>Note that in GWT, class names are often obfuscated.
123   *
124   * @param self the object to generate the string for (typically {@code this}), used only for its
125   *     class name
126   * @since 18.0 (since 2.0 as {@code Objects.toStringHelper()}).
127   */
128  public static ToStringHelper toStringHelper(Object self) {
129    return new ToStringHelper(self.getClass().getSimpleName());
130  }
131
132  /**
133   * Creates an instance of {@link ToStringHelper} in the same manner as {@link
134   * #toStringHelper(Object)}, but using the simple name of {@code clazz} instead of using an
135   * instance's {@link Object#getClass()}.
136   *
137   * <p>Note that in GWT, class names are often obfuscated.
138   *
139   * @param clazz the {@link Class} of the instance
140   * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}).
141   */
142  public static ToStringHelper toStringHelper(Class<?> clazz) {
143    return new ToStringHelper(clazz.getSimpleName());
144  }
145
146  /**
147   * Creates an instance of {@link ToStringHelper} in the same manner as {@link
148   * #toStringHelper(Object)}, but using {@code className} instead of using an instance's {@link
149   * Object#getClass()}.
150   *
151   * @param className the name of the instance type
152   * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}).
153   */
154  public static ToStringHelper toStringHelper(String className) {
155    return new ToStringHelper(className);
156  }
157
158  /**
159   * Support class for {@link MoreObjects#toStringHelper}.
160   *
161   * @author Jason Lee
162   * @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}).
163   */
164  public static final class ToStringHelper {
165    private final String className;
166    private final ValueHolder holderHead = new ValueHolder();
167    private ValueHolder holderTail = holderHead;
168    private boolean omitNullValues = false;
169    private boolean omitEmptyValues = false;
170
171    /** Use {@link MoreObjects#toStringHelper(Object)} to create an instance. */
172    private ToStringHelper(String className) {
173      this.className = checkNotNull(className);
174    }
175
176    /**
177     * Configures the {@link ToStringHelper} so {@link #toString()} will ignore properties with null
178     * value. The order of calling this method, relative to the {@code add()}/{@code addValue()}
179     * methods, is not significant.
180     *
181     * @since 18.0 (since 12.0 as {@code Objects.ToStringHelper.omitNullValues()}).
182     */
183    @CanIgnoreReturnValue
184    public ToStringHelper omitNullValues() {
185      omitNullValues = true;
186      return this;
187    }
188
189    /**
190     * Adds a name/value pair to the formatted output in {@code name=value} format. If {@code value}
191     * is {@code null}, the string {@code "null"} is used, unless {@link #omitNullValues()} is
192     * called, in which case this name/value pair will not be added.
193     */
194    @CanIgnoreReturnValue
195    public ToStringHelper add(String name, @CheckForNull Object value) {
196      return addHolder(name, value);
197    }
198
199    /**
200     * Adds a name/value pair to the formatted output in {@code name=value} format.
201     *
202     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
203     */
204    @CanIgnoreReturnValue
205    public ToStringHelper add(String name, boolean value) {
206      return addUnconditionalHolder(name, String.valueOf(value));
207    }
208
209    /**
210     * Adds a name/value pair to the formatted output in {@code name=value} format.
211     *
212     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
213     */
214    @CanIgnoreReturnValue
215    public ToStringHelper add(String name, char value) {
216      return addUnconditionalHolder(name, String.valueOf(value));
217    }
218
219    /**
220     * Adds a name/value pair to the formatted output in {@code name=value} format.
221     *
222     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
223     */
224    @CanIgnoreReturnValue
225    public ToStringHelper add(String name, double value) {
226      return addUnconditionalHolder(name, String.valueOf(value));
227    }
228
229    /**
230     * Adds a name/value pair to the formatted output in {@code name=value} format.
231     *
232     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
233     */
234    @CanIgnoreReturnValue
235    public ToStringHelper add(String name, float value) {
236      return addUnconditionalHolder(name, String.valueOf(value));
237    }
238
239    /**
240     * Adds a name/value pair to the formatted output in {@code name=value} format.
241     *
242     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
243     */
244    @CanIgnoreReturnValue
245    public ToStringHelper add(String name, int value) {
246      return addUnconditionalHolder(name, String.valueOf(value));
247    }
248
249    /**
250     * Adds a name/value pair to the formatted output in {@code name=value} format.
251     *
252     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}).
253     */
254    @CanIgnoreReturnValue
255    public ToStringHelper add(String name, long value) {
256      return addUnconditionalHolder(name, String.valueOf(value));
257    }
258
259    /**
260     * Adds an unnamed value to the formatted output.
261     *
262     * <p>It is strongly encouraged to use {@link #add(String, Object)} instead and give value a
263     * readable name.
264     */
265    @CanIgnoreReturnValue
266    public ToStringHelper addValue(@CheckForNull Object value) {
267      return addHolder(value);
268    }
269
270    /**
271     * Adds an unnamed value to the formatted output.
272     *
273     * <p>It is strongly encouraged to use {@link #add(String, boolean)} instead and give value a
274     * readable name.
275     *
276     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
277     */
278    @CanIgnoreReturnValue
279    public ToStringHelper addValue(boolean value) {
280      return addUnconditionalHolder(String.valueOf(value));
281    }
282
283    /**
284     * Adds an unnamed value to the formatted output.
285     *
286     * <p>It is strongly encouraged to use {@link #add(String, char)} instead and give value a
287     * readable name.
288     *
289     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
290     */
291    @CanIgnoreReturnValue
292    public ToStringHelper addValue(char value) {
293      return addUnconditionalHolder(String.valueOf(value));
294    }
295
296    /**
297     * Adds an unnamed value to the formatted output.
298     *
299     * <p>It is strongly encouraged to use {@link #add(String, double)} instead and give value a
300     * readable name.
301     *
302     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
303     */
304    @CanIgnoreReturnValue
305    public ToStringHelper addValue(double value) {
306      return addUnconditionalHolder(String.valueOf(value));
307    }
308
309    /**
310     * Adds an unnamed value to the formatted output.
311     *
312     * <p>It is strongly encouraged to use {@link #add(String, float)} instead and give value a
313     * readable name.
314     *
315     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
316     */
317    @CanIgnoreReturnValue
318    public ToStringHelper addValue(float value) {
319      return addUnconditionalHolder(String.valueOf(value));
320    }
321
322    /**
323     * Adds an unnamed value to the formatted output.
324     *
325     * <p>It is strongly encouraged to use {@link #add(String, int)} instead and give value a
326     * readable name.
327     *
328     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
329     */
330    @CanIgnoreReturnValue
331    public ToStringHelper addValue(int value) {
332      return addUnconditionalHolder(String.valueOf(value));
333    }
334
335    /**
336     * Adds an unnamed value to the formatted output.
337     *
338     * <p>It is strongly encouraged to use {@link #add(String, long)} instead and give value a
339     * readable name.
340     *
341     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}).
342     */
343    @CanIgnoreReturnValue
344    public ToStringHelper addValue(long value) {
345      return addUnconditionalHolder(String.valueOf(value));
346    }
347
348    private static boolean isEmpty(Object value) {
349      // Put types estimated to be most frequent first.
350      if (value instanceof CharSequence) {
351        return ((CharSequence) value).length() == 0;
352      } else if (value instanceof Collection) {
353        return ((Collection<?>) value).isEmpty();
354      } else if (value instanceof Map) {
355        return ((Map<?, ?>) value).isEmpty();
356      } else if (value instanceof Optional) {
357        return !((Optional) value).isPresent();
358      } else if (value.getClass().isArray()) {
359        return Array.getLength(value) == 0;
360      }
361      return false;
362    }
363
364    /**
365     * Returns a string in the format specified by {@link MoreObjects#toStringHelper(Object)}.
366     *
367     * <p>After calling this method, you can keep adding more properties to later call toString()
368     * again and get a more complete representation of the same object; but properties cannot be
369     * removed, so this only allows limited reuse of the helper instance. The helper allows
370     * duplication of properties (multiple name/value pairs with the same name can be added).
371     */
372    @Override
373    public String toString() {
374      // create a copy to keep it consistent in case value changes
375      boolean omitNullValuesSnapshot = omitNullValues;
376      boolean omitEmptyValuesSnapshot = omitEmptyValues;
377      String nextSeparator = "";
378      StringBuilder builder = new StringBuilder(32).append(className).append('{');
379      for (ValueHolder valueHolder = holderHead.next;
380          valueHolder != null;
381          valueHolder = valueHolder.next) {
382        Object value = valueHolder.value;
383        if (valueHolder instanceof UnconditionalValueHolder
384            || (value == null
385                ? !omitNullValuesSnapshot
386                : (!omitEmptyValuesSnapshot || !isEmpty(value)))) {
387          builder.append(nextSeparator);
388          nextSeparator = ", ";
389
390          if (valueHolder.name != null) {
391            builder.append(valueHolder.name).append('=');
392          }
393          if (value != null && value.getClass().isArray()) {
394            Object[] objectArray = {value};
395            String arrayString = Arrays.deepToString(objectArray);
396            builder.append(arrayString, 1, arrayString.length() - 1);
397          } else {
398            builder.append(value);
399          }
400        }
401      }
402      return builder.append('}').toString();
403    }
404
405    private ValueHolder addHolder() {
406      ValueHolder valueHolder = new ValueHolder();
407      holderTail = holderTail.next = valueHolder;
408      return valueHolder;
409    }
410
411    private ToStringHelper addHolder(@CheckForNull Object value) {
412      ValueHolder valueHolder = addHolder();
413      valueHolder.value = value;
414      return this;
415    }
416
417    private ToStringHelper addHolder(String name, @CheckForNull Object value) {
418      ValueHolder valueHolder = addHolder();
419      valueHolder.value = value;
420      valueHolder.name = checkNotNull(name);
421      return this;
422    }
423
424    private UnconditionalValueHolder addUnconditionalHolder() {
425      UnconditionalValueHolder valueHolder = new UnconditionalValueHolder();
426      holderTail = holderTail.next = valueHolder;
427      return valueHolder;
428    }
429
430    private ToStringHelper addUnconditionalHolder(Object value) {
431      UnconditionalValueHolder valueHolder = addUnconditionalHolder();
432      valueHolder.value = value;
433      return this;
434    }
435
436    private ToStringHelper addUnconditionalHolder(String name, Object value) {
437      UnconditionalValueHolder valueHolder = addUnconditionalHolder();
438      valueHolder.value = value;
439      valueHolder.name = checkNotNull(name);
440      return this;
441    }
442
443    // Holder object for values that might be null and/or empty.
444    private static class ValueHolder {
445      @CheckForNull String name;
446      @CheckForNull Object value;
447      @CheckForNull ValueHolder next;
448    }
449
450    /**
451     * Holder object for values that cannot be null or empty (will be printed unconditionally). This
452     * helps to shortcut most calls to isEmpty(), which is important because the check for emptiness
453     * is relatively expensive. Use a subtype so this also doesn't need any extra storage.
454     */
455    private static final class UnconditionalValueHolder extends ValueHolder {}
456  }
457
458  private MoreObjects() {}
459}