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