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 org.checkerframework.checker.nullness.qual.Nullable;
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
039public final class MoreObjects {
040  /**
041   * Returns the first of two given parameters that is not {@code null}, if either is, or otherwise
042   * throws a {@link NullPointerException}.
043   *
044   * <p>To find the first non-null element in an iterable, use {@code Iterables.find(iterable,
045   * Predicates.notNull())}. For varargs, use {@code Iterables.find(Arrays.asList(a, b, c, ...),
046   * Predicates.notNull())}, static importing as necessary.
047   *
048   * <p><b>Note:</b> if {@code first} is represented as an {@link Optional}, this can be
049   * accomplished with {@link Optional#or(Object) first.or(second)}. That approach also allows for
050   * lazy evaluation of the fallback instance, using {@link Optional#or(Supplier)
051   * first.or(supplier)}.
052   *
053   * <p><b>Java 9 users:</b> use {@code java.util.Objects.requireNonNullElse(first, second)}
054   * instead.
055   *
056   * @return {@code first} if it is non-null; otherwise {@code second} if it is non-null
057   * @throws NullPointerException if both {@code first} and {@code second} are null
058   * @since 18.0 (since 3.0 as {@code Objects.firstNonNull()}).
059   */
060  public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
061    if (first != null) {
062      return first;
063    }
064    if (second != null) {
065      return second;
066    }
067    throw new NullPointerException("Both parameters are null");
068  }
069
070  /**
071   * Creates an instance of {@link ToStringHelper}.
072   *
073   * <p>This is helpful for implementing {@link Object#toString()}. Specification by example:
074   *
075   * <pre>{@code
076   * // Returns "ClassName{}"
077   * MoreObjects.toStringHelper(this)
078   *     .toString();
079   *
080   * // Returns "ClassName{x=1}"
081   * MoreObjects.toStringHelper(this)
082   *     .add("x", 1)
083   *     .toString();
084   *
085   * // Returns "MyObject{x=1}"
086   * MoreObjects.toStringHelper("MyObject")
087   *     .add("x", 1)
088   *     .toString();
089   *
090   * // Returns "ClassName{x=1, y=foo}"
091   * MoreObjects.toStringHelper(this)
092   *     .add("x", 1)
093   *     .add("y", "foo")
094   *     .toString();
095   *
096   * // Returns "ClassName{x=1}"
097   * MoreObjects.toStringHelper(this)
098   *     .omitNullValues()
099   *     .add("x", 1)
100   *     .add("y", null)
101   *     .toString();
102   * }</pre>
103   *
104   * <p>Note that in GWT, class names are often obfuscated.
105   *
106   * @param self the object to generate the string for (typically {@code this}), used only for its
107   *     class name
108   * @since 18.0 (since 2.0 as {@code Objects.toStringHelper()}).
109   */
110  public static ToStringHelper toStringHelper(Object self) {
111    return new ToStringHelper(self.getClass().getSimpleName());
112  }
113
114  /**
115   * Creates an instance of {@link ToStringHelper} in the same manner as {@link
116   * #toStringHelper(Object)}, but using the simple name of {@code clazz} instead of using an
117   * instance's {@link Object#getClass()}.
118   *
119   * <p>Note that in GWT, class names are often obfuscated.
120   *
121   * @param clazz the {@link Class} of the instance
122   * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}).
123   */
124  public static ToStringHelper toStringHelper(Class<?> clazz) {
125    return new ToStringHelper(clazz.getSimpleName());
126  }
127
128  /**
129   * Creates an instance of {@link ToStringHelper} in the same manner as {@link
130   * #toStringHelper(Object)}, but using {@code className} instead of using an instance's {@link
131   * Object#getClass()}.
132   *
133   * @param className the name of the instance type
134   * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}).
135   */
136  public static ToStringHelper toStringHelper(String className) {
137    return new ToStringHelper(className);
138  }
139
140  /**
141   * Support class for {@link MoreObjects#toStringHelper}.
142   *
143   * @author Jason Lee
144   * @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}).
145   */
146  public static final class ToStringHelper {
147    private final String className;
148    private final ValueHolder holderHead = new ValueHolder();
149    private ValueHolder holderTail = holderHead;
150    private boolean omitNullValues = false;
151    private boolean omitEmptyValues = false;
152
153    /** Use {@link MoreObjects#toStringHelper(Object)} to create an instance. */
154    private ToStringHelper(String className) {
155      this.className = checkNotNull(className);
156    }
157
158    /**
159     * Configures the {@link ToStringHelper} so {@link #toString()} will ignore properties with null
160     * value. The order of calling this method, relative to the {@code add()}/{@code addValue()}
161     * methods, is not significant.
162     *
163     * @since 18.0 (since 12.0 as {@code Objects.ToStringHelper.omitNullValues()}).
164     */
165    @CanIgnoreReturnValue
166    public ToStringHelper omitNullValues() {
167      omitNullValues = true;
168      return this;
169    }
170
171    /**
172     * Configures the {@link ToStringHelper} so {@link #toString()} will ignore properties with
173     * empty values. The order of calling this method, relative to the {@code add()}/{@code
174     * addValue()} methods, is not significant.
175     *
176     * <p><b>Note:</b> in general, code should assume that the string form returned by {@code
177     * ToStringHelper} for a given object may change. In particular, the list of types which are
178     * checked for emptiness is subject to change. We currently check {@code CharSequence}s, {@code
179     * Collection}s, {@code Map}s, optionals (including Guava's), and arrays.
180     *
181     * @since 33.4.0
182     */
183    @CanIgnoreReturnValue
184    public ToStringHelper omitEmptyValues() {
185      omitEmptyValues = 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, @Nullable 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(@Nullable 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 the 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    @CanIgnoreReturnValue
412    private ToStringHelper addHolder(@Nullable Object value) {
413      ValueHolder valueHolder = addHolder();
414      valueHolder.value = value;
415      return this;
416    }
417
418    @CanIgnoreReturnValue
419    private ToStringHelper addHolder(String name, @Nullable Object value) {
420      ValueHolder valueHolder = addHolder();
421      valueHolder.value = value;
422      valueHolder.name = checkNotNull(name);
423      return this;
424    }
425
426    private UnconditionalValueHolder addUnconditionalHolder() {
427      UnconditionalValueHolder valueHolder = new UnconditionalValueHolder();
428      holderTail = holderTail.next = valueHolder;
429      return valueHolder;
430    }
431
432    @CanIgnoreReturnValue
433    private ToStringHelper addUnconditionalHolder(Object value) {
434      UnconditionalValueHolder valueHolder = addUnconditionalHolder();
435      valueHolder.value = value;
436      return this;
437    }
438
439    @CanIgnoreReturnValue
440    private ToStringHelper addUnconditionalHolder(String name, Object value) {
441      UnconditionalValueHolder valueHolder = addUnconditionalHolder();
442      valueHolder.value = value;
443      valueHolder.name = checkNotNull(name);
444      return this;
445    }
446
447    // Holder object for values that might be null and/or empty.
448    static class ValueHolder {
449      @Nullable String name;
450      @Nullable Object value;
451      @Nullable ValueHolder next;
452    }
453
454    /**
455     * Holder object for values that cannot be null or empty (will be printed unconditionally). This
456     * helps to shortcut most calls to isEmpty(), which is important because the check for emptiness
457     * is relatively expensive. Use a subtype so this also doesn't need any extra storage.
458     */
459    private static final class UnconditionalValueHolder extends ValueHolder {}
460  }
461
462  private MoreObjects() {}
463}