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    
017    package com.google.common.base;
018    
019    import static com.google.common.base.Preconditions.checkNotNull;
020    
021    import com.google.common.annotations.GwtCompatible;
022    
023    import java.util.Arrays;
024    
025    import javax.annotation.Nullable;
026    
027    /**
028     * Helper functions that can operate on any {@code Object}.
029     *
030     * @author Laurence Gonsalves
031     * @since 2 (imported from Google Collections Library)
032     */
033    @GwtCompatible
034    public final class Objects {
035      private Objects() {}
036    
037      /**
038       * Determines whether two possibly-null objects are equal. Returns:
039       *
040       * <ul>
041       * <li>{@code true} if {@code a} and {@code b} are both null.
042       * <li>{@code true} if {@code a} and {@code b} are both non-null and they are
043       *     equal according to {@link Object#equals(Object)}.
044       * <li>{@code false} in all other situations.
045       * </ul>
046       *
047       * <p>This assumes that any non-null objects passed to this function conform
048       * to the {@code equals()} contract.
049       */
050      public static boolean equal(@Nullable Object a, @Nullable Object b) {
051        return a == b || (a != null && a.equals(b));
052      }
053    
054      /**
055       * Generates a hash code for multiple values. The hash code is generated by
056       * calling {@link Arrays#hashCode(Object[])}.
057       *
058       * <p>This is useful for implementing {@link Object#hashCode()}. For example,
059       * in an object that has three properties, {@code x}, {@code y}, and
060       * {@code z}, one could write:
061       * <pre>
062       * public int hashCode() {
063       *   return Objects.hashCode(getX(), getY(), getZ());
064       * }</pre>
065       *
066       * <b>Warning</b>: When a single object is supplied, the returned hash code
067       * does not equal the hash code of that object.
068       */
069      public static int hashCode(@Nullable Object... objects) {
070        return Arrays.hashCode(objects);
071      }
072    
073      /**
074       * Creates an instance of {@link ToStringHelper}.
075       *
076       * <p>This is helpful for implementing {@link Object#toString()}.
077       * Specification by example: <pre>   {@code
078       *   // Returns "ClassName{}"
079       *   Objects.toStringHelper(this)
080       *       .toString();
081       *
082       *   // Returns "ClassName{x=1}"
083       *   Objects.toStringHelper(this)
084       *       .add("x", 1)
085       *       .toString();
086       *
087       *   // Returns "MyObject{x=1}"
088       *   Objects.toStringHelper("MyObject")
089       *       .add("x", 1)
090       *       .toString();
091       *
092       *   // Returns "ClassName{x=1, y=foo}"
093       *   Objects.toStringHelper(this)
094       *       .add("x", 1)
095       *       .add("y", "foo")
096       *       .toString();
097       *   }}</pre>
098       *
099       * @param self the object to generate the string for (typically {@code this}),
100       *        used only for its class name
101       * @since 2
102       */
103      public static ToStringHelper toStringHelper(Object self) {
104        return new ToStringHelper(simpleName(self.getClass()));
105      }
106    
107      /**
108       * Creates an instance of {@link ToStringHelper} in the same manner as
109       * {@link Objects#toStringHelper(Object)}, but using the name of {@code clazz}
110       * instead of using an instance's {@link Object#getClass()}.
111       *
112       * @param clazz the {@link Class} of the instance
113       * @since 7 (source-compatible since 2)
114       */
115      public static ToStringHelper toStringHelper(Class<?> clazz) {
116        return new ToStringHelper(simpleName(clazz));
117      }
118    
119      /**
120       * Creates an instance of {@link ToStringHelper} in the same manner as
121       * {@link Objects#toStringHelper(Object)}, but using {@code className} instead
122       * of using an instance's {@link Object#getClass()}.
123       *
124       * @param className the name of the instance type
125       * @since 7 (source-compatible since 2)
126       */
127      public static ToStringHelper toStringHelper(String className) {
128        return new ToStringHelper(className);
129      }
130    
131      /**
132       * {@link Class#getSimpleName()} is not GWT compatible yet, so we
133       * provide our own implementation.
134       */
135      private static String simpleName(Class<?> clazz) {
136        String name = clazz.getName();
137    
138        // we want the name of the inner class all by its lonesome
139        int start = name.lastIndexOf('$');
140    
141        // if this isn't an inner class, just find the start of the
142        // top level class name.
143        if (start == -1) {
144          start = name.lastIndexOf('.');
145        }
146        return name.substring(start + 1);
147      }
148    
149      /**
150       * Returns the first of two given parameters that is not {@code null}, if
151       * either is, or otherwise throws a {@link NullPointerException}.
152       *
153       * @return {@code first} if {@code first} is not {@code null}, or
154       *     {@code second} if {@code first} is {@code null} and {@code second} is
155       *     not {@code null}
156       * @throws NullPointerException if both {@code first} and {@code second} were
157       *     {@code null}
158       * @since 3
159       */
160      public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
161        return first != null ? first : checkNotNull(second);
162      }
163    
164      /**
165       * Support class for {@link Objects#toStringHelper}.
166       *
167       * @author Jason Lee
168       * @since 2
169       */
170      public static final class ToStringHelper {
171        private final StringBuilder builder;
172        private String separator = "";
173    
174        /**
175         * Use {@link Objects#toStringHelper(Object)} to create an instance.
176         */
177        private ToStringHelper(String className) {
178          this.builder = new StringBuilder(32)
179              .append(checkNotNull(className))
180              .append('{');
181        }
182    
183        /**
184         * Adds a name/value pair to the formatted output in {@code name=value}
185         * format. If {@code value} is {@code null}, the string {@code "null"}
186         * is used.
187         */
188        public ToStringHelper add(String name, @Nullable Object value) {
189          builder.append(separator)
190              .append(checkNotNull(name))
191              .append('=')
192              .append(value);
193          separator = ", ";
194          return this;
195        }
196    
197        /**
198         * Adds a value to the formatted output in {@code value} format.
199         *
200         * <p>It is strongly encouraged to use {@link #add(String, Object)} instead
201         * and give value a readable name.
202         */
203        public ToStringHelper addValue(@Nullable Object value) {
204          builder.append(separator).append(value);
205          separator = ", ";
206          return this;
207        }
208    
209        /**
210         * Returns a string in the format specified by {@link
211         * Objects#toStringHelper(Object)}.
212         */
213        @Override public String toString() {
214          return builder.append('}').toString();
215        }
216      }
217    }