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