Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2014 The Guava Authors
      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 
     17 package com.google.common.base;
     18 
     19 import static com.google.common.base.Preconditions.checkNotNull;
     20 
     21 import com.google.common.annotations.GwtCompatible;
     22 
     23 import javax.annotation.Nullable;
     24 
     25 /**
     26  * Helper functions that operate on any {@code Object}, and are not already provided in
     27  * {@link java.util.Objects}.
     28  *
     29  * <p>See the Guava User Guide on <a
     30  * href="http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained">writing
     31  * {@code Object} methods with {@code MoreObjects}</a>.
     32  *
     33  * @author Laurence Gonsalves
     34  * @since 18.0 (since 2.0 as {@code Objects})
     35  */
     36 @GwtCompatible
     37 public final class MoreObjects {
     38   /**
     39    * Returns the first of two given parameters that is not {@code null}, if either is, or otherwise
     40    * throws a {@link NullPointerException}.
     41    *
     42    * <p><b>Note:</b> if {@code first} is represented as an {@link Optional}, this can be
     43    * accomplished with {@link Optional#or(Object) first.or(second)}. That approach also allows for
     44    * lazy evaluation of the fallback instance, using {@link Optional#or(Supplier)
     45    * first.or(supplier)}.
     46    *
     47    * @return {@code first} if it is non-null; otherwise {@code second} if it is non-null
     48    * @throws NullPointerException if both {@code first} and {@code second} are null
     49    * @since 18.0 (since 3.0 as {@code Objects.firstNonNull()}.
     50    */
     51   public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
     52     return first != null ? first : checkNotNull(second);
     53   }
     54 
     55   /**
     56    * Creates an instance of {@link ToStringHelper}.
     57    *
     58    * <p>This is helpful for implementing {@link Object#toString()}.
     59    * Specification by example: <pre>   {@code
     60    *   // Returns "ClassName{}"
     61    *   MoreObjects.toStringHelper(this)
     62    *       .toString();
     63    *
     64    *   // Returns "ClassName{x=1}"
     65    *   MoreObjects.toStringHelper(this)
     66    *       .add("x", 1)
     67    *       .toString();
     68    *
     69    *   // Returns "MyObject{x=1}"
     70    *   MoreObjects.toStringHelper("MyObject")
     71    *       .add("x", 1)
     72    *       .toString();
     73    *
     74    *   // Returns "ClassName{x=1, y=foo}"
     75    *   MoreObjects.toStringHelper(this)
     76    *       .add("x", 1)
     77    *       .add("y", "foo")
     78    *       .toString();
     79    *
     80    *   // Returns "ClassName{x=1}"
     81    *   MoreObjects.toStringHelper(this)
     82    *       .omitNullValues()
     83    *       .add("x", 1)
     84    *       .add("y", null)
     85    *       .toString();
     86    *   }}</pre>
     87    *
     88    * <p>Note that in GWT, class names are often obfuscated.
     89    *
     90    * @param self the object to generate the string for (typically {@code this}), used only for its
     91    *     class name
     92    * @since 18.0 (since 2.0 as {@code Objects.toStringHelper()}.
     93    */
     94   public static ToStringHelper toStringHelper(Object self) {
     95     return new ToStringHelper(simpleName(self.getClass()));
     96   }
     97 
     98   /**
     99    * Creates an instance of {@link ToStringHelper} in the same manner as {@link
    100    * #toStringHelper(Object)}, but using the simple name of {@code clazz} instead of using an
    101    * instance's {@link Object#getClass()}.
    102    *
    103    * <p>Note that in GWT, class names are often obfuscated.
    104    *
    105    * @param clazz the {@link Class} of the instance
    106    * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}.
    107    */
    108   public static ToStringHelper toStringHelper(Class<?> clazz) {
    109     return new ToStringHelper(simpleName(clazz));
    110   }
    111 
    112   /**
    113    * Creates an instance of {@link ToStringHelper} in the same manner as {@link
    114    * #toStringHelper(Object)}, but using {@code className} instead of using an instance's {@link
    115    * Object#getClass()}.
    116    *
    117    * @param className the name of the instance type
    118    * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}.
    119    */
    120   public static ToStringHelper toStringHelper(String className) {
    121     return new ToStringHelper(className);
    122   }
    123 
    124   /**
    125    * {@link Class#getSimpleName()} is not GWT compatible yet, so we
    126    * provide our own implementation.
    127    */
    128   // Package-private so Objects can call it.
    129   static String simpleName(Class<?> clazz) {
    130     String name = clazz.getName();
    131 
    132     // the nth anonymous class has a class name ending in "Outer$n"
    133     // and local inner classes have names ending in "Outer.$1Inner"
    134     name = name.replaceAll("\\$[0-9]+", "\\$");
    135 
    136     // we want the name of the inner class all by its lonesome
    137     int start = name.lastIndexOf('$');
    138 
    139     // if this isn't an inner class, just find the start of the
    140     // top level class name.
    141     if (start == -1) {
    142       start = name.lastIndexOf('.');
    143     }
    144     return name.substring(start + 1);
    145   }
    146 
    147   /**
    148    * Support class for {@link MoreObjects#toStringHelper}.
    149    *
    150    * @author Jason Lee
    151    * @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}.
    152    */
    153   public static final class ToStringHelper {
    154     private final String className;
    155     private ValueHolder holderHead = new ValueHolder();
    156     private ValueHolder holderTail = holderHead;
    157     private boolean omitNullValues = false;
    158 
    159     /**
    160      * Use {@link MoreObjects#toStringHelper(Object)} to create an instance.
    161      */
    162     private ToStringHelper(String className) {
    163       this.className = checkNotNull(className);
    164     }
    165 
    166     /**
    167      * Configures the {@link ToStringHelper} so {@link #toString()} will ignore
    168      * properties with null value. The order of calling this method, relative
    169      * to the {@code add()}/{@code addValue()} methods, is not significant.
    170      *
    171      * @since 18.0 (since 12.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    172      */
    173     public ToStringHelper omitNullValues() {
    174       omitNullValues = true;
    175       return this;
    176     }
    177 
    178     /**
    179      * Adds a name/value pair to the formatted output in {@code name=value}
    180      * format. If {@code value} is {@code null}, the string {@code "null"}
    181      * is used, unless {@link #omitNullValues()} is called, in which case this
    182      * name/value pair will not be added.
    183      */
    184     public ToStringHelper add(String name, @Nullable Object value) {
    185       return addHolder(name, value);
    186     }
    187 
    188     /**
    189      * Adds a name/value pair to the formatted output in {@code name=value}
    190      * format.
    191      *
    192      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    193      */
    194     public ToStringHelper add(String name, boolean value) {
    195       return addHolder(name, String.valueOf(value));
    196     }
    197 
    198     /**
    199      * Adds a name/value pair to the formatted output in {@code name=value}
    200      * format.
    201      *
    202      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    203      */
    204     public ToStringHelper add(String name, char value) {
    205       return addHolder(name, String.valueOf(value));
    206     }
    207 
    208     /**
    209      * Adds a name/value pair to the formatted output in {@code name=value}
    210      * format.
    211      *
    212      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    213      */
    214     public ToStringHelper add(String name, double value) {
    215       return addHolder(name, String.valueOf(value));
    216     }
    217 
    218     /**
    219      * Adds a name/value pair to the formatted output in {@code name=value}
    220      * format.
    221      *
    222      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    223      */
    224     public ToStringHelper add(String name, float value) {
    225       return addHolder(name, String.valueOf(value));
    226     }
    227 
    228     /**
    229      * Adds a name/value pair to the formatted output in {@code name=value}
    230      * format.
    231      *
    232      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    233      */
    234     public ToStringHelper add(String name, int value) {
    235       return addHolder(name, String.valueOf(value));
    236     }
    237 
    238     /**
    239      * Adds a name/value pair to the formatted output in {@code name=value}
    240      * format.
    241      *
    242      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    243      */
    244     public ToStringHelper add(String name, long value) {
    245       return addHolder(name, String.valueOf(value));
    246     }
    247 
    248     /**
    249      * Adds an unnamed value to the formatted output.
    250      *
    251      * <p>It is strongly encouraged to use {@link #add(String, Object)} instead
    252      * and give value a readable name.
    253      *
    254      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    255      */
    256     public ToStringHelper addValue(@Nullable Object value) {
    257       return addHolder(value);
    258     }
    259 
    260     /**
    261      * Adds an unnamed value to the formatted output.
    262      *
    263      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    264      *
    265      * <p>It is strongly encouraged to use {@link #add(String, boolean)} instead
    266      * and give value a readable name.
    267      *
    268      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    269      */
    270     public ToStringHelper addValue(boolean value) {
    271       return addHolder(String.valueOf(value));
    272     }
    273 
    274     /**
    275      * Adds an unnamed value to the formatted output.
    276      *
    277      * <p>It is strongly encouraged to use {@link #add(String, char)} instead
    278      * and give value a readable name.
    279      *
    280      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    281      */
    282     public ToStringHelper addValue(char value) {
    283       return addHolder(String.valueOf(value));
    284     }
    285 
    286     /**
    287      * Adds an unnamed value to the formatted output.
    288      *
    289      * <p>It is strongly encouraged to use {@link #add(String, double)} instead
    290      * and give value a readable name.
    291      *
    292      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    293      */
    294     public ToStringHelper addValue(double value) {
    295       return addHolder(String.valueOf(value));
    296     }
    297 
    298     /**
    299      * Adds an unnamed value to the formatted output.
    300      *
    301      * <p>It is strongly encouraged to use {@link #add(String, float)} instead
    302      * and give value a readable name.
    303      *
    304      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    305      */
    306     public ToStringHelper addValue(float value) {
    307       return addHolder(String.valueOf(value));
    308     }
    309 
    310     /**
    311      * Adds an unnamed value to the formatted output.
    312      *
    313      * <p>It is strongly encouraged to use {@link #add(String, int)} instead
    314      * and give value a readable name.
    315      *
    316      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    317      */
    318     public ToStringHelper addValue(int value) {
    319       return addHolder(String.valueOf(value));
    320     }
    321 
    322     /**
    323      * Adds an unnamed value to the formatted output.
    324      *
    325      * <p>It is strongly encouraged to use {@link #add(String, long)} instead
    326      * and give value a readable name.
    327      *
    328      * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.omitNullValues()}.
    329      */
    330     public ToStringHelper addValue(long value) {
    331       return addHolder(String.valueOf(value));
    332     }
    333 
    334     /**
    335      * Returns a string in the format specified by
    336      * {@link MoreObjects#toStringHelper(Object)}.
    337      *
    338      * <p>After calling this method, you can keep adding more properties to later
    339      * call toString() again and get a more complete representation of the
    340      * same object; but properties cannot be removed, so this only allows
    341      * limited reuse of the helper instance. The helper allows duplication of
    342      * properties (multiple name/value pairs with the same name can be added).
    343      */
    344     @Override public String toString() {
    345       // create a copy to keep it consistent in case value changes
    346       boolean omitNullValuesSnapshot = omitNullValues;
    347       String nextSeparator = "";
    348       StringBuilder builder = new StringBuilder(32).append(className)
    349           .append('{');
    350       for (ValueHolder valueHolder = holderHead.next; valueHolder != null;
    351           valueHolder = valueHolder.next) {
    352         if (!omitNullValuesSnapshot || valueHolder.value != null) {
    353           builder.append(nextSeparator);
    354           nextSeparator = ", ";
    355 
    356           if (valueHolder.name != null) {
    357             builder.append(valueHolder.name).append('=');
    358           }
    359           builder.append(valueHolder.value);
    360         }
    361       }
    362       return builder.append('}').toString();
    363     }
    364 
    365     private ValueHolder addHolder() {
    366       ValueHolder valueHolder = new ValueHolder();
    367       holderTail = holderTail.next = valueHolder;
    368       return valueHolder;
    369     }
    370 
    371     private ToStringHelper addHolder(@Nullable Object value) {
    372       ValueHolder valueHolder = addHolder();
    373       valueHolder.value = value;
    374       return this;
    375     }
    376 
    377     private ToStringHelper addHolder(String name, @Nullable Object value) {
    378       ValueHolder valueHolder = addHolder();
    379       valueHolder.value = value;
    380       valueHolder.name = checkNotNull(name);
    381       return this;
    382     }
    383 
    384     private static final class ValueHolder {
    385       String name;
    386       Object value;
    387       ValueHolder next;
    388     }
    389   }
    390 
    391   private MoreObjects() {}
    392 }
    393