001/* 002 * Copyright (C) 2014 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 017package com.google.common.base; 018 019import static com.google.common.base.Preconditions.checkNotNull; 020 021import com.google.common.annotations.GwtCompatible; 022 023import java.util.Arrays; 024 025import javax.annotation.CheckReturnValue; 026import javax.annotation.Nullable; 027 028/** 029 * Helper functions that operate on any {@code Object}, and are not already provided in 030 * {@link java.util.Objects}. 031 * 032 * <p>See the Guava User Guide on <a 033 * href="https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained">writing 034 * {@code Object} methods with {@code MoreObjects}</a>. 035 * 036 * @author Laurence Gonsalves 037 * @since 18.0 (since 2.0 as {@code Objects}) 038 */ 039@GwtCompatible 040public final class MoreObjects { 041 /** 042 * Returns the first of two given parameters that is not {@code null}, if either is, or otherwise 043 * throws a {@link NullPointerException}. 044 * 045 * <p><b>Note:</b> if {@code first} is represented as an {@link Optional}, this can be 046 * accomplished with {@link Optional#or(Object) first.or(second)}. That approach also allows for 047 * lazy evaluation of the fallback instance, using {@link Optional#or(Supplier) 048 * first.or(supplier)}. 049 * 050 * @return {@code first} if it is non-null; otherwise {@code second} if it is non-null 051 * @throws NullPointerException if both {@code first} and {@code second} are null 052 * @since 18.0 (since 3.0 as {@code Objects.firstNonNull()}). 053 */ 054 @CheckReturnValue 055 public static <T> T firstNonNull(@Nullable T first, @Nullable T second) { 056 return first != null ? first : checkNotNull(second); 057 } 058 059 /** 060 * Creates an instance of {@link ToStringHelper}. 061 * 062 * <p>This is helpful for implementing {@link Object#toString()}. 063 * Specification by example: <pre> {@code 064 * // Returns "ClassName{}" 065 * MoreObjects.toStringHelper(this) 066 * .toString(); 067 * 068 * // Returns "ClassName{x=1}" 069 * MoreObjects.toStringHelper(this) 070 * .add("x", 1) 071 * .toString(); 072 * 073 * // Returns "MyObject{x=1}" 074 * MoreObjects.toStringHelper("MyObject") 075 * .add("x", 1) 076 * .toString(); 077 * 078 * // Returns "ClassName{x=1, y=foo}" 079 * MoreObjects.toStringHelper(this) 080 * .add("x", 1) 081 * .add("y", "foo") 082 * .toString(); 083 * 084 * // Returns "ClassName{x=1}" 085 * MoreObjects.toStringHelper(this) 086 * .omitNullValues() 087 * .add("x", 1) 088 * .add("y", null) 089 * .toString(); 090 * }}</pre> 091 * 092 * <p>Note that in GWT, class names are often obfuscated. 093 * 094 * @param self the object to generate the string for (typically {@code this}), used only for its 095 * class name 096 * @since 18.0 (since 2.0 as {@code Objects.toStringHelper()}). 097 */ 098 @CheckReturnValue 099 public static ToStringHelper toStringHelper(Object self) { 100 return new ToStringHelper(self.getClass().getSimpleName()); 101 } 102 103 /** 104 * Creates an instance of {@link ToStringHelper} in the same manner as {@link 105 * #toStringHelper(Object)}, but using the simple name of {@code clazz} instead of using an 106 * instance's {@link Object#getClass()}. 107 * 108 * <p>Note that in GWT, class names are often obfuscated. 109 * 110 * @param clazz the {@link Class} of the instance 111 * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}). 112 */ 113 @CheckReturnValue 114 public static ToStringHelper toStringHelper(Class<?> clazz) { 115 return new ToStringHelper(clazz.getSimpleName()); 116 } 117 118 /** 119 * Creates an instance of {@link ToStringHelper} in the same manner as {@link 120 * #toStringHelper(Object)}, but using {@code className} instead of using an instance's {@link 121 * Object#getClass()}. 122 * 123 * @param className the name of the instance type 124 * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}). 125 */ 126 @CheckReturnValue 127 public static ToStringHelper toStringHelper(String className) { 128 return new ToStringHelper(className); 129 } 130 131 /** 132 * Support class for {@link MoreObjects#toStringHelper}. 133 * 134 * @author Jason Lee 135 * @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}). 136 */ 137 public static final class ToStringHelper { 138 private final String className; 139 private ValueHolder holderHead = new ValueHolder(); 140 private ValueHolder holderTail = holderHead; 141 private boolean omitNullValues = false; 142 143 /** 144 * Use {@link MoreObjects#toStringHelper(Object)} to create an instance. 145 */ 146 private ToStringHelper(String className) { 147 this.className = checkNotNull(className); 148 } 149 150 /** 151 * Configures the {@link ToStringHelper} so {@link #toString()} will ignore 152 * properties with null value. The order of calling this method, relative 153 * to the {@code add()}/{@code addValue()} methods, is not significant. 154 * 155 * @since 18.0 (since 12.0 as {@code Objects.ToStringHelper.omitNullValues()}). 156 */ 157 public ToStringHelper omitNullValues() { 158 omitNullValues = true; 159 return this; 160 } 161 162 /** 163 * Adds a name/value pair to the formatted output in {@code name=value} 164 * format. If {@code value} is {@code null}, the string {@code "null"} 165 * is used, unless {@link #omitNullValues()} is called, in which case this 166 * name/value pair will not be added. 167 */ 168 public ToStringHelper add(String name, @Nullable Object value) { 169 return addHolder(name, value); 170 } 171 172 /** 173 * Adds a name/value pair to the formatted output in {@code name=value} 174 * format. 175 * 176 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 177 */ 178 public ToStringHelper add(String name, boolean value) { 179 return addHolder(name, String.valueOf(value)); 180 } 181 182 /** 183 * Adds a name/value pair to the formatted output in {@code name=value} 184 * format. 185 * 186 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 187 */ 188 public ToStringHelper add(String name, char value) { 189 return addHolder(name, String.valueOf(value)); 190 } 191 192 /** 193 * Adds a name/value pair to the formatted output in {@code name=value} 194 * format. 195 * 196 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 197 */ 198 public ToStringHelper add(String name, double value) { 199 return addHolder(name, String.valueOf(value)); 200 } 201 202 /** 203 * Adds a name/value pair to the formatted output in {@code name=value} 204 * format. 205 * 206 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 207 */ 208 public ToStringHelper add(String name, float value) { 209 return addHolder(name, String.valueOf(value)); 210 } 211 212 /** 213 * Adds a name/value pair to the formatted output in {@code name=value} 214 * format. 215 * 216 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 217 */ 218 public ToStringHelper add(String name, int value) { 219 return addHolder(name, String.valueOf(value)); 220 } 221 222 /** 223 * Adds a name/value pair to the formatted output in {@code name=value} 224 * format. 225 * 226 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 227 */ 228 public ToStringHelper add(String name, long value) { 229 return addHolder(name, String.valueOf(value)); 230 } 231 232 /** 233 * Adds an unnamed value to the formatted output. 234 * 235 * <p>It is strongly encouraged to use {@link #add(String, Object)} instead 236 * and give value a readable name. 237 */ 238 public ToStringHelper addValue(@Nullable Object value) { 239 return addHolder(value); 240 } 241 242 /** 243 * Adds an unnamed value to the formatted output. 244 * 245 * <p>It is strongly encouraged to use {@link #add(String, boolean)} instead 246 * and give value a readable name. 247 * 248 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 249 */ 250 public ToStringHelper addValue(boolean value) { 251 return addHolder(String.valueOf(value)); 252 } 253 254 /** 255 * Adds an unnamed value to the formatted output. 256 * 257 * <p>It is strongly encouraged to use {@link #add(String, char)} instead 258 * and give value a readable name. 259 * 260 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 261 */ 262 public ToStringHelper addValue(char value) { 263 return addHolder(String.valueOf(value)); 264 } 265 266 /** 267 * Adds an unnamed value to the formatted output. 268 * 269 * <p>It is strongly encouraged to use {@link #add(String, double)} instead 270 * and give value a readable name. 271 * 272 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 273 */ 274 public ToStringHelper addValue(double value) { 275 return addHolder(String.valueOf(value)); 276 } 277 278 /** 279 * Adds an unnamed value to the formatted output. 280 * 281 * <p>It is strongly encouraged to use {@link #add(String, float)} instead 282 * and give value a readable name. 283 * 284 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 285 */ 286 public ToStringHelper addValue(float value) { 287 return addHolder(String.valueOf(value)); 288 } 289 290 /** 291 * Adds an unnamed value to the formatted output. 292 * 293 * <p>It is strongly encouraged to use {@link #add(String, int)} instead 294 * and give value a readable name. 295 * 296 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 297 */ 298 public ToStringHelper addValue(int value) { 299 return addHolder(String.valueOf(value)); 300 } 301 302 /** 303 * Adds an unnamed value to the formatted output. 304 * 305 * <p>It is strongly encouraged to use {@link #add(String, long)} instead 306 * and give value a readable name. 307 * 308 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 309 */ 310 public ToStringHelper addValue(long value) { 311 return addHolder(String.valueOf(value)); 312 } 313 314 /** 315 * Returns a string in the format specified by 316 * {@link MoreObjects#toStringHelper(Object)}. 317 * 318 * <p>After calling this method, you can keep adding more properties to later 319 * call toString() again and get a more complete representation of the 320 * same object; but properties cannot be removed, so this only allows 321 * limited reuse of the helper instance. The helper allows duplication of 322 * properties (multiple name/value pairs with the same name can be added). 323 */ 324 @CheckReturnValue 325 @Override 326 public String toString() { 327 // create a copy to keep it consistent in case value changes 328 boolean omitNullValuesSnapshot = omitNullValues; 329 String nextSeparator = ""; 330 StringBuilder builder = new StringBuilder(32).append(className).append('{'); 331 for (ValueHolder valueHolder = holderHead.next; 332 valueHolder != null; 333 valueHolder = valueHolder.next) { 334 Object value = valueHolder.value; 335 if (!omitNullValuesSnapshot || value != null) { 336 builder.append(nextSeparator); 337 nextSeparator = ", "; 338 339 if (valueHolder.name != null) { 340 builder.append(valueHolder.name).append('='); 341 } 342 if (value != null && value.getClass().isArray()) { 343 Object[] objectArray = {value}; 344 String arrayString = Arrays.deepToString(objectArray); 345 builder.append(arrayString.substring(1, arrayString.length() - 1)); 346 } else { 347 builder.append(value); 348 } 349 } 350 } 351 return builder.append('}').toString(); 352 } 353 354 private ValueHolder addHolder() { 355 ValueHolder valueHolder = new ValueHolder(); 356 holderTail = holderTail.next = valueHolder; 357 return valueHolder; 358 } 359 360 private ToStringHelper addHolder(@Nullable Object value) { 361 ValueHolder valueHolder = addHolder(); 362 valueHolder.value = value; 363 return this; 364 } 365 366 private ToStringHelper addHolder(String name, @Nullable Object value) { 367 ValueHolder valueHolder = addHolder(); 368 valueHolder.value = value; 369 valueHolder.name = checkNotNull(name); 370 return this; 371 } 372 373 private static final class ValueHolder { 374 String name; 375 Object value; 376 ValueHolder next; 377 } 378 } 379 380 private MoreObjects() {} 381}