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.0 (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       * <p>Note that in GWT, class names are often obfuscated.
100       *
101       * @param self the object to generate the string for (typically {@code this}),
102       *        used only for its class name
103       * @since 2.0
104       */
105      public static ToStringHelper toStringHelper(Object self) {
106        return new ToStringHelper(simpleName(self.getClass()));
107      }
108    
109      /**
110       * Creates an instance of {@link ToStringHelper} in the same manner as
111       * {@link Objects#toStringHelper(Object)}, but using the name of {@code clazz}
112       * instead of using an instance's {@link Object#getClass()}.
113       *
114       * <p>Note that in GWT, class names are often obfuscated.
115       *
116       * @param clazz the {@link Class} of the instance
117       * @since 7.0 (source-compatible since 2.0)
118       */
119      public static ToStringHelper toStringHelper(Class<?> clazz) {
120        return new ToStringHelper(simpleName(clazz));
121      }
122    
123      /**
124       * Creates an instance of {@link ToStringHelper} in the same manner as
125       * {@link Objects#toStringHelper(Object)}, but using {@code className} instead
126       * of using an instance's {@link Object#getClass()}.
127       *
128       * @param className the name of the instance type
129       * @since 7.0 (source-compatible since 2.0)
130       */
131      public static ToStringHelper toStringHelper(String className) {
132        return new ToStringHelper(className);
133      }
134    
135      /**
136       * {@link Class#getSimpleName()} is not GWT compatible yet, so we
137       * provide our own implementation.
138       */
139      private static String simpleName(Class<?> clazz) {
140        String name = clazz.getName();
141    
142        // the nth anonymous class has a class name ending in "Outer$n"
143        // and local inner classes have names ending in "Outer.$1Inner"
144        name = name.replaceAll("\\$[0-9]+", "\\$");
145    
146        // we want the name of the inner class all by its lonesome
147        int start = name.lastIndexOf('$');
148    
149        // if this isn't an inner class, just find the start of the
150        // top level class name.
151        if (start == -1) {
152          start = name.lastIndexOf('.');
153        }
154        return name.substring(start + 1);
155      }
156    
157      /**
158       * Returns the first of two given parameters that is not {@code null}, if
159       * either is, or otherwise throws a {@link NullPointerException}.
160       *
161       * <p><b>Note:</b> if {@code first} is represented as an {@code Optional<T>},
162       * this can be accomplished with {@code first.or(second)}. That approach also
163       * allows for lazy evaluation of the fallback instance, using
164       * {@code first.or(Supplier)}.
165       *
166       * @return {@code first} if {@code first} is not {@code null}, or
167       *     {@code second} if {@code first} is {@code null} and {@code second} is
168       *     not {@code null}
169       * @throws NullPointerException if both {@code first} and {@code second} were
170       *     {@code null}
171       * @since 3.0
172       */
173      public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
174        return first != null ? first : checkNotNull(second);
175      }
176    
177      /**
178       * Support class for {@link Objects#toStringHelper}.
179       *
180       * @author Jason Lee
181       * @since 2.0
182       */
183      public static final class ToStringHelper {
184        private final StringBuilder builder;
185        private boolean needsSeparator = false;
186    
187        /**
188         * Use {@link Objects#toStringHelper(Object)} to create an instance.
189         */
190        private ToStringHelper(String className) {
191          checkNotNull(className);
192          this.builder = new StringBuilder(32).append(className).append('{');
193        }
194    
195        /**
196         * Adds a name/value pair to the formatted output in {@code name=value}
197         * format. If {@code value} is {@code null}, the string {@code "null"}
198         * is used.
199         */
200        public ToStringHelper add(String name, @Nullable Object value) {
201          checkNotNull(name);
202          maybeAppendSeparator().append(name).append('=').append(value);
203          return this;
204        }
205    
206        /**
207         * Adds a value to the formatted output in {@code value} format.
208         *
209         * <p>It is strongly encouraged to use {@link #add(String, Object)} instead
210         * and give value a readable name.
211         */
212        public ToStringHelper addValue(@Nullable Object value) {
213          maybeAppendSeparator().append(value);
214          return this;
215        }
216    
217        /**
218         * Returns a string in the format specified by {@link
219         * Objects#toStringHelper(Object)}.
220         */
221        @Override public String toString() {
222          try {
223            return builder.append('}').toString();
224          } finally {
225            // Slice off the closing brace in case there are additional calls to
226            // #add or #addValue.
227            builder.setLength(builder.length() - 1);
228          }
229        }
230    
231        private StringBuilder maybeAppendSeparator() {
232          if (needsSeparator) {
233            return builder.append(", ");
234          } else {
235            needsSeparator = true;
236            return builder;
237          }
238        }
239      }
240    }