001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau; 014 015import static org.apache.juneau.Visibility.*; 016import static org.apache.juneau.collections.JsonMap.*; 017import static org.apache.juneau.common.internal.StringUtils.*; 018import static org.apache.juneau.common.internal.ThrowableUtils.*; 019import static org.apache.juneau.internal.ClassUtils.*; 020import static org.apache.juneau.internal.CollectionUtils.*; 021 022import java.beans.*; 023import java.io.*; 024import java.lang.annotation.*; 025import java.lang.reflect.*; 026import java.util.*; 027import java.util.concurrent.*; 028import java.util.stream.*; 029 030import org.apache.juneau.annotation.*; 031import org.apache.juneau.collections.*; 032import org.apache.juneau.cp.*; 033import org.apache.juneau.internal.*; 034import org.apache.juneau.json.*; 035import org.apache.juneau.marshaller.*; 036import org.apache.juneau.reflect.*; 037import org.apache.juneau.serializer.*; 038import org.apache.juneau.swap.*; 039import org.apache.juneau.utils.*; 040 041/** 042 * Bean context. 043 * 044 * <p> 045 * This class servers multiple purposes: 046 * <ul class='spaced-list'> 047 * <li> 048 * Provides the ability to wrap beans inside {@link Map} interfaces. 049 * <li> 050 * Serves as a repository for metadata on POJOs, such as associated {@link Bean @Bean} annotations, 051 * {@link PropertyNamer PropertyNamers}, etc... which are used to tailor how POJOs are serialized and parsed. 052 * </ul> 053 * 054 * <p> 055 * All serializers and parsers use this context so that they can handle POJOs using a common framework. 056 * 057 * <h5 class='topic'>Bean Contexts</h5> 058 * 059 * <p> 060 * Bean contexts are created through the {@link BeanContext#create() BeanContext.create()} and {@link Builder#build()} methods. 061 * <br>These context objects are read-only, reusable, and thread-safe. 062 * 063 * <p> 064 * Each bean context maintains a cache of {@link ClassMeta} objects that describe information about classes encountered. 065 * These <c>ClassMeta</c> objects are time-consuming to construct. 066 * Therefore, instances of {@link BeanContext} that share the same <js>"BeanContext.*"</js> property values share 067 * the same cache. This allows for efficient reuse of <c>ClassMeta</c> objects so that the information about 068 * classes only needs to be calculated once. 069 * Because of this, many of the properties defined on the {@link BeanContext} class cannot be overridden on the session. 070 * 071 * <h5 class='topic'>Bean Sessions</h5> 072 * 073 * <p> 074 * Whereas <c>BeanContext</c> objects are permanent, unchangeable, cached, and thread-safe, 075 * {@link BeanSession} objects are ephemeral and not thread-safe. 076 * They are meant to be used as quickly-constructed scratchpads for creating bean maps. 077 * {@link BeanMap} objects can only be created through the session. 078 * 079 * <h5 class='topic'>BeanContext configuration properties</h5> 080 * 081 * <p> 082 * <c>BeanContexts</c> have several configuration properties that can be used to tweak behavior on how beans are 083 * handled. These are denoted as the static <jsf>BEAN_*</jsf> fields on this class. 084 * 085 * <p> 086 * Some settings (e.g. {@link Builder#beansRequireDefaultConstructor()}) are used to differentiate between bean 087 * and non-bean classes. 088 * Attempting to create a bean map around one of these objects will throw a {@link BeanRuntimeException}. 089 * The purpose for this behavior is so that the serializers can identify these non-bean classes and convert them to 090 * plain strings using the {@link Object#toString()} method. 091 * 092 * <p> 093 * Some settings (e.g. {@link Builder#beanFieldVisibility(Visibility)}) are used to determine what kinds of properties are 094 * detected on beans. 095 * 096 * <p> 097 * Some settings (e.g. {@link Builder#beanMapPutReturnsOldValue()}) change the runtime behavior of bean maps. 098 * 099 * <h5 class='section'>Example:</h5> 100 * 101 * <p class='bjava'> 102 * <jc>// Construct a context from scratch.</jc> 103 * BeanContext <jv>beanContext</jv> = BeanContext 104 * .<jsm>create</jsm>() 105 * .beansRequireDefaultConstructor() 106 * .notBeanClasses(Foo.<jk>class</jk>) 107 * .build(); 108 * </p> 109 * 110 * <h5 class='topic'>Bean Maps</h5> 111 * 112 * <p> 113 * {@link BeanMap BeanMaps} are wrappers around Java beans that allow properties to be retrieved and 114 * set using the common {@link Map#put(Object,Object)} and {@link Map#get(Object)} methods. 115 * 116 * <p> 117 * Bean maps are created in two ways... 118 * <ol> 119 * <li>{@link BeanSession#toBeanMap(Object) BeanSession.toBeanMap()} - Wraps an existing bean inside a {@code Map} 120 * wrapper. 121 * <li>{@link BeanSession#newBeanMap(Class) BeanSession.newBeanMap()} - Create a new bean instance wrapped in a 122 * {@code Map} wrapper. 123 * </ol> 124 * 125 * <h5 class='section'>Example:</h5> 126 * 127 * <p class='bjava'> 128 * <jc>// A sample bean class</jc> 129 * <jk>public class</jk> Person { 130 * <jk>public</jk> String getName(); 131 * <jk>public void</jk> setName(String <jv>name</jv>); 132 * <jk>public int</jk> getAge(); 133 * <jk>public void</jk> setAge(<jk>int</jk> <jv>age</jv>); 134 * } 135 * 136 * <jc>// Create a new bean session</jc> 137 * BeanSession <jv>session</jv> = BeanContext.<jsf>DEFAULT</jsf>.createSession(); 138 * 139 * <jc>// Wrap an existing bean in a new bean map</jc> 140 * BeanMap<Person> <jv>map1</jv> = <jv>session</jv>.toBeanMap(<jk>new</jk> Person()); 141 * <jv>map1</jv>.put(<js>"name"</js>, <js>"John Smith"</js>); 142 * <jv>map1</jv>.put(<js>"age"</js>, 45); 143 * 144 * <jc>// Create a new bean instance wrapped in a new bean map</jc> 145 * BeanMap<Person> <jv>map2</jv> = <jv>session</jv>.newBeanMap(Person.<jk>class</jk>); 146 * <jv>map2</jv>.put(<js>"name"</js>, <js>"John Smith"</js>); 147 * <jv>map2</jv>.put(<js>"age"</js>, 45); 148 * Person <jv>person</jv> = <jv>map2</jv>.getBean(); <jc>// Get the bean instance that was created.</jc> 149 * </p> 150 * 151 * <h5 class='section'>Notes:</h5><ul> 152 * <li class='note'>This class is thread safe and reusable. 153 * </ul> 154 * 155 * <h5 class='section'>See Also:</h5><ul> 156 * <li class='link'><a class="doclink" href="../../../index.html#jm.BeanContexts">Bean Contexts</a> 157 * </ul> 158 */ 159@SuppressWarnings({"unchecked","rawtypes"}) 160public class BeanContext extends Context { 161 162 //----------------------------------------------------------------------------------------------------------------- 163 // Static 164 //----------------------------------------------------------------------------------------------------------------- 165 166 /* 167 * The default package pattern exclusion list. 168 * Any beans in packages in this list will not be considered beans. 169 */ 170 private static final String[] DEFAULT_NOTBEAN_PACKAGES = { 171 "java.lang", 172 "java.lang.annotation", 173 "java.lang.ref", 174 "java.lang.reflect", 175 "java.io", 176 "java.net", 177 "java.nio.*", 178 "java.util.*" 179 }; 180 181 /* 182 * The default bean class exclusion list. 183 * Anything in this list will not be considered beans. 184 */ 185 private static final Class<?>[] DEFAULT_NOTBEAN_CLASSES = { 186 Map.class, 187 Collection.class, 188 Reader.class, 189 Writer.class, 190 InputStream.class, 191 OutputStream.class, 192 Throwable.class 193 }; 194 195 196 /** Default config. All default settings. */ 197 public static final BeanContext DEFAULT = create().build(); 198 199 /** Default config. All default settings except sort bean properties. */ 200 public static final BeanContext DEFAULT_SORTED = create().sortProperties().build(); 201 202 /** Default reusable unmodifiable session. Can be used to avoid overhead of creating a session (for creating BeanMaps for example).*/ 203 public static final BeanSession DEFAULT_SESSION = DEFAULT.createSession().unmodifiable().build(); 204 205 /** 206 * Creates a new builder for this object. 207 * 208 * @return A new builder. 209 */ 210 public static Builder create() { 211 return new Builder(); 212 } 213 214 //----------------------------------------------------------------------------------------------------------------- 215 // Builder 216 //----------------------------------------------------------------------------------------------------------------- 217 218 /** 219 * Builder class. 220 */ 221 @FluentSetters 222 public static class Builder extends Context.Builder { 223 224 private static final Cache<HashKey,BeanContext> CACHE = Cache.of(HashKey.class, BeanContext.class).build(); 225 226 Visibility beanClassVisibility, beanConstructorVisibility, beanMethodVisibility, beanFieldVisibility; 227 boolean disableBeansRequireSomeProperties, beanMapPutReturnsOldValue, beansRequireDefaultConstructor, beansRequireSerializable, 228 beansRequireSettersForGetters, disableIgnoreTransientFields, disableIgnoreUnknownNullBeanProperties, disableIgnoreMissingSetters, 229 disableInterfaceProxies, findFluentSetters, ignoreInvocationExceptionsOnGetters, ignoreInvocationExceptionsOnSetters, 230 ignoreUnknownBeanProperties, ignoreUnknownEnumValues, sortProperties, useEnumNames, useJavaBeanIntrospector; 231 String typePropertyName; 232 MediaType mediaType; 233 Locale locale; 234 TimeZone timeZone; 235 Class<? extends PropertyNamer> propertyNamer; 236 List<Class<?>> beanDictionary; 237 List<Object> swaps; 238 Set<Class<?>> notBeanClasses; 239 Set<String> notBeanPackages; 240 241 /** 242 * Constructor. 243 * 244 * All default settings. 245 */ 246 protected Builder() { 247 beanClassVisibility = env("BeanContext.beanClassVisibility", PUBLIC); 248 beanConstructorVisibility = env("BeanContext.beanConstructorVisibility", PUBLIC); 249 beanMethodVisibility = env("BeanContext.beanMethodVisibility", PUBLIC); 250 beanFieldVisibility = env("BeanContext.beanFieldVisibility", PUBLIC); 251 beanDictionary = null; 252 swaps = null; 253 notBeanClasses = null; 254 notBeanPackages = null; 255 disableBeansRequireSomeProperties = env("BeanContext.disableBeansRequireSomeProperties", false); 256 beanMapPutReturnsOldValue = env("BeanContext.beanMapPutReturnsOldValue", false); 257 beansRequireDefaultConstructor = env("BeanContext.beansRequireDefaultConstructor", false); 258 beansRequireSerializable = env("BeanContext.beansRequireSerializable", false); 259 beansRequireSettersForGetters = env("BeanContext.beansRequireSettersForGetters", false); 260 disableIgnoreTransientFields = env("BeanContext.disableIgnoreTransientFields", false); 261 disableIgnoreUnknownNullBeanProperties = env("BeanContext.disableIgnoreUnknownNullBeanProperties", false); 262 disableIgnoreMissingSetters = env("BeanContext.disableIgnoreMissingSetters", false); 263 disableInterfaceProxies = env("BeanContext.disableInterfaceProxies", false); 264 findFluentSetters = env("BeanContext.findFluentSetters", false); 265 ignoreInvocationExceptionsOnGetters = env("BeanContext.ignoreInvocationExceptionsOnGetters", false); 266 ignoreInvocationExceptionsOnSetters = env("BeanContext.ignoreInvocationExceptionsOnSetters", false); 267 ignoreUnknownBeanProperties = env("BeanContext.ignoreUnknownBeanProperties", false); 268 ignoreUnknownEnumValues = env("BeanContext.ignoreUnknownEnumValues", false); 269 sortProperties = env("BeanContext.sortProperties", false); 270 useEnumNames = env("BeanContext.useEnumNames", false); 271 useJavaBeanIntrospector = env("BeanContext.useJavaBeanIntrospector", false); 272 typePropertyName = env("BeanContext.typePropertyName", "_type"); 273 mediaType = env("BeanContext.mediaType", (MediaType)null); 274 timeZone = env("BeanContext.timeZone", (TimeZone)null); 275 locale = env("BeanContext.locale", Locale.getDefault()); 276 propertyNamer = null; 277 } 278 279 /** 280 * Copy constructor. 281 * 282 * @param copyFrom The bean to copy from. 283 */ 284 protected Builder(BeanContext copyFrom) { 285 super(copyFrom); 286 beanClassVisibility = copyFrom.beanClassVisibility; 287 beanConstructorVisibility = copyFrom.beanConstructorVisibility; 288 beanMethodVisibility = copyFrom.beanMethodVisibility; 289 beanFieldVisibility = copyFrom.beanFieldVisibility; 290 beanDictionary = listFrom(copyFrom.beanDictionary, true); 291 swaps = listFrom(copyFrom.swaps, true); 292 notBeanClasses = classSet(copyFrom.notBeanClasses, true); 293 notBeanPackages = sortedSetFrom(copyFrom.notBeanPackages, true); 294 disableBeansRequireSomeProperties = ! copyFrom.beansRequireSomeProperties; 295 beanMapPutReturnsOldValue = copyFrom.beanMapPutReturnsOldValue; 296 beansRequireDefaultConstructor = copyFrom.beansRequireDefaultConstructor; 297 beansRequireSerializable = copyFrom.beansRequireSerializable; 298 beansRequireSettersForGetters = copyFrom.beansRequireSettersForGetters; 299 disableIgnoreTransientFields = ! copyFrom.ignoreTransientFields; 300 disableIgnoreUnknownNullBeanProperties = ! copyFrom.ignoreUnknownNullBeanProperties; 301 disableIgnoreMissingSetters = ! copyFrom.ignoreMissingSetters; 302 disableInterfaceProxies = ! copyFrom.useInterfaceProxies; 303 findFluentSetters = copyFrom.findFluentSetters; 304 ignoreInvocationExceptionsOnGetters = copyFrom.ignoreInvocationExceptionsOnGetters; 305 ignoreInvocationExceptionsOnSetters = copyFrom.ignoreInvocationExceptionsOnSetters; 306 ignoreUnknownBeanProperties = copyFrom.ignoreUnknownBeanProperties; 307 ignoreUnknownEnumValues = copyFrom.ignoreUnknownEnumValues; 308 sortProperties = copyFrom.sortProperties; 309 useEnumNames = copyFrom.useEnumNames; 310 useJavaBeanIntrospector = copyFrom.useJavaBeanIntrospector; 311 typePropertyName = copyFrom.typePropertyName; 312 mediaType = copyFrom.mediaType; 313 timeZone = copyFrom.timeZone; 314 locale = copyFrom.locale; 315 propertyNamer = copyFrom.propertyNamer; 316 } 317 318 /** 319 * Copy constructor. 320 * 321 * @param copyFrom The builder to copy from. 322 */ 323 protected Builder(Builder copyFrom) { 324 super(copyFrom); 325 beanClassVisibility = copyFrom.beanClassVisibility; 326 beanConstructorVisibility = copyFrom.beanConstructorVisibility; 327 beanMethodVisibility = copyFrom.beanMethodVisibility; 328 beanFieldVisibility = copyFrom.beanFieldVisibility; 329 beanDictionary = copyOf(copyFrom.beanDictionary); 330 swaps = copyOf(copyFrom.swaps); 331 notBeanClasses = classSet(copyFrom.notBeanClasses); 332 notBeanPackages = sortedSetFrom(copyFrom.notBeanPackages); 333 disableBeansRequireSomeProperties = copyFrom.disableBeansRequireSomeProperties; 334 beanMapPutReturnsOldValue = copyFrom.beanMapPutReturnsOldValue; 335 beansRequireDefaultConstructor = copyFrom.beansRequireDefaultConstructor; 336 beansRequireSerializable = copyFrom.beansRequireSerializable; 337 beansRequireSettersForGetters = copyFrom.beansRequireSettersForGetters; 338 disableIgnoreTransientFields = copyFrom.disableIgnoreTransientFields; 339 disableIgnoreUnknownNullBeanProperties = copyFrom.disableIgnoreUnknownNullBeanProperties; 340 disableIgnoreMissingSetters = copyFrom.disableIgnoreMissingSetters; 341 disableInterfaceProxies = copyFrom.disableInterfaceProxies; 342 findFluentSetters = copyFrom.findFluentSetters; 343 ignoreInvocationExceptionsOnGetters = copyFrom.ignoreInvocationExceptionsOnGetters; 344 ignoreInvocationExceptionsOnSetters = copyFrom.ignoreInvocationExceptionsOnSetters; 345 ignoreUnknownBeanProperties = copyFrom.ignoreUnknownBeanProperties; 346 ignoreUnknownEnumValues = copyFrom.ignoreUnknownEnumValues; 347 sortProperties = copyFrom.sortProperties; 348 useEnumNames = copyFrom.useEnumNames; 349 useJavaBeanIntrospector = copyFrom.useJavaBeanIntrospector; 350 typePropertyName = copyFrom.typePropertyName; 351 mediaType = copyFrom.mediaType; 352 timeZone = copyFrom.timeZone; 353 locale = copyFrom.locale; 354 propertyNamer = copyFrom.propertyNamer; 355 } 356 357 @Override /* Context.Builder */ 358 public Builder copy() { 359 return new Builder(this); 360 } 361 362 @Override /* Context.Builder */ 363 public BeanContext build() { 364 return cache(CACHE).build(BeanContext.class); 365 } 366 367 @Override /* Context.Builder */ 368 public HashKey hashKey() { 369 return HashKey.of( 370 super.hashKey(), 371 beanClassVisibility, 372 beanConstructorVisibility, 373 beanMethodVisibility, 374 beanFieldVisibility, 375 beanDictionary, 376 swaps, 377 notBeanClasses, 378 notBeanPackages, 379 integer( 380 disableBeansRequireSomeProperties, 381 beanMapPutReturnsOldValue, 382 beansRequireDefaultConstructor, 383 beansRequireSerializable, 384 beansRequireSettersForGetters, 385 disableIgnoreTransientFields, 386 disableIgnoreUnknownNullBeanProperties, 387 disableIgnoreMissingSetters, 388 disableInterfaceProxies, 389 findFluentSetters, 390 ignoreInvocationExceptionsOnGetters, 391 ignoreInvocationExceptionsOnSetters, 392 ignoreUnknownBeanProperties, 393 ignoreUnknownEnumValues, 394 sortProperties, 395 useEnumNames, 396 useJavaBeanIntrospector 397 ), 398 typePropertyName, 399 mediaType, 400 timeZone, 401 locale, 402 propertyNamer 403 ); 404 } 405 406 private int integer(boolean...values) { 407 int n = 0; 408 for (boolean b : values) 409 n = (n << 1) | (b ? 1 : 0); 410 return n; 411 } 412 413 //----------------------------------------------------------------------------------------------------------------- 414 // Properties 415 //----------------------------------------------------------------------------------------------------------------- 416 417 /** 418 * Minimum bean class visibility. 419 * 420 * <p> 421 * Classes are not considered beans unless they meet the minimum visibility requirements. 422 * For example, if the visibility is <jsf>PUBLIC</jsf> and the bean class is <jk>protected</jk>, then the class 423 * will not be interpreted as a bean class and be serialized as a string. 424 * Use this setting to reduce the visibility requirement. 425 * 426 * <h5 class='section'>Example:</h5> 427 * <p class='bjava'> 428 * <jc>// A bean with a protected class and one field.</jc> 429 * <jk>protected class</jk> MyBean { 430 * <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>; 431 * } 432 * 433 * <jc>// Create a serializer that's capable of serializing the class.</jc> 434 * WriterSerializer <jv>serializer</jv> = JsonSerializer 435 * .<jsm>create</jsm>() 436 * .beanClassVisibility(<jsf>PROTECTED</jsf>) 437 * .build(); 438 * 439 * <jc>// Produces: {"foo","bar"}</jc> 440 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 441 * </p> 442 * 443 * <h5 class='section'>Notes:</h5><ul> 444 * <li class='note'>The {@link Bean @Bean} annotation can be used on a non-public bean class to override this setting. 445 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean class to ignore it as a bean. 446 * </ul> 447 * 448 * <h5 class='section'>See Also:</h5><ul> 449 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanClassVisibility()} 450 * </ul> 451 * 452 * @param value 453 * The new value for this setting. 454 * <br>The default is {@link Visibility#PUBLIC}. 455 * @return This object. 456 */ 457 @FluentSetter 458 public Builder beanClassVisibility(Visibility value) { 459 beanClassVisibility = value; 460 return this; 461 } 462 463 /** 464 * Minimum bean constructor visibility. 465 * 466 * <p> 467 * Only look for constructors with the specified minimum visibility. 468 * 469 * <p> 470 * This setting affects the logic for finding no-arg constructors for bean. Normally, only <jk>public</jk> no-arg 471 * constructors are used. Use this setting if you want to reduce the visibility requirement. 472 * 473 * <h5 class='section'>Example:</h5> 474 * <p class='bjava'> 475 * <jc>// A bean with a protected constructor and one field.</jc> 476 * <jk>public class</jk> MyBean { 477 * <jk>public</jk> String <jf>foo</jf>; 478 * 479 * <jk>protected</jk> MyBean() {} 480 * } 481 * 482 * <jc>// Create a parser capable of calling the protected constructor.</jc> 483 * ReaderParser <jv>parser</jv> = ReaderParser 484 * .<jsm>create</jsm>() 485 * .beanConstructorVisibility(<jsf>PROTECTED</jsf>) 486 * .build(); 487 * 488 * <jc>// Use it.</jc> 489 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>); 490 * </p> 491 * 492 * <h5 class='section'>Notes:</h5><ul> 493 * <li class='note'>The {@link Beanc @Beanc} annotation can also be used to expose a non-public constructor. 494 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean constructor to ignore it. 495 * </ul> 496 * 497 * <h5 class='section'>See Also:</h5><ul> 498 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanConstructorVisibility()} 499 * </ul> 500 * 501 * @param value 502 * The new value for this setting. 503 * <br>The default is {@link Visibility#PUBLIC}. 504 * @return This object. 505 */ 506 @FluentSetter 507 public Builder beanConstructorVisibility(Visibility value) { 508 beanConstructorVisibility = value; 509 return this; 510 } 511 512 /** 513 * Minimum bean field visibility. 514 * 515 * <p> 516 * Only look for bean fields with the specified minimum visibility. 517 * 518 * <p> 519 * This affects which fields on a bean class are considered bean properties. Normally only <jk>public</jk> fields are considered. 520 * Use this setting if you want to reduce the visibility requirement. 521 * 522 * <h5 class='section'>Example:</h5> 523 * <p class='bjava'> 524 * <jc>// A bean with a protected field.</jc> 525 * <jk>public class</jk> MyBean { 526 * <jk>protected</jk> String <jf>foo</jf> = <js>"bar"</js>; 527 * } 528 * 529 * <jc>// Create a serializer that recognizes the protected field.</jc> 530 * WriterSerializer <jv>serializer</jv> = JsonSerializer 531 * .<jsm>create</jsm>() 532 * .beanFieldVisibility(<jsf>PROTECTED</jsf>) 533 * .build(); 534 * 535 * <jc>// Produces: {"foo":"bar"}</jc> 536 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 537 * </p> 538 * 539 * <p> 540 * Bean fields can be ignored as properties entirely by setting the value to {@link Visibility#NONE} 541 * 542 * <p class='bjava'> 543 * <jc>// Disable using fields as properties entirely.</jc> 544 * WriterSerializer <jv>serializer</jv> = JsonSerializer 545 * .<jsm>create</jsm>() 546 * .beanFieldVisibility(<jsf>NONE</jsf>) 547 * .build(); 548 * </p> 549 * 550 * <h5 class='section'>Notes:</h5><ul> 551 * <li class='note'>The {@link Beanp @Beanp} annotation can also be used to expose a non-public field. 552 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean field to ignore it as a bean property. 553 * </ul> 554 * 555 * <h5 class='section'>See Also:</h5><ul> 556 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanFieldVisibility()} 557 * </ul> 558 * 559 * @param value 560 * The new value for this setting. 561 * <br>The default is {@link Visibility#PUBLIC}. 562 * @return This object. 563 */ 564 @FluentSetter 565 public Builder beanFieldVisibility(Visibility value) { 566 beanFieldVisibility = value; 567 return this; 568 } 569 570 /** 571 * Bean interceptor. 572 * 573 * <p> 574 * Bean interceptors can be used to intercept calls to getters and setters and alter their values in transit. 575 * 576 * <h5 class='section'>Example:</h5> 577 * <p class='bjava'> 578 * <jc>// Interceptor that strips out sensitive information.</jc> 579 * <jk>public class</jk> AddressInterceptor <jk>extends</jk> BeanInterceptor<Address> { 580 * 581 * <jk>public</jk> Object readProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) { 582 * <jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>)) 583 * <jk>return</jk> <js>"redacted"</js>; 584 * <jk>return</jk> <jv>value</jv>; 585 * } 586 * 587 * <jk>public</jk> Object writeProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) { 588 * <jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>) && <js>"redacted"</js>.equals(<jv>value</jv>)) 589 * <jk>return</jk> TaxInfoUtils.<jsm>lookup</jsm>(<jv>bean</jv>.getStreet(), <jv>bean</jv>.getCity(), <jv>bean</jv>.getState()); 590 * <jk>return</jk> <jv>value</jv>; 591 * } 592 * } 593 * 594 * <jc>// Our bean class.</jc> 595 * <jk>public class</jk> Address { 596 * <jk>public</jk> String getTaxInfo() {...} 597 * <jk>public void</jk> setTaxInfo(String <jv>value</jv>) {...} 598 * } 599 * 600 * <jc>// Register filter on serializer or parser.</jc> 601 * WriterSerializer <jv>serializer</jv> = JsonSerializer 602 * .<jsm>create</jsm>() 603 * .beanInterceptor(Address.<jk>class</jk>, AddressInterceptor.<jk>class</jk>) 604 * .build(); 605 * 606 * <jc>// Produces: {"taxInfo":"redacted"}</jc> 607 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> Address()); 608 * </p> 609 * 610 * <h5 class='section'>See Also:</h5><ul> 611 * <li class='jc'>{@link BeanInterceptor} 612 * <li class='ja'>{@link Bean#interceptor() Bean(interceptor)} 613 * </ul> 614 * 615 * @param on The bean that the filter applies to. 616 * @param value 617 * The new value for this setting. 618 * @return This object. 619 */ 620 @FluentSetter 621 public Builder beanInterceptor(Class<?> on, Class<? extends BeanInterceptor<?>> value) { 622 return annotations(BeanAnnotation.create(on).interceptor(value).build()); 623 } 624 625 /** 626 * BeanMap.put() returns old property value. 627 * 628 * <p> 629 * When enabled, then the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property 630 * values. Otherwise, it returns <jk>null</jk>. 631 * 632 * <p> 633 * Disabled by default because it introduces a slight performance penalty during serialization. 634 * 635 * <h5 class='section'>Example:</h5> 636 * <p class='bjava'> 637 * <jc>// Create a context that creates BeanMaps with normal put() behavior.</jc> 638 * BeanContext <jv>context</jv> = BeanContext 639 * .<jsm>create</jsm>() 640 * .beanMapPutReturnsOldValue() 641 * .build(); 642 * 643 * BeanMap<MyBean> <jv>myBeanMap</jv> = <jv>context</jv>.createSession().toBeanMap(<jk>new</jk> MyBean()); 644 * <jv>myBeanMap</jv>.put(<js>"foo"</js>, <js>"bar"</js>); 645 * Object <jv>oldValue</jv> = <jv>myBeanMap</jv>.put(<js>"foo"</js>, <js>"baz"</js>); <jc>// oldValue == "bar"</jc> 646 * </p> 647 * 648 * <h5 class='section'>See Also:</h5><ul> 649 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanMapPutReturnsOldValue()} 650 * </ul> 651 * 652 * @return This object. 653 */ 654 @FluentSetter 655 public Builder beanMapPutReturnsOldValue() { 656 return beanMapPutReturnsOldValue(true); 657 } 658 659 /** 660 * Same as {@link #beanMapPutReturnsOldValue()} but allows you to explicitly specify the value. 661 * 662 * @param value The value for this setting. 663 * @return This object. 664 */ 665 @FluentSetter 666 public Builder beanMapPutReturnsOldValue(boolean value) { 667 beanMapPutReturnsOldValue = value; 668 return this; 669 } 670 671 /** 672 * Minimum bean method visibility. 673 * 674 * <p> 675 * Only look for bean methods with the specified minimum visibility. 676 * 677 * <p> 678 * This affects which methods are detected as getters and setters on a bean class. Normally only <jk>public</jk> getters and setters are considered. 679 * Use this setting if you want to reduce the visibility requirement. 680 * 681 * <h5 class='section'>Example:</h5> 682 * <p class='bjava'> 683 * <jc>// A bean with a protected getter.</jc> 684 * <jk>public class</jk> MyBean { 685 * <jk>public</jk> String getFoo() { <jk>return</jk> <js>"foo"</js>; } 686 * <jk>protected</jk> String getBar() { <jk>return</jk> <js>"bar"</js>; } 687 * } 688 * 689 * <jc>// Create a serializer that looks for protected getters and setters.</jc> 690 * WriterSerializer <jv>serializer</jv> = JsonSerializer 691 * .<jsm>create</jsm>() 692 * .beanMethodVisibility(<jsf>PROTECTED</jsf>) 693 * .build(); 694 * 695 * <jc>// Produces: {"foo":"foo","bar":"bar"}</jc> 696 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 697 * </p> 698 * 699 * <h5 class='section'>Notes:</h5><ul> 700 * <li class='note'>The {@link Beanp @Beanp} annotation can also be used to expose a non-public method. 701 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean getter/setter to ignore it as a bean property. 702 * </ul> 703 * 704 * <h5 class='section'>See Also:</h5><ul> 705 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanMethodVisibility()} 706 * </ul> 707 * 708 * @param value 709 * The new value for this setting. 710 * <br>The default is {@link Visibility#PUBLIC} 711 * @return This object. 712 */ 713 @FluentSetter 714 public Builder beanMethodVisibility(Visibility value) { 715 beanMethodVisibility = value; 716 return this; 717 } 718 719 /** 720 * Beans require no-arg constructors. 721 * 722 * <p> 723 * When enabled, a Java class must implement a default no-arg constructor to be considered a bean. 724 * Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 725 * 726 * <h5 class='section'>Example:</h5> 727 * <p class='bjava'> 728 * <jc>// A bean without a no-arg constructor.</jc> 729 * <jk>public class</jk> MyBean { 730 * 731 * <jc>// A property method.</jc> 732 * <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>; 733 * 734 * <jc>// A no-arg constructor</jc> 735 * <jk>public</jk> MyBean(String <jv>foo</jv>) { 736 * <jk>this</jk>.<jf>foo</jf> = <jv>foo</jv>; 737 * } 738 * 739 * <ja>@Override</ja> 740 * <jk>public</jk> String toString() { 741 * <jk>return</jk> <js>"bar"</js>; 742 * } 743 * } 744 * 745 * <jc>// Create a serializer that ignores beans without default constructors.</jc> 746 * WriterSerializer <jv>serializer</jv> = JsonSerializer 747 * .<jsm>create</jsm>() 748 * .beansRequireDefaultConstructor() 749 * .build(); 750 * 751 * <jc>// Produces: "bar"</jc> 752 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 753 * </p> 754 * 755 * <h5 class='section'>Notes:</h5><ul> 756 * <li class='note'>The {@link Bean @Bean} annotation can be used on a bean class to override this setting. 757 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a class to ignore it as a bean. 758 * </ul> 759 * 760 * <h5 class='section'>See Also:</h5><ul> 761 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beansRequireDefaultConstructor()} 762 * </ul> 763 * 764 * @return This object. 765 */ 766 @FluentSetter 767 public Builder beansRequireDefaultConstructor() { 768 return beansRequireDefaultConstructor(true); 769 } 770 771 /** 772 * Same as {@link #beansRequireDefaultConstructor()} but allows you to explicitly specify the value. 773 * 774 * @param value The value for this setting. 775 * @return This object. 776 */ 777 @FluentSetter 778 public Builder beansRequireDefaultConstructor(boolean value) { 779 beansRequireDefaultConstructor = value; 780 return this; 781 } 782 783 /** 784 * Beans require Serializable interface. 785 * 786 * <p> 787 * When enabled, a Java class must implement the {@link Serializable} interface to be considered a bean. 788 * Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 789 * 790 * <h5 class='section'>Example:</h5> 791 * <p class='bjava'> 792 * <jc>// A bean without a Serializable interface.</jc> 793 * <jk>public class</jk> MyBean { 794 * 795 * <jc>// A property method.</jc> 796 * <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>; 797 * 798 * <ja>@Override</ja> 799 * <jk>public</jk> String toString() { 800 * <jk>return</jk> <js>"bar"</js>; 801 * } 802 * } 803 * 804 * <jc>// Create a serializer that ignores beans not implementing Serializable.</jc> 805 * WriterSerializer <jv>serializer</jv> = JsonSerializer 806 * .<jsm>create</jsm>() 807 * .beansRequireSerializable() 808 * .build(); 809 * 810 * <jc>// Produces: "bar"</jc> 811 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 812 * </p> 813 * 814 * <h5 class='section'>Notes:</h5><ul> 815 * <li class='note'>The {@link Bean @Bean} annotation can be used on a bean class to override this setting. 816 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a class to ignore it as a bean. 817 * </ul> 818 * 819 * <h5 class='section'>See Also:</h5><ul> 820 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beansRequireSerializable()} 821 * </ul> 822 * 823 * @return This object. 824 */ 825 @FluentSetter 826 public Builder beansRequireSerializable() { 827 return beansRequireSerializable(true); 828 } 829 830 /** 831 * Same as {@link #beansRequireSerializable()} but allows you to explicitly specify the value. 832 * 833 * @param value The value for this setting. 834 * @return This object. 835 */ 836 @FluentSetter 837 public Builder beansRequireSerializable(boolean value) { 838 beansRequireSerializable = value; 839 return this; 840 } 841 842 /** 843 * Beans require setters for getters. 844 * 845 * <p> 846 * When enabled, ignore read-only properties (properties with getters but not setters). 847 * 848 * <h5 class='section'>Example:</h5> 849 * <p class='bjava'> 850 * <jc>// A bean without a Serializable interface.</jc> 851 * <jk>public class</jk> MyBean { 852 * 853 * <jc>// A read/write property.</jc> 854 * <jk>public</jk> String getFoo() { <jk>return</jk> <js>"foo"</js>; } 855 * <jk>public void</jk> setFoo(String <jv>foo</jv>) { ... } 856 * 857 * <jc>// A read-only property.</jc> 858 * <jk>public</jk> String getBar() { <jk>return</jk> <js>"bar"</js>; } 859 * } 860 * 861 * <jc>// Create a serializer that ignores bean properties without setters.</jc> 862 * WriterSerializer <jv>serializer</jv> = JsonSerializer 863 * .<jsm>create</jsm>() 864 * .beansRequireSettersForGetters() 865 * .build(); 866 * 867 * <jc>// Produces: {"foo":"foo"}</jc> 868 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 869 * </p> 870 * 871 * <h5 class='section'>Notes:</h5><ul> 872 * <li class='note'>The {@link Beanp @Beanp} annotation can be used on the getter to override this setting. 873 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on getters to ignore them as bean properties. 874 * </ul> 875 * 876 * @return This object. 877 */ 878 @FluentSetter 879 public Builder beansRequireSettersForGetters() { 880 return beansRequireSettersForGetters(true); 881 } 882 883 /** 884 * Same as {@link #beansRequireSettersForGetters()} but allows you to explicitly specify the value. 885 * 886 * @param value The value for this setting. 887 * @return This object. 888 */ 889 @FluentSetter 890 public Builder beansRequireSettersForGetters(boolean value) { 891 beansRequireSettersForGetters = value; 892 return this; 893 } 894 895 /** 896 * Beans don't require at least one property. 897 * 898 * <p> 899 * When enabled, then a Java class doesn't need to contain at least 1 property to be considered a bean. 900 * Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 901 * 902 * <p> 903 * The {@link Bean @Bean} annotation can be used on a class to override this setting when <jk>true</jk>. 904 * 905 * <h5 class='section'>Example:</h5> 906 * <p class='bjava'> 907 * <jc>// A bean with no properties.</jc> 908 * <jk>public class</jk> MyBean { 909 * } 910 * 911 * <jc>// Create a serializer that serializes beans even if they have zero properties.</jc> 912 * WriterSerializer <jv>serializer</jv> = JsonSerializer 913 * .<jsm>create</jsm>() 914 * .disableBeansRequireSomeProperties() 915 * .build(); 916 * 917 * <jc>// Produces: {}</jc> 918 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 919 * </p> 920 * 921 * <h5 class='section'>Notes:</h5><ul> 922 * <li class='note'>The {@link Bean @Bean} annotation can be used on the class to force it to be recognized as a bean class 923 * even if it has no properties. 924 * </ul> 925 * 926 * <h5 class='section'>See Also:</h5><ul> 927 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableBeansRequireSomeProperties()} 928 * </ul> 929 * 930 * @return This object. 931 */ 932 @FluentSetter 933 public Builder disableBeansRequireSomeProperties() { 934 return disableBeansRequireSomeProperties(true); 935 } 936 937 /** 938 * Same as {@link #disableBeansRequireSomeProperties()} but allows you to explicitly specify the value. 939 * 940 * @param value The value for this setting. 941 * @return This object. 942 */ 943 @FluentSetter 944 public Builder disableBeansRequireSomeProperties(boolean value) { 945 disableBeansRequireSomeProperties = value; 946 return this; 947 } 948 949 /** 950 * Bean property includes. 951 * 952 * <p> 953 * Specifies the set and order of names of properties associated with the bean class. 954 * 955 * <p> 956 * For example, <c>beanProperties(MyBean.<jk>class</jk>, <js>"foo,bar"</js>)</c> means only serialize the <c>foo</c> and 957 * <c>bar</c> properties on the specified bean. Likewise, parsing will ignore any bean properties not specified 958 * and either throw an exception or silently ignore them depending on whether {@link #ignoreUnknownBeanProperties()} 959 * has been called. 960 * 961 * <p> 962 * This value is entirely optional if you simply want to expose all the getters and public fields on 963 * a class as bean properties. However, it's useful if you want certain getters to be ignored or you want the properties to be 964 * serialized in a particular order. Note that on IBM JREs, the property order is the same as the order in the source code, 965 * whereas on Oracle JREs, the order is entirely random. 966 * 967 * <p> 968 * Setting applies to specified class and all subclasses. 969 * 970 * <h5 class='section'>Example:</h5> 971 * <p class='bjava'> 972 * <jc>// A bean with 3 properties.</jc> 973 * <jk>public class</jk> MyBean { 974 * <jk>public</jk> String 975 * <jf>foo</jf> = <js>"foo"</js>, 976 * <jf>bar</jf> = <js>"bar"</js>, 977 * <jf>baz</jf> = <js>"baz"</js>; 978 * } 979 * 980 * <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc> 981 * WriterSerializer <jv>serializer</jv> = JsonSerializer 982 * .<jsm>create</jsm>() 983 * .beanProperties(MyBean.<jk>class</jk>, <js>"foo,bar"</js>) 984 * .build(); 985 * 986 * <jc>// Produces: {"foo":"foo","bar":"bar"}</jc> 987 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 988 * </p> 989 * 990 * <p> 991 * This method is functionally equivalent to the following code: 992 * <p class='bjava'> 993 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).properties(<jv>properties</jv>).build()); 994 * </p> 995 * 996 * <h5 class='section'>See Also:</h5><ul> 997 * <li class='jma'>{@link Bean#properties()}/{@link Bean#p()} - On an annotation on the bean class itself. 998 * </ul> 999 * 1000 * @param beanClass The bean class. 1001 * @param properties Comma-delimited list of property names. 1002 * @return This object. 1003 */ 1004 @FluentSetter 1005 public Builder beanProperties(Class<?> beanClass, String properties) { 1006 return annotations(BeanAnnotation.create(beanClass).p(properties).build()); 1007 } 1008 1009 /** 1010 * Bean property includes. 1011 * 1012 * <p> 1013 * Specifies the set and order of names of properties associated with bean classes. 1014 * 1015 * <p> 1016 * For example, <c>beanProperties(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"foo,bar"</js>))</c> means only serialize the <c>foo</c> and 1017 * <c>bar</c> properties on the specified bean. Likewise, parsing will ignore any bean properties not specified 1018 * and either throw an exception or silently ignore them depending on whether {@link #ignoreUnknownBeanProperties()} 1019 * has been called. 1020 * 1021 * <p> 1022 * This value is entirely optional if you simply want to expose all the getters and public fields on 1023 * a class as bean properties. However, it's useful if you want certain getters to be ignored or you want the properties to be 1024 * serialized in a particular order. Note that on IBM JREs, the property order is the same as the order in the source code, 1025 * whereas on Oracle JREs, the order is entirely random. 1026 * 1027 * <p> 1028 * Setting applies to specified class and all subclasses. 1029 * 1030 * <h5 class='section'>Example:</h5> 1031 * <p class='bjava'> 1032 * <jc>// A bean with 3 properties.</jc> 1033 * <jk>public class</jk> MyBean { 1034 * <jk>public</jk> String 1035 * <jf>foo</jf> = <js>"foo"</js>, 1036 * <jf>bar</jf> = <js>"bar"</js>, 1037 * <jf>baz</jf> = <js>"baz"</js>; 1038 * } 1039 * 1040 * <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc> 1041 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1042 * .<jsm>create</jsm>() 1043 * .beanProperties(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"foo,bar"</js>)) 1044 * .build(); 1045 * 1046 * <jc>// Produces: {"foo":"foo","bar":"bar"}</jc> 1047 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1048 * </p> 1049 * 1050 * <p> 1051 * This method is functionally equivalent to the following code for each entry: 1052 * <p class='bjava'> 1053 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).properties(<jv>value</jv>.toString()).build()); 1054 * </p> 1055 * 1056 * <h5 class='section'>See Also:</h5><ul> 1057 * <li class='jma'>{@link Bean#properties()} / {@link Bean#p()}- On an annotation on the bean class itself. 1058 * </ul> 1059 * 1060 * @param values 1061 * The values to add to this builder. 1062 * <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans. 1063 * <br>Values are comma-delimited lists of property names. Non-String objects are first converted to Strings. 1064 * @return This object. 1065 */ 1066 @FluentSetter 1067 public Builder beanProperties(Map<String,Object> values) { 1068 values.forEach((k,v) -> annotations(BeanAnnotation.create(k).p(stringify(v)).build())); 1069 return this; 1070 } 1071 1072 /** 1073 * Bean property includes. 1074 * 1075 * <p> 1076 * Specifies the set and order of names of properties associated with the bean class. 1077 * 1078 * <p> 1079 * For example, <c>beanProperties(<js>"MyBean"</js>, <js>"foo,bar"</js>)</c> means only serialize the <c>foo</c> and 1080 * <c>bar</c> properties on the specified bean. Likewise, parsing will ignore any bean properties not specified 1081 * and either throw an exception or silently ignore them depending on whether {@link #ignoreUnknownBeanProperties()} 1082 * has been called. 1083 * 1084 * <p> 1085 * This value is entirely optional if you simply want to expose all the getters and public fields on 1086 * a class as bean properties. However, it's useful if you want certain getters to be ignored or you want the properties to be 1087 * serialized in a particular order. Note that on IBM JREs, the property order is the same as the order in the source code, 1088 * whereas on Oracle JREs, the order is entirely random. 1089 * 1090 * <p> 1091 * Setting applies to specified class and all subclasses. 1092 * 1093 * <h5 class='section'>Example:</h5> 1094 * <p class='bjava'> 1095 * <jc>// A bean with 3 properties.</jc> 1096 * <jk>public class</jk> MyBean { 1097 * <jk>public</jk> String 1098 * <jf>foo</jf> = <js>"foo"</js>, 1099 * <jf>bar</jf> = <js>"bar"</js>, 1100 * <jf>baz</jf> = <js>"baz"</js>; 1101 * } 1102 * 1103 * <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc> 1104 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1105 * .<jsm>create</jsm>() 1106 * .beanProperties(<js>"MyBean"</js>, <js>"foo,bar"</js>) 1107 * .build(); 1108 * 1109 * <jc>// Produces: {"foo":"foo","bar":"bar"}</jc> 1110 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1111 * </p> 1112 * 1113 * <p> 1114 * This method is functionally equivalent to the following code: 1115 * <p class='bjava'> 1116 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).properties(<jv>properties</jv>).build()); 1117 * </p> 1118 * 1119 * <h5 class='section'>See Also:</h5><ul> 1120 * <li class='jma'>{@link Bean#properties()} / {@link Bean#p()} - On an annotation on the bean class itself. 1121 * </ul> 1122 * 1123 * @param beanClassName 1124 * The bean class name. 1125 * <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all beans. 1126 * @param properties Comma-delimited list of property names. 1127 * @return This object. 1128 */ 1129 @FluentSetter 1130 public Builder beanProperties(String beanClassName, String properties) { 1131 return annotations(BeanAnnotation.create(beanClassName).p(properties).build()); 1132 } 1133 1134 /** 1135 * Bean property excludes. 1136 * 1137 * <p> 1138 * Specifies to exclude the specified list of properties for the specified bean class. 1139 * 1140 * <p> 1141 * Same as {@link #beanProperties(Class, String)} except you specify a list of bean property names that you want to exclude from 1142 * serialization. 1143 * 1144 * <p> 1145 * Setting applies to specified class and all subclasses. 1146 * 1147 * <h5 class='section'>Example:</h5> 1148 * <p class='bjava'> 1149 * <jc>// A bean with 3 properties.</jc> 1150 * <jk>public class</jk> MyBean { 1151 * <jk>public</jk> String 1152 * <jf>foo</jf> = <js>"foo"</js>, 1153 * <jf>bar</jf> = <js>"bar"</js>, 1154 * <jf>baz</jf> = <js>"baz"</js>; 1155 * } 1156 * 1157 * <jc>// Create a serializer that excludes the "bar" and "baz" properties on the MyBean class.</jc> 1158 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1159 * .<jsm>create</jsm>() 1160 * .beanPropertiesExcludes(MyBean.<jk>class</jk>, <js>"bar,baz"</js>) 1161 * .build(); 1162 * 1163 * <jc>// Produces: {"foo":"foo"}</jc> 1164 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1165 * </p> 1166 * 1167 * <p> 1168 * This method is functionally equivalent to the following code: 1169 * <p class='bjava'> 1170 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).excludeProperties(<jv>properties</jv>).build()); 1171 * </p> 1172 * 1173 * <h5 class='section'>See Also:</h5><ul> 1174 * <li class='jma'>{@link Bean#excludeProperties()} / {@link Bean#xp()} 1175 * </ul> 1176 * 1177 * @param beanClass The bean class. 1178 * @param properties Comma-delimited list of property names. 1179 * @return This object. 1180 */ 1181 @FluentSetter 1182 public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) { 1183 return annotations(BeanAnnotation.create(beanClass).xp(properties).build()); 1184 } 1185 1186 /** 1187 * Bean property excludes. 1188 * 1189 * <p> 1190 * Specifies to exclude the specified list of properties for the specified bean classes. 1191 * 1192 * <p> 1193 * Same as {@link #beanProperties(Map)} except you specify a list of bean property names that you want to exclude from 1194 * serialization. 1195 * 1196 * <p> 1197 * Setting applies to specified class and all subclasses. 1198 * 1199 * <h5 class='section'>Example:</h5> 1200 * <p class='bjava'> 1201 * <jc>// A bean with 3 properties.</jc> 1202 * <jk>public class</jk> MyBean { 1203 * <jk>public</jk> String 1204 * <jf>foo</jf> = <js>"foo"</js>, 1205 * <jf>bar</jf> = <js>"bar"</js>, 1206 * <jf>baz</jf> = <js>"baz"</js>; 1207 * } 1208 * 1209 * <jc>// Create a serializer that excludes the "bar" and "baz" properties on the MyBean class.</jc> 1210 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1211 * .<jsm>create</jsm>() 1212 * .beanPropertiesExcludes(AMap.of(<js>"MyBean"</js>, <js>"bar,baz"</js>)) 1213 * .build(); 1214 * 1215 * <jc>// Produces: {"foo":"foo"}</jc> 1216 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1217 * </p> 1218 * 1219 * <p> 1220 * This method is functionally equivalent to the following code for each entry: 1221 * <p class='bjava'> 1222 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).excludeProperties(<jv>value</jv>.toString()).build()); 1223 * </p> 1224 * 1225 * <h5 class='section'>See Also:</h5><ul> 1226 * <li class='jma'>{@link Bean#excludeProperties()} / {@link Bean#xp()} 1227 * </ul> 1228 * 1229 * @param values 1230 * The values to add to this builder. 1231 * <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans. 1232 * <br>Values are comma-delimited lists of property names. Non-String objects are first converted to Strings. 1233 * @return This object. 1234 */ 1235 @FluentSetter 1236 public Builder beanPropertiesExcludes(Map<String,Object> values) { 1237 values.forEach((k,v) -> annotations(BeanAnnotation.create(k).xp(stringify(v)).build())); 1238 return this; 1239 } 1240 1241 /** 1242 * Bean property excludes. 1243 * 1244 * <p> 1245 * Specifies to exclude the specified list of properties for the specified bean class. 1246 * 1247 * <p> 1248 * Same as {@link #beanPropertiesExcludes(String, String)} except you specify a list of bean property names that you want to exclude from 1249 * serialization. 1250 * 1251 * <p> 1252 * Setting applies to specified class and all subclasses. 1253 * 1254 * <h5 class='section'>Example:</h5> 1255 * <p class='bjava'> 1256 * <jc>// A bean with 3 properties.</jc> 1257 * <jk>public class</jk> MyBean { 1258 * <jk>public</jk> String 1259 * <jf>foo</jf> = <js>"foo"</js>, 1260 * <jf>bar</jf> = <js>"bar"</js>, 1261 * <jf>baz</jf> = <js>"baz"</js>; 1262 * } 1263 * 1264 * <jc>// Create a serializer that excludes the "bar" and "baz" properties on the MyBean class.</jc> 1265 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1266 * .<jsm>create</jsm>() 1267 * .beanPropertiesExcludes(<js>"MyBean"</js>, <js>"bar,baz"</js>) 1268 * .build(); 1269 * 1270 * <jc>// Produces: {"foo":"foo"}</jc> 1271 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1272 * </p> 1273 * 1274 * <p> 1275 * This method is functionally equivalent to the following code: 1276 * <p class='bjava'> 1277 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).excludeProperties(<jv>properties</jv>).build()); 1278 * </p> 1279 * 1280 * <h5 class='section'>See Also:</h5><ul> 1281 * <li class='jma'>{@link Bean#excludeProperties()} / {@link Bean#xp()} 1282 * </ul> 1283 * 1284 * @param beanClassName 1285 * The bean class name. 1286 * <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all bean classes. 1287 * @param properties Comma-delimited list of property names. 1288 * @return This object. 1289 */ 1290 @FluentSetter 1291 public Builder beanPropertiesExcludes(String beanClassName, String properties) { 1292 return annotations(BeanAnnotation.create(beanClassName).xp(properties).build()); 1293 } 1294 1295 /** 1296 * Read-only bean properties. 1297 * 1298 * <p> 1299 * Specifies one or more properties on a bean that are read-only despite having valid getters. 1300 * Serializers will serialize such properties as usual, but parsers will silently ignore them. 1301 * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties 1302 * for both serializers and parsers. 1303 * 1304 * <h5 class='section'>Example:</h5> 1305 * <p class='bjava'> 1306 * <jc>// A bean with 3 properties.</jc> 1307 * <jk>public class</jk> MyBean { 1308 * <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>; 1309 * } 1310 * 1311 * <jc>// Create a serializer with read-only property settings.</jc> 1312 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1313 * .<jsm>create</jsm>() 1314 * .beanPropertiesReadOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>) 1315 * .build(); 1316 * 1317 * <jc>// All 3 properties will be serialized.</jc> 1318 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1319 * 1320 * <jc>// Create a parser with read-only property settings.</jc> 1321 * ReaderParser <jv>parser</jv> = JsonParser 1322 * .<jsm>create</jsm>() 1323 * .beanPropertiesReadOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>) 1324 * .ignoreUnknownBeanProperties() 1325 * .build(); 1326 * 1327 * <jc>// Parser ignores bar and baz properties.</jc> 1328 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>); 1329 * </p> 1330 * 1331 * <p> 1332 * This method is functionally equivalent to the following code: 1333 * <p class='bjava'> 1334 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).readOnlyProperties(<jv>properties</jv>).build()); 1335 * </p> 1336 * 1337 * <h5 class='section'>See Also:</h5><ul> 1338 * <li class='jma'>{@link Bean#readOnlyProperties()} / {@link Bean#ro()} 1339 * </ul> 1340 * 1341 * @param beanClass The bean class. 1342 * @param properties Comma-delimited list of property names. 1343 * @return This object. 1344 */ 1345 @FluentSetter 1346 public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) { 1347 return annotations(BeanAnnotation.create(beanClass).ro(properties).build()); 1348 } 1349 1350 /** 1351 * Read-only bean properties. 1352 * 1353 * <p> 1354 * Specifies one or more properties on beans that are read-only despite having valid getters. 1355 * Serializers will serialize such properties as usual, but parsers will silently ignore them. 1356 * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties 1357 * for both serializers and parsers. 1358 * 1359 * <h5 class='section'>Example:</h5> 1360 * <p class='bjava'> 1361 * <jc>// A bean with 3 properties.</jc> 1362 * <jk>public class</jk> MyBean { 1363 * <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>; 1364 * } 1365 * 1366 * <jc>// Create a serializer with read-only property settings.</jc> 1367 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1368 * .<jsm>create</jsm>() 1369 * .beanPropertiesReadOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>)) 1370 * .build(); 1371 * 1372 * <jc>// All 3 properties will be serialized.</jc> 1373 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1374 * 1375 * <jc>// Create a parser with read-only property settings.</jc> 1376 * ReaderParser <jv>parser</jv> = JsonParser 1377 * .<jsm>create</jsm>() 1378 * .beanPropertiesReadOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>)) 1379 * .ignoreUnknownBeanProperties() 1380 * .build(); 1381 * 1382 * <jc>// Parser ignores bar and baz properties.</jc> 1383 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>); 1384 * </p> 1385 * 1386 * <p> 1387 * This method is functionally equivalent to the following code for each entry: 1388 * <p class='bjava'> 1389 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).readOnlyProperties(<jv>value</jv>.toString()).build()); 1390 * </p> 1391 * 1392 * <h5 class='section'>See Also:</h5><ul> 1393 * <li class='jma'>{@link Bean#readOnlyProperties()} / {@link Bean#ro()} 1394 * </ul> 1395 * 1396 * @param values 1397 * The values to add to this builder. 1398 * <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans. 1399 * <br>Values are comma-delimited lists of property names. Non-String objects are first converted to Strings. 1400 * @return This object. 1401 */ 1402 @FluentSetter 1403 public Builder beanPropertiesReadOnly(Map<String,Object> values) { 1404 values.forEach((k,v) -> annotations(BeanAnnotation.create(k).ro(stringify(v)).build())); 1405 return this; 1406 } 1407 1408 /** 1409 * Read-only bean properties. 1410 * 1411 * <p> 1412 * Specifies one or more properties on a bean that are read-only despite having valid getters. 1413 * Serializers will serialize such properties as usual, but parsers will silently ignore them. 1414 * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties 1415 * for both serializers and parsers. 1416 * 1417 * <h5 class='section'>Example:</h5> 1418 * <p class='bjava'> 1419 * <jc>// A bean with 3 properties.</jc> 1420 * <jk>public class</jk> MyBean { 1421 * <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>; 1422 * } 1423 * 1424 * <jc>// Create a serializer with read-only property settings.</jc> 1425 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1426 * .<jsm>create</jsm>() 1427 * .beanPropertiesReadOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>) 1428 * .build(); 1429 * 1430 * <jc>// All 3 properties will be serialized.</jc> 1431 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1432 * 1433 * <jc>// Create a parser with read-only property settings.</jc> 1434 * ReaderParser <jv>parser</jv> = JsonParser 1435 * .<jsm>create</jsm>() 1436 * .beanPropertiesReadOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>) 1437 * .ignoreUnknownBeanProperties() 1438 * .build(); 1439 * 1440 * <jc>// Parser ignores bar and baz properties.</jc> 1441 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>); 1442 * </p> 1443 * 1444 * <p> 1445 * This method is functionally equivalent to the following code: 1446 * <p class='bjava'> 1447 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).readOnlyProperties(<jv>properties</jv>).build()); 1448 * </p> 1449 * 1450 * <h5 class='section'>See Also:</h5><ul> 1451 * <li class='jma'>{@link Bean#readOnlyProperties()} / {@link Bean#ro()} 1452 * </ul> 1453 * 1454 * @param beanClassName 1455 * The bean class name. 1456 * <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all bean classes. 1457 * @param properties Comma-delimited list of property names. 1458 * @return This object. 1459 */ 1460 @FluentSetter 1461 public Builder beanPropertiesReadOnly(String beanClassName, String properties) { 1462 return annotations(BeanAnnotation.create(beanClassName).ro(properties).build()); 1463 } 1464 1465 /** 1466 * Write-only bean properties. 1467 * 1468 * <p> 1469 * Specifies one or more properties on a bean that are write-only despite having valid setters. 1470 * Parsers will parse such properties as usual, but serializers will silently ignore them. 1471 * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties 1472 * for both serializers and parsers. 1473 * 1474 * <h5 class='section'>Example:</h5> 1475 * <p class='bjava'> 1476 * <jc>// A bean with 3 properties.</jc> 1477 * <jk>public class</jk> MyBean { 1478 * <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>; 1479 * } 1480 * 1481 * <jc>// Create a serializer with write-only property settings.</jc> 1482 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1483 * .<jsm>create</jsm>() 1484 * .beanPropertiesWriteOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>) 1485 * .build(); 1486 * 1487 * <jc>// Only foo will be serialized.</jc> 1488 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1489 * 1490 * <jc>// Create a parser with write-only property settings.</jc> 1491 * ReaderParser <jv>parser</jv> = JsonParser 1492 * .<jsm>create</jsm>() 1493 * .beanPropertiesWriteOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>) 1494 * .build(); 1495 * 1496 * <jc>// Parser parses all 3 properties.</jc> 1497 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>); 1498 * </p> 1499 * 1500 * <p> 1501 * This method is functionally equivalent to the following code: 1502 * <p class='bjava'> 1503 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).writeOnlyProperties(<jv>properties</jv>).build()); 1504 * </p> 1505 * 1506 * <h5 class='section'>See Also:</h5><ul> 1507 * <li class='jma'>{@link Bean#writeOnlyProperties()} / {@link Bean#wo()} 1508 * </ul> 1509 * 1510 * @param beanClass The bean class. 1511 * @param properties Comma-delimited list of property names. 1512 * @return This object. 1513 */ 1514 @FluentSetter 1515 public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) { 1516 return annotations(BeanAnnotation.create(beanClass).wo(properties).build()); 1517 } 1518 1519 /** 1520 * Write-only bean properties. 1521 * 1522 * <p> 1523 * Specifies one or more properties on a bean that are write-only despite having valid setters. 1524 * Parsers will parse such properties as usual, but serializers will silently ignore them. 1525 * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties 1526 * for both serializers and parsers. 1527 * 1528 * <h5 class='section'>Example:</h5> 1529 * <p class='bjava'> 1530 * <jc>// A bean with 3 properties.</jc> 1531 * <jk>public class</jk> MyBean { 1532 * <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>; 1533 * } 1534 * 1535 * <jc>// Create a serializer with write-only property settings.</jc> 1536 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1537 * .<jsm>create</jsm>() 1538 * .beanPropertiesWriteOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>)) 1539 * .build(); 1540 * 1541 * <jc>// Only foo will be serialized.</jc> 1542 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1543 * 1544 * <jc>// Create a parser with write-only property settings.</jc> 1545 * ReaderParser <jv>parser</jv> = JsonParser 1546 * .<jsm>create</jsm>() 1547 * .beanPropertiesWriteOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>)) 1548 * .build(); 1549 * 1550 * <jc>// Parser parses all 3 properties.</jc> 1551 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>); 1552 * </p> 1553 * 1554 * <p> 1555 * This method is functionally equivalent to the following code for each entry: 1556 * <p class='bjava'> 1557 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).writeOnlyProperties(<jv>value</jv>.toString()).build()); 1558 * </p> 1559 * 1560 * <h5 class='section'>See Also:</h5><ul> 1561 * <li class='jma'>{@link Bean#writeOnlyProperties()} / {@link Bean#wo()} 1562 * </ul> 1563 * 1564 * @param values 1565 * The values to add to this builder. 1566 * <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans. 1567 * <br>Values are comma-delimited lists of property names. Non-String objects are first converted to Strings. 1568 * @return This object. 1569 */ 1570 @FluentSetter 1571 public Builder beanPropertiesWriteOnly(Map<String,Object> values) { 1572 values.forEach((k,v) -> annotations(BeanAnnotation.create(k).wo(stringify(v)).build())); 1573 return this; 1574 } 1575 1576 /** 1577 * Write-only bean properties. 1578 * 1579 * <p> 1580 * Specifies one or more properties on a bean that are write-only despite having valid setters. 1581 * Parsers will parse such properties as usual, but serializers will silently ignore them. 1582 * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties 1583 * for both serializers and parsers. 1584 * 1585 * <h5 class='section'>Example:</h5> 1586 * <p class='bjava'> 1587 * <jc>// A bean with 3 properties.</jc> 1588 * <jk>public class</jk> MyBean { 1589 * <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>; 1590 * } 1591 * 1592 * <jc>// Create a serializer with write-only property settings.</jc> 1593 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1594 * .<jsm>create</jsm>() 1595 * .beanPropertiesWriteOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>) 1596 * .build(); 1597 * 1598 * <jc>// Only foo will be serialized.</jc> 1599 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 1600 * 1601 * <jc>// Create a parser with write-only property settings.</jc> 1602 * ReaderParser <jv>parser</jv> = JsonParser 1603 * .<jsm>create</jsm>() 1604 * .beanPropertiesWriteOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>) 1605 * .build(); 1606 * 1607 * <jc>// Parser parses all 3 properties.</jc> 1608 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>); 1609 * </p> 1610 * 1611 * <p> 1612 * This method is functionally equivalent to the following code: 1613 * <p class='bjava'> 1614 * <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).writeOnlyProperties(<jv>properties</jv>).build()); 1615 * </p> 1616 * 1617 * <h5 class='section'>See Also:</h5><ul> 1618 * <li class='jma'>{@link Bean#writeOnlyProperties()} / {@link Bean#wo()} 1619 * </ul> 1620 * 1621 * @param beanClassName 1622 * The bean class name. 1623 * <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all bean classes. 1624 * @param properties Comma-delimited list of property names. 1625 * @return This object. 1626 */ 1627 @FluentSetter 1628 public Builder beanPropertiesWriteOnly(String beanClassName, String properties) { 1629 return annotations(BeanAnnotation.create(beanClassName).wo(properties).build()); 1630 } 1631 1632 /** 1633 * Bean dictionary. 1634 * 1635 * <p> 1636 * The list of classes that make up the bean dictionary in this bean context. 1637 * 1638 * <p> 1639 * Values are prepended to the list so that later calls can override classes of earlier calls. 1640 * 1641 * <p> 1642 * A dictionary is a name/class mapping used to find class types during parsing when they cannot be inferred 1643 * through reflection. The names are defined through the {@link Bean#typeName() @Bean(typeName)} annotation defined 1644 * on the bean class. For example, if a class <c>Foo</c> has a type-name of <js>"myfoo"</js>, then it would end up 1645 * serialized as <js>"{_type:'myfoo',...}"</js> in JSON 1646 * or <js>"<myfoo>...</myfoo>"</js> in XML. 1647 * 1648 * <p> 1649 * This setting tells the parsers which classes to look for when resolving <js>"_type"</js> attributes. 1650 * 1651 * <p> 1652 * Values can consist of any of the following types: 1653 * <ul> 1654 * <li>Any bean class that specifies a value for {@link Bean#typeName() @Bean(typeName)}. 1655 * <li>Any subclass of {@link BeanDictionaryList} containing a collection of bean classes with type name annotations. 1656 * <li>Any subclass of {@link BeanDictionaryMap} containing a mapping of type names to classes without type name annotations. 1657 * <li>Any array or collection of the objects above. 1658 * </ul> 1659 * 1660 * <h5 class='section'>Example:</h5> 1661 * <p class='bjava'> 1662 * <jc>// POJOs with @Bean(name) annotations.</jc> 1663 * <ja>@Bean</ja>(typeName=<js>"foo"</js>) 1664 * <jk>public class</jk> Foo {...} 1665 * <ja>@Bean</ja>(typeName=<js>"bar"</js>) 1666 * <jk>public class</jk> Bar {...} 1667 * 1668 * <jc>// Create a parser and tell it which classes to try to resolve.</jc> 1669 * ReaderParser <jv>parser</jv> = JsonParser 1670 * .<jsm>create</jsm>() 1671 * .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>) 1672 * .addBeanTypes() 1673 * .build(); 1674 * 1675 * <jc>// A bean with a field with an indeterminate type.</jc> 1676 * <jk>public class</jk> MyBean { 1677 * <jk>public</jk> Object <jf>mySimpleField</jf>; 1678 * } 1679 * 1680 * <jc>// Parse bean.</jc> 1681 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{mySimpleField:{_type:'foo',...}}"</js>, MyBean.<jk>class</jk>); 1682 * </p> 1683 * 1684 * <p> 1685 * Another option is to use the {@link Bean#dictionary()} annotation on the POJO class itself: 1686 * 1687 * <p class='bjava'> 1688 * <jc>// Instead of by parser, define a bean dictionary on a class through an annotation.</jc> 1689 * <jc>// This applies to all properties on this class and all subclasses.</jc> 1690 * <ja>@Bean</ja>(dictionary={Foo.<jk>class</jk>,Bar.<jk>class</jk>}) 1691 * <jk>public class</jk> MyBean { 1692 * <jk>public</jk> Object <jf>mySimpleField</jf>; <jc>// May contain Foo or Bar object.</jc> 1693 * <jk>public</jk> Map<String,Object> <jf>myMapField</jf>; <jc>// May contain Foo or Bar objects.</jc> 1694 * } 1695 * </p> 1696 * 1697 * <p> 1698 * A typical usage is to allow for HTML documents to be parsed back into HTML beans: 1699 * <p class='bjava'> 1700 * <jc>// Use the predefined HTML5 bean dictionary which is a BeanDictionaryList.</jc> 1701 * ReaderParser <jv>parser</jv> = HtmlParser 1702 * .<jsm>create</jsm>() 1703 * .dictionary(HtmlBeanDictionary.<jk>class</jk>) 1704 * .build(); 1705 * 1706 * <jc>// Parse an HTML body into HTML beans.</jc> 1707 * Body <jv>body</jv> = <jv>parser</jv>.parse(<js>"<body><ul><li>foo</li><li>bar</li></ul>"</js>, Body.<jk>class</jk>); 1708 * </p> 1709 * 1710 * <h5 class='section'>See Also:</h5><ul> 1711 * <li class='ja'>{@link org.apache.juneau.annotation.Bean#dictionary()} 1712 * <li class='ja'>{@link org.apache.juneau.annotation.Beanp#dictionary()} 1713 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#dictionary()} 1714 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#dictionary_replace()} 1715 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanDictionary(Class...)} 1716 * </ul> 1717 * 1718 * @param values 1719 * The values to add to this setting. 1720 * @return This object. 1721 */ 1722 @FluentSetter 1723 public Builder beanDictionary(Class<?>...values) { 1724 return beanDictionary(alist(values)); 1725 } 1726 1727 /** 1728 * Same as {@link #beanDictionary(Class...)} but allows you to pass in a collection of classes. 1729 * 1730 * @param values 1731 * The values to add to this setting. 1732 * @return This object. 1733 * @see #beanDictionary(Class...) 1734 */ 1735 @FluentSetter 1736 public Builder beanDictionary(Collection<Class<?>> values) { 1737 beanDictionary().addAll(0, values); 1738 return this; 1739 } 1740 1741 /** 1742 * Returns the bean dictionary list. 1743 * 1744 * <p> 1745 * Gives access to the inner list if you need to make more than simple additions via {@link #beanDictionary(Class...)}. 1746 * 1747 * @return The bean dictionary list. 1748 * @see #beanDictionary(Class...) 1749 */ 1750 public List<Class<?>> beanDictionary() { 1751 if (beanDictionary == null) 1752 beanDictionary = list(); 1753 return beanDictionary; 1754 } 1755 1756 /** 1757 * Bean dictionary. 1758 * 1759 * <p> 1760 * This is identical to {@link #beanDictionary(Class...)}, but specifies a dictionary within the context of 1761 * a single class as opposed to globally. 1762 * 1763 * <h5 class='section'>Example:</h5> 1764 * <p class='bjava'> 1765 * <jc>// POJOs with @Bean(name) annotations.</jc> 1766 * <ja>@Bean</ja>(typeName=<js>"foo"</js>) 1767 * <jk>public class</jk> Foo {...} 1768 * <ja>@Bean</ja>(typeName=<js>"bar"</js>) 1769 * <jk>public class</jk> Bar {...} 1770 * 1771 * <jc>// A bean with a field with an indeterminate type.</jc> 1772 * <jk>public class</jk> MyBean { 1773 * <jk>public</jk> Object <jf>mySimpleField</jf>; 1774 * } 1775 * 1776 * <jc>// Create a parser and tell it which classes to try to resolve.</jc> 1777 * ReaderParser <jv>parser</jv> = JsonParser 1778 * .<jsm>create</jsm>() 1779 * .dictionaryOn(MyBean.<jk>class</jk>, Foo.<jk>class</jk>, Bar.<jk>class</jk>) 1780 * .build(); 1781 * 1782 * <jc>// Parse bean.</jc> 1783 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{mySimpleField:{_type:'foo',...}}"</js>, MyBean.<jk>class</jk>); 1784 * </p> 1785 * 1786 * <p> 1787 * This is functionally equivalent to the {@link Bean#dictionary()} annotation. 1788 * 1789 * <h5 class='section'>See Also:</h5><ul> 1790 * <li class='jma'>{@link Bean#dictionary()} 1791 * <li class='jm'>{@link #beanDictionary(Class...)} 1792 * </ul> 1793 * 1794 * @param on The class that the dictionary values apply to. 1795 * @param values 1796 * The new values for this setting. 1797 * @return This object. 1798 */ 1799 @FluentSetter 1800 public Builder dictionaryOn(Class<?> on, Class<?>...values) { 1801 return annotations(BeanAnnotation.create(on).dictionary(values).build()); 1802 } 1803 1804 /** 1805 * POJO example. 1806 * 1807 * <p> 1808 * Specifies an example of the specified class. 1809 * 1810 * <p> 1811 * Examples are used in cases such as POJO examples in Swagger documents. 1812 * 1813 * <h5 class='section'>Example:</h5> 1814 * <p class='bjava'> 1815 * <jc>// Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class.</jc> 1816 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1817 * .<jsm>create</jsm>() 1818 * .example(MyBean.<jk>class</jk>, <jk>new</jk> MyBean().setFoo(<js>"foo"</js>).setBar(123)) 1819 * .build(); 1820 * </p> 1821 * 1822 * <p> 1823 * This is a shorthand method for the following code: 1824 * <p class='bjava'> 1825 * <jv>builder</jv>.annotations(MarshalledAnnotation.<jsm>create</jsm>(<jv>pojoClass</jv>).example(Json5.<jsf>DEFAULT</jsf>.toString(<jv>object</jv>)).build()) 1826 * </p> 1827 * 1828 * <h5 class='section'>Notes:</h5><ul> 1829 * <li class='note'>Using this method assumes the serialized form of the object is the same as that produced 1830 * by the default serializer. This may not be true based on settings or swaps on the constructed serializer. 1831 * </ul> 1832 * 1833 * <p> 1834 * POJO examples can also be defined on classes via the following: 1835 * <ul class='spaced-list'> 1836 * <li>The {@link Marshalled#example()} annotation on the class itself. 1837 * <li>A static field annotated with {@link Example @Example}. 1838 * <li>A static method annotated with {@link Example @Example} with zero arguments or one {@link BeanSession} argument. 1839 * <li>A static method with name <c>example</c> with no arguments or one {@link BeanSession} argument. 1840 * </ul> 1841 * 1842 * @param <T> The POJO class. 1843 * @param pojoClass The POJO class. 1844 * @param o 1845 * An instance of the POJO class used for examples. 1846 * @return This object. 1847 */ 1848 @FluentSetter 1849 public <T> Builder example(Class<T> pojoClass, T o) { 1850 return annotations(MarshalledAnnotation.create(pojoClass).example(Json5.of(o)).build()); 1851 } 1852 1853 /** 1854 * POJO example. 1855 * 1856 * <p> 1857 * Specifies an example in JSON of the specified class. 1858 * 1859 * <p> 1860 * Examples are used in cases such as POJO examples in Swagger documents. 1861 * 1862 * <p> 1863 * Setting applies to specified class and all subclasses. 1864 * 1865 * <h5 class='section'>Example:</h5> 1866 * <p class='bjava'> 1867 * <jc>// Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class.</jc> 1868 * WriterSerializer <jv>serializer</jv> = JsonSerializer 1869 * .<jsm>create</jsm>() 1870 * .example(MyBean.<jk>class</jk>, <js>"{foo:'bar'}"</js>) 1871 * .build(); 1872 * </p> 1873 * 1874 * <p> 1875 * This is a shorthand method for the following code: 1876 * <p class='bjava'> 1877 * <jv>builder</jv>.annotations(MarshalledAnnotation.<jsm>create</jsm>(<jv>pojoClass</jv>).example(<jv>json</jv>).build()) 1878 * </p> 1879 * 1880 * <p> 1881 * POJO examples can also be defined on classes via the following: 1882 * <ul class='spaced-list'> 1883 * <li>A static field annotated with {@link Example @Example}. 1884 * <li>A static method annotated with {@link Example @Example} with zero arguments or one {@link BeanSession} argument. 1885 * <li>A static method with name <c>example</c> with no arguments or one {@link BeanSession} argument. 1886 * </ul> 1887 * 1888 * <h5 class='section'>See Also:</h5><ul> 1889 * <li class='ja'>{@link Marshalled#example()} 1890 * </ul> 1891 * 1892 * @param <T> The POJO class type. 1893 * @param pojoClass The POJO class. 1894 * @param json The JSON 5 representation of the example. 1895 * @return This object. 1896 */ 1897 @FluentSetter 1898 public <T> Builder example(Class<T> pojoClass, String json) { 1899 return annotations(MarshalledAnnotation.create(pojoClass).example(json).build()); 1900 } 1901 1902 /** 1903 * Find fluent setters. 1904 * 1905 * <p> 1906 * When enabled, fluent setters are detected on beans during parsing. 1907 * 1908 * <p> 1909 * Fluent setters must have the following attributes: 1910 * <ul> 1911 * <li>Public. 1912 * <li>Not static. 1913 * <li>Take in one parameter. 1914 * <li>Return the bean itself. 1915 * </ul> 1916 * 1917 * <h5 class='section'>Example:</h5> 1918 * <p class='bjava'> 1919 * <jc>// A bean with a fluent setter.</jc> 1920 * <jk>public class</jk> MyBean { 1921 * <jk>public</jk> MyBean foo(String <jv>value</jv>) {...} 1922 * } 1923 * 1924 * <jc>// Create a parser that finds fluent setters.</jc> 1925 * ReaderParser <jv>parser</jv> = JsonParser 1926 * .<jsm>create</jsm>() 1927 * .findFluentSetters() 1928 * .build(); 1929 * 1930 * <jc>// Parse into bean using fluent setter.</jc> 1931 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>); 1932 * </p> 1933 * 1934 * <h5 class='section'>Notes:</h5><ul> 1935 * <li class='note'>The {@link Beanp @Beanp} annotation can also be used on methods to individually identify them as fluent setters. 1936 * <li class='note'>The {@link Bean#findFluentSetters() @Bean.fluentSetters()} annotation can also be used on classes to specify to look for fluent setters. 1937 * </ul> 1938 * 1939 * <h5 class='section'>See Also:</h5><ul> 1940 * <li class='ja'>{@link org.apache.juneau.annotation.Bean#findFluentSetters()} 1941 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#findFluentSetters()} 1942 * </ul> 1943 * 1944 * @return This object. 1945 */ 1946 @FluentSetter 1947 public Builder findFluentSetters() { 1948 return findFluentSetters(true); 1949 } 1950 1951 /** 1952 * Same as {@link #findFluentSetters()} but allows you to explicitly specify the value. 1953 * 1954 * @param value The value for this setting. 1955 * @return This object. 1956 */ 1957 @FluentSetter 1958 public Builder findFluentSetters(boolean value) { 1959 findFluentSetters = value; 1960 return this; 1961 } 1962 1963 /** 1964 * Find fluent setters. 1965 * 1966 * <p> 1967 * Identical to {@link #findFluentSetters()} but enables it on a specific class only. 1968 * 1969 * <h5 class='section'>Example:</h5> 1970 * <p class='bjava'> 1971 * <jc>// A bean with a fluent setter.</jc> 1972 * <jk>public class</jk> MyBean { 1973 * <jk>public</jk> MyBean foo(String <jv>value</jv>) {...} 1974 * } 1975 * 1976 * <jc>// Create a parser that finds fluent setters.</jc> 1977 * ReaderParser <jv>parser</jv> = JsonParser 1978 * .<jsm>create</jsm>() 1979 * .findFluentSetters(MyBean.<jk>class</jk>) 1980 * .build(); 1981 * 1982 * <jc>// Parse into bean using fluent setter.</jc> 1983 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>); 1984 * </p> 1985 * 1986 * <h5 class='section'>Notes:</h5><ul> 1987 * <li class='note'>This method is functionally equivalent to using the {@link Bean#findFluentSetters()} annotation. 1988 * </ul> 1989 * 1990 * <h5 class='section'>See Also:</h5><ul> 1991 * <li class='ja'>{@link Bean#findFluentSetters()} 1992 * <li class='jm'>{@link #findFluentSetters()} 1993 * </ul> 1994 * 1995 * @param on The class that this applies to. 1996 * @return This object. 1997 */ 1998 @FluentSetter 1999 public Builder findFluentSetters(Class<?> on) { 2000 return annotations(BeanAnnotation.create(on).findFluentSetters(true).build()); 2001 } 2002 2003 /** 2004 * Ignore invocation errors on getters. 2005 * 2006 * <p> 2007 * When enabled, errors thrown when calling bean getter methods will silently be ignored. 2008 * Otherwise, a {@code BeanRuntimeException} is thrown. 2009 * 2010 * <h5 class='section'>Example:</h5> 2011 * <p class='bjava'> 2012 * <jc>// A bean with a property that throws an exception.</jc> 2013 * <jk>public class</jk> MyBean { 2014 * <jk>public</jk> String getFoo() { 2015 * <jk>throw new</jk> RuntimeException(<js>"foo"</js>); 2016 * } 2017 * } 2018 * 2019 * <jc>// Create a serializer that ignores bean getter exceptions.</jc> 2020 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2021 * .<jsm>create</jsm>() 2022 * .ingoreInvocationExceptionsOnGetters() 2023 * .build(); 2024 * 2025 * <jc>// Exception is ignored.</jc> 2026 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2027 * </p> 2028 * 2029 * <h5 class='section'>See Also:</h5><ul> 2030 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#ignoreInvocationExceptionsOnGetters()} 2031 * </ul> 2032 * 2033 * @return This object. 2034 */ 2035 @FluentSetter 2036 public Builder ignoreInvocationExceptionsOnGetters() { 2037 return ignoreInvocationExceptionsOnGetters(true); 2038 } 2039 2040 /** 2041 * Same as {@link #ignoreInvocationExceptionsOnGetters()} but allows you to explicitly specify the value. 2042 * 2043 * @param value The value for this setting. 2044 * @return This object. 2045 */ 2046 @FluentSetter 2047 public Builder ignoreInvocationExceptionsOnGetters(boolean value) { 2048 ignoreInvocationExceptionsOnGetters = value; 2049 return this; 2050 } 2051 2052 /** 2053 * Ignore invocation errors on setters. 2054 * 2055 * <p> 2056 * When enabled, errors thrown when calling bean setter methods will silently be ignored. 2057 * Otherwise, a {@code BeanRuntimeException} is thrown. 2058 * 2059 * <h5 class='section'>Example:</h5> 2060 * <p class='bjava'> 2061 * <jc>// A bean with a property that throws an exception.</jc> 2062 * <jk>public class</jk> MyBean { 2063 * <jk>public void</jk> setFoo(String <jv>foo</jv>) { 2064 * <jk>throw new</jk> RuntimeException(<js>"foo"</js>); 2065 * } 2066 * } 2067 * 2068 * <jc>// Create a parser that ignores bean setter exceptions.</jc> 2069 * ReaderParser <jv>parser</jv> = JsonParser 2070 * .<jsm>create</jsm>() 2071 * .ignoreInvocationExceptionsOnSetters() 2072 * .build(); 2073 * 2074 * <jc>// Exception is ignored.</jc> 2075 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>); 2076 * </p> 2077 * 2078 * <h5 class='section'>See Also:</h5><ul> 2079 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#ignoreInvocationExceptionsOnSetters()} 2080 * </ul> 2081 * 2082 * @return This object. 2083 */ 2084 @FluentSetter 2085 public Builder ignoreInvocationExceptionsOnSetters() { 2086 return ignoreInvocationExceptionsOnSetters(true); 2087 } 2088 2089 /** 2090 * Same as {@link #ignoreInvocationExceptionsOnSetters()} but allows you to explicitly specify the value. 2091 * 2092 * @param value The value for this setting. 2093 * @return This object. 2094 */ 2095 @FluentSetter 2096 public Builder ignoreInvocationExceptionsOnSetters(boolean value) { 2097 ignoreInvocationExceptionsOnSetters = value; 2098 return this; 2099 } 2100 2101 /** 2102 * Don't silently ignore missing setters. 2103 * 2104 * <p> 2105 * When enabled, trying to set a value on a bean property without a setter will throw a {@link BeanRuntimeException}. 2106 * Otherwise, it will be silently ignored. 2107 * 2108 * <h5 class='section'>Example:</h5> 2109 * <p class='bjava'> 2110 * <jc>// A bean with a property with a getter but not a setter.</jc> 2111 * <jk>public class</jk> MyBean { 2112 * <jk>public void</jk> getFoo() { 2113 * <jk>return</jk> <js>"foo"</js>; 2114 * } 2115 * } 2116 * 2117 * <jc>// Create a parser that throws an exception if a setter is not found but a getter is.</jc> 2118 * ReaderParser <jv>parser</jv> = JsonParser 2119 * .<jsm>create</jsm>() 2120 * .disableIgnoreMissingSetters() 2121 * .build(); 2122 * 2123 * <jc>// Throws a ParseException.</jc> 2124 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>); 2125 * </p> 2126 * 2127 * <h5 class='section'>Notes:</h5><ul> 2128 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on getters and fields to ignore them. 2129 * </ul> 2130 * 2131 * <h5 class='section'>See Also:</h5><ul> 2132 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableIgnoreMissingSetters()} 2133 * </ul> 2134 * 2135 * @return This object. 2136 */ 2137 @FluentSetter 2138 public Builder disableIgnoreMissingSetters() { 2139 return disableIgnoreMissingSetters(true); 2140 } 2141 2142 /** 2143 * Same as {@link #disableIgnoreMissingSetters()} but allows you to explicitly specify the value. 2144 * 2145 * @param value The value for this setting. 2146 * @return This object. 2147 */ 2148 @FluentSetter 2149 public Builder disableIgnoreMissingSetters(boolean value) { 2150 disableIgnoreMissingSetters = value; 2151 return this; 2152 } 2153 2154 /** 2155 * Don't ignore transient fields. 2156 * 2157 * <p> 2158 * When enabled, methods and fields marked as <jk>transient</jk> will not be ignored as bean properties. 2159 * 2160 * <h5 class='section'>Example:</h5> 2161 * <p class='bjava'> 2162 * <jc>// A bean with a transient field.</jc> 2163 * <jk>public class</jk> MyBean { 2164 * <jk>public transient</jk> String <jf>foo</jf> = <js>"foo"</js>; 2165 * } 2166 * 2167 * <jc>// Create a serializer that doesn't ignore transient fields.</jc> 2168 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2169 * .<jsm>create</jsm>() 2170 * .disableIgnoreTransientFields() 2171 * .build(); 2172 * 2173 * <jc>// Produces: {"foo":"foo"}</jc> 2174 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2175 * </p> 2176 * 2177 * <h5 class='section'>Notes:</h5><ul> 2178 * <li class='note'>The {@link Beanp @Beanp} annotation can also be used on transient fields to keep them from being ignored. 2179 * </ul> 2180 * 2181 * <h5 class='section'>See Also:</h5><ul> 2182 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableIgnoreTransientFields()} 2183 * </ul> 2184 * 2185 * @return This object. 2186 */ 2187 @FluentSetter 2188 public Builder disableIgnoreTransientFields() { 2189 return disableIgnoreTransientFields(true); 2190 } 2191 2192 /** 2193 * Same as {@link #disableIgnoreTransientFields()} but allows you to explicitly specify the value. 2194 * 2195 * @param value The value for this setting. 2196 * @return This object. 2197 */ 2198 @FluentSetter 2199 public Builder disableIgnoreTransientFields(boolean value) { 2200 disableIgnoreTransientFields = value; 2201 return this; 2202 } 2203 2204 /** 2205 * Ignore unknown properties. 2206 * 2207 * <p> 2208 * When enabled, trying to set a value on a non-existent bean property will silently be ignored. 2209 * Otherwise, a {@code BeanRuntimeException} is thrown. 2210 * 2211 * <h5 class='section'>Example:</h5> 2212 * <p class='bjava'> 2213 * <jc>// A bean with a single property.</jc> 2214 * <jk>public class</jk> MyBean { 2215 * <jk>public</jk> String <jf>foo</jf>; 2216 * } 2217 * 2218 * <jc>// Create a parser that ignores missing bean properties.</jc> 2219 * ReaderParser <jv>parser</jv> = JsonParser 2220 * .<jsm>create</jsm>() 2221 * .ignoreUnknownBeanProperties() 2222 * .build(); 2223 * 2224 * <jc>// Doesn't throw an exception on unknown 'bar' property.</jc> 2225 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar'}"</js>, MyBean.<jk>class</jk>); 2226 * </p> 2227 * 2228 * <h5 class='section'>See Also:</h5><ul> 2229 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#ignoreUnknownBeanProperties()} 2230 * </ul> 2231 * 2232 * @return This object. 2233 */ 2234 @FluentSetter 2235 public Builder ignoreUnknownBeanProperties() { 2236 return ignoreUnknownBeanProperties(true); 2237 } 2238 2239 /** 2240 * Same as {@link #ignoreUnknownBeanProperties()} but allows you to explicitly specify the value. 2241 * 2242 * @param value The value for this setting. 2243 * @return This object. 2244 */ 2245 @FluentSetter 2246 public Builder ignoreUnknownBeanProperties(boolean value) { 2247 ignoreUnknownBeanProperties = value; 2248 return this; 2249 } 2250 2251 /** 2252 * Ignore unknown properties. 2253 * 2254 * <p> 2255 * When enabled, unknown enum values will be set to <jk>null</jk> instead of throwing an exception. 2256 * 2257 * <h5 class='section'>See Also:</h5><ul> 2258 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#ignoreUnknownEnumValues()} 2259 * </ul> 2260 * 2261 * @return This object. 2262 */ 2263 @FluentSetter 2264 public Builder ignoreUnknownEnumValues() { 2265 return ignoreUnknownEnumValues(true); 2266 } 2267 2268 /** 2269 * Same as {@link #ignoreUnknownEnumValues()} but allows you to explicitly specify the value. 2270 * 2271 * @param value The value for this setting. 2272 * @return This object. 2273 */ 2274 @FluentSetter 2275 public Builder ignoreUnknownEnumValues(boolean value) { 2276 ignoreUnknownEnumValues = value; 2277 return this; 2278 } 2279 2280 /** 2281 * Don't ignore unknown properties with null values. 2282 * 2283 * <p> 2284 * When enabled, trying to set a <jk>null</jk> value on a non-existent bean property will throw a {@link BeanRuntimeException}. 2285 * Otherwise it will be silently ignored. 2286 * 2287 * <h5 class='section'>Example:</h5> 2288 * <p class='bjava'> 2289 * <jc>// A bean with a single property.</jc> 2290 * <jk>public class</jk> MyBean { 2291 * <jk>public</jk> String <jf>foo</jf>; 2292 * } 2293 * 2294 * <jc>// Create a parser that throws an exception on an unknown property even if the value being set is null.</jc> 2295 * ReaderParser <jv>parser</jv> = JsonParser 2296 * .<jsm>create</jsm>() 2297 * .disableIgnoreUnknownNullBeanProperties() 2298 * .build(); 2299 * 2300 * <jc>// Throws a BeanRuntimeException wrapped in a ParseException on the unknown 'bar' property.</jc> 2301 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:null}"</js>, MyBean.<jk>class</jk>); 2302 * </p> 2303 * 2304 * <h5 class='section'>See Also:</h5><ul> 2305 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableIgnoreUnknownNullBeanProperties()} 2306 * </ul> 2307 * 2308 * @return This object. 2309 */ 2310 @FluentSetter 2311 public Builder disableIgnoreUnknownNullBeanProperties() { 2312 return disableIgnoreUnknownNullBeanProperties(true); 2313 } 2314 2315 /** 2316 * Same as {@link #disableIgnoreUnknownNullBeanProperties()} but allows you to explicitly specify the value. 2317 * 2318 * @param value The value for this setting. 2319 * @return This object. 2320 */ 2321 @FluentSetter 2322 public Builder disableIgnoreUnknownNullBeanProperties(boolean value) { 2323 disableIgnoreUnknownNullBeanProperties = value; 2324 return this; 2325 } 2326 2327 /** 2328 * Implementation classes. 2329 * 2330 * <p> 2331 * For interfaces and abstract classes this method can be used to specify an implementation class for the 2332 * interface/abstract class so that instances of the implementation class are used when instantiated (e.g. during a 2333 * parse). 2334 * 2335 * <h5 class='section'>Example:</h5> 2336 * <p class='bjava'> 2337 * <jc>// A bean interface.</jc> 2338 * <jk>public interface</jk> MyBean { 2339 * ... 2340 * } 2341 * 2342 * <jc>// A bean implementation.</jc> 2343 * <jk>public class</jk> MyBeanImpl <jk>implements</jk> MyBean { 2344 * ... 2345 * } 2346 2347 * <jc>// Create a parser that instantiates MyBeanImpls when parsing MyBeans.</jc> 2348 * ReaderParser <jv>parser</jv> = JsonParser 2349 * .<jsm>create</jsm>() 2350 * .implClass(MyBean.<jk>class</jk>, MyBeanImpl.<jk>class</jk>) 2351 * .build(); 2352 * 2353 * <jc>// Instantiates a MyBeanImpl,</jc> 2354 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"..."</js>, MyBean.<jk>class</jk>); 2355 * </p> 2356 * 2357 * @param interfaceClass The interface class. 2358 * @param implClass The implementation class. 2359 * @return This object. 2360 */ 2361 @FluentSetter 2362 public Builder implClass(Class<?> interfaceClass, Class<?> implClass) { 2363 return annotations(MarshalledAnnotation.create(interfaceClass).implClass(implClass).build()); 2364 } 2365 2366 /** 2367 * Implementation classes. 2368 * 2369 * <p> 2370 * For interfaces and abstract classes this method can be used to specify an implementation class for the 2371 * interface/abstract class so that instances of the implementation class are used when instantiated (e.g. during a 2372 * parse). 2373 * 2374 * <h5 class='section'>Example:</h5> 2375 * <p class='bjava'> 2376 * <jc>// A bean with a single property.</jc> 2377 * <jk>public interface</jk> MyBean { 2378 * ... 2379 * } 2380 * 2381 * <jc>// A bean with a single property.</jc> 2382 * <jk>public class</jk> MyBeanImpl <jk>implements</jk> MyBean { 2383 * ... 2384 * } 2385 2386 * <jc>// Create a parser that instantiates MyBeanImpls when parsing MyBeans.</jc> 2387 * ReaderParser <jv>parser</jv> = JsonParser 2388 * .<jsm>create</jsm>() 2389 * .implClasses(AMap.<jsm>of</jsm>(MyBean.<jk>class</jk>, MyBeanImpl.<jk>class</jk>)) 2390 * .build(); 2391 * 2392 * <jc>// Instantiates a MyBeanImpl,</jc> 2393 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"..."</js>, MyBean.<jk>class</jk>); 2394 * </p> 2395 * 2396 * @param values 2397 * The new value for this setting. 2398 * @return This object. 2399 */ 2400 @FluentSetter 2401 public Builder implClasses(Map<Class<?>,Class<?>> values) { 2402 values.forEach((k,v) -> annotations(MarshalledAnnotation.create(k).implClass(v).build())); 2403 return this; 2404 } 2405 2406 /** 2407 * Identifies a class to be used as the interface class for the specified class and all subclasses. 2408 * 2409 * <p> 2410 * When specified, only the list of properties defined on the interface class will be used during serialization. 2411 * Additional properties on subclasses will be ignored. 2412 * 2413 * <p class='bjava'> 2414 * <jc>// Parent class or interface</jc> 2415 * <jk>public abstract class</jk> A { 2416 * <jk>public</jk> String <jf>foo</jf> = <js>"foo"</js>; 2417 * } 2418 * 2419 * <jc>// Sub class</jc> 2420 * <jk>public class</jk> A1 <jk>extends</jk> A { 2421 * <jk>public</jk> String <jf>bar</jf> = <js>"bar"</js>; 2422 * } 2423 * 2424 * <jc>// Create a serializer and define our interface class mapping.</jc> 2425 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2426 * .<jsm>create</jsm>() 2427 * .interfaceClass(A1.<jk>class</jk>, A.<jk>class</jk>) 2428 * .build(); 2429 * 2430 * <jc>// Produces "{"foo":"foo"}"</jc> 2431 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> A1()); 2432 * </p> 2433 * 2434 * <p> 2435 * This annotation can be used on the parent class so that it filters to all child classes, or can be set 2436 * individually on the child classes. 2437 * 2438 * <h5 class='section'>Notes:</h5><ul> 2439 * <li class='note'>The {@link Bean#interfaceClass() @Bean(interfaceClass)} annotation is the equivalent annotation-based solution. 2440 * </ul> 2441 * 2442 * @param on The class that the interface class applies to. 2443 * @param value 2444 * The new value for this setting. 2445 * @return This object. 2446 */ 2447 @FluentSetter 2448 public Builder interfaceClass(Class<?> on, Class<?> value) { 2449 return annotations(BeanAnnotation.create(on).interfaceClass(value).build()); 2450 } 2451 2452 /** 2453 * Identifies a set of interfaces. 2454 * 2455 * <p> 2456 * When specified, only the list of properties defined on the interface class will be used during serialization 2457 * of implementation classes. Additional properties on subclasses will be ignored. 2458 * 2459 * <p class='bjava'> 2460 * <jc>// Parent class or interface</jc> 2461 * <jk>public abstract class</jk> A { 2462 * <jk>public</jk> String <jf>foo</jf> = <js>"foo"</js>; 2463 * } 2464 * 2465 * <jc>// Sub class</jc> 2466 * <jk>public class</jk> A1 <jk>extends</jk> A { 2467 * <jk>public</jk> String <jf>bar</jf> = <js>"bar"</js>; 2468 * } 2469 * 2470 * <jc>// Create a serializer and define our interface class mapping.</jc> 2471 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2472 * .<jsm>create</jsm>() 2473 * .interfaces(A.<jk>class</jk>) 2474 * .build(); 2475 * 2476 * <jc>// Produces "{"foo":"foo"}"</jc> 2477 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> A1()); 2478 * </p> 2479 * 2480 * <p> 2481 * This annotation can be used on the parent class so that it filters to all child classes, or can be set 2482 * individually on the child classes. 2483 * 2484 * <h5 class='section'>Notes:</h5><ul> 2485 * <li class='note'>The {@link Bean#interfaceClass() @Bean(interfaceClass)} annotation is the equivalent annotation-based solution. 2486 * </ul> 2487 * 2488 * @param value 2489 * The new value for this setting. 2490 * @return This object. 2491 */ 2492 @FluentSetter 2493 public Builder interfaces(Class<?>...value) { 2494 for (Class<?> v : value) 2495 annotations(BeanAnnotation.create(v).interfaceClass(v).build()); 2496 return this; 2497 } 2498 2499 /** 2500 * <i><l>Context</l> configuration property: </i> Locale. 2501 * 2502 * <p> 2503 * Specifies the default locale for serializer and parser sessions when not specified via {@link BeanSession.Builder#locale(Locale)}. 2504 * Typically used for POJO swaps that need to deal with locales such as swaps that convert <l>Date</l> and <l>Calendar</l> 2505 * objects to strings by accessing it via the session passed into the {@link ObjectSwap#swap(BeanSession, Object)} and 2506 * {@link ObjectSwap#unswap(BeanSession, Object, ClassMeta, String)} methods. 2507 * 2508 * <h5 class='section'>Example:</h5> 2509 * <p class='bjava'> 2510 * <jc>// Define a POJO swap that skips serializing beans if we're in the UK.</jc> 2511 * <jk>public class</jk> MyBeanSwap <jk>extends</jk> StringSwap<MyBean> { 2512 * <ja>@Override</ja> 2513 * <jk>public</jk> String swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) <jk>throws</jk> Exception { 2514 * <jk>if</jk> (<jv>session</jv>.getLocale().equals(Locale.<jsf>UK</jsf>)) 2515 * <jk>return null</jk>; 2516 * <jk>return</jk> <jv>bean</jv>.toString(); 2517 * } 2518 * } 2519 * 2520 * <jc>// Create a serializer that uses the specified locale if it's not passed in through session args.</jc> 2521 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2522 * .<jsm>create</jsm>() 2523 * .locale(Locale.<jsf>UK</jsf>) 2524 * .swaps(MyBeanSwap.<jk>class</jk>) 2525 * .build(); 2526 * </p> 2527 * 2528 * <h5 class='section'>See Also:</h5><ul> 2529 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#locale()} 2530 * <li class='jm'>{@link org.apache.juneau.BeanSession.Builder#locale(Locale)} 2531 * </ul> 2532 * 2533 * @param value The new value for this property. 2534 * @return This object. 2535 */ 2536 @FluentSetter 2537 public Builder locale(Locale value) { 2538 locale = value; 2539 return this; 2540 } 2541 2542 /** 2543 * <i><l>Context</l> configuration property: </i> Media type. 2544 * 2545 * <p> 2546 * Specifies the default media type for serializer and parser sessions when not specified via {@link BeanSession.Builder#mediaType(MediaType)}. 2547 * Typically used for POJO swaps that need to serialize the same POJO classes differently depending on 2548 * the specific requested media type. For example, a swap could handle a request for media types <js>"application/json"</js> 2549 * and <js>"application/json+foo"</js> slightly differently even though they're both being handled by the same JSON 2550 * serializer or parser. 2551 * 2552 * <h5 class='section'>Example:</h5> 2553 * <p class='bjava'> 2554 * <jc>// Define a POJO swap that skips serializing beans if the media type is application/json.</jc> 2555 * <jk>public class</jk> MyBeanSwap <jk>extends</jk> StringSwap<MyBean> { 2556 * <ja>@Override</ja> 2557 * <jk>public</jk> String swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) <jk>throws</jk> Exception { 2558 * <jk>if</jk> (<jv>session</jv>.getMediaType().equals(<js>"application/json"</js>)) 2559 * <jk>return null</jk>; 2560 * <jk>return</jk> <jv>bean</jv>.toString(); 2561 * } 2562 * } 2563 * 2564 * <jc>// Create a serializer that uses the specified media type if it's not passed in through session args.</jc> 2565 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2566 * .<jsm>create</jsm>() 2567 * .mediaType(MediaType.<jsf>JSON</jsf>) 2568 * .build(); 2569 * </p> 2570 * 2571 * <h5 class='section'>See Also:</h5><ul> 2572 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#mediaType()} 2573 * <li class='jm'>{@link org.apache.juneau.BeanSession.Builder#mediaType(MediaType)} 2574 * </ul> 2575 * 2576 * @param value The new value for this property. 2577 * @return This object. 2578 */ 2579 @FluentSetter 2580 public Builder mediaType(MediaType value) { 2581 mediaType = value; 2582 return this; 2583 } 2584 2585 /** 2586 * Bean class exclusions. 2587 * 2588 * <p> 2589 * List of classes that should not be treated as beans even if they appear to be bean-like. 2590 * Not-bean classes are converted to <c>Strings</c> during serialization. 2591 * 2592 * <p> 2593 * Values can consist of any of the following types: 2594 * <ul> 2595 * <li>Classes. 2596 * <li>Arrays and collections of classes. 2597 * </ul> 2598 * 2599 * <h5 class='section'>Example:</h5> 2600 * <p class='bjava'> 2601 * <jc>// A bean with a single property.</jc> 2602 * <jk>public class</jk> MyBean { 2603 * <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>; 2604 * 2605 * <jk>public</jk> String toString() { 2606 * <jk>return</jk> <js>"baz"</js>; 2607 * } 2608 * } 2609 * 2610 * <jc>// Create a serializer that doesn't treat MyBean as a bean class.</jc> 2611 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2612 * .<jsm>create</jsm>() 2613 * .notBeanClasses(MyBean.<jk>class</jk>) 2614 * .build(); 2615 * 2616 * <jc>// Produces "baz" instead of {"foo":"bar"}</jc> 2617 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2618 * </p> 2619 * 2620 * <h5 class='section'>Notes:</h5><ul> 2621 * <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on classes to prevent them from being recognized as beans. 2622 * </ul> 2623 * 2624 * <h5 class='section'>See Also:</h5><ul> 2625 * <li class='ja'>{@link org.apache.juneau.annotation.BeanIgnore} 2626 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#notBeanClasses()} 2627 * </ul> 2628 * 2629 * @param values 2630 * The values to add to this setting. 2631 * <br>Values can consist of any of the following types: 2632 * <ul> 2633 * <li>Classes. 2634 * <li>Arrays and collections of classes. 2635 * </ul> 2636 * @return This object. 2637 */ 2638 @FluentSetter 2639 public Builder notBeanClasses(Class<?>...values) { 2640 return notBeanClasses(alist(values)); 2641 } 2642 2643 /** 2644 * Same as {@link #notBeanClasses(Class...)} but allows you to pass in a collection of classes. 2645 * 2646 * @param values 2647 * The values to add to this setting. 2648 * @return This object. 2649 * @see #notBeanClasses(Class...) 2650 */ 2651 @FluentSetter 2652 public Builder notBeanClasses(Collection<Class<?>> values) { 2653 notBeanClasses().addAll(values); 2654 return this; 2655 } 2656 2657 /** 2658 * Returns the list of not-bean classes. 2659 * 2660 * <p> 2661 * Gives access to the inner list if you need to make more than simple additions via {@link #notBeanClasses(Class...)}. 2662 * 2663 * @return The list of not-bean classes. 2664 * @see #notBeanClasses(Class...) 2665 */ 2666 public Set<Class<?>> notBeanClasses() { 2667 if (notBeanClasses == null) 2668 notBeanClasses = classSet(); 2669 return notBeanClasses; 2670 } 2671 2672 /** 2673 * Bean package exclusions. 2674 * 2675 * <p> 2676 * Used as a convenient way of defining the {@link #notBeanClasses(Class...)} property for entire packages. 2677 * Any classes within these packages will be serialized to strings using {@link Object#toString()}. 2678 * 2679 * <p> 2680 * Note that you can specify suffix patterns to include all subpackages. 2681 * 2682 * <p> 2683 * Values can consist of any of the following types: 2684 * <ul> 2685 * <li>Strings. 2686 * <li>Arrays and collections of strings. 2687 * </ul> 2688 * 2689 * <h5 class='section'>Example:</h5> 2690 * <p class='bjava'> 2691 * <jc>// Create a serializer that ignores beans in the specified packages.</jc> 2692 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2693 * .<jsm>create</jsm>() 2694 * .notBeanPackages(<js>"org.apache.foo"</js>, <js>"org.apache.bar.*"</js>) 2695 * .build(); 2696 * </p> 2697 * 2698 * @param values 2699 * The values to add to this setting. 2700 * <br>Values can consist of any of the following types: 2701 * <ul> 2702 * <li>{@link Package} objects. 2703 * <li>Strings. 2704 * <li>Arrays and collections of anything in this list. 2705 * </ul> 2706 * @return This object. 2707 */ 2708 @FluentSetter 2709 public Builder notBeanPackages(String...values) { 2710 return notBeanPackages(alist(values)); 2711 } 2712 2713 /** 2714 * Same as {@link #notBeanPackages(String...)} but allows you to pass in a collection of classes. 2715 * 2716 * @param values 2717 * The values to add to this setting. 2718 * @return This object. 2719 * @see #notBeanPackages(String...) 2720 */ 2721 @FluentSetter 2722 public Builder notBeanPackages(Collection<String> values) { 2723 notBeanPackages().addAll(values); 2724 return this; 2725 } 2726 2727 /** 2728 * Returns the list of not-bean Java package names. 2729 * 2730 * <p> 2731 * Gives access to the inner list if you need to make more than simple additions via {@link #notBeanPackages(String...)}. 2732 * 2733 * @return The list of not-bean Java package names. 2734 * @see #notBeanPackages(String...) 2735 */ 2736 public Set<String> notBeanPackages() { 2737 if (notBeanPackages == null) 2738 notBeanPackages = new TreeSet<>(); 2739 return notBeanPackages; 2740 } 2741 2742 /** 2743 * Bean property namer 2744 * 2745 * <p> 2746 * The class to use for calculating bean property names. 2747 * 2748 * <p> 2749 * Predefined classes: 2750 * <ul> 2751 * <li>{@link BasicPropertyNamer} - Default. 2752 * <li>{@link PropertyNamerDLC} - Dashed-lower-case names. 2753 * <li>{@link PropertyNamerULC} - Dashed-upper-case names. 2754 * </ul> 2755 * 2756 * <h5 class='section'>Example:</h5> 2757 * <p class='bjava'> 2758 * <jc>// A bean with a single property.</jc> 2759 * <jk>public class</jk> MyBean { 2760 * <jk>public</jk> String <jf>fooBarBaz</jf> = <js>"fooBarBaz"</js>; 2761 * } 2762 * 2763 * <jc>// Create a serializer that uses Dashed-Lower-Case property names.</jc> 2764 * <jc>// (e.g. "foo-bar-baz" instead of "fooBarBaz")</jc> 2765 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2766 * .<jsm>create</jsm>() 2767 * .propertyNamer(PropertyNamerDLC.<jk>class</jk>) 2768 * .build(); 2769 * 2770 * <jc>// Produces: {"foo-bar-baz":"fooBarBaz"}</jc> 2771 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2772 * </p> 2773 * 2774 * @param value 2775 * The new value for this setting. 2776 * <br>The default is {@link BasicPropertyNamer}. 2777 * @return This object. 2778 */ 2779 @FluentSetter 2780 public Builder propertyNamer(Class<? extends PropertyNamer> value) { 2781 propertyNamer = value; 2782 return this; 2783 } 2784 2785 /** 2786 * Bean property namer 2787 * 2788 * <p> 2789 * Same as {@link #propertyNamer(Class)} but allows you to specify a namer for a specific class. 2790 * 2791 * <h5 class='section'>Example:</h5> 2792 * <p class='bjava'> 2793 * <jc>// A bean with a single property.</jc> 2794 * <jk>public class</jk> MyBean { 2795 * <jk>public</jk> String <jf>fooBarBaz</jf> = <js>"fooBarBaz"</js>; 2796 * } 2797 * 2798 * <jc>// Create a serializer that uses Dashed-Lower-Case property names for the MyBean class only.</jc> 2799 * <jc>// (e.g. "foo-bar-baz" instead of "fooBarBaz")</jc> 2800 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2801 * .<jsm>create</jsm>() 2802 * .propertyNamer(MyBean.<jk>class</jk>, PropertyNamerDLC.<jk>class</jk>) 2803 * .build(); 2804 * 2805 * <jc>// Produces: {"foo-bar-baz":"fooBarBaz"}</jc> 2806 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2807 * </p> 2808 * 2809 * <h5 class='section'>See Also:</h5><ul> 2810 * <li class='ja'>{@link Bean#propertyNamer() Bean(propertyNamer)} 2811 * <li class='jm'>{@link #propertyNamer(Class)} 2812 * </ul> 2813 * 2814 * @param on The class that the namer applies to. 2815 * @param value 2816 * The new value for this setting. 2817 * <br>The default is {@link BasicPropertyNamer}. 2818 * @return This object. 2819 */ 2820 @FluentSetter 2821 public Builder propertyNamer(Class<?> on, Class<? extends PropertyNamer> value) { 2822 return annotations(BeanAnnotation.create(on).propertyNamer(value).build()); 2823 } 2824 2825 /** 2826 * Sort bean properties. 2827 * 2828 * <p> 2829 * When enabled, all bean properties will be serialized and access in alphabetical order. 2830 * Otherwise, the natural order of the bean properties is used which is dependent on the JVM vendor. 2831 * On IBM JVMs, the bean properties are ordered based on their ordering in the Java file. 2832 * On Oracle JVMs, the bean properties are not ordered (which follows the official JVM specs). 2833 * 2834 * <p> 2835 * this setting is disabled by default so that IBM JVM users don't have to use {@link Bean @Bean} annotations 2836 * to force bean properties to be in a particular order and can just alter the order of the fields/methods 2837 * in the Java file. 2838 * 2839 * <h5 class='section'>Example:</h5> 2840 * <p class='bjava'> 2841 * <jc>// A bean with 3 properties.</jc> 2842 * <jk>public class</jk> MyBean { 2843 * <jk>public</jk> String <jf>c</jf> = <js>"1"</js>; 2844 * <jk>public</jk> String <jf>b</jf> = <js>"2"</js>; 2845 * <jk>public</jk> String <jf>a</jf> = <js>"3"</js>; 2846 * } 2847 * 2848 * <jc>// Create a serializer that sorts bean properties.</jc> 2849 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2850 * .<jsm>create</jsm>() 2851 * .sortProperties() 2852 * .build(); 2853 * 2854 * <jc>// Produces: {"a":"3","b":"2","c":"1"}</jc> 2855 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2856 * </p> 2857 * 2858 * <h5 class='section'>Notes:</h5><ul> 2859 * <li class='note'>The {@link Bean#sort() @Bean.sort()} annotation can also be used to sort properties on just a single class. 2860 * </ul> 2861 * 2862 * @return This object. 2863 */ 2864 @FluentSetter 2865 public Builder sortProperties() { 2866 sortProperties = true; 2867 return sortProperties(true); 2868 } 2869 2870 /** 2871 * Same as {@link #sortProperties()} but allows you to explicitly specify the value. 2872 * 2873 * @param value The value for this setting. 2874 * @return This object. 2875 */ 2876 @FluentSetter 2877 public Builder sortProperties(boolean value) { 2878 sortProperties = value; 2879 return this; 2880 } 2881 2882 /** 2883 * Sort bean properties. 2884 * 2885 * <p> 2886 * Same as {@link #sortProperties()} but allows you to specify individual bean classes instead of globally. 2887 * 2888 * <h5 class='section'>Example:</h5> 2889 * <p class='bjava'> 2890 * <jc>// A bean with 3 properties.</jc> 2891 * <jk>public class</jk> MyBean { 2892 * <jk>public</jk> String <jf>c</jf> = <js>"1"</js>; 2893 * <jk>public</jk> String <jf>b</jf> = <js>"2"</js>; 2894 * <jk>public</jk> String <jf>a</jf> = <js>"3"</js>; 2895 * } 2896 * 2897 * <jc>// Create a serializer that sorts properties on MyBean.</jc> 2898 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2899 * .<jsm>create</jsm>() 2900 * .sortProperties(MyBean.<jk>class</jk>) 2901 * .build(); 2902 * 2903 * <jc>// Produces: {"a":"3","b":"2","c":"1"}</jc> 2904 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 2905 * </p> 2906 * 2907 * <h5 class='section'>See Also:</h5><ul> 2908 * <li class='ja'>{@link Bean#sort() Bean(sort)} 2909 * <li class='jm'>{@link #sortProperties()} 2910 * </ul> 2911 * 2912 * @param on The bean classes to sort properties on. 2913 * @return This object. 2914 */ 2915 @FluentSetter 2916 public Builder sortProperties(Class<?>...on) { 2917 for (Class<?> c : on) 2918 annotations(BeanAnnotation.create(c).sort(true).build()); 2919 return this; 2920 } 2921 2922 /** 2923 * Identifies a stop class for the annotated class. 2924 * 2925 * <p> 2926 * Identical in purpose to the stop class specified by {@link Introspector#getBeanInfo(Class, Class)}. 2927 * Any properties in the stop class or in its base classes will be ignored during analysis. 2928 * 2929 * <p> 2930 * For example, in the following class hierarchy, instances of <c>C3</c> will include property <c>p3</c>, 2931 * but not <c>p1</c> or <c>p2</c>. 2932 * 2933 * <h5 class='section'>Example:</h5> 2934 * <p class='bjava'> 2935 * <jk>public class</jk> C1 { 2936 * <jk>public int</jk> getP1(); 2937 * } 2938 * 2939 * <jk>public class</jk> C2 <jk>extends</jk> C1 { 2940 * <jk>public int</jk> getP2(); 2941 * } 2942 * 2943 * <jk>public class</jk> C3 <jk>extends</jk> C2 { 2944 * <jk>public int</jk> getP3(); 2945 * } 2946 * 2947 * <jc>// Create a serializer specifies a stop class for C3.</jc> 2948 * WriterSerializer <jv>serializer</jv> = JsonSerializer 2949 * .<jsm>create</jsm>() 2950 * .stopClass(C3.<jk>class</jk>, C2.<jk>class</jk>) 2951 * .build(); 2952 * 2953 * <jc>// Produces: {"p3":"..."}</jc> 2954 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> C3()); 2955 * </p> 2956 * 2957 * @param on The class on which the stop class is being applied. 2958 * @param value 2959 * The new value for this setting. 2960 * @return This object. 2961 */ 2962 @FluentSetter 2963 public Builder stopClass(Class<?> on, Class<?> value) { 2964 return annotations(BeanAnnotation.create(on).stopClass(value).build()); 2965 } 2966 2967 /** 2968 * Java object swaps. 2969 * 2970 * <p> 2971 * Swaps are used to "swap out" non-serializable classes with serializable equivalents during serialization, 2972 * and "swap in" the non-serializable class during parsing. 2973 * 2974 * <p> 2975 * An example of a swap would be a <c>Calendar</c> object that gets swapped out for an ISO8601 string. 2976 * 2977 * <p> 2978 * Multiple swaps can be associated with a single class. 2979 * When multiple swaps are applicable to the same class, the media type pattern defined by 2980 * {@link ObjectSwap#forMediaTypes()} or {@link Swap#mediaTypes() @Swap(mediaTypes)} are used to come up with the best match. 2981 * 2982 * <p> 2983 * Values can consist of any of the following types: 2984 * <ul> 2985 * <li>Any subclass of {@link ObjectSwap}. 2986 * <li>Any instance of {@link ObjectSwap}. 2987 * <li>Any surrogate class. A shortcut for defining a {@link SurrogateSwap}. 2988 * <li>Any array or collection of the objects above. 2989 * </ul> 2990 * 2991 * <h5 class='section'>Example:</h5> 2992 * <p class='bjava'> 2993 * <jc>// Sample swap for converting Dates to ISO8601 strings.</jc> 2994 * <jk>public class</jk> MyDateSwap <jk>extends</jk> StringSwap<Date> { 2995 * <jc>// ISO8601 formatter.</jc> 2996 * <jk>private</jk> DateFormat <jf>format</jf> = <jk>new</jk> SimpleDateFormat(<js>"yyyy-MM-dd'T'HH:mm:ssZ"</js>); 2997 * 2998 * <ja>@Override</ja> 2999 * <jk>public</jk> String swap(BeanSession <jv>session</jv>, Date <jv>date</jv>) { 3000 * <jk>return</jk> <jf>format</jf>.format(<jv>date</jv>); 3001 * } 3002 * 3003 * <ja>@Override</ja> 3004 * <jk>public</jk> Date unswap(BeanSession <jv>session</jv>, String <jv>string</jv>, ClassMeta <jv>hint</jv>) <jk>throws</jk> Exception { 3005 * <jk>return</jk> <jf>format</jf>.parse(<jv>string</jv>); 3006 * } 3007 * } 3008 * 3009 * <jc>// Sample bean with a Date field.</jc> 3010 * <jk>public class</jk> MyBean { 3011 * <jk>public</jk> Date <jf>date</jf> = <jk>new</jk> Date(112, 2, 3, 4, 5, 6); 3012 * } 3013 * 3014 * <jc>// Create a serializer that uses our date swap.</jc> 3015 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3016 * .<jsm>create</jsm>() 3017 * .swaps(MyDateSwap.<jk>class</jk>) 3018 * .build(); 3019 * 3020 * <jc>// Produces: {"date":"2012-03-03T04:05:06-0500"}</jc> 3021 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 3022 * 3023 * <jc>// Create a serializer that uses our date swap.</jc> 3024 * ReaderParser <jv>parser</jv> = JsonParser 3025 * .<jsm>create</jsm>() 3026 * .swaps(MyDateSwap.<jk>class</jk>) 3027 * .build(); 3028 * 3029 * <jc>// Use our parser to parse a bean.</jc> 3030 * MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>); 3031 * </p> 3032 * 3033 * <h5 class='section'>Notes:</h5><ul> 3034 * <li class='note'>The {@link Swap @Swap} annotation can also be used on classes to identify swaps for the class. 3035 * <li class='note'>The {@link Swap @Swap} annotation can also be used on bean methods and fields to identify swaps for values of those bean properties. 3036 * </ul> 3037 * 3038 * @param values 3039 * The values to add to this setting. 3040 * <br>Values can consist of any of the following types: 3041 * <ul> 3042 * <li>Any subclass of {@link ObjectSwap}. 3043 * <li>Any surrogate class. A shortcut for defining a {@link SurrogateSwap}. 3044 * <li>Any array or collection of the objects above. 3045 * </ul> 3046 * @return This object. 3047 */ 3048 @FluentSetter 3049 public Builder swaps(Class<?>...values) { 3050 return swaps(alist(values)); 3051 } 3052 3053 /** 3054 * Same as {@link #swaps(Class...)} but allows you to pass in a collection of classes. 3055 * 3056 * @param values 3057 * The values to add to this setting. 3058 * @return This object. 3059 * @see #swaps(Class...) 3060 */ 3061 @FluentSetter 3062 public Builder swaps(Collection<Class<?>> values) { 3063 swaps().addAll(0, values); 3064 return this; 3065 } 3066 3067 /** 3068 * A shortcut for defining a {@link FunctionalSwap}. 3069 * 3070 * <h5 class='section'>Example:</h5> 3071 * <p class='bjava'> 3072 * <jc>// Create a serializer that performs a custom format for DAte objects.</jc> 3073 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3074 * .<jsm>create</jsm>() 3075 * .swap(Date.<jk>class</jk>, String.<jk>class</jk>, <jv>x</jv> -> <jsm>format</jsm>(<jv>x</jv>)) 3076 * .build(); 3077 * </p> 3078 * 3079 * @param <T> The object type being swapped out. 3080 * @param <S> The object type being swapped in. 3081 * @param normalClass The object type being swapped out. 3082 * @param swappedClass The object type being swapped in. 3083 * @param swapFunction The function to convert the object. 3084 * @return This object. 3085 */ 3086 @FluentSetter 3087 public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) { 3088 return swap(normalClass, swappedClass, swapFunction, null); 3089 } 3090 3091 /** 3092 * A shortcut for defining a {@link FunctionalSwap}. 3093 * 3094 * <h5 class='section'>Example:</h5> 3095 * <p class='bjava'> 3096 * <jc>// Create a serializer that performs a custom format for Date objects.</jc> 3097 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3098 * .<jsm>create</jsm>() 3099 * .swap(Date.<jk>class</jk>, String.<jk>class</jk>, <jv>x</jv> -> <jsm>format</jsm>(<jv>x</jv>), <jv>x</jv> -> <jsm>parse</jsm>(<jv>x</jv>)) 3100 * .build(); 3101 * </p> 3102 * 3103 * @param <T> The object type being swapped out. 3104 * @param <S> The object type being swapped in. 3105 * @param normalClass The object type being swapped out. 3106 * @param swappedClass The object type being swapped in. 3107 * @param swapFunction The function to convert the object during serialization. 3108 * @param unswapFunction The function to convert the object during parsing. 3109 * @return This object. 3110 */ 3111 @FluentSetter 3112 public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) { 3113 swaps().add(0, new FunctionalSwap<>(normalClass, swappedClass, swapFunction, unswapFunction)); 3114 return this; 3115 } 3116 3117 /** 3118 * Returns the bean swaps list. 3119 * 3120 * <p> 3121 * Gives access to the inner list if you need to make more than simple additions via {@link #swaps(Class...)}. 3122 * 3123 * @return The bean swaps list. 3124 * @see #swaps(Class...) 3125 */ 3126 public List<Object> swaps() { 3127 if (swaps == null) 3128 swaps = list(); 3129 return swaps; 3130 } 3131 3132 /** 3133 * <i><l>Context</l> configuration property: </i> TimeZone. 3134 * 3135 * <p> 3136 * Specifies the default time zone for serializer and parser sessions when not specified via {@link BeanSession.Builder#timeZone(TimeZone)}. 3137 * Typically used for POJO swaps that need to deal with timezones such as swaps that convert <l>Date</l> and <l>Calendar</l> 3138 * objects to strings by accessing it via the session passed into the {@link ObjectSwap#swap(BeanSession, Object)} and 3139 * {@link ObjectSwap#unswap(BeanSession, Object, ClassMeta, String)} methods. 3140 * 3141 * <h5 class='section'>Example:</h5> 3142 * <p class='bjava'> 3143 * <jc>// Define a POJO swap that skips serializing beans if the time zone is GMT.</jc> 3144 * <jk>public class</jk> MyBeanSwap <jk>extends</jk> StringSwap<MyBean> { 3145 * <ja>@Override</ja> 3146 * <jk>public</jk> String swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) <jk>throws</jk> Exception { 3147 * <jk>if</jk> (<jv>session</jv>.getTimeZone().equals(TimeZone.<jsf>GMT</jsf>)) 3148 * <jk>return null</jk>; 3149 * <jk>return</jk> <jv>bean</jv>.toString(); 3150 * } 3151 * } 3152 * 3153 * <jc>// Create a serializer that uses GMT if the timezone is not specified in the session args.</jc> 3154 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3155 * .<jsm>create</jsm>() 3156 * .timeZone(TimeZone.<jsf>GMT</jsf>) 3157 * .build(); 3158 * </p> 3159 * 3160 * <h5 class='section'>See Also:</h5><ul> 3161 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#timeZone()} 3162 * <li class='jm'>{@link org.apache.juneau.BeanSession.Builder#timeZone(TimeZone)} 3163 * </ul> 3164 * 3165 * @param value The new value for this property. 3166 * @return This object. 3167 */ 3168 @FluentSetter 3169 public Builder timeZone(TimeZone value) { 3170 timeZone = value; 3171 return this; 3172 } 3173 3174 /** 3175 * An identifying name for this class. 3176 * 3177 * <p> 3178 * The name is used to identify the class type during parsing when it cannot be inferred through reflection. 3179 * For example, if a bean property is of type <c>Object</c>, then the serializer will add the name to the 3180 * output so that the class can be determined during parsing. 3181 * 3182 * <p> 3183 * It is also used to specify element names in XML. 3184 * 3185 * <h5 class='section'>Example:</h5> 3186 * <p class='bjava'> 3187 * <jc>// Use _type='mybean' to identify this bean.</jc> 3188 * <jk>public class</jk> MyBean {...} 3189 * 3190 * <jc>// Create a serializer and specify the type name..</jc> 3191 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3192 * .<jsm>create</jsm>() 3193 * .typeName(MyBean.<jk>class</jk>, <js>"mybean"</js>) 3194 * .build(); 3195 * 3196 * <jc>// Produces: {"_type":"mybean",...}</jc> 3197 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 3198 * </p> 3199 * 3200 * <h5 class='section'>Notes:</h5><ul> 3201 * <li class='note'>Equivalent to the {@link Bean#typeName() Bean(typeName)} annotation. 3202 * </ul> 3203 * 3204 * <h5 class='section'>See Also:</h5><ul> 3205 * <li class='jc'>{@link Bean#typeName() Bean(typeName)} 3206 * <li class='jm'>{@link #beanDictionary(Class...)} 3207 * </ul> 3208 * 3209 * @param on 3210 * The class the type name is being defined on. 3211 * @param value 3212 * The new value for this setting. 3213 * @return This object. 3214 */ 3215 @FluentSetter 3216 public Builder typeName(Class<?> on, String value) { 3217 return annotations(BeanAnnotation.create(on).typeName(value).build()); 3218 } 3219 3220 /** 3221 * Bean type property name. 3222 * 3223 * <p> 3224 * This specifies the name of the bean property used to store the dictionary name of a bean type so that the 3225 * parser knows the data type to reconstruct. 3226 * 3227 * <h5 class='section'>Example:</h5> 3228 * <p class='bjava'> 3229 * <jc>// POJOs with @Bean(name) annotations.</jc> 3230 * <ja>@Bean</ja>(typeName=<js>"foo"</js>) 3231 * <jk>public class</jk> Foo {...} 3232 * <ja>@Bean</ja>(typeName=<js>"bar"</js>) 3233 * <jk>public class</jk> Bar {...} 3234 * 3235 * <jc>// Create a serializer that uses 't' instead of '_type' for dictionary names.</jc> 3236 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3237 * .<jsm>create</jsm>() 3238 * .typePropertyName(<js>"t"</js>) 3239 * .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>) 3240 * .build(); 3241 * 3242 * <jc>// Create a serializer that uses 't' instead of '_type' for dictionary names.</jc> 3243 * ReaderParser <jv>parser</jv> = JsonParser 3244 * .<jsm>create</jsm>() 3245 * .typePropertyName(<js>"t"</js>) 3246 * .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>) 3247 * .build(); 3248 * 3249 * <jc>// A bean with a field with an indeterminate type.</jc> 3250 * <jk>public class</jk> MyBean { 3251 * <jk>public</jk> Object <jf>mySimpleField</jf>; 3252 * } 3253 * 3254 * <jc>// Produces "{mySimpleField:{t:'foo',...}}".</jc> 3255 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 3256 * 3257 * <jc>// Parse bean.</jc> 3258 * MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>); 3259 * </p> 3260 * 3261 * <h5 class='section'>See Also:</h5><ul> 3262 * <li class='ja'>{@link org.apache.juneau.annotation.Bean#typePropertyName()} 3263 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#typePropertyName()} 3264 * </ul> 3265 * 3266 * @param value 3267 * The new value for this setting. 3268 * <br>The default is <js>"_type"</js>. 3269 * @return This object. 3270 */ 3271 @FluentSetter 3272 public Builder typePropertyName(String value) { 3273 typePropertyName = value; 3274 return this; 3275 } 3276 3277 /** 3278 * Bean type property name. 3279 * 3280 * <p> 3281 * Same as {@link #typePropertyName(String)} except targets a specific bean class instead of globally. 3282 * 3283 * <h5 class='section'>Example:</h5> 3284 * <p class='bjava'> 3285 * <jc>// POJOs with @Bean(name) annotations.</jc> 3286 * <ja>@Bean</ja>(typeName=<js>"foo"</js>) 3287 * <jk>public class</jk> Foo {...} 3288 * <ja>@Bean</ja>(typeName=<js>"bar"</js>) 3289 * <jk>public class</jk> Bar {...} 3290 * 3291 * <jc>// A bean with a field with an indeterminate type.</jc> 3292 * <jk>public class</jk> MyBean { 3293 * <jk>public</jk> Object <jf>mySimpleField</jf>; 3294 * } 3295 * 3296 * <jc>// Create a serializer that uses 't' instead of '_type' for dictionary names.</jc> 3297 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3298 * .<jsm>create</jsm>() 3299 * .typePropertyName(MyBean.<jk>class</jk>, <js>"t"</js>) 3300 * .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>) 3301 * .build(); 3302 * 3303 * <jc>// Produces "{mySimpleField:{t:'foo',...}}".</jc> 3304 * String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean()); 3305 * </p> 3306 * 3307 * <h5 class='section'>See Also:</h5><ul> 3308 * <li class='ja'>{@link Bean#typePropertyName() Bean(typePropertyName)} 3309 * </ul> 3310 * 3311 * @param on The class the type property name applies to. 3312 * @param value 3313 * The new value for this setting. 3314 * <br>The default is <js>"_type"</js>. 3315 * @return This object. 3316 */ 3317 @FluentSetter 3318 public Builder typePropertyName(Class<?> on, String value) { 3319 return annotations(BeanAnnotation.create(on).typePropertyName(value).build()); 3320 } 3321 3322 /** 3323 * Use enum names. 3324 * 3325 * <p> 3326 * When enabled, enums are always serialized by name, not using {@link Object#toString()}. 3327 * 3328 * <h5 class='section'>Example:</h5> 3329 * <p class='bjava'> 3330 * <jc>// Create a serializer with debug enabled.</jc> 3331 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3332 * .<jsm>create</jsm>() 3333 * .useEnumNames() 3334 * .build(); 3335 * 3336 * <jc>// Enum with overridden toString().</jc> 3337 * <jc>// Will be serialized as ONE/TWO/THREE even though there's a toString() method.</jc> 3338 * <jk>public enum</jk> Option { 3339 * <jsf>ONE</jsf>(1), 3340 * <jsf>TWO</jsf>(2), 3341 * <jsf>THREE</jsf>(3); 3342 * 3343 * <jk>private int</jk> <jf>value</jf>; 3344 * 3345 * Option(<jk>int</jk> <jv>value</jv>) { 3346 * <jk>this</jk>.<jf>value</jf> = <jv>value</jv>; 3347 * } 3348 * 3349 * <ja>@Override</ja> 3350 * <jk>public</jk> String toString() { 3351 * <jk>return</jk> String.<jsm>valueOf</jsm>(<jf>value</jf>); 3352 * } 3353 * } 3354 * </p> 3355 * 3356 * @return This object. 3357 */ 3358 @FluentSetter 3359 public Builder useEnumNames() { 3360 return useEnumNames(true); 3361 } 3362 3363 /** 3364 * Same as {@link #useEnumNames()} but allows you to explicitly specify the value. 3365 * 3366 * @param value The value for this setting. 3367 * @return This object. 3368 */ 3369 @FluentSetter 3370 public Builder useEnumNames(boolean value) { 3371 useEnumNames = value; 3372 return this; 3373 } 3374 3375 /** 3376 * Don't use interface proxies. 3377 * 3378 * <p> 3379 * When enabled, interfaces will be instantiated as proxy classes through the use of an 3380 * {@link InvocationHandler} if there is no other way of instantiating them. 3381 * Otherwise, throws a {@link BeanRuntimeException}. 3382 * 3383 * <h5 class='section'>See Also:</h5><ul> 3384 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableInterfaceProxies()} 3385 * </ul> 3386 * 3387 * @return This object. 3388 */ 3389 @FluentSetter 3390 public Builder disableInterfaceProxies() { 3391 return disableInterfaceProxies(true); 3392 } 3393 3394 /** 3395 * Same as {@link #disableInterfaceProxies()} but allows you to explicitly specify the value. 3396 * 3397 * @param value The value for this setting. 3398 * @return This object. 3399 */ 3400 @FluentSetter 3401 public Builder disableInterfaceProxies(boolean value) { 3402 disableInterfaceProxies = value; 3403 return this; 3404 } 3405 3406 /** 3407 * Use Java Introspector. 3408 * 3409 * <p> 3410 * Using the built-in Java bean introspector will not pick up fields or non-standard getters/setters. 3411 * <br>Most {@link Bean @Bean} annotations will be ignored. 3412 * 3413 * <h5 class='section'>Example:</h5> 3414 * <p class='bjava'> 3415 * <jc>// Create a serializer that only uses the built-in java bean introspector for finding properties.</jc> 3416 * WriterSerializer <jv>serializer</jv> = JsonSerializer 3417 * .<jsm>create</jsm>() 3418 * .useJavaBeanIntrospector() 3419 * .build(); 3420 * </p> 3421 * 3422 * @return This object. 3423 */ 3424 @FluentSetter 3425 public Builder useJavaBeanIntrospector() { 3426 return useJavaBeanIntrospector(true); 3427 } 3428 3429 /** 3430 * Same as {@link #useJavaBeanIntrospector()} but allows you to explicitly specify the value. 3431 * 3432 * @param value The value for this setting. 3433 * @return This object. 3434 */ 3435 @FluentSetter 3436 public Builder useJavaBeanIntrospector(boolean value) { 3437 useJavaBeanIntrospector = value; 3438 return this; 3439 } 3440 3441 // <FluentSetters> 3442 3443 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3444 public Builder annotations(Annotation...values) { 3445 super.annotations(values); 3446 return this; 3447 } 3448 3449 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3450 public Builder apply(AnnotationWorkList work) { 3451 super.apply(work); 3452 return this; 3453 } 3454 3455 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3456 public Builder applyAnnotations(java.lang.Class<?>...fromClasses) { 3457 super.applyAnnotations(fromClasses); 3458 return this; 3459 } 3460 3461 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3462 public Builder applyAnnotations(Method...fromMethods) { 3463 super.applyAnnotations(fromMethods); 3464 return this; 3465 } 3466 3467 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3468 public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) { 3469 super.cache(value); 3470 return this; 3471 } 3472 3473 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3474 public Builder debug() { 3475 super.debug(); 3476 return this; 3477 } 3478 3479 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3480 public Builder debug(boolean value) { 3481 super.debug(value); 3482 return this; 3483 } 3484 3485 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3486 public Builder impl(Context value) { 3487 super.impl(value); 3488 return this; 3489 } 3490 3491 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 3492 public Builder type(Class<? extends org.apache.juneau.Context> value) { 3493 super.type(value); 3494 return this; 3495 } 3496 3497 // </FluentSetters> 3498 3499 //----------------------------------------------------------------------------------------------------------------- 3500 // Helpers 3501 //----------------------------------------------------------------------------------------------------------------- 3502 3503 private static Set<Class<?>> classSet() { 3504 return new TreeSet<>(Comparator.comparing(Class::getName)); 3505 } 3506 3507 private static Set<Class<?>> classSet(Collection<Class<?>> copy) { 3508 return classSet(copy, false); 3509 } 3510 3511 private static Set<Class<?>> classSet(Collection<Class<?>> copy, boolean nullIfEmpty) { 3512 if (copy == null || (nullIfEmpty && copy.isEmpty())) 3513 return null; 3514 Set<Class<?>> x = classSet(); 3515 x.addAll(copy); 3516 return x; 3517 } 3518 } 3519 3520 //----------------------------------------------------------------------------------------------------------------- 3521 // Instance 3522 //----------------------------------------------------------------------------------------------------------------- 3523 3524 final boolean 3525 beansRequireDefaultConstructor, 3526 beansRequireSerializable, 3527 beansRequireSettersForGetters, 3528 beansRequireSomeProperties, 3529 beanMapPutReturnsOldValue, 3530 useInterfaceProxies, 3531 ignoreUnknownBeanProperties, 3532 ignoreUnknownNullBeanProperties, 3533 ignoreUnknownEnumValues, 3534 ignoreMissingSetters, 3535 ignoreTransientFields, 3536 ignoreInvocationExceptionsOnGetters, 3537 ignoreInvocationExceptionsOnSetters, 3538 useJavaBeanIntrospector, 3539 useEnumNames, 3540 sortProperties, 3541 findFluentSetters; 3542 final Visibility 3543 beanConstructorVisibility, 3544 beanClassVisibility, 3545 beanMethodVisibility, 3546 beanFieldVisibility; 3547 final String typePropertyName; 3548 final Locale locale; 3549 final TimeZone timeZone; 3550 final MediaType mediaType; 3551 final Class<? extends PropertyNamer> propertyNamer; 3552 final List<Class<?>> beanDictionary, notBeanClasses; 3553 final List<Object> swaps; 3554 final List<String> notBeanPackages; 3555 final HashKey hashKey; 3556 3557 final Map<Class,ClassMeta> cmCache; 3558 3559 private final String[] notBeanPackageNames, notBeanPackagePrefixes; 3560 private final BeanRegistry beanRegistry; 3561 private final PropertyNamer propertyNamerBean; 3562 private final ObjectSwap[] swapArray; 3563 private final Class<?>[] notBeanClassesArray; 3564 private final ClassMeta<Object> cmObject; // Reusable ClassMeta that represents general Objects. 3565 private final ClassMeta<String> cmString; // Reusable ClassMeta that represents general Strings. 3566 private final ClassMeta<Class> cmClass; // Reusable ClassMeta that represents general Classes. 3567 3568 private final BeanSession defaultSession; 3569 private volatile WriterSerializer beanToStringSerializer; 3570 3571 /** 3572 * Constructor. 3573 * 3574 * @param builder The builder for this object. 3575 */ 3576 public BeanContext(Builder builder) { 3577 super(builder); 3578 3579 hashKey = builder.hashKey(); 3580 3581 beanConstructorVisibility = builder.beanConstructorVisibility; 3582 beanClassVisibility = builder.beanClassVisibility; 3583 beanMethodVisibility = builder.beanMethodVisibility; 3584 beanFieldVisibility = builder.beanFieldVisibility; 3585 beansRequireDefaultConstructor = builder.beansRequireDefaultConstructor; 3586 beansRequireSerializable = builder.beansRequireSerializable; 3587 beansRequireSettersForGetters = builder.beansRequireSettersForGetters; 3588 beansRequireSomeProperties = ! builder.disableBeansRequireSomeProperties; 3589 beanMapPutReturnsOldValue = builder.beanMapPutReturnsOldValue; 3590 useEnumNames = builder.useEnumNames; 3591 useInterfaceProxies = ! builder.disableInterfaceProxies; 3592 ignoreUnknownBeanProperties = builder.ignoreUnknownBeanProperties; 3593 ignoreUnknownNullBeanProperties = ! builder.disableIgnoreUnknownNullBeanProperties; 3594 ignoreUnknownEnumValues = builder.ignoreUnknownEnumValues; 3595 ignoreMissingSetters = ! builder.disableIgnoreMissingSetters; 3596 ignoreTransientFields = ! builder.disableIgnoreTransientFields; 3597 ignoreInvocationExceptionsOnGetters = builder.ignoreInvocationExceptionsOnGetters; 3598 ignoreInvocationExceptionsOnSetters = builder.ignoreInvocationExceptionsOnSetters; 3599 useJavaBeanIntrospector = builder.useJavaBeanIntrospector; 3600 sortProperties = builder.sortProperties; 3601 findFluentSetters = builder.findFluentSetters; 3602 typePropertyName = builder.typePropertyName != null ? builder.typePropertyName : "_type"; 3603 locale = builder.locale != null ? builder.locale : Locale.getDefault(); 3604 timeZone = builder.timeZone; 3605 mediaType = builder.mediaType; 3606 beanDictionary = optional(builder.beanDictionary).map(Collections::unmodifiableList).orElse(emptyList()); 3607 swaps = optional(builder.swaps).map(Collections::unmodifiableList).orElse(emptyList()); 3608 notBeanClasses = optional(builder.notBeanClasses).map(ArrayList::new).map(Collections::unmodifiableList).orElse(emptyList()); 3609 notBeanPackages = optional(builder.notBeanPackages).map(ArrayList::new).map(Collections::unmodifiableList).orElse(emptyList()); 3610 propertyNamer = builder.propertyNamer != null ? builder.propertyNamer : BasicPropertyNamer.class; 3611 3612 notBeanClassesArray = notBeanClasses.isEmpty() ? DEFAULT_NOTBEAN_CLASSES : Stream.of(notBeanClasses, alist(DEFAULT_NOTBEAN_CLASSES)).flatMap(Collection::stream).toArray(Class[]::new); 3613 3614 String[] _notBeanPackages = notBeanPackages.isEmpty() ? DEFAULT_NOTBEAN_PACKAGES : Stream.of(notBeanPackages, alist(DEFAULT_NOTBEAN_PACKAGES)).flatMap(Collection::stream).toArray(String[]::new); 3615 notBeanPackageNames = Stream.of(_notBeanPackages).filter(x -> ! x.endsWith(".*")).toArray(String[]::new); 3616 notBeanPackagePrefixes = Stream.of(_notBeanPackages).filter(x -> x.endsWith(".*")).map(x -> x.substring(0, x.length()-2)).toArray(String[]::new); 3617 3618 try { 3619 propertyNamerBean = propertyNamer.getDeclaredConstructor().newInstance(); 3620 } catch (Exception e) { 3621 throw asRuntimeException(e); 3622 } 3623 3624 LinkedList<ObjectSwap<?,?>> _swaps = new LinkedList<>(); 3625 swaps.forEach(x -> { 3626 if (x instanceof ObjectSwap) { 3627 _swaps.add((ObjectSwap<?,?>)x); 3628 } else { 3629 ClassInfo ci = ClassInfo.of((Class<?>)x); 3630 if (ci.isChildOf(ObjectSwap.class)) 3631 _swaps.add(BeanCreator.of(ObjectSwap.class).type(ci).run()); 3632 else if (ci.isChildOf(Surrogate.class)) 3633 _swaps.addAll(SurrogateSwap.findObjectSwaps(ci.inner(), this)); 3634 else 3635 throw new BasicRuntimeException("Invalid class {0} specified in BeanContext.swaps property. Must be a subclass of ObjectSwap or Surrogate.", ci.inner()); 3636 } 3637 }); 3638 swapArray = _swaps.toArray(new ObjectSwap[_swaps.size()]); 3639 3640 cmCache = new ConcurrentHashMap<>(); 3641 cmCache.put(String.class, new ClassMeta(String.class, this, findObjectSwaps(String.class), findChildObjectSwaps(String.class))); 3642 cmCache.put(Object.class, new ClassMeta(Object.class, this, findObjectSwaps(Object.class), findChildObjectSwaps(Object.class))); 3643 cmString = cmCache.get(String.class); 3644 cmObject = cmCache.get(Object.class); 3645 cmClass = cmCache.get(Class.class); 3646 3647 beanRegistry = new BeanRegistry(this, null); 3648 defaultSession = createSession().unmodifiable().build(); 3649 } 3650 3651 @Override /* Context */ 3652 public Builder copy() { 3653 return new Builder(this); 3654 } 3655 3656 @Override /* Context */ 3657 public BeanSession.Builder createSession() { 3658 return BeanSession.create(this); 3659 } 3660 3661 @Override /* Context */ 3662 public BeanSession getSession() { 3663 return defaultSession; 3664 } 3665 3666 /** 3667 * Returns <jk>true</jk> if the specified bean context shares the same cache as this bean context. 3668 * 3669 * <p> 3670 * Useful for testing purposes. 3671 * 3672 * @param bc The bean context to compare to. 3673 * @return <jk>true</jk> if the bean contexts have equivalent settings and thus share caches. 3674 */ 3675 public final boolean hasSameCache(BeanContext bc) { 3676 return bc.cmCache == this.cmCache; 3677 } 3678 3679 /** 3680 * Wraps an object inside a {@link BeanMap} object (a modifiable {@link Map}). 3681 * 3682 * <p> 3683 * This is a shortcut for the following code: <c>createSession().build().toBeanMap(<jv>object</jv>);</c> 3684 * 3685 * <h5 class='section'>Example:</h5> 3686 * <p class='bjava'> 3687 * <jc>// Construct a bean map around a bean instance</jc> 3688 * BeanMap<Person> <jv>beanMap</jv> = BeanContext.<jsf>DEFAULT</jsf>.toBeanMap(<jk>new</jk> Person()); 3689 * </p> 3690 * 3691 * @param <T> The class of the object being wrapped. 3692 * @param object The object to wrap in a map interface. Must not be null. 3693 * @return The wrapped object. 3694 * @see BeanSession#toBeanMap(Object) 3695 */ 3696 public <T> BeanMap<T> toBeanMap(T object) { 3697 return defaultSession.toBeanMap(object); 3698 } 3699 3700 /** 3701 * Creates a new {@link BeanMap} object (a modifiable {@link Map}) of the given class with uninitialized 3702 * property values. 3703 * 3704 * <p> 3705 * This is a shortcut for the following code: <c>createSession().build().newBeanMap(<jv>_class</jv>);</c> 3706 * 3707 * <h5 class='section'>Example:</h5> 3708 * <p class='bjava'> 3709 * <jc>// Construct a new bean map wrapped around a new Person object</jc> 3710 * BeanMap<Person> <jv>beanMap</jv> = BeanContext.<jsf>DEFAULT</jsf>.newBeanMap(Person.<jk>class</jk>); 3711 * </p> 3712 * 3713 * @param <T> The class of the object being wrapped. 3714 * @param c The name of the class to create a new instance of. 3715 * @return A new instance of the class. 3716 * @see BeanSession#newBeanMap(Class) 3717 */ 3718 public <T> BeanMap<T> newBeanMap(Class<T> c) { 3719 return defaultSession.newBeanMap(c); 3720 } 3721 3722 /** 3723 * Converts the specified value to the specified class type. 3724 * 3725 * <p> 3726 * This is a shortcut for the following code: <c>createSession().build().convertToType(<jv>value</jv>, <jv>type</jv>);</c> 3727 * 3728 * @param <T> The class type to convert the value to. 3729 * @param value The value to convert. 3730 * @param type The class type to convert the value to. 3731 * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. 3732 * @return The converted value. 3733 * @see BeanSession#convertToType(Object, Class) 3734 */ 3735 public final <T> T convertToType(Object value, Class<T> type) throws InvalidDataConversionException { 3736 return defaultSession.convertToType(value, type); 3737 } 3738 3739 /** 3740 * Same as {@link #convertToType(Object, Class)}, except used for instantiating inner member classes that must 3741 * be instantiated within another class instance. 3742 * 3743 * <p> 3744 * This is a shortcut for the following code: <c>createSession().build().convertToMemberType(<jv>outer</jv>, <jv>value</jv>, <jv>type</jv>);</c> 3745 * 3746 * @param <T> The class type to convert the value to. 3747 * @param outer 3748 * If class is a member class, this is the instance of the containing class. 3749 * Should be <jk>null</jk> if not a member class. 3750 * @param value The value to convert. 3751 * @param type The class type to convert the value to. 3752 * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. 3753 * @return The converted value. 3754 * @see BeanSession#convertToMemberType(Object, Object, Class) 3755 */ 3756 public final <T> T convertToMemberType(Object outer, Object value, Class<T> type) throws InvalidDataConversionException { 3757 return defaultSession.convertToMemberType(outer, value, getClassMeta(type)); 3758 } 3759 3760 /** 3761 * Same as {@link #convertToType(Object, Class)}, but allows for complex data types consisting of collections or maps. 3762 * 3763 * <p> 3764 * This is a shortcut for the following code: <c>createSession().build().convertToType(<jv>value</jv>, <jv>type</jv>, <jv>args</jv>);</c> 3765 * 3766 * @param <T> The class type to convert the value to. 3767 * @param value The value to be converted. 3768 * @param type The target object type. 3769 * @param args The target object parameter types. 3770 * @return The converted type. 3771 * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. 3772 * @see BeanSession#convertToType(Object, Type, Type...) 3773 */ 3774 public final <T> T convertToType(Object value, Type type, Type...args) throws InvalidDataConversionException { 3775 return (T)defaultSession.convertToMemberType(null, value, getClassMeta(type, args)); 3776 } 3777 3778 /** 3779 * Determines whether the specified class is ignored as a bean class based on the various exclusion parameters 3780 * specified on this context class. 3781 * 3782 * @param c The class type being tested. 3783 * @return <jk>true</jk> if the specified class matches any of the exclusion parameters. 3784 */ 3785 protected final boolean isNotABean(Class<?> c) { 3786 if (c.isArray() || c.isPrimitive() || c.isEnum() || c.isAnnotation()) 3787 return true; 3788 Package p = c.getPackage(); 3789 if (p != null) { 3790 for (String p2 : notBeanPackageNames) 3791 if (p.getName().equals(p2)) 3792 return true; 3793 for (String p2 : notBeanPackagePrefixes) 3794 if (p.getName().startsWith(p2)) 3795 return true; 3796 } 3797 ClassInfo ci = ClassInfo.of(c); 3798 for (Class exclude : notBeanClassesArray) 3799 if (ci.isChildOf(exclude)) 3800 return true; 3801 return false; 3802 } 3803 3804 /** 3805 * Returns <jk>true</jk> if the specified object is a bean. 3806 * 3807 * @param o The object to test. 3808 * @return <jk>true</jk> if the specified object is a bean. <jk>false</jk> if the bean is <jk>null</jk>. 3809 */ 3810 public boolean isBean(Object o) { 3811 if (o == null) 3812 return false; 3813 return getClassMetaForObject(o).isBean(); 3814 } 3815 3816 /** 3817 * Returns the {@link BeanMeta} class for the specified class. 3818 * 3819 * @param <T> The class type to get the meta-data on. 3820 * @param c The class to get the meta-data on. 3821 * @return 3822 * The {@link BeanMeta} for the specified class, or <jk>null</jk> if the class is not a bean per the settings on 3823 * this context. 3824 */ 3825 public final <T> BeanMeta<T> getBeanMeta(Class<T> c) { 3826 if (c == null) 3827 return null; 3828 return getClassMeta(c).getBeanMeta(); 3829 } 3830 3831 /** 3832 * Construct a {@code ClassMeta} wrapper around a {@link Class} object. 3833 * 3834 * @param <T> The class type being wrapped. 3835 * @param type The class to resolve. 3836 * @return 3837 * If the class is not an array, returns a cached {@link ClassMeta} object. 3838 * Otherwise, returns a new {@link ClassMeta} object every time. 3839 */ 3840 public final <T> ClassMeta<T> getClassMeta(Class<T> type) { 3841 return getClassMeta(type, true); 3842 } 3843 3844 /** 3845 * Construct a {@code ClassMeta} wrapper around a {@link Class} object. 3846 * 3847 * @param <T> The class type being wrapped. 3848 * @param type The class to resolve. 3849 * @param waitForInit 3850 * When enabled, wait for the ClassMeta constructor to finish before returning. 3851 * @return 3852 * If the class is not an array, returns a cached {@link ClassMeta} object. 3853 * Otherwise, returns a new {@link ClassMeta} object every time. 3854 */ 3855 final <T> ClassMeta<T> getClassMeta(Class<T> type, boolean waitForInit) { 3856 3857 // This can happen if we have transforms defined against String or Object. 3858 if (cmCache == null) 3859 return null; 3860 3861 ClassMeta<T> cm = cmCache.get(type); 3862 if (cm == null) { 3863 3864 synchronized (this) { 3865 // Make sure someone didn't already set it while this thread was blocked. 3866 cm = cmCache.get(type); 3867 if (cm == null) 3868 cm = new ClassMeta<>(type, this, findObjectSwaps(type), findChildObjectSwaps(type)); 3869 } 3870 } 3871 if (waitForInit) 3872 cm.waitForInit(); 3873 return cm; 3874 } 3875 3876 /** 3877 * Used to resolve <c>ClassMetas</c> of type <c>Collection</c> and <c>Map</c> that have 3878 * <c>ClassMeta</c> values that themselves could be collections or maps. 3879 * 3880 * <p> 3881 * <c>Collection</c> meta objects are assumed to be followed by zero or one meta objects indicating the element type. 3882 * 3883 * <p> 3884 * <c>Map</c> meta objects are assumed to be followed by zero or two meta objects indicating the key and value types. 3885 * 3886 * <p> 3887 * The array can be arbitrarily long to indicate arbitrarily complex data structures. 3888 * 3889 * <h5 class='section'>Examples:</h5> 3890 * <ul> 3891 * <li><code>getClassMeta(String.<jk>class</jk>);</code> - A normal type. 3892 * <li><code>getClassMeta(List.<jk>class</jk>);</code> - A list containing objects. 3893 * <li><code>getClassMeta(List.<jk>class</jk>, String.<jk>class</jk>);</code> - A list containing strings. 3894 * <li><code>getClassMeta(LinkedList.<jk>class</jk>, String.<jk>class</jk>);</code> - A linked-list containing 3895 * strings. 3896 * <li><code>getClassMeta(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);</code> - 3897 * A linked-list containing linked-lists of strings. 3898 * <li><code>getClassMeta(Map.<jk>class</jk>);</code> - A map containing object keys/values. 3899 * <li><code>getClassMeta(Map.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);</code> - A map 3900 * containing string keys/values. 3901 * <li><code>getClassMeta(Map.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);</code> - 3902 * A map containing string keys and values of lists containing beans. 3903 * </ul> 3904 * 3905 * @param <T> 3906 * The class to resolve. 3907 * @param type 3908 * The class to resolve. 3909 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 3910 * @param args 3911 * The type arguments of the class if it's a collection or map. 3912 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 3913 * <br>Ignored if the main type is not a map or collection. 3914 * @return The resolved class meta. 3915 */ 3916 public final <T> ClassMeta<T> getClassMeta(Type type, Type...args) { 3917 if (type == null) 3918 return null; 3919 ClassMeta<T> cm = type instanceof Class ? getClassMeta((Class)type) : resolveClassMeta(type, null); 3920 if (args.length == 0) 3921 return cm; 3922 ClassMeta<?>[] cma = new ClassMeta[args.length+1]; 3923 cma[0] = cm; 3924 for (int i = 0; i < Array.getLength(args); i++) { 3925 Type arg = (Type)Array.get(args, i); 3926 cma[i+1] = arg instanceof Class ? getClassMeta((Class)arg) : resolveClassMeta(arg, null); 3927 } 3928 return (ClassMeta<T>) getTypedClassMeta(cma, 0); 3929 } 3930 3931 /* 3932 * Resolves the 'genericized' class meta at the specified position in the ClassMeta array. 3933 */ 3934 private ClassMeta<?> getTypedClassMeta(ClassMeta<?>[] c, int pos) { 3935 ClassMeta<?> cm = c[pos++]; 3936 if (cm.isCollection() || cm.isOptional()) { 3937 ClassMeta<?> ce = c.length == pos ? object() : getTypedClassMeta(c, pos); 3938 return (ce.isObject() ? cm : new ClassMeta(cm, null, null, ce)); 3939 } else if (cm.isMap()) { 3940 ClassMeta<?> ck = c.length == pos ? object() : c[pos++]; 3941 ClassMeta<?> cv = c.length == pos ? object() : getTypedClassMeta(c, pos); 3942 return (ck.isObject() && cv.isObject() ? cm : new ClassMeta(cm, ck, cv, null)); 3943 } 3944 return cm; 3945 } 3946 3947 final ClassMeta resolveClassMeta(Type o, Map<Class<?>,Class<?>[]> typeVarImpls) { 3948 if (o == null) 3949 return null; 3950 3951 if (o instanceof ClassMeta) { 3952 ClassMeta<?> cm = (ClassMeta)o; 3953 3954 // This classmeta could have been created by a different context. 3955 // Need to re-resolve it to pick up ObjectSwaps and stuff on this context. 3956 if (cm.getBeanContext() == this) 3957 return cm; 3958 if (cm.isMap()) 3959 return getClassMeta(cm.innerClass, cm.getKeyType(), cm.getValueType()); 3960 if (cm.isCollection() || cm.isOptional()) 3961 return getClassMeta(cm.innerClass, cm.getElementType()); 3962 return getClassMeta(cm.innerClass); 3963 } 3964 3965 Class c = resolve(o, typeVarImpls); 3966 3967 // This can happen when trying to resolve the "E getFirst()" method on LinkedList, whose type is a TypeVariable 3968 // These should just resolve to Object. 3969 if (c == null) 3970 return object(); 3971 3972 ClassMeta rawType = getClassMeta(c); 3973 3974 // If this is a Map or Collection, and the parameter types aren't part 3975 // of the class definition itself (e.g. class AddressBook extends List<Person>), 3976 // then we need to figure out the parameters. 3977 if (rawType.isMap() || rawType.isCollection() || rawType.isOptional()) { 3978 ClassMeta[] params = findParameters(o, c); 3979 if (params == null) 3980 return rawType; 3981 if (rawType.isMap()) { 3982 if (params.length != 2 || (params[0].isObject() && params[1].isObject())) 3983 return rawType; 3984 return new ClassMeta(rawType, params[0], params[1], null); 3985 } 3986 if (rawType.isCollection() || rawType.isOptional()) { 3987 if (params.length != 1 || params[0].isObject()) 3988 return rawType; 3989 return new ClassMeta(rawType, null, null, params[0]); 3990 } 3991 } 3992 3993 if (rawType.isArray()) { 3994 if (o instanceof GenericArrayType) { 3995 GenericArrayType gat = (GenericArrayType)o; 3996 ClassMeta elementType = resolveClassMeta(gat.getGenericComponentType(), typeVarImpls); 3997 return new ClassMeta(rawType, null, null, elementType); 3998 } 3999 } 4000 4001 return rawType; 4002 } 4003 4004 /** 4005 * Convert a Type to a Class if possible. 4006 * Return null if not possible. 4007 */ 4008 final Class resolve(Type t, Map<Class<?>,Class<?>[]> typeVarImpls) { 4009 4010 if (t instanceof Class) 4011 return (Class)t; 4012 4013 if (t instanceof ParameterizedType) 4014 // A parameter (e.g. <String>. 4015 return (Class)((ParameterizedType)t).getRawType(); 4016 4017 if (t instanceof GenericArrayType) { 4018 // An array parameter (e.g. <byte[]>). 4019 Type gatct = ((GenericArrayType)t).getGenericComponentType(); 4020 4021 if (gatct instanceof Class) 4022 return Array.newInstance((Class)gatct, 0).getClass(); 4023 4024 if (gatct instanceof ParameterizedType) 4025 return Array.newInstance((Class)((ParameterizedType)gatct).getRawType(), 0).getClass(); 4026 4027 if (gatct instanceof GenericArrayType) 4028 return Array.newInstance(resolve(gatct, typeVarImpls), 0).getClass(); 4029 4030 return null; 4031 4032 } else if (t instanceof TypeVariable) { 4033 if (typeVarImpls != null) { 4034 TypeVariable tv = (TypeVariable)t; 4035 String varName = tv.getName(); 4036 int varIndex = -1; 4037 Class gc = (Class)tv.getGenericDeclaration(); 4038 TypeVariable[] tvv = gc.getTypeParameters(); 4039 for (int i = 0; i < tvv.length; i++) { 4040 if (tvv[i].getName().equals(varName)) { 4041 varIndex = i; 4042 } 4043 } 4044 if (varIndex != -1) { 4045 4046 // If we couldn't find a type variable implementation, that means 4047 // the type was defined at runtime (e.g. Bean b = new Bean<Foo>();) 4048 // in which case the type is lost through erasure. 4049 // Assume java.lang.Object as the type. 4050 if (! typeVarImpls.containsKey(gc)) 4051 return null; 4052 4053 return typeVarImpls.get(gc)[varIndex]; 4054 } 4055 } 4056 } 4057 return null; 4058 } 4059 4060 final ClassMeta[] findParameters(Type o, Class c) { 4061 if (o == null) 4062 o = c; 4063 4064 // Loop until we find a ParameterizedType 4065 if (! (o instanceof ParameterizedType)) { 4066 loop: do { 4067 o = c.getGenericSuperclass(); 4068 if (o instanceof ParameterizedType) 4069 break loop; 4070 for (Type t : c.getGenericInterfaces()) { 4071 o = t; 4072 if (o instanceof ParameterizedType) 4073 break loop; 4074 } 4075 c = c.getSuperclass(); 4076 } while (c != null); 4077 } 4078 4079 if (o instanceof ParameterizedType) { 4080 ParameterizedType pt = (ParameterizedType)o; 4081 if (! pt.getRawType().equals(Enum.class)) { 4082 List<ClassMeta<?>> l = new LinkedList<>(); 4083 for (Type pt2 : pt.getActualTypeArguments()) { 4084 if (pt2 instanceof WildcardType || pt2 instanceof TypeVariable) 4085 return null; 4086 l.add(resolveClassMeta(pt2, null)); 4087 } 4088 if (l.isEmpty()) 4089 return null; 4090 return l.toArray(new ClassMeta[l.size()]); 4091 } 4092 } 4093 4094 return null; 4095 } 4096 4097 /** 4098 * Shortcut for calling {@code getClassMeta(o.getClass())}. 4099 * 4100 * @param <T> The class of the object being passed in. 4101 * @param o The class to find the class type for. 4102 * @return The ClassMeta object, or <jk>null</jk> if {@code o} is <jk>null</jk>. 4103 */ 4104 public final <T> ClassMeta<T> getClassMetaForObject(T o) { 4105 if (o == null) 4106 return null; 4107 return (ClassMeta<T>)getClassMeta(o.getClass()); 4108 } 4109 4110 4111 /** 4112 * Used for determining the class type on a method or field where a {@code @Beanp} annotation may be present. 4113 * 4114 * @param <T> The class type we're wrapping. 4115 * @param p The property annotation on the type if there is one. 4116 * @param t The type. 4117 * @param typeVarImpls 4118 * Contains known resolved type parameters on the specified class so that we can result 4119 * {@code ParameterizedTypes} and {@code TypeVariables}. 4120 * Can be <jk>null</jk> if the information is not known. 4121 * @return The new {@code ClassMeta} object wrapped around the {@code Type} object. 4122 */ 4123 protected final <T> ClassMeta<T> resolveClassMeta(Beanp p, Type t, Map<Class<?>,Class<?>[]> typeVarImpls) { 4124 ClassMeta<T> cm = resolveClassMeta(t, typeVarImpls); 4125 ClassMeta<T> cm2 = cm; 4126 4127 if (p != null) { 4128 4129 if (isNotVoid(p.type())) 4130 cm2 = resolveClassMeta(p.type(), typeVarImpls); 4131 4132 if (cm2.isMap()) { 4133 Class<?>[] pParams = (p.params().length == 0 ? new Class[]{Object.class, Object.class} : p.params()); 4134 if (pParams.length != 2) 4135 throw new BasicRuntimeException("Invalid number of parameters specified for Map (must be 2): {0}", pParams.length); 4136 ClassMeta<?> keyType = resolveType(pParams[0], cm2.getKeyType(), cm.getKeyType()); 4137 ClassMeta<?> valueType = resolveType(pParams[1], cm2.getValueType(), cm.getValueType()); 4138 if (keyType.isObject() && valueType.isObject()) 4139 return cm2; 4140 return new ClassMeta<>(cm2, keyType, valueType, null); 4141 } 4142 4143 if (cm2.isCollection() || cm2.isOptional()) { 4144 Class<?>[] pParams = (p.params().length == 0 ? new Class[]{Object.class} : p.params()); 4145 if (pParams.length != 1) 4146 throw new BasicRuntimeException("Invalid number of parameters specified for {1} (must be 1): {0}", pParams.length, (cm2.isCollection() ? "Collection" : cm2.isOptional() ? "Optional" : "Array")); 4147 ClassMeta<?> elementType = resolveType(pParams[0], cm2.getElementType(), cm.getElementType()); 4148 if (elementType.isObject()) 4149 return cm2; 4150 return new ClassMeta<>(cm2, null, null, elementType); 4151 } 4152 4153 return cm2; 4154 } 4155 4156 return cm; 4157 } 4158 4159 private ClassMeta<?> resolveType(Type...t) { 4160 for (Type tt : t) { 4161 if (tt != null) { 4162 ClassMeta<?> cm = getClassMeta(tt); 4163 if (tt != cmObject) 4164 return cm; 4165 } 4166 } 4167 return cmObject; 4168 } 4169 4170 /** 4171 * Returns the {@link ObjectSwap} associated with the specified class, or <jk>null</jk> if there is no POJO swap 4172 * associated with the class. 4173 * 4174 * @param <T> The class associated with the swap. 4175 * @param c The class associated with the swap. 4176 * @return The swap associated with the class, or null if there is no association. 4177 */ 4178 private final <T> ObjectSwap[] findObjectSwaps(Class<T> c) { 4179 // Note: On first 4180 if (c != null) { 4181 List<ObjectSwap> l = list(); 4182 for (ObjectSwap f : swapArray) 4183 if (f.getNormalClass().isParentOf(c)) 4184 l.add(f); 4185 return l.size() == 0 ? null : l.toArray(new ObjectSwap[l.size()]); 4186 } 4187 return null; 4188 } 4189 4190 /** 4191 * Checks whether a class has a {@link ObjectSwap} associated with it in this bean context. 4192 * 4193 * @param c The class to check. 4194 * @return <jk>true</jk> if the specified class or one of its subclasses has a {@link ObjectSwap} associated with it. 4195 */ 4196 private final ObjectSwap[] findChildObjectSwaps(Class<?> c) { 4197 if (c == null || swapArray.length == 0) 4198 return null; 4199 List<ObjectSwap> l = null; 4200 for (ObjectSwap f : swapArray) { 4201 if (f.getNormalClass().isChildOf(c)) { 4202 if (l == null) 4203 l = list(); 4204 l.add(f); 4205 } 4206 } 4207 return l == null ? null : l.toArray(new ObjectSwap[l.size()]); 4208 } 4209 4210 /** 4211 * Returns a reusable {@link ClassMeta} representation for the class <c>Object</c>. 4212 * 4213 * <p> 4214 * This <c>ClassMeta</c> is often used to represent "any object type" when an object type is not known. 4215 * 4216 * <p> 4217 * This method is identical to calling <code>getClassMeta(Object.<jk>class</jk>)</code> but uses a cached copy to 4218 * avoid a hashmap lookup. 4219 * 4220 * @return The {@link ClassMeta} object associated with the <c>Object</c> class. 4221 */ 4222 protected final ClassMeta<Object> object() { 4223 return cmObject; 4224 } 4225 4226 /** 4227 * Returns a reusable {@link ClassMeta} representation for the class <c>String</c>. 4228 * 4229 * <p> 4230 * This <c>ClassMeta</c> is often used to represent key types in maps. 4231 * 4232 * <p> 4233 * This method is identical to calling <code>getClassMeta(String.<jk>class</jk>)</code> but uses a cached copy to 4234 * avoid a hashmap lookup. 4235 * 4236 * @return The {@link ClassMeta} object associated with the <c>String</c> class. 4237 */ 4238 protected final ClassMeta<String> string() { 4239 return cmString; 4240 } 4241 4242 /** 4243 * Returns a reusable {@link ClassMeta} representation for the class <c>Class</c>. 4244 * 4245 * <p> 4246 * This <c>ClassMeta</c> is often used to represent key types in maps. 4247 * 4248 * <p> 4249 * This method is identical to calling <code>getClassMeta(Class.<jk>class</jk>)</code> but uses a cached copy to 4250 * avoid a hashmap lookup. 4251 * 4252 * @return The {@link ClassMeta} object associated with the <c>String</c> class. 4253 */ 4254 protected final ClassMeta<Class> _class() { 4255 return cmClass; 4256 } 4257 4258 /** 4259 * Returns the lookup table for resolving bean types by name. 4260 * 4261 * @return The lookup table for resolving bean types by name. 4262 */ 4263 protected final BeanRegistry getBeanRegistry() { 4264 return beanRegistry; 4265 } 4266 4267 //----------------------------------------------------------------------------------------------------------------- 4268 // Properties 4269 //----------------------------------------------------------------------------------------------------------------- 4270 4271 /** 4272 * Minimum bean class visibility. 4273 * 4274 * @see BeanContext.Builder#beanClassVisibility(Visibility) 4275 * @return 4276 * Classes are not considered beans unless they meet the minimum visibility requirements. 4277 */ 4278 public final Visibility getBeanClassVisibility() { 4279 return beanClassVisibility; 4280 } 4281 4282 /** 4283 * Minimum bean constructor visibility. 4284 * 4285 * @see BeanContext.Builder#beanConstructorVisibility(Visibility) 4286 * @return 4287 * Only look for constructors with this specified minimum visibility. 4288 */ 4289 public final Visibility getBeanConstructorVisibility() { 4290 return beanConstructorVisibility; 4291 } 4292 4293 /** 4294 * Bean dictionary. 4295 * 4296 * @see BeanContext.Builder#beanDictionary() 4297 * @return 4298 * The list of classes that make up the bean dictionary in this bean context. 4299 */ 4300 public final List<Class<?>> getBeanDictionary() { 4301 return beanDictionary; 4302 } 4303 4304 /** 4305 * Minimum bean field visibility. 4306 * 4307 * 4308 * @see BeanContext.Builder#beanFieldVisibility(Visibility) 4309 * @return 4310 * Only look for bean fields with this specified minimum visibility. 4311 */ 4312 public final Visibility getBeanFieldVisibility() { 4313 return beanFieldVisibility; 4314 } 4315 4316 /** 4317 * BeanMap.put() returns old property value. 4318 * 4319 * @see BeanContext.Builder#beanMapPutReturnsOldValue() 4320 * @return 4321 * <jk>true</jk> if the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property values. 4322 * <br>Otherwise, it returns <jk>null</jk>. 4323 */ 4324 public final boolean isBeanMapPutReturnsOldValue() { 4325 return beanMapPutReturnsOldValue; 4326 } 4327 4328 /** 4329 * Minimum bean method visibility. 4330 * 4331 * @see BeanContext.Builder#beanMethodVisibility(Visibility) 4332 * @return 4333 * Only look for bean methods with this specified minimum visibility. 4334 */ 4335 public final Visibility getBeanMethodVisibility() { 4336 return beanMethodVisibility; 4337 } 4338 4339 /** 4340 * Beans require no-arg constructors. 4341 * 4342 * @see BeanContext.Builder#beansRequireDefaultConstructor() 4343 * @return 4344 * <jk>true</jk> if a Java class must implement a default no-arg constructor to be considered a bean. 4345 * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 4346 */ 4347 public final boolean isBeansRequireDefaultConstructor() { 4348 return beansRequireDefaultConstructor; 4349 } 4350 4351 /** 4352 * Beans require Serializable interface. 4353 * 4354 * @see BeanContext.Builder#beansRequireSerializable() 4355 * @return 4356 * <jk>true</jk> if a Java class must implement the {@link Serializable} interface to be considered a bean. 4357 * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 4358 */ 4359 public final boolean isBeansRequireSerializable() { 4360 return beansRequireSerializable; 4361 } 4362 4363 /** 4364 * Beans require setters for getters. 4365 * 4366 * @see BeanContext.Builder#beansRequireSettersForGetters() 4367 * @return 4368 * <jk>true</jk> if only getters that have equivalent setters will be considered as properties on a bean. 4369 * <br>Otherwise, they are ignored. 4370 */ 4371 public final boolean isBeansRequireSettersForGetters() { 4372 return beansRequireSettersForGetters; 4373 } 4374 4375 /** 4376 * Beans require at least one property. 4377 * 4378 * @see BeanContext.Builder#disableBeansRequireSomeProperties() 4379 * @return 4380 * <jk>true</jk> if a Java class doesn't need to contain at least 1 property to be considered a bean. 4381 * <br>Otherwise, the bean is serialized as a string using the {@link Object#toString()} method. 4382 */ 4383 public final boolean isBeansRequireSomeProperties() { 4384 return beansRequireSomeProperties; 4385 } 4386 4387 /** 4388 * Bean type property name. 4389 * 4390 * @see BeanContext.Builder#typePropertyName(String) 4391 * @return 4392 * The name of the bean property used to store the dictionary name of a bean type so that the parser knows the data type to reconstruct. 4393 */ 4394 public final String getBeanTypePropertyName() { 4395 return typePropertyName; 4396 } 4397 4398 /** 4399 * Find fluent setters. 4400 * 4401 * <h5 class='section'>Description:</h5> 4402 * <p> 4403 * 4404 * @see BeanContext.Builder#findFluentSetters() 4405 * @return 4406 * <jk>true</jk> if fluent setters are detected on beans. 4407 */ 4408 public final boolean isFindFluentSetters() { 4409 return findFluentSetters; 4410 } 4411 4412 /** 4413 * Ignore invocation errors on getters. 4414 * 4415 * @see BeanContext.Builder#ignoreInvocationExceptionsOnGetters() 4416 * @return 4417 * <jk>true</jk> if errors thrown when calling bean getter methods are silently ignored. 4418 */ 4419 public final boolean isIgnoreInvocationExceptionsOnGetters() { 4420 return ignoreInvocationExceptionsOnGetters; 4421 } 4422 4423 /** 4424 * Ignore invocation errors on setters. 4425 * 4426 * @see BeanContext.Builder#ignoreInvocationExceptionsOnSetters() 4427 * @return 4428 * <jk>true</jk> if errors thrown when calling bean setter methods are silently ignored. 4429 */ 4430 public final boolean isIgnoreInvocationExceptionsOnSetters() { 4431 return ignoreInvocationExceptionsOnSetters; 4432 } 4433 4434 /** 4435 * Silently ignore missing setters. 4436 * 4437 * @see BeanContext.Builder#disableIgnoreMissingSetters() 4438 * @return 4439 * <jk>true</jk> if trying to set a value on a bean property without a setter should throw a {@link BeanRuntimeException}. 4440 */ 4441 public final boolean isIgnoreMissingSetters() { 4442 return ignoreMissingSetters; 4443 } 4444 4445 /** 4446 * Ignore transient fields. 4447 * 4448 * @see BeanContext.Builder#disableIgnoreTransientFields() 4449 * @return 4450 * <jk>true</jk> if fields and methods marked as transient should not be ignored. 4451 */ 4452 protected final boolean isIgnoreTransientFields() { 4453 return ignoreTransientFields; 4454 } 4455 4456 /** 4457 * Ignore unknown properties. 4458 * 4459 * @see BeanContext.Builder#ignoreUnknownBeanProperties() 4460 * @return 4461 * <jk>true</jk> if trying to set a value on a non-existent bean property is silently ignored. 4462 * <br>Otherwise, a {@code RuntimeException} is thrown. 4463 */ 4464 public final boolean isIgnoreUnknownBeanProperties() { 4465 return ignoreUnknownBeanProperties; 4466 } 4467 4468 /** 4469 * Ignore unknown enum values. 4470 * 4471 * @see BeanContext.Builder#ignoreUnknownEnumValues() 4472 * @return 4473 * <jk>true</jk> if unknown enum values should be set as <jk>null</jk> instead of throwing an exception. 4474 */ 4475 public final boolean isIgnoreUnknownEnumValues() { 4476 return ignoreUnknownEnumValues; 4477 } 4478 4479 /** 4480 * Ignore unknown properties with null values. 4481 * 4482 * @see BeanContext.Builder#disableIgnoreUnknownNullBeanProperties() 4483 * @return 4484 * <jk>true</jk> if trying to set a <jk>null</jk> value on a non-existent bean property should throw a {@link BeanRuntimeException}. 4485 */ 4486 public final boolean isIgnoreUnknownNullBeanProperties() { 4487 return ignoreUnknownNullBeanProperties; 4488 } 4489 4490 /** 4491 * Bean class exclusions. 4492 * 4493 * @see BeanContext.Builder#notBeanClasses(Class...) 4494 * @return 4495 * The list of classes that are explicitly not beans. 4496 */ 4497 protected final Class<?>[] getNotBeanClasses() { 4498 return notBeanClassesArray; 4499 } 4500 4501 /** 4502 * Bean package exclusions. 4503 * 4504 * @see BeanContext.Builder#notBeanPackages(String...) 4505 * @return 4506 * The list of fully-qualified package names to exclude from being classified as beans. 4507 */ 4508 public final String[] getNotBeanPackagesNames() { 4509 return notBeanPackageNames; 4510 } 4511 4512 /** 4513 * Bean package exclusions. 4514 * 4515 * @see BeanContext.Builder#notBeanPackages(String...) 4516 * @return 4517 * The list of package name prefixes to exclude from being classified as beans. 4518 */ 4519 protected final String[] getNotBeanPackagesPrefixes() { 4520 return notBeanPackagePrefixes; 4521 } 4522 4523 /** 4524 * Java object swaps. 4525 * 4526 * @see BeanContext.Builder#swaps(Class...) 4527 * @return 4528 * The list POJO swaps defined. 4529 */ 4530 public final ObjectSwap<?,?>[] getSwaps() { 4531 return swapArray; 4532 } 4533 4534 /** 4535 * Bean property namer. 4536 * 4537 * @see BeanContext.Builder#propertyNamer(Class) 4538 * @return 4539 * The interface used to calculate bean property names. 4540 */ 4541 public final PropertyNamer getPropertyNamer() { 4542 return propertyNamerBean; 4543 } 4544 4545 /** 4546 * Sort bean properties. 4547 * 4548 * @see BeanContext.Builder#sortProperties() 4549 * @return 4550 * <jk>true</jk> if all bean properties will be serialized and access in alphabetical order. 4551 */ 4552 public final boolean isSortProperties() { 4553 return sortProperties; 4554 } 4555 4556 /** 4557 * Use enum names. 4558 * 4559 * @see BeanContext.Builder#useEnumNames() 4560 * @return 4561 * <jk>true</jk> if enums are always serialized by name, not using {@link Object#toString()}. 4562 */ 4563 public final boolean isUseEnumNames() { 4564 return useEnumNames; 4565 } 4566 4567 /** 4568 * Use interface proxies. 4569 * 4570 * @see BeanContext.Builder#disableInterfaceProxies() 4571 * @return 4572 * <jk>true</jk> if interfaces will be instantiated as proxy classes through the use of an 4573 * {@link InvocationHandler} if there is no other way of instantiating them. 4574 */ 4575 public final boolean isUseInterfaceProxies() { 4576 return useInterfaceProxies; 4577 } 4578 4579 /** 4580 * Use Java Introspector. 4581 * 4582 * @see BeanContext.Builder#useJavaBeanIntrospector() 4583 * @return 4584 * <jk>true</jk> if the built-in Java bean introspector should be used for bean introspection. 4585 */ 4586 public final boolean isUseJavaBeanIntrospector() { 4587 return useJavaBeanIntrospector; 4588 } 4589 4590 /** 4591 * Locale. 4592 * 4593 * @see BeanContext.Builder#locale(Locale) 4594 * @return 4595 * The default locale for serializer and parser sessions. 4596 */ 4597 public final Locale getDefaultLocale() { 4598 return locale; 4599 } 4600 4601 /** 4602 * Media type. 4603 * 4604 * @see BeanContext.Builder#mediaType(MediaType) 4605 * @return 4606 * The default media type value for serializer and parser sessions. 4607 */ 4608 public final MediaType getDefaultMediaType() { 4609 return mediaType; 4610 } 4611 4612 /** 4613 * Time zone. 4614 * 4615 * @see BeanContext.Builder#timeZone(TimeZone) 4616 * @return 4617 * The default timezone for serializer and parser sessions. 4618 */ 4619 public final TimeZone getDefaultTimeZone() { 4620 return timeZone; 4621 } 4622 4623 /** 4624 * Returns the serializer to use for serializing beans when using the {@link BeanSession#convertToType(Object, Class)} 4625 * and related methods. 4626 * 4627 * @return The serializer. May be <jk>null</jk> if all initialization has occurred. 4628 */ 4629 protected WriterSerializer getBeanToStringSerializer() { 4630 if (beanToStringSerializer == null) { 4631 if (JsonSerializer.DEFAULT == null) 4632 return null; 4633 this.beanToStringSerializer = JsonSerializer.create().beanContext(this).sq().simpleAttrs().build(); 4634 } 4635 return beanToStringSerializer; 4636 } 4637 4638 //----------------------------------------------------------------------------------------------------------------- 4639 // Other methods 4640 //----------------------------------------------------------------------------------------------------------------- 4641 4642 @Override /* Context */ 4643 protected JsonMap properties() { 4644 return filteredMap() 4645 .append("id", System.identityHashCode(this)) 4646 .append("beanClassVisibility", beanClassVisibility) 4647 .append("beanConstructorVisibility", beanConstructorVisibility) 4648 .append("beanDictionary", beanDictionary) 4649 .append("beanFieldVisibility", beanFieldVisibility) 4650 .append("beanMethodVisibility", beanMethodVisibility) 4651 .append("beansRequireDefaultConstructor", beansRequireDefaultConstructor) 4652 .append("beansRequireSerializable", beansRequireSerializable) 4653 .append("beansRequireSettersForGetters", beansRequireSettersForGetters) 4654 .append("beansRequireSomeProperties", beansRequireSomeProperties) 4655 .append("ignoreTransientFields", ignoreTransientFields) 4656 .append("ignoreInvocationExceptionsOnGetters", ignoreInvocationExceptionsOnGetters) 4657 .append("ignoreInvocationExceptionsOnSetters", ignoreInvocationExceptionsOnSetters) 4658 .append("ignoreUnknownBeanProperties", ignoreUnknownBeanProperties) 4659 .append("ignoreUnknownNullBeanProperties", ignoreUnknownNullBeanProperties) 4660 .append("notBeanClasses", notBeanClasses) 4661 .append("notBeanPackageNames", notBeanPackageNames) 4662 .append("notBeanPackagePrefixes", notBeanPackagePrefixes) 4663 .append("swaps", swaps) 4664 .append("sortProperties", sortProperties) 4665 .append("useEnumNames", useEnumNames) 4666 .append("useInterfaceProxies", useInterfaceProxies) 4667 .append("useJavaBeanIntrospector", useJavaBeanIntrospector); 4668 } 4669}