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