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 {@code Optional<T>},
175   * this can be accomplished with {@code first.or(second)}. That approach also
176   * allows for lazy evaluation of the fallback instance, using
177   * {@code first.or(Supplier)}.
178   *
179   * @return {@code first} if {@code first} is not {@code null}, or
180   *     {@code second} if {@code first} is {@code null} and {@code second} is
181   *     not {@code null}
182   * @throws NullPointerException if both {@code first} and {@code second} were
183   *     {@code null}
184   * @since 3.0
185   */
186  public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
187    return first != null ? first : checkNotNull(second);
188  }
189
190  /**
191   * Support class for {@link Objects#toStringHelper}.
192   *
193   * @author Jason Lee
194   * @since 2.0
195   */
196  public static final class ToStringHelper {
197    private final String className;
198    private ValueHolder holderHead = new ValueHolder();
199    private ValueHolder holderTail = holderHead;
200    private boolean omitNullValues = false;
201
202    /**
203     * Use {@link Objects#toStringHelper(Object)} to create an instance.
204     */
205    private ToStringHelper(String className) {
206      this.className = checkNotNull(className);
207    }
208
209    /**
210     * Configures the {@link ToStringHelper} so {@link #toString()} will ignore
211     * properties with null value. The order of calling this method, relative
212     * to the {@code add()}/{@code addValue()} methods, is not significant.
213     *
214     * @since 12.0
215     */
216    public ToStringHelper omitNullValues() {
217      omitNullValues = true;
218      return this;
219    }
220
221    /**
222     * Adds a name/value pair to the formatted output in {@code name=value}
223     * format. If {@code value} is {@code null}, the string {@code "null"}
224     * is used, unless {@link #omitNullValues()} is called, in which case this
225     * name/value pair will not be added.
226     */
227    public ToStringHelper add(String name, @Nullable Object value) {
228      return addHolder(name, value);
229    }
230
231    /**
232     * Adds a name/value pair to the formatted output in {@code name=value}
233     * format.
234     *
235     * @since 11.0 (source-compatible since 2.0)
236     */
237    public ToStringHelper add(String name, boolean value) {
238      return addHolder(name, String.valueOf(value));
239    }
240
241    /**
242     * Adds a name/value pair to the formatted output in {@code name=value}
243     * format.
244     *
245     * @since 11.0 (source-compatible since 2.0)
246     */
247    public ToStringHelper add(String name, char value) {
248      return addHolder(name, String.valueOf(value));
249    }
250
251    /**
252     * Adds a name/value pair to the formatted output in {@code name=value}
253     * format.
254     *
255     * @since 11.0 (source-compatible since 2.0)
256     */
257    public ToStringHelper add(String name, double value) {
258      return addHolder(name, String.valueOf(value));
259    }
260
261    /**
262     * Adds a name/value pair to the formatted output in {@code name=value}
263     * format.
264     *
265     * @since 11.0 (source-compatible since 2.0)
266     */
267    public ToStringHelper add(String name, float value) {
268      return addHolder(name, String.valueOf(value));
269    }
270
271    /**
272     * Adds a name/value pair to the formatted output in {@code name=value}
273     * format.
274     *
275     * @since 11.0 (source-compatible since 2.0)
276     */
277    public ToStringHelper add(String name, int value) {
278      return addHolder(name, String.valueOf(value));
279    }
280
281    /**
282     * Adds a name/value pair to the formatted output in {@code name=value}
283     * format.
284     *
285     * @since 11.0 (source-compatible since 2.0)
286     */
287    public ToStringHelper add(String name, long value) {
288      return addHolder(name, String.valueOf(value));
289    }
290
291    /**
292     * Adds an unnamed value to the formatted output.
293     *
294     * <p>It is strongly encouraged to use {@link #add(String, Object)} instead
295     * and give value a readable name.
296     */
297    public ToStringHelper addValue(@Nullable Object value) {
298      return addHolder(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, boolean)} instead
305     * and give value a readable name.
306     *
307     * @since 11.0 (source-compatible since 2.0)
308     */
309    public ToStringHelper addValue(boolean value) {
310      return addHolder(String.valueOf(value));
311    }
312
313    /**
314     * Adds an unnamed value to the formatted output.
315     *
316     * <p>It is strongly encouraged to use {@link #add(String, char)} instead
317     * and give value a readable name.
318     *
319     * @since 11.0 (source-compatible since 2.0)
320     */
321    public ToStringHelper addValue(char value) {
322      return addHolder(String.valueOf(value));
323    }
324
325    /**
326     * Adds an unnamed value to the formatted output.
327     *
328     * <p>It is strongly encouraged to use {@link #add(String, double)} instead
329     * and give value a readable name.
330     *
331     * @since 11.0 (source-compatible since 2.0)
332     */
333    public ToStringHelper addValue(double value) {
334      return addHolder(String.valueOf(value));
335    }
336
337    /**
338     * Adds an unnamed value to the formatted output.
339     *
340     * <p>It is strongly encouraged to use {@link #add(String, float)} instead
341     * and give value a readable name.
342     *
343     * @since 11.0 (source-compatible since 2.0)
344     */
345    public ToStringHelper addValue(float value) {
346      return addHolder(String.valueOf(value));
347    }
348
349    /**
350     * Adds an unnamed value to the formatted output.
351     *
352     * <p>It is strongly encouraged to use {@link #add(String, int)} instead
353     * and give value a readable name.
354     *
355     * @since 11.0 (source-compatible since 2.0)
356     */
357    public ToStringHelper addValue(int value) {
358      return addHolder(String.valueOf(value));
359    }
360
361    /**
362     * Adds an unnamed value to the formatted output.
363     *
364     * <p>It is strongly encouraged to use {@link #add(String, long)} instead
365     * and give value a readable name.
366     *
367     * @since 11.0 (source-compatible since 2.0)
368     */
369    public ToStringHelper addValue(long value) {
370      return addHolder(String.valueOf(value));
371    }
372
373    /**
374     * Returns a string in the format specified by {@link
375     * Objects#toStringHelper(Object)}.
376     *
377     * <p>After calling this method, you can keep adding more properties to later
378     * call toString() again and get a more complete representation of the
379     * same object; but properties cannot be removed, so this only allows
380     * limited reuse of the helper instance. The helper allows duplication of
381     * properties (multiple name/value pairs with the same name can be added).
382     */
383    @Override public String toString() {
384      // create a copy to keep it consistent in case value changes
385      boolean omitNullValuesSnapshot = omitNullValues;
386      String nextSeparator = "";
387      StringBuilder builder = new StringBuilder(32).append(className)
388          .append('{');
389      for (ValueHolder valueHolder = holderHead.next; valueHolder != null;
390          valueHolder = valueHolder.next) {
391        if (!omitNullValuesSnapshot || valueHolder.value != null) {
392          builder.append(nextSeparator);
393          nextSeparator = ", ";
394
395          if (valueHolder.name != null) {
396            builder.append(valueHolder.name).append('=');
397          }
398          builder.append(valueHolder.value);
399        }
400      }
401      return builder.append('}').toString();
402    }
403
404    private ValueHolder addHolder() {
405      ValueHolder valueHolder = new ValueHolder();
406      holderTail = holderTail.next = valueHolder;
407      return valueHolder;
408    }
409
410    private ToStringHelper addHolder(@Nullable Object value) {
411      ValueHolder valueHolder = addHolder();
412      valueHolder.value = value;
413      return this;
414    }
415
416    private ToStringHelper addHolder(String name, @Nullable Object value) {
417      ValueHolder valueHolder = addHolder();
418      valueHolder.value = value;
419      valueHolder.name = checkNotNull(name);
420      return this;
421    }
422
423    private static final class ValueHolder {
424      String name;
425      Object value;
426      ValueHolder next;
427    }
428  }
429}