001/*
002 * Copyright (C) 2007 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 java.util.Arrays;
024
025import javax.annotation.CheckReturnValue;
026import javax.annotation.Nullable;
027
028/**
029 * Helper functions that can operate on any {@code Object}.
030 *
031 * <p>See the Guava User Guide on <a
032 * href="http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained">writing
033 * {@code Object} methods with {@code Objects}</a>.
034 *
035 * @author Laurence Gonsalves
036 * @since 2.0 (imported from Google Collections Library)
037 */
038@GwtCompatible
039public final class Objects {
040  private Objects() {}
041
042  /**
043   * Determines whether two possibly-null objects are equal. Returns:
044   *
045   * <ul>
046   * <li>{@code true} if {@code a} and {@code b} are both null.
047   * <li>{@code true} if {@code a} and {@code b} are both non-null and they are
048   *     equal according to {@link Object#equals(Object)}.
049   * <li>{@code false} in all other situations.
050   * </ul>
051   *
052   * <p>This assumes that any non-null objects passed to this function conform
053   * to the {@code equals()} contract.
054   */
055  @CheckReturnValue
056  public static boolean equal(@Nullable Object a, @Nullable Object b) {
057    return a == b || (a != null && a.equals(b));
058  }
059
060  /**
061   * Generates a hash code for multiple values. The hash code is generated by
062   * calling {@link Arrays#hashCode(Object[])}. Note that array arguments to
063   * this method, with the exception of a single Object array, do not get any
064   * special handling; their hash codes are based on identity and not contents.
065   *
066   * <p>This is useful for implementing {@link Object#hashCode()}. For example,
067   * in an object that has three properties, {@code x}, {@code y}, and
068   * {@code z}, one could write:
069   * <pre>   {@code
070   *   public int hashCode() {
071   *     return Objects.hashCode(getX(), getY(), getZ());
072   *   }}</pre>
073   *
074   * <p><b>Warning</b>: When a single object is supplied, the returned hash code
075   * does not equal the hash code of that object.
076   */
077  public static int hashCode(@Nullable Object... objects) {
078    return Arrays.hashCode(objects);
079  }
080
081  /**
082   * Creates an instance of {@link ToStringHelper}.
083   *
084   * <p>This is helpful for implementing {@link Object#toString()}.
085   * Specification by example: <pre>   {@code
086   *   // Returns "ClassName{}"
087   *   Objects.toStringHelper(this)
088   *       .toString();
089   *
090   *   // Returns "ClassName{x=1}"
091   *   Objects.toStringHelper(this)
092   *       .add("x", 1)
093   *       .toString();
094   *
095   *   // Returns "MyObject{x=1}"
096   *   Objects.toStringHelper("MyObject")
097   *       .add("x", 1)
098   *       .toString();
099   *
100   *   // Returns "ClassName{x=1, y=foo}"
101   *   Objects.toStringHelper(this)
102   *       .add("x", 1)
103   *       .add("y", "foo")
104   *       .toString();
105   *
106   *   // Returns "ClassName{x=1}"
107   *   Objects.toStringHelper(this)
108   *       .omitNullValues()
109   *       .add("x", 1)
110   *       .add("y", null)
111   *       .toString();
112   *   }}</pre>
113   *
114   * <p>Note that in GWT, class names are often obfuscated.
115   *
116   * @param self the object to generate the string for (typically {@code this}),
117   *        used only for its class name
118   * @since 2.0
119   */
120  public static ToStringHelper toStringHelper(Object self) {
121    return new ToStringHelper(simpleName(self.getClass()));
122  }
123
124  /**
125   * Creates an instance of {@link ToStringHelper} in the same manner as
126   * {@link Objects#toStringHelper(Object)}, but using the name of {@code clazz}
127   * instead of using an instance's {@link Object#getClass()}.
128   *
129   * <p>Note that in GWT, class names are often obfuscated.
130   *
131   * @param clazz the {@link Class} of the instance
132   * @since 7.0 (source-compatible since 2.0)
133   */
134  public static ToStringHelper toStringHelper(Class<?> clazz) {
135    return new ToStringHelper(simpleName(clazz));
136  }
137
138  /**
139   * Creates an instance of {@link ToStringHelper} in the same manner as
140   * {@link Objects#toStringHelper(Object)}, but using {@code className} instead
141   * of using an instance's {@link Object#getClass()}.
142   *
143   * @param className the name of the instance type
144   * @since 7.0 (source-compatible since 2.0)
145   */
146  public static ToStringHelper toStringHelper(String className) {
147    return new ToStringHelper(className);
148  }
149
150  /**
151   * {@link Class#getSimpleName()} is not GWT compatible yet, so we
152   * provide our own implementation.
153   */
154  private static String simpleName(Class<?> clazz) {
155    String name = clazz.getName();
156
157    // the nth anonymous class has a class name ending in "Outer$n"
158    // and local inner classes have names ending in "Outer.$1Inner"
159    name = name.replaceAll("\\$[0-9]+", "\\$");
160
161    // we want the name of the inner class all by its lonesome
162    int start = name.lastIndexOf('$');
163
164    // if this isn't an inner class, just find the start of the
165    // top level class name.
166    if (start == -1) {
167      start = name.lastIndexOf('.');
168    }
169    return name.substring(start + 1);
170  }
171
172  /**
173   * Returns the first of two given parameters that is not {@code null}, if
174   * either is, or otherwise throws a {@link NullPointerException}.
175   *
176   * <p><b>Note:</b> if {@code first} is represented as an {@link Optional},
177   * this can be accomplished with
178   * {@linkplain Optional#or(Object) first.or(second)}.
179   * That approach also allows for lazy evaluation of the fallback instance,
180   * using {@linkplain Optional#or(Supplier) first.or(Supplier)}.
181   *
182   * @return {@code first} if {@code first} is not {@code null}, or
183   *     {@code second} if {@code first} is {@code null} and {@code second} is
184   *     not {@code null}
185   * @throws NullPointerException if both {@code first} and {@code second} were
186   *     {@code null}
187   * @since 3.0
188   */
189  public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
190    return first != null ? first : checkNotNull(second);
191  }
192
193  /**
194   * Support class for {@link Objects#toStringHelper}.
195   *
196   * @author Jason Lee
197   * @since 2.0
198   */
199  public static final class ToStringHelper {
200    private final String className;
201    private ValueHolder holderHead = new ValueHolder();
202    private ValueHolder holderTail = holderHead;
203    private boolean omitNullValues = false;
204
205    /**
206     * Use {@link Objects#toStringHelper(Object)} to create an instance.
207     */
208    private ToStringHelper(String className) {
209      this.className = checkNotNull(className);
210    }
211
212    /**
213     * Configures the {@link ToStringHelper} so {@link #toString()} will ignore
214     * properties with null value. The order of calling this method, relative
215     * to the {@code add()}/{@code addValue()} methods, is not significant.
216     *
217     * @since 12.0
218     */
219    public ToStringHelper omitNullValues() {
220      omitNullValues = true;
221      return this;
222    }
223
224    /**
225     * Adds a name/value pair to the formatted output in {@code name=value}
226     * format. If {@code value} is {@code null}, the string {@code "null"}
227     * is used, unless {@link #omitNullValues()} is called, in which case this
228     * name/value pair will not be added.
229     */
230    public ToStringHelper add(String name, @Nullable Object value) {
231      return addHolder(name, value);
232    }
233
234    /**
235     * Adds a name/value pair to the formatted output in {@code name=value}
236     * format.
237     *
238     * @since 11.0 (source-compatible since 2.0)
239     */
240    public ToStringHelper add(String name, boolean value) {
241      return addHolder(name, String.valueOf(value));
242    }
243
244    /**
245     * Adds a name/value pair to the formatted output in {@code name=value}
246     * format.
247     *
248     * @since 11.0 (source-compatible since 2.0)
249     */
250    public ToStringHelper add(String name, char value) {
251      return addHolder(name, String.valueOf(value));
252    }
253
254    /**
255     * Adds a name/value pair to the formatted output in {@code name=value}
256     * format.
257     *
258     * @since 11.0 (source-compatible since 2.0)
259     */
260    public ToStringHelper add(String name, double value) {
261      return addHolder(name, String.valueOf(value));
262    }
263
264    /**
265     * Adds a name/value pair to the formatted output in {@code name=value}
266     * format.
267     *
268     * @since 11.0 (source-compatible since 2.0)
269     */
270    public ToStringHelper add(String name, float value) {
271      return addHolder(name, String.valueOf(value));
272    }
273
274    /**
275     * Adds a name/value pair to the formatted output in {@code name=value}
276     * format.
277     *
278     * @since 11.0 (source-compatible since 2.0)
279     */
280    public ToStringHelper add(String name, int value) {
281      return addHolder(name, String.valueOf(value));
282    }
283
284    /**
285     * Adds a name/value pair to the formatted output in {@code name=value}
286     * format.
287     *
288     * @since 11.0 (source-compatible since 2.0)
289     */
290    public ToStringHelper add(String name, long value) {
291      return addHolder(name, String.valueOf(value));
292    }
293
294    /**
295     * Adds an unnamed value to the formatted output.
296     *
297     * <p>It is strongly encouraged to use {@link #add(String, Object)} instead
298     * and give value a readable name.
299     */
300    public ToStringHelper addValue(@Nullable Object value) {
301      return addHolder(value);
302    }
303
304    /**
305     * Adds an unnamed value to the formatted output.
306     *
307     * <p>It is strongly encouraged to use {@link #add(String, boolean)} instead
308     * and give value a readable name.
309     *
310     * @since 11.0 (source-compatible since 2.0)
311     */
312    public ToStringHelper addValue(boolean value) {
313      return addHolder(String.valueOf(value));
314    }
315
316    /**
317     * Adds an unnamed value to the formatted output.
318     *
319     * <p>It is strongly encouraged to use {@link #add(String, char)} instead
320     * and give value a readable name.
321     *
322     * @since 11.0 (source-compatible since 2.0)
323     */
324    public ToStringHelper addValue(char value) {
325      return addHolder(String.valueOf(value));
326    }
327
328    /**
329     * Adds an unnamed value to the formatted output.
330     *
331     * <p>It is strongly encouraged to use {@link #add(String, double)} instead
332     * and give value a readable name.
333     *
334     * @since 11.0 (source-compatible since 2.0)
335     */
336    public ToStringHelper addValue(double value) {
337      return addHolder(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, float)} instead
344     * and give value a readable name.
345     *
346     * @since 11.0 (source-compatible since 2.0)
347     */
348    public ToStringHelper addValue(float value) {
349      return addHolder(String.valueOf(value));
350    }
351
352    /**
353     * Adds an unnamed value to the formatted output.
354     *
355     * <p>It is strongly encouraged to use {@link #add(String, int)} instead
356     * and give value a readable name.
357     *
358     * @since 11.0 (source-compatible since 2.0)
359     */
360    public ToStringHelper addValue(int value) {
361      return addHolder(String.valueOf(value));
362    }
363
364    /**
365     * Adds an unnamed value to the formatted output.
366     *
367     * <p>It is strongly encouraged to use {@link #add(String, long)} instead
368     * and give value a readable name.
369     *
370     * @since 11.0 (source-compatible since 2.0)
371     */
372    public ToStringHelper addValue(long value) {
373      return addHolder(String.valueOf(value));
374    }
375
376    /**
377     * Returns a string in the format specified by {@link
378     * Objects#toStringHelper(Object)}.
379     *
380     * <p>After calling this method, you can keep adding more properties to later
381     * call toString() again and get a more complete representation of the
382     * same object; but properties cannot be removed, so this only allows
383     * limited reuse of the helper instance. The helper allows duplication of
384     * properties (multiple name/value pairs with the same name can be added).
385     */
386    @Override public String toString() {
387      // create a copy to keep it consistent in case value changes
388      boolean omitNullValuesSnapshot = omitNullValues;
389      String nextSeparator = "";
390      StringBuilder builder = new StringBuilder(32).append(className)
391          .append('{');
392      for (ValueHolder valueHolder = holderHead.next; valueHolder != null;
393          valueHolder = valueHolder.next) {
394        if (!omitNullValuesSnapshot || valueHolder.value != null) {
395          builder.append(nextSeparator);
396          nextSeparator = ", ";
397
398          if (valueHolder.name != null) {
399            builder.append(valueHolder.name).append('=');
400          }
401          builder.append(valueHolder.value);
402        }
403      }
404      return builder.append('}').toString();
405    }
406
407    private ValueHolder addHolder() {
408      ValueHolder valueHolder = new ValueHolder();
409      holderTail = holderTail.next = valueHolder;
410      return valueHolder;
411    }
412
413    private ToStringHelper addHolder(@Nullable Object value) {
414      ValueHolder valueHolder = addHolder();
415      valueHolder.value = value;
416      return this;
417    }
418
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 static final class ValueHolder {
427      String name;
428      Object value;
429      ValueHolder next;
430    }
431  }
432}