001/*
002 * Copyright (C) 2014 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.base;
018
019import static com.google.common.base.Preconditions.checkNotNull;
020
021import com.google.common.annotations.GwtCompatible;
022
023import javax.annotation.Nullable;
024
025/**
026 * Helper functions that operate on any {@code Object}, and are not already provided in
027 * {@link java.util.Objects}.
028 *
029 * <p>See the Guava User Guide on <a
030 * href="http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained">writing
031 * {@code Object} methods with {@code MoreObjects}</a>.
032 *
033 * @author Laurence Gonsalves
034 * @since 18.0 (since 2.0 as {@code Objects})
035 */
036@GwtCompatible
037public final class MoreObjects {
038  /**
039   * Returns the first of two given parameters that is not {@code null}, if either is, or otherwise
040   * throws a {@link NullPointerException}.
041   *
042   * <p><b>Note:</b> if {@code first} is represented as an {@link Optional}, this can be
043   * accomplished with {@link Optional#or(Object) first.or(second)}. That approach also allows for
044   * lazy evaluation of the fallback instance, using {@link Optional#or(Supplier)
045   * first.or(supplier)}.
046   *
047   * @return {@code first} if it is non-null; otherwise {@code second} if it is non-null
048   * @throws NullPointerException if both {@code first} and {@code second} are null
049   * @since 18.0 (since 3.0 as {@code Objects.firstNonNull()}.
050   */
051  public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
052    return first != null ? first : checkNotNull(second);
053  }
054
055  /**
056   * Creates an instance of {@link ToStringHelper}.
057   *
058   * <p>This is helpful for implementing {@link Object#toString()}.
059   * Specification by example: <pre>   {@code
060   *   // Returns "ClassName{}"
061   *   MoreObjects.toStringHelper(this)
062   *       .toString();
063   *
064   *   // Returns "ClassName{x=1}"
065   *   MoreObjects.toStringHelper(this)
066   *       .add("x", 1)
067   *       .toString();
068   *
069   *   // Returns "MyObject{x=1}"
070   *   MoreObjects.toStringHelper("MyObject")
071   *       .add("x", 1)
072   *       .toString();
073   *
074   *   // Returns "ClassName{x=1, y=foo}"
075   *   MoreObjects.toStringHelper(this)
076   *       .add("x", 1)
077   *       .add("y", "foo")
078   *       .toString();
079   *
080   *   // Returns "ClassName{x=1}"
081   *   MoreObjects.toStringHelper(this)
082   *       .omitNullValues()
083   *       .add("x", 1)
084   *       .add("y", null)
085   *       .toString();
086   *   }}</pre>
087   *
088   * <p>Note that in GWT, class names are often obfuscated.
089   *
090   * @param self the object to generate the string for (typically {@code this}), used only for its
091   *     class name
092   * @since 18.0 (since 2.0 as {@code Objects.toStringHelper()}.
093   */
094  public static ToStringHelper toStringHelper(Object self) {
095    return new ToStringHelper(simpleName(self.getClass()));
096  }
097
098  /**
099   * Creates an instance of {@link ToStringHelper} in the same manner as {@link
100   * #toStringHelper(Object)}, but using the simple name of {@code clazz} instead of using an
101   * instance's {@link Object#getClass()}.
102   *
103   * <p>Note that in GWT, class names are often obfuscated.
104   *
105   * @param clazz the {@link Class} of the instance
106   * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}.
107   */
108  public static ToStringHelper toStringHelper(Class<?> clazz) {
109    return new ToStringHelper(simpleName(clazz));
110  }
111
112  /**
113   * Creates an instance of {@link ToStringHelper} in the same manner as {@link
114   * #toStringHelper(Object)}, but using {@code className} instead of using an instance's {@link
115   * Object#getClass()}.
116   *
117   * @param className the name of the instance type
118   * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}.
119   */
120  public static ToStringHelper toStringHelper(String className) {
121    return new ToStringHelper(className);
122  }
123
124  /**
125   * {@link Class#getSimpleName()} is not GWT compatible yet, so we
126   * provide our own implementation.
127   */
128  // Package-private so Objects can call it.
129  static String simpleName(Class<?> clazz) {
130    String name = clazz.getName();
131
132    // the nth anonymous class has a class name ending in "Outer$n"
133    // and local inner classes have names ending in "Outer.$1Inner"
134    name = name.replaceAll("\\$[0-9]+", "\\$");
135
136    // we want the name of the inner class all by its lonesome
137    int start = name.lastIndexOf('$');
138
139    // if this isn't an inner class, just find the start of the
140    // top level class name.
141    if (start == -1) {
142      start = name.lastIndexOf('.');
143    }
144    return name.substring(start + 1);
145  }
146
147  /**
148   * Support class for {@link MoreObjects#toStringHelper}.
149   *
150   * @author Jason Lee
151   * @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}.
152   */
153  public static final class ToStringHelper {
154    private final String className;
155    private ValueHolder holderHead = new ValueHolder();
156    private ValueHolder holderTail = holderHead;
157    private boolean omitNullValues = false;
158
159    /**
160     * Use {@link MoreObjects#toStringHelper(Object)} to create an instance.
161     */
162    private ToStringHelper(String className) {
163      this.className = checkNotNull(className);
164    }
165
166    /**
167     * Configures the {@link ToStringHelper} so {@link #toString()} will ignore
168     * properties with null value. The order of calling this method, relative
169     * to the {@code add()}/{@code addValue()} methods, is not significant.
170     *
171     * @since 18.0 (since 12.0 as {@code Objects.ToStringHelper.omitNullValues()}.
172     */
173    public ToStringHelper omitNullValues() {
174      omitNullValues = true;
175      return this;
176    }
177
178    /**
179     * Adds a name/value pair to the formatted output in {@code name=value}
180     * format. If {@code value} is {@code null}, the string {@code "null"}
181     * is used, unless {@link #omitNullValues()} is called, in which case this
182     * name/value pair will not be added.
183     */
184    public ToStringHelper add(String name, @Nullable Object value) {
185      return addHolder(name, value);
186    }
187
188    /**
189     * Adds a name/value pair to the formatted output in {@code name=value}
190     * format.
191     *
192     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
193     */
194    public ToStringHelper add(String name, boolean value) {
195      return addHolder(name, String.valueOf(value));
196    }
197
198    /**
199     * Adds a name/value pair to the formatted output in {@code name=value}
200     * format.
201     *
202     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
203     */
204    public ToStringHelper add(String name, char value) {
205      return addHolder(name, String.valueOf(value));
206    }
207
208    /**
209     * Adds a name/value pair to the formatted output in {@code name=value}
210     * format.
211     *
212     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
213     */
214    public ToStringHelper add(String name, double value) {
215      return addHolder(name, String.valueOf(value));
216    }
217
218    /**
219     * Adds a name/value pair to the formatted output in {@code name=value}
220     * format.
221     *
222     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
223     */
224    public ToStringHelper add(String name, float value) {
225      return addHolder(name, String.valueOf(value));
226    }
227
228    /**
229     * Adds a name/value pair to the formatted output in {@code name=value}
230     * format.
231     *
232     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
233     */
234    public ToStringHelper add(String name, int value) {
235      return addHolder(name, String.valueOf(value));
236    }
237
238    /**
239     * Adds a name/value pair to the formatted output in {@code name=value}
240     * format.
241     *
242     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
243     */
244    public ToStringHelper add(String name, long value) {
245      return addHolder(name, String.valueOf(value));
246    }
247
248    /**
249     * Adds an unnamed value to the formatted output.
250     *
251     * <p>It is strongly encouraged to use {@link #add(String, Object)} instead
252     * and give value a readable name.
253     *
254     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
255     */
256    public ToStringHelper addValue(@Nullable Object value) {
257      return addHolder(value);
258    }
259
260    /**
261     * Adds an unnamed value to the formatted output.
262     *
263     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
264     *
265     * <p>It is strongly encouraged to use {@link #add(String, boolean)} instead
266     * and give value a readable name.
267     *
268     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
269     */
270    public ToStringHelper addValue(boolean value) {
271      return addHolder(String.valueOf(value));
272    }
273
274    /**
275     * Adds an unnamed value to the formatted output.
276     *
277     * <p>It is strongly encouraged to use {@link #add(String, char)} instead
278     * and give value a readable name.
279     *
280     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
281     */
282    public ToStringHelper addValue(char value) {
283      return addHolder(String.valueOf(value));
284    }
285
286    /**
287     * Adds an unnamed value to the formatted output.
288     *
289     * <p>It is strongly encouraged to use {@link #add(String, double)} instead
290     * and give value a readable name.
291     *
292     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
293     */
294    public ToStringHelper addValue(double value) {
295      return addHolder(String.valueOf(value));
296    }
297
298    /**
299     * Adds an unnamed value to the formatted output.
300     *
301     * <p>It is strongly encouraged to use {@link #add(String, float)} instead
302     * and give value a readable name.
303     *
304     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
305     */
306    public ToStringHelper addValue(float value) {
307      return addHolder(String.valueOf(value));
308    }
309
310    /**
311     * Adds an unnamed value to the formatted output.
312     *
313     * <p>It is strongly encouraged to use {@link #add(String, int)} instead
314     * and give value a readable name.
315     *
316     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
317     */
318    public ToStringHelper addValue(int value) {
319      return addHolder(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, long)} instead
326     * and give value a readable name.
327     *
328     * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
329     */
330    public ToStringHelper addValue(long value) {
331      return addHolder(String.valueOf(value));
332    }
333
334    /**
335     * Returns a string in the format specified by
336     * {@link MoreObjects#toStringHelper(Object)}.
337     *
338     * <p>After calling this method, you can keep adding more properties to later
339     * call toString() again and get a more complete representation of the
340     * same object; but properties cannot be removed, so this only allows
341     * limited reuse of the helper instance. The helper allows duplication of
342     * properties (multiple name/value pairs with the same name can be added).
343     */
344    @Override public String toString() {
345      // create a copy to keep it consistent in case value changes
346      boolean omitNullValuesSnapshot = omitNullValues;
347      String nextSeparator = "";
348      StringBuilder builder = new StringBuilder(32).append(className)
349          .append('{');
350      for (ValueHolder valueHolder = holderHead.next; valueHolder != null;
351          valueHolder = valueHolder.next) {
352        if (!omitNullValuesSnapshot || valueHolder.value != null) {
353          builder.append(nextSeparator);
354          nextSeparator = ", ";
355
356          if (valueHolder.name != null) {
357            builder.append(valueHolder.name).append('=');
358          }
359          builder.append(valueHolder.value);
360        }
361      }
362      return builder.append('}').toString();
363    }
364
365    private ValueHolder addHolder() {
366      ValueHolder valueHolder = new ValueHolder();
367      holderTail = holderTail.next = valueHolder;
368      return valueHolder;
369    }
370
371    private ToStringHelper addHolder(@Nullable Object value) {
372      ValueHolder valueHolder = addHolder();
373      valueHolder.value = value;
374      return this;
375    }
376
377    private ToStringHelper addHolder(String name, @Nullable Object value) {
378      ValueHolder valueHolder = addHolder();
379      valueHolder.value = value;
380      valueHolder.name = checkNotNull(name);
381      return this;
382    }
383
384    private static final class ValueHolder {
385      String name;
386      Object value;
387      ValueHolder next;
388    }
389  }
390
391  private MoreObjects() {}
392}