1/*
2 * Copyright (C) 2007 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.base;
18
19import com.google.common.annotations.GwtCompatible;
20import com.google.common.annotations.VisibleForTesting;
21
22import java.util.ArrayList;
23import java.util.Arrays;
24import java.util.List;
25
26import javax.annotation.Nullable;
27
28/**
29 * Helper functions that can operate on any {@code Object}.
30 *
31 * @author Laurence Gonsalves
32 * @since 2010.01.04 <b>stable</b> (imported from Google Collections Library)
33 */
34@GwtCompatible
35public final class Objects {
36  private Objects() {}
37
38  /**
39   * Determines whether two possibly-null objects are equal. Returns:
40   *
41   * <ul>
42   * <li>{@code true} if {@code a} and {@code b} are both null.
43   * <li>{@code true} if {@code a} and {@code b} are both non-null and they are
44   *     equal according to {@link Object#equals(Object)}.
45   * <li>{@code false} in all other situations.
46   * </ul>
47   *
48   * <p>This assumes that any non-null objects passed to this function conform
49   * to the {@code equals()} contract.
50   */
51  public static boolean equal(@Nullable Object a, @Nullable Object b) {
52    return a == b || (a != null && a.equals(b));
53  }
54
55  /**
56   * Generates a hash code for multiple values. The hash code is generated by
57   * calling {@link Arrays#hashCode(Object[])}.
58   *
59   * <p>This is useful for implementing {@link Object#hashCode()}. For example,
60   * in an object that has three properties, {@code x}, {@code y}, and
61   * {@code z}, one could write:
62   * <pre>
63   * public int hashCode() {
64   *   return Objects.hashCode(getX(), getY(), getZ());
65   * }</pre>
66   *
67   * <b>Warning</b>: When a single object is supplied, the returned hash code
68   * does not equal the hash code of that object.
69   */
70  public static int hashCode(Object... objects) {
71    return Arrays.hashCode(objects);
72  }
73
74  /**
75   * Creates an instance of {@link ToStringHelper}.
76   *
77   * <p>This is helpful for implementing {@link Object#toString()}. For
78   * example, in an object that contains two member variables, {@code x},
79   * and {@code y}, one could write:<pre>   <tt>
80   *   public class ClassName {
81   *     public String toString() {
82   *       return Objects.toStringHelper(this)
83   *           .add("x", x)
84   *           .add("y", y)
85   *           .toString();
86   *     }
87   *   }</tt>
88   * </pre>
89   *
90   * Assuming the values of {@code x} and {@code y} are 1 and 2,
91   * this code snippet returns the string <tt>"ClassName{x=1, y=2}"</tt>.
92   *
93   * @since 2010.01.04 <b>tentative</b>
94   */
95  public static ToStringHelper toStringHelper(Object object) {
96    return new ToStringHelper(object);
97  }
98
99  /**
100   * Support class for {@link Objects#toStringHelper}.
101   *
102   * @author Jason Lee
103   * @since 2010.01.04 <b>tentative</b>
104   */
105  public static class ToStringHelper {
106    private final List<String> fieldString = new ArrayList<String>();
107    private final Object instance;
108
109    /**
110     * Use {@link Objects#toStringHelper(Object)} to create an instance.
111     */
112    private ToStringHelper(Object instance) {
113      this.instance = Preconditions.checkNotNull(instance);
114    }
115
116    /**
117     * Adds a name/value pair to the formatted output in {@code name=value}
118     * format. If {@code value} is {@code null}, the string {@code "null"}
119     * is used.
120     */
121    public ToStringHelper add(String name, @Nullable Object value) {
122      return addValue(Preconditions.checkNotNull(name) + "=" + value);
123    }
124
125    /**
126     * Adds a value to the formatted output in {@code value} format.<p/>
127     *
128     * It is strongly encouraged to use {@link #add(String, Object)} instead and
129     * give value a readable name.
130     */
131    public ToStringHelper addValue(@Nullable Object value) {
132      fieldString.add(String.valueOf(value));
133      return this;
134    }
135
136    private static final Joiner JOINER = Joiner.on(", ");
137
138    /**
139     * Returns the formatted string.
140     */
141    @Override public String toString() {
142      StringBuilder builder = new StringBuilder(100)
143          .append(simpleName(instance.getClass()))
144          .append('{');
145      return JOINER.appendTo(builder, fieldString)
146          .append('}')
147          .toString();
148    }
149
150    /**
151     * {@link Class#getSimpleName()} is not GWT compatible yet, so we
152     * provide our own implementation.
153     */
154    @VisibleForTesting
155    static String simpleName(Class<?> clazz) {
156      String name = clazz.getName();
157
158      // we want the name of the inner class all by its lonesome
159      int start = name.lastIndexOf('$');
160
161      // if this isn't an inner class, just find the start of the
162      // top level class name.
163      if (start == -1) {
164        start = name.lastIndexOf('.');
165      }
166      return name.substring(start + 1);
167    }
168  }
169}
170