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 javax.annotation.Nullable; 024 025/** 026 * Helper functions that operate on any {@code Object}, and are not already provided in 027 * {@link java.util.Objects}. 028 * 029 * <p>See the Guava User Guide on <a 030 * href="http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained">writing 031 * {@code Object} methods with {@code MoreObjects}</a>. 032 * 033 * @author Laurence Gonsalves 034 * @since 18.0 (since 2.0 as {@code Objects}) 035 */ 036@GwtCompatible 037public final class MoreObjects { 038 /** 039 * Returns the first of two given parameters that is not {@code null}, if either is, or otherwise 040 * throws a {@link NullPointerException}. 041 * 042 * <p><b>Note:</b> if {@code first} is represented as an {@link Optional}, this can be 043 * accomplished with {@link Optional#or(Object) first.or(second)}. That approach also allows for 044 * lazy evaluation of the fallback instance, using {@link Optional#or(Supplier) 045 * first.or(supplier)}. 046 * 047 * @return {@code first} if it is non-null; otherwise {@code second} if it is non-null 048 * @throws NullPointerException if both {@code first} and {@code second} are null 049 * @since 18.0 (since 3.0 as {@code Objects.firstNonNull()}. 050 */ 051 public static <T> T firstNonNull(@Nullable T first, @Nullable T second) { 052 return first != null ? first : checkNotNull(second); 053 } 054 055 /** 056 * Creates an instance of {@link ToStringHelper}. 057 * 058 * <p>This is helpful for implementing {@link Object#toString()}. 059 * Specification by example: <pre> {@code 060 * // Returns "ClassName{}" 061 * MoreObjects.toStringHelper(this) 062 * .toString(); 063 * 064 * // Returns "ClassName{x=1}" 065 * MoreObjects.toStringHelper(this) 066 * .add("x", 1) 067 * .toString(); 068 * 069 * // Returns "MyObject{x=1}" 070 * MoreObjects.toStringHelper("MyObject") 071 * .add("x", 1) 072 * .toString(); 073 * 074 * // Returns "ClassName{x=1, y=foo}" 075 * MoreObjects.toStringHelper(this) 076 * .add("x", 1) 077 * .add("y", "foo") 078 * .toString(); 079 * 080 * // Returns "ClassName{x=1}" 081 * MoreObjects.toStringHelper(this) 082 * .omitNullValues() 083 * .add("x", 1) 084 * .add("y", null) 085 * .toString(); 086 * }}</pre> 087 * 088 * <p>Note that in GWT, class names are often obfuscated. 089 * 090 * @param self the object to generate the string for (typically {@code this}), used only for its 091 * class name 092 * @since 18.0 (since 2.0 as {@code Objects.toStringHelper()}. 093 */ 094 public static ToStringHelper toStringHelper(Object self) { 095 return new ToStringHelper(simpleName(self.getClass())); 096 } 097 098 /** 099 * 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}