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.internal.ClassUtils.*; 017import static org.apache.juneau.internal.CollectionUtils.*; 018import static org.apache.juneau.internal.StringUtils.*; 019 020import java.io.*; 021import java.lang.reflect.*; 022import java.util.*; 023import java.util.concurrent.*; 024 025import org.apache.juneau.annotation.*; 026import org.apache.juneau.http.*; 027import org.apache.juneau.json.*; 028import org.apache.juneau.reflect.*; 029import org.apache.juneau.serializer.*; 030import org.apache.juneau.transform.*; 031 032/** 033 * Core class of the Juneau architecture. 034 * 035 * <p> 036 * This class servers multiple purposes: 037 * <ul class='spaced-list'> 038 * <li> 039 * Provides the ability to wrap beans inside {@link Map} interfaces. 040 * <li> 041 * Serves as a repository for metadata on POJOs, such as associated {@link BeanFilter BeanFilters}, 042 * {@link PropertyNamer PropertyNamers}, etc... which are used to tailor how POJOs are serialized and parsed. 043 * </ul> 044 * 045 * <p> 046 * All serializers and parsers extend from this context so that they can handle POJOs using a common framework. 047 * 048 * <h5 class='topic'>Bean Contexts</h5> 049 * 050 * Bean contexts are created through the {@link BeanContext#create() BeanContext.create()} and {@link BeanContextBuilder#build()} methods. 051 * <br>These context objects are read-only, reusable, and thread-safe. 052 * 053 * <p> 054 * Each bean context maintains a cache of {@link ClassMeta} objects that describe information about classes encountered. 055 * These <c>ClassMeta</c> objects are time-consuming to construct. 056 * Therefore, instances of {@link BeanContext} that share the same <js>"BeanContext.*"</js> property values share 057 * the same cache. This allows for efficient reuse of <c>ClassMeta</c> objects so that the information about 058 * classes only needs to be calculated once. 059 * Because of this, many of the properties defined on the {@link BeanContext} class cannot be overridden on the session. 060 * 061 * <h5 class='topic'>Bean Sessions</h5> 062 * 063 * Whereas <c>BeanContext</c> objects are permanent, unchangeable, cached, and thread-safe, 064 * {@link BeanSession} objects are ephemeral and not thread-safe. 065 * They are meant to be used as quickly-constructed scratchpads for creating bean maps. 066 * {@link BeanMap} objects can only be created through the session. 067 * 068 * <h5 class='topic'>BeanContext configuration properties</h5> 069 * 070 * <c>BeanContexts</c> have several configuration properties that can be used to tweak behavior on how beans are 071 * handled. These are denoted as the static <jsf>BEAN_*</jsf> fields on this class. 072 * 073 * <p> 074 * Some settings (e.g. {@link #BEAN_beansRequireDefaultConstructor}) are used to differentiate between bean 075 * and non-bean classes. 076 * Attempting to create a bean map around one of these objects will throw a {@link BeanRuntimeException}. 077 * The purpose for this behavior is so that the serializers can identify these non-bean classes and convert them to 078 * plain strings using the {@link Object#toString()} method. 079 * 080 * <p> 081 * Some settings (e.g. {@link #BEAN_beanFieldVisibility}) are used to determine what kinds of properties are 082 * detected on beans. 083 * 084 * <p> 085 * Some settings (e.g. {@link #BEAN_beanMapPutReturnsOldValue}) change the runtime behavior of bean maps. 086 * 087 * <p> 088 * Settings are specified using the {@link BeanContextBuilder#set(String, Object)} method and related convenience 089 * methods. 090 * 091 * <h5 class='section'>Example:</h5> 092 * 093 * <p class='bcode w800'> 094 * <jc>// Construct a context from scratch.</jc> 095 * BeanContext beanContext = BeanContext 096 * .<jsm>create</jsm>() 097 * .set(BeanContext.<jsf>BEAN_beansRequireDefaultConstructor</jsf>, <jk>true</jk>) 098 * .notBeanClasses(Foo.<jk>class</jk>) 099 * .build(); 100 * </p> 101 * 102 * <h5 class='topic'>Bean Maps</h5> 103 * 104 * {@link BeanMap BeanMaps} are wrappers around Java beans that allow properties to be retrieved and 105 * set using the common {@link Map#put(Object,Object)} and {@link Map#get(Object)} methods. 106 * 107 * <p> 108 * Bean maps are created in two ways... 109 * <ol> 110 * <li>{@link BeanSession#toBeanMap(Object) BeanSession.toBeanMap()} - Wraps an existing bean inside a {@code Map} 111 * wrapper. 112 * <li>{@link BeanSession#newBeanMap(Class) BeanSession.newBeanMap()} - Create a new bean instance wrapped in a 113 * {@code Map} wrapper. 114 * </ol> 115 * 116 * <h5 class='section'>Example:</h5> 117 * 118 * <p class='bcode w800'> 119 * <jc>// A sample bean class</jc> 120 * <jk>public class</jk> Person { 121 * <jk>public</jk> String getName(); 122 * <jk>public void</jk> setName(String name); 123 * <jk>public int</jk> getAge(); 124 * <jk>public void</jk> setAge(<jk>int</jk> age); 125 * } 126 * 127 * <jc>// Create a new bean session</jc> 128 * BeanSession session = BeanContext.<jsf>DEFAULT</jsf>.createSession(); 129 * 130 * <jc>// Wrap an existing bean in a new bean map</jc> 131 * BeanMap<Person> m1 = session.toBeanMap(<jk>new</jk> Person()); 132 * m1.put(<js>"name"</js>, <js>"John Smith"</js>); 133 * m1.put(<js>"age"</js>, 45); 134 * 135 * <jc>// Create a new bean instance wrapped in a new bean map</jc> 136 * BeanMap<Person> m2 = session.newBeanMap(Person.<jk>class</jk>); 137 * m2.put(<js>"name"</js>, <js>"John Smith"</js>); 138 * m2.put(<js>"age"</js>, 45); 139 * Person p = m2.getBean(); <jc>// Get the bean instance that was created.</jc> 140 * </p> 141 * 142 * <ul class='seealso'> 143 * <li class='link'>{@doc juneau-marshall.ContextsBuildersSessionsPropertyStores} 144 * </ul> 145 */ 146@SuppressWarnings({"unchecked","rawtypes"}) 147@ConfigurableContext 148public class BeanContext extends Context { 149 150 static final String PREFIX = "BeanContext"; 151 152 /** 153 * Configuration property: Minimum bean class visibility. 154 * 155 * <h5 class='section'>Property:</h5> 156 * <ul> 157 * <li><b>Name:</b> <js>"BeanContext.beanClassVisibility.s"</js> 158 * <li><b>Data type:</b> <c>String</c> ({@link Visibility}) 159 * <li><b>Default:</b> <js>"PUBLIC"</js> 160 * <li><b>Session property:</b> <jk>false</jk> 161 * <li><b>Methods:</b> 162 * <ul> 163 * <li class='jm'>{@link BeanContextBuilder#beanClassVisibility(Visibility)} 164 * </ul> 165 * </ul> 166 * 167 * <h5 class='section'>Description:</h5> 168 * <p> 169 * Classes are not considered beans unless they meet the minimum visibility requirements. 170 * 171 * <p> 172 * For example, if the visibility is <c>PUBLIC</c> and the bean class is <jk>protected</jk>, then the class 173 * will not be interpreted as a bean class and be serialized as a string. 174 * <br>Use this setting to reduce the visibility requirement. 175 * 176 * <h5 class='section'>Example:</h5> 177 * <p class='bcode w800'> 178 * <jc>// Create a serializer that serializes protected classes.</jc> 179 * WriterSerializer s = JsonSerializer 180 * .<jsm>create</jsm>() 181 * .beanClassVisibility(<jsf>PROTECTED</jsf>) 182 * .build(); 183 * 184 * <jc>// Same, but use property.</jc> 185 * WriterSerializer s = JsonSerializer 186 * .<jsm>create</jsm>() 187 * .set(<jsf>BEAN_beanClassVisibility</jsf>, <js>"PROTECTED"</js>) 188 * .build(); 189 * </p> 190 */ 191 public static final String BEAN_beanClassVisibility = PREFIX + ".beanClassVisibility.s"; 192 193 /** 194 * Configuration property: Minimum bean constructor visibility. 195 * 196 * <h5 class='section'>Property:</h5> 197 * <ul> 198 * <li><b>Name:</b> <js>"BeanContext.beanConstructorVisibility.s"</js> 199 * <li><b>Data type:</b> <c>String</c> ({@link Visibility}) 200 * <li><b>Default:</b> <js>"PUBLIC"</js> 201 * <li><b>Session property:</b> <jk>false</jk> 202 * <li><b>Methods:</b> 203 * <ul> 204 * <li class='jm'>{@link BeanContextBuilder#beanConstructorVisibility(Visibility)} 205 * </ul> 206 * </ul> 207 * 208 * <h5 class='section'>Description:</h5> 209 * <p> 210 * Only look for constructors with the specified minimum visibility. 211 * 212 * <p> 213 * This setting affects the logic for finding no-arg constructors for bean. 214 * <br>Normally, only <jk>public</jk> no-arg constructors are used. 215 * <br>Use this setting if you want to reduce the visibility requirement. 216 * 217 * <h5 class='section'>Example:</h5> 218 * <p class='bcode w800'> 219 * <jc>// Create a serializer that looks for protected no-arg constructors.</jc> 220 * WriterSerializer s = JsonSerializer 221 * .<jsm>create</jsm>() 222 * .beanConstructorVisibility(<jsf>PROTECTED</jsf>) 223 * .build(); 224 * 225 * <jc>// Same, but use property.</jc> 226 * WriterSerializer s = JsonSerializer 227 * .<jsm>create</jsm>() 228 * .set(<jsf>BEAN_beanConstructorVisibility</jsf>, <js>"PROTECTED"</js>) 229 * .build(); 230 * </p> 231 */ 232 public static final String BEAN_beanConstructorVisibility = PREFIX + ".beanConstructorVisibility.s"; 233 234 /** 235 * Configuration property: Bean dictionary. 236 * 237 * <h5 class='section'>Property:</h5> 238 * <ul> 239 * <li><b>Name:</b> <js>"BeanContext.beanDictionary.lc"</js> 240 * <li><b>Data type:</b> <c>List<Class></c> 241 * <li><b>Default:</b> empty list 242 * <li><b>Session property:</b> <jk>false</jk> 243 * <li><b>Annotations:</b> 244 * <ul> 245 * <li class='ja'>{@link Bean#dictionary()} 246 * <li class='ja'>{@link Beanp#dictionary()} 247 * </ul> 248 * <li><b>Methods:</b> 249 * <ul> 250 * <li class='jm'>{@link BeanContextBuilder#dictionary(Object...)} 251 * <li class='jm'>{@link BeanContextBuilder#dictionary(Class...)} 252 * <li class='jm'>{@link BeanContextBuilder#dictionaryReplace(Object...)} 253 * <li class='jm'>{@link BeanContextBuilder#dictionaryReplace(Class...)} 254 * <li class='jm'>{@link BeanContextBuilder#dictionaryRemove(Object...)} 255 * <li class='jm'>{@link BeanContextBuilder#dictionaryRemove(Class...)} 256 * <li class='jm'>{@link BeanFilterBuilder#dictionary(Class...)} 257 * </ul> 258 * </ul> 259 * 260 * <h5 class='section'>Description:</h5> 261 * <p> 262 * The list of classes that make up the bean dictionary in this bean context. 263 * 264 * <p> 265 * A dictionary is a name/class mapping used to find class types during parsing when they cannot be inferred 266 * through reflection. 267 * <br>The names are defined through the {@link Bean#typeName() @Bean(typeName)} annotation defined on the bean class. 268 * <br>For example, if a class <c>Foo</c> has a type-name of <js>"myfoo"</js>, then it would end up serialized 269 * as <js>"{_type:'myfoo',...}"</js>. 270 * 271 * <p> 272 * This setting tells the parsers which classes to look for when resolving <js>"_type"</js> attributes. 273 * 274 * <p> 275 * Values can consist of any of the following types: 276 * <ul> 277 * <li>Any bean class that specifies a value for {@link Bean#typeName() @Bean(typeName)}. 278 * <li>Any subclass of {@link BeanDictionaryList} containing a collection of bean classes with type name annotations. 279 * <li>Any subclass of {@link BeanDictionaryMap} containing a mapping of type names to classes without type name annotations. 280 * <li>Any array or collection of the objects above. 281 * </ul> 282 * 283 * <h5 class='section'>Example:</h5> 284 * <p class='bcode w800'> 285 * <jc>// Create a parser and tell it which classes to try to resolve.</jc> 286 * ReaderParser p = JsonParser 287 * .<jsm>create</jsm>() 288 * .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>) 289 * .build(); 290 * 291 * <jc>// Same, but use property.</jc> 292 * ReaderParser p = JsonParser 293 * .<jsm>create</jsm>() 294 * .addTo(<jsf>BEAN_beanDictionary</jsf>, Foo.<jk>class</jk>) 295 * .addTo(<jsf>BEAN_beanDictionary</jsf>, Bar.<jk>class</jk>) 296 * .build(); 297 * 298 * <jc>// Instead of by parser, define a bean dictionary on a class through an annotation.</jc> 299 * <jc>// This applies to all properties on this class and all subclasses.</jc> 300 * <ja>@Bean</ja>(dictionary={Foo.<jk>class</jk>,Bar.<jk>class</jk>}) 301 * <jk>public class</jk> MyBean {...} 302 * 303 * <jc>// Use the predefined HTML5 bean dictionary which is a BeanDictionaryList.</jc> 304 * ReaderParser p = HtmlParser 305 * .<jsm>create</jsm>() 306 * .dictionary(HtmlBeanDictionary.<jk>class</jk>) 307 * .build(); 308 * </p> 309 * 310 * <ul class='seealso'> 311 * <li class='link'>{@doc juneau-marshall.BeanDictionaries} 312 * </ul> 313 */ 314 public static final String BEAN_beanDictionary = PREFIX + ".beanDictionary.lc"; 315 316 /** 317 * Configuration property: Add to bean dictionary. 318 */ 319 public static final String BEAN_beanDictionary_add = PREFIX + ".beanDictionary.lc/add"; 320 321 /** 322 * Configuration property: Remove from bean dictionary. 323 */ 324 public static final String BEAN_beanDictionary_remove = PREFIX + ".beanDictionary.lc/remove"; 325 326 /** 327 * Configuration property: Minimum bean field visibility. 328 * 329 * <h5 class='section'>Property:</h5> 330 * <ul> 331 * <li><b>Name:</b> <js>"BeanContext.beanFieldVisibility.s"</js> 332 * <li><b>Data type:</b> <c>String</c> ({@link Visibility}) 333 * <li><b>Default:</b> <js>"PUBLIC"</js> 334 * <li><b>Session property:</b> <jk>false</jk> 335 * <li><b>Methods:</b> 336 * <ul> 337 * <li class='jm'>{@link BeanContextBuilder#beanFieldVisibility(Visibility)} 338 * </ul> 339 * </ul> 340 * 341 * <h5 class='section'>Description:</h5> 342 * <p> 343 * Only look for bean fields with the specified minimum visibility. 344 * 345 * <p> 346 * This affects which fields on a bean class are considered bean properties. 347 * <br>Normally only <jk>public</jk> fields are considered. 348 * <br>Use this setting if you want to reduce the visibility requirement. 349 * 350 * <h5 class='section'>Example:</h5> 351 * <p class='bcode w800'> 352 * <jc>// Create a serializer that looks for protected fields.</jc> 353 * WriterSerializer s = JsonSerializer 354 * .<jsm>create</jsm>() 355 * .beanFieldVisibility(<jsf>PROTECTED</jsf>) 356 * .build(); 357 * 358 * <jc>// Same, but use property.</jc> 359 * WriterSerializer s = JsonSerializer 360 * .<jsm>create</jsm>() 361 * .set(<jsf>BEAN_beanFieldVisibility</jsf>, <js>"PROTECTED"</js>) 362 * .build(); 363 * 364 * <jc>// Disable using fields as properties entirely.</jc> 365 * WriterSerializer s = JsonSerializer 366 * .<jsm>create</jsm>() 367 * .beanFieldVisibility(<jsf>NONE</jsf>) 368 * .build(); 369 * </p> 370 */ 371 public static final String BEAN_beanFieldVisibility = PREFIX + ".beanFieldVisibility.s"; 372 373 /** 374 * Configuration property: Bean filters. 375 * 376 * <h5 class='section'>Property:</h5> 377 * <ul> 378 * <li><b>Name:</b> <js>"BeanContext.beanFilters.lc"</js> 379 * <li><b>Data type:</b> <c>List<Class></c> 380 * <li><b>Default:</b> empty list 381 * <li><b>Session property:</b> <jk>false</jk> 382 * <li><b>Methods:</b> 383 * <ul> 384 * <li class='jm'>{@link BeanContextBuilder#beanFilters(Object...)} 385 * <li class='jm'>{@link BeanContextBuilder#beanFilters(Class...)} 386 * <li class='jm'>{@link BeanContextBuilder#beanFiltersReplace(Object...)} 387 * <li class='jm'>{@link BeanContextBuilder#beanFiltersReplace(Class...)} 388 * <li class='jm'>{@link BeanContextBuilder#beanFiltersRemove(Object...)} 389 * <li class='jm'>{@link BeanContextBuilder#beanFiltersRemove(Class...)} 390 * </ul> 391 * </ul> 392 * 393 * <h5 class='section'>Description:</h5> 394 * <p> 395 * This is a programmatic equivalent to the {@link Bean @Bean} annotation. 396 * <br>It's useful when you want to use the <c>@Bean</c> annotation functionality, but you don't have the ability to alter 397 * the bean classes. 398 * 399 * <p> 400 * Values can consist of any of the following types: 401 * <ul class='spaced-list'> 402 * <li>Any subclass of {@link BeanFilterBuilder}. 403 * <br>These must have a public no-arg constructor. 404 * <li>Any bean interfaces. 405 * <br>A shortcut for defining a {@link InterfaceBeanFilterBuilder}. 406 * <br>Any subclasses of an interface class will only have properties defined on the interface. 407 * All other bean properties will be ignored. 408 * <li>Any array or collection of the objects above. 409 * </ul> 410 * 411 * <h5 class='section'>Example:</h5> 412 * <p class='bcode w800'> 413 * <jc>// Create a bean filter for the MyBean class.</jc> 414 * <jk>public class</jk> MyBeanFilter <jk>extends</jk> BeanFilterBuilder<MyBean> { 415 * 416 * <jc>// Must provide a no-arg constructor!</jc> 417 * <jk>public</jk> MyBeanFilter() { 418 * bpi(<js>"foo,bar,baz"</js>); <jc>// The properties we want exposed.</jc> 419 * } 420 * } 421 * 422 * <jc>// Associate our bean filter with a serializer.</jc> 423 * WriterSerializer s = JsonSerializer 424 * .<jsm>create</jsm>() 425 * .beanFilters(MyBeanFilter.<jk>class</jk>) 426 * .build(); 427 * 428 * <jc>// Same, but use property.</jc> 429 * WriterSerializer s = JsonSerializer 430 * .<jsm>create</jsm>() 431 * .addTo(<jsf>BEAN_beanFilters</jsf>, MyBeanFilter.<jk>class</jk>) 432 * .build(); 433 * </p> 434 * 435 * <ul class='seealso'> 436 * <li class='link'>{@doc juneau-marshall.Transforms.BeanFilters} 437 * <li class='link'>{@doc juneau-marshall.Transforms.InterfaceFilters} 438 * </ul> 439 */ 440 public static final String BEAN_beanFilters = PREFIX + ".beanFilters.lc"; 441 442 /** 443 * Configuration property: Add to bean filters. 444 */ 445 public static final String BEAN_beanFilters_add = PREFIX + ".beanFilters.lc/add"; 446 447 /** 448 * Configuration property: Remove from bean filters. 449 */ 450 public static final String BEAN_beanFilters_remove = PREFIX + ".beanFilters.lc/remove"; 451 452 /** 453 * Configuration property: BeanMap.put() returns old property value. 454 * 455 * <h5 class='section'>Property:</h5> 456 * <ul> 457 * <li><b>Name:</b> <js>"BeanContext.beanMapPutReturnsOldValue.b"</js> 458 * <li><b>Data type:</b> <c>Boolean</c> 459 * <li><b>Default:</b> <jk>false</jk> 460 * <li><b>Session property:</b> <jk>false</jk> 461 * <li><b>Methods:</b> 462 * <ul> 463 * <li class='jm'>{@link BeanContextBuilder#beanMapPutReturnsOldValue(boolean)} 464 * <li class='jm'>{@link BeanContextBuilder#beanMapPutReturnsOldValue()} 465 * </ul> 466 * </ul> 467 * 468 * <h5 class='section'>Description:</h5> 469 * <p> 470 * If <jk>true</jk>, then the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property 471 * values. 472 * <br>Otherwise, it returns <jk>null</jk>. 473 * 474 * <p> 475 * Disabled by default because it introduces a slight performance penalty during serialization. 476 * 477 * <h5 class='section'>Example:</h5> 478 * <p class='bcode w800'> 479 * <jc>// Create a serializer that creates BeanMaps with normal put() behavior.</jc> 480 * WriterSerializer s = JsonSerializer 481 * .<jsm>create</jsm>() 482 * .beanMapPutReturnsOldValue() 483 * .build(); 484 * 485 * <jc>// Same, but use property.</jc> 486 * WriterSerializer s = JsonSerializer 487 * .<jsm>create</jsm>() 488 * .set(<jsf>BEAN_beanMapPutReturnsOldValue</jsf>, <jk>true</jk>) 489 * .build(); 490 * 491 * BeanMap<MyBean> bm = s.createSession().toBeanMap(<jk>new</jk> MyBean()); 492 * bm.put(<js>"foo"</js>, <js>"bar"</js>); 493 * Object oldValue = bm.put(<js>"foo"</js>, <js>"baz"</js>); <jc>// oldValue == "bar"</jc> 494 * </p> 495 */ 496 public static final String BEAN_beanMapPutReturnsOldValue = PREFIX + ".beanMapPutReturnsOldValue.b"; 497 498 /** 499 * Configuration property: Minimum bean method visibility. 500 * 501 * <h5 class='section'>Property:</h5> 502 * <ul> 503 * <li><b>Name:</b> <js>"BeanContext.beanMethodVisibility.s"</js> 504 * <li><b>Data type:</b> <c>String</c> ({@link Visibility}) 505 * <li><b>Default:</b> <js>"PUBLIC"</js> 506 * <li><b>Session property:</b> <jk>false</jk> 507 * <li><b>Methods:</b> 508 * <ul> 509 * <li class='jm'>{@link BeanContextBuilder#beanMethodVisibility(Visibility)} 510 * </ul> 511 * </ul> 512 * 513 * <h5 class='section'>Description:</h5> 514 * <p> 515 * Only look for bean methods with the specified minimum visibility. 516 * 517 * <p> 518 * This affects which methods are detected as getters and setters on a bean class. 519 * <br>Normally only <jk>public</jk> getters and setters are considered. 520 * <br>Use this setting if you want to reduce the visibility requirement. 521 * 522 * <h5 class='section'>Example:</h5> 523 * <p class='bcode w800'> 524 * <jc>// Create a serializer that looks for protected getters and setters.</jc> 525 * WriterSerializer s = JsonSerializer 526 * .<jsm>create</jsm>() 527 * .beanMethodVisibility(<jsf>PROTECTED</jsf>) 528 * .build(); 529 * 530 * <jc>// Same, but use property.</jc> 531 * WriterSerializer s = JsonSerializer 532 * .<jsm>create</jsm>() 533 * .set(<jsf>BEAN_beanMethodVisibility</jsf>, <js>"PROTECTED"</js>) 534 * .build(); 535 * </p> 536 */ 537 public static final String BEAN_beanMethodVisibility = PREFIX + ".beanMethodVisibility.s"; 538 539 /** 540 * Configuration property: Beans require no-arg constructors. 541 * 542 * <h5 class='section'>Property:</h5> 543 * <ul> 544 * <li><b>Name:</b> <js>"BeanContext.beansRequireDefaultConstructor.b"</js> 545 * <li><b>Data type:</b> <c>Boolean</c> 546 * <li><b>Default:</b> <jk>false</jk> 547 * <li><b>Session property:</b> <jk>false</jk> 548 * <li><b>Methods:</b> 549 * <ul> 550 * <li class='jm'>{@link BeanContextBuilder#beansRequireDefaultConstructor(boolean)} 551 * <li class='jm'>{@link BeanContextBuilder#beansRequireDefaultConstructor()} 552 * </ul> 553 * </ul> 554 * 555 * <h5 class='section'>Description:</h5> 556 * <p> 557 * If <jk>true</jk>, a Java class must implement a default no-arg constructor to be considered a bean. 558 * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 559 * 560 * <p> 561 * The {@link Bean @Bean} annotation can be used on a class to override this setting when <jk>true</jk>. 562 * 563 * <h5 class='section'>Example:</h5> 564 * <p class='bcode w800'> 565 * <jc>// Create a serializer that ignores beans without default constructors.</jc> 566 * WriterSerializer s = JsonSerializer 567 * .<jsm>create</jsm>() 568 * .beansRequireDefaultConstructor() 569 * .build(); 570 * 571 * <jc>// Same, but use property.</jc> 572 * WriterSerializer s = JsonSerializer 573 * .<jsm>create</jsm>() 574 * .set(<jsf>BEAN_beansRequireDefaultConstructor</jsf>, <jk>true</jk>) 575 * .build(); 576 * </p> 577 */ 578 public static final String BEAN_beansRequireDefaultConstructor = PREFIX + ".beansRequireDefaultConstructor.b"; 579 580 /** 581 * Configuration property: Beans require Serializable interface. 582 * 583 * <h5 class='section'>Property:</h5> 584 * <ul> 585 * <li><b>Name:</b> <js>"BeanContext.beansRequireSerializable.b"</js> 586 * <li><b>Data type:</b> <c>Boolean</c> 587 * <li><b>Default:</b> <jk>false</jk> 588 * <li><b>Session property:</b> <jk>false</jk> 589 * <li><b>Methods:</b> 590 * <ul> 591 * <li class='jm'>{@link BeanContextBuilder#beansRequireSerializable(boolean)} 592 * <li class='jm'>{@link BeanContextBuilder#beansRequireSerializable()} 593 * </ul> 594 * </ul> 595 * 596 * <h5 class='section'>Description:</h5> 597 * <p> 598 * If <jk>true</jk>, a Java class must implement the {@link Serializable} interface to be considered a bean. 599 * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 600 * 601 * <p> 602 * The {@link Bean @Bean} annotation can be used on a class to override this setting when <jk>true</jk>. 603 * 604 * <h5 class='section'>Example:</h5> 605 * <p class='bcode w800'> 606 * <jc>// Create a serializer that ignores beans not implementing Serializable.</jc> 607 * WriterSerializer s = JsonSerializer 608 * .<jsm>create</jsm>() 609 * .beansRequireSerializable() 610 * .build(); 611 * 612 * <jc>// Same, but use property.</jc> 613 * WriterSerializer s = JsonSerializer 614 * .<jsm>create</jsm>() 615 * .set(<jsf>BEAN_beansRequireSerializable</jsf>, <jk>true</jk>) 616 * .build(); 617 * </p> 618 */ 619 public static final String BEAN_beansRequireSerializable = PREFIX + ".beansRequireSerializable.b"; 620 621 /** 622 * Configuration property: Beans require setters for getters. 623 * 624 * <h5 class='section'>Property:</h5> 625 * <ul> 626 * <li><b>Name:</b> <js>"BeanContext.beansRequireSettersForGetters.b"</js> 627 * <li><b>Data type:</b> <c>Boolean</c> 628 * <li><b>Default:</b> <jk>false</jk> 629 * <li><b>Session property:</b> <jk>false</jk> 630 * <li><b>Methods:</b> 631 * <ul> 632 * <li class='jm'>{@link BeanContextBuilder#beansRequireSettersForGetters(boolean)} 633 * <li class='jm'>{@link BeanContextBuilder#beansRequireSettersForGetters()} 634 * </ul> 635 * </ul> 636 * 637 * <h5 class='section'>Description:</h5> 638 * <p> 639 * If <jk>true</jk>, only getters that have equivalent setters will be considered as properties on a bean. 640 * <br>Otherwise, they will be ignored. 641 * 642 * <h5 class='section'>Example:</h5> 643 * <p class='bcode w800'> 644 * <jc>// Create a serializer that ignores bean properties without setters.</jc> 645 * WriterSerializer s = JsonSerializer 646 * .<jsm>create</jsm>() 647 * .beansRequireSettersForGetter() 648 * .build(); 649 * 650 * <jc>// Same, but use property.</jc> 651 * WriterSerializer s = JsonSerializer 652 * .<jsm>create</jsm>() 653 * .set(<jsf>BEAN_beansRequireSettersForGetters</jsf>, <jk>true</jk>) 654 * .build(); 655 * </p> 656 */ 657 public static final String BEAN_beansRequireSettersForGetters = PREFIX + ".beansRequireSettersForGetters.b"; 658 659 /** 660 * Configuration property: Beans require at least one property. 661 * 662 * <h5 class='section'>Property:</h5> 663 * <ul> 664 * <li><b>Name:</b> <js>"BeanContext.beansRequireSomeProperties.b"</js> 665 * <li><b>Data type:</b> <c>Boolean</c> 666 * <li><b>Default:</b> <jk>true</jk> 667 * <li><b>Session property:</b> <jk>false</jk> 668 * <li><b>Methods:</b> 669 * <ul> 670 * <li class='jm'>{@link BeanContextBuilder#beansRequireSomeProperties(boolean)} 671 * </ul> 672 * </ul> 673 * 674 * <h5 class='section'>Description:</h5> 675 * <p> 676 * If <jk>true</jk>, then a Java class must contain at least 1 property to be considered a bean. 677 * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 678 * 679 * <p> 680 * The {@link Bean @Bean} annotation can be used on a class to override this setting when <jk>true</jk>. 681 * 682 * <h5 class='section'>Example:</h5> 683 * <p class='bcode w800'> 684 * <jc>// Create a serializer that serializes beans even if they have zero properties.</jc> 685 * WriterSerializer s = JsonSerializer 686 * .<jsm>create</jsm>() 687 * .beansRequireSomeProperties(<jk>false</jk>) 688 * .build(); 689 * 690 * <jc>// Same, but use property.</jc> 691 * WriterSerializer s = JsonSerializer 692 * .<jsm>create</jsm>() 693 * .set(<jsf>BEAN_beansRequireSomeProperties</jsf>, <jk>false</jk>) 694 * .build(); 695 * </p> 696 */ 697 public static final String BEAN_beansRequireSomeProperties = PREFIX + ".beansRequireSomeProperties.b"; 698 699 /** 700 * Configuration property: Bean type property name. 701 * 702 * <h5 class='section'>Property:</h5> 703 * <ul> 704 * <li><b>Name:</b> <js>"BeanContext.beanTypePropertyName.s"</js> 705 * <li><b>Data type:</b> <c>String</c> 706 * <li><b>Default:</b> <js>"_type"</js> 707 * <li><b>Session property:</b> <jk>false</jk> 708 * <li><b>Annotations:</b> 709 * <ul> 710 * <li class='ja'>{@link Bean#typePropertyName()} 711 * </ul> 712 * <li><b>Methods:</b> 713 * <ul> 714 * <li class='jm'>{@link BeanContextBuilder#beanTypePropertyName(String)} 715 * </ul> 716 * </ul> 717 * 718 * <p> 719 * This specifies the name of the bean property used to store the dictionary name of a bean type so that the 720 * parser knows the data type to reconstruct. 721 * 722 * <h5 class='section'>Example:</h5> 723 * <p class='bcode w800'> 724 * <jc>// Create a serializer that uses 'type' instead of '_type' for dictionary names.</jc> 725 * WriterSerializer s = JsonSerializer 726 * .<jsm>create</jsm>() 727 * .beanTypePropertyName(<js>"type"</js>) 728 * .build(); 729 * 730 * <jc>// Same, but use property.</jc> 731 * WriterSerializer s = JsonSerializer 732 * .<jsm>create</jsm>() 733 * .set(<jsf>BEAN_beanTypePropertyName</jsf>, <js>"type"</js>) 734 * .build(); 735 * </p> 736 * 737 * <ul class='seealso'> 738 * <li class='link'>{@doc juneau-marshall.BeanDictionaries} 739 * </ul> 740 */ 741 public static final String BEAN_beanTypePropertyName = PREFIX + ".beanTypePropertyName.s"; 742 743 /** 744 * Configuration property: Bean property includes. 745 * 746 * <h5 class='section'>Property:</h5> 747 * <ul> 748 * <li><b>Name:</b> <js>"BeanContext.bpi.sms"</js> 749 * <li><b>Data type:</b> <c>Map<String,String></c> 750 * <li><b>Default:</b> <c>{}</c> 751 * <li><b>Session property:</b> <jk>false</jk> 752 * <li><b>Annotations:</b> 753 * <ul> 754 * <li class='ja'>{@link Bean#bpi()} 755 * <li class='ja'>{@link Beanp#bpi()} 756 * </ul> 757 * <li><b>Methods:</b> 758 * <ul> 759 * <li class='jm'>{@link BeanContextBuilder#bpi(Class, String)} 760 * <li class='jm'>{@link BeanContextBuilder#bpi(String, String)} 761 * <li class='jm'>{@link BeanContextBuilder#bpi(Map)} 762 * <li class='jm'>{@link BeanFilterBuilder#bpi(String...)} 763 * </ul> 764 * </ul> 765 * 766 * <h5 class='section'>Description:</h5> 767 * <p> 768 * Specifies the set and order of names of properties associated with the bean class. 769 * 770 * <p> 771 * The keys are either fully-qualified or simple class names, and the values are comma-delimited lists of property 772 * names. 773 * The key <js>"*"</js> means all bean classes. 774 * 775 * <p> 776 * For example, <code>{Bean1:<js>'foo,bar'</js>}</code> means only serialize the <c>foo</c> and 777 * <c>bar</c> properties on the specified bean. 778 * 779 * <p> 780 * Setting applies to specified class and all subclasses. 781 * 782 * <h5 class='section'>Example:</h5> 783 * <p class='bcode w800'> 784 * <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc> 785 * WriterSerializer s = JsonSerializer 786 * .<jsm>create</jsm>() 787 * .bpi(MyBean.<jk>class</jk>, <js>"foo,bar"</js>) 788 * .build(); 789 * 790 * <jc>// Same, but use property.</jc> 791 * WriterSerializer s = JsonSerializer 792 * .<jsm>create</jsm>() 793 * .addTo(<jsf>BEAN_bpi</jsf>, MyBean.<jk>class</jk>.getName(), <js>"foo,bar"</js>) 794 * .build(); 795 * 796 * <jc>// Alternate using JSON object.</jc> 797 * WriterSerializer s = JsonSerializer 798 * .<jsm>create</jsm>() 799 * .addTo(<jsf>BEAN_bpi</jsf>, <js>"{'org.apache.MyBean':'foo,bar'}"</js>) 800 * .build(); 801 * </p> 802 */ 803 public static final String BEAN_bpi = PREFIX + ".bpi.sms"; 804 805 /** 806 * Configuration property: Bean property excludes. 807 * 808 * <h5 class='section'>Property:</h5> 809 * <ul> 810 * <li><b>Name:</b> <js>"BeanContext.bpx.sms"</js> 811 * <li><b>Data type:</b> <c>Map<String,String></c> 812 * <li><b>Default:</b> <c>{}</c> 813 * <li><b>Session property:</b> <jk>false</jk> 814 * <li><b>Annotations:</b> 815 * <ul> 816 * <li class='ja'>{@link Bean#bpx()} 817 * </ul> 818 * <li><b>Methods:</b> 819 * <ul> 820 * <li class='jm'>{@link BeanContextBuilder#bpx(Class, String)} 821 * <li class='jm'>{@link BeanContextBuilder#bpx(String, String)} 822 * <li class='jm'>{@link BeanContextBuilder#bpx(Map)} 823 * <li class='jm'>{@link BeanFilterBuilder#bpx(String...)} 824 * </ul> 825 * </ul> 826 * 827 * <h5 class='section'>Description:</h5> 828 * <p> 829 * Specifies to exclude the specified list of properties for the specified bean class. 830 * 831 * <p> 832 * The keys are either fully-qualified or simple class names, and the values are comma-delimited lists of property 833 * names. 834 * The key <js>"*"</js> means all bean classes. 835 * 836 * <p> 837 * For example, <code>{Bean1:<js>'foo,bar'</js>}</code> means don't serialize the <c>foo</c> and 838 * <c>bar</c> properties on any beans whose simple class name is <c>Bean1</c>. 839 * 840 * <p> 841 * Setting applies to specified class and all subclasses. 842 * 843 * <h5 class='section'>Example:</h5> 844 * <p class='bcode w800'> 845 * <jc>// Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class.</jc> 846 * WriterSerializer s = JsonSerializer 847 * .<jsm>create</jsm>() 848 * .bpx(MyBean.<jk>class</jk>, <js>"foo,bar"</js>) 849 * .build(); 850 * 851 * <jc>// Same, but use property.</jc> 852 * WriterSerializer s = JsonSerializer 853 * .<jsm>create</jsm>() 854 * .addTo(<jsf>BEAN_bpx</jsf>, MyBean.<jk>class</jk>.getName(), <js>"foo,bar"</js>) 855 * .build(); 856 * 857 * <jc>// Alternate using JSON object.</jc> 858 * WriterSerializer s = JsonSerializer 859 * .<jsm>create</jsm>() 860 * .addTo(<jsf>BEAN_bpx</jsf>, <js>"{'org.apache.MyBean':'foo,bar'}"</js>) 861 * .build(); 862 * </p> 863 */ 864 public static final String BEAN_bpx = PREFIX + ".bpx.sms"; 865 866 /** 867 * Configuration property: Read-only bean properties. 868 * 869 * <h5 class='section'>Property:</h5> 870 * <ul> 871 * <li><b>Name:</b> <js>"BeanContext.bpro.sms"</js> 872 * <li><b>Data type:</b> <c>Map<String,String></c> 873 * <li><b>Default:</b> <c>{}</c> 874 * <li><b>Session property:</b> <jk>false</jk> 875 * <li><b>Annotations:</b> 876 * <ul> 877 * <li class='ja'>{@link Bean#bpro()} 878 * <li class='ja'>{@link Beanp#ro()} 879 * </ul> 880 * <li><b>Methods:</b> 881 * <ul> 882 * <li class='jm'>{@link BeanContextBuilder#bpro(Class, String)} 883 * <li class='jm'>{@link BeanContextBuilder#bpro(String, String)} 884 * <li class='jm'>{@link BeanContextBuilder#bpro(Map)} 885 * <li class='jm'>{@link BeanFilterBuilder#bpro(String...)} 886 * </ul> 887 * </ul> 888 * 889 * <h5 class='section'>Description:</h5> 890 * <p> 891 * Specifies one or more properties on a bean that are read-only despite having valid getters. 892 * Serializers will serialize such properties as usual, but parsers will silently ignore them. 893 * 894 * <p> 895 * The keys are either fully-qualified or simple class names, and the values are comma-delimited lists of property 896 * names. 897 * The key <js>"*"</js> means all bean classes. 898 * 899 * <p> 900 * For example, <code>{Bean1:<js>'foo,bar'</js>}</code> means the <c>foo</c> and 901 * <c>bar</c> properties on any beans whose simple class name is <c>Bean1</c>. 902 * 903 * <p> 904 * Setting applies to specified class and all subclasses. 905 * 906 * <h5 class='section'>Example:</h5> 907 * <p class='bcode w800'> 908 * <jc>// Create a parser that excludes the 'foo' and 'bar' properties on the MyBean class.</jc> 909 * ReaderParser p = JsonParser 910 * .<jsm>create</jsm>() 911 * .bpro(MyBean.<jk>class</jk>, <js>"foo,bar"</js>) 912 * .build(); 913 * 914 * <jc>// Same, but use property.</jc> 915 * ReaderParser p = JsonParser 916 * .<jsm>create</jsm>() 917 * .addTo(<jsf>BEAN_bpro</jsf>, MyBean.<jk>class</jk>.getName(), <js>"foo,bar"</js>) 918 * .build(); 919 * 920 * <jc>// Alternate using JSON object.</jc> 921 * ReaderParser p = JsonParser 922 * .<jsm>create</jsm>() 923 * .addTo(<jsf>BEAN_bpro</jsf>, <js>"{'org.apache.MyBean':'foo,bar'}"</js>) 924 * .build(); 925 * </p> 926 */ 927 public static final String BEAN_bpro = PREFIX + ".bpro.sms"; 928 929 /** 930 * Configuration property: Write-only bean properties. 931 * 932 * <h5 class='section'>Property:</h5> 933 * <ul> 934 * <li><b>Name:</b> <js>"BeanContext.bpwo.sms"</js> 935 * <li><b>Data type:</b> <c>Map<String,String></c> 936 * <li><b>Default:</b> <c>{}</c> 937 * <li><b>Session property:</b> <jk>false</jk> 938 * <li><b>Annotations:</b> 939 * <ul> 940 * <li class='ja'>{@link Bean#bpwo()} 941 * <li class='ja'>{@link Beanp#wo()} 942 * </ul> 943 * <li><b>Methods:</b> 944 * <ul> 945 * <li class='jm'>{@link BeanContextBuilder#bpwo(Class, String)} 946 * <li class='jm'>{@link BeanContextBuilder#bpwo(String, String)} 947 * <li class='jm'>{@link BeanContextBuilder#bpwo(Map)} 948 * <li class='jm'>{@link BeanFilterBuilder#bpwo(String...)} 949 * </ul> 950 * </ul> 951 * 952 * <h5 class='section'>Description:</h5> 953 * <p> 954 * Specifies one or more properties on a bean that are write-only despite having valid setters. 955 * Parsers will parse such properties as usual, but serializers will silently ignore them. 956 * 957 * <p> 958 * The keys are either fully-qualified or simple class names, and the values are comma-delimited lists of property 959 * names. 960 * The key <js>"*"</js> means all bean classes. 961 * 962 * <p> 963 * For example, <code>{Bean1:<js>'foo,bar'</js>}</code> means the <c>foo</c> and 964 * <c>bar</c> properties on any beans whose simple class name is <c>Bean1</c>. 965 * 966 * <p> 967 * Setting applies to specified class and all subclasses. 968 * 969 * <h5 class='section'>Example:</h5> 970 * <p class='bcode w800'> 971 * <jc>// Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class.</jc> 972 * WriterSerializer s = JsonSerializer 973 * .<jsm>create</jsm>() 974 * .bpwo(MyBean.<jk>class</jk>, <js>"foo,bar"</js>) 975 * .build(); 976 * 977 * <jc>// Same, but use property.</jc> 978 * WriterSerializer s = JsonSerializer 979 * .<jsm>create</jsm>() 980 * .addTo(<jsf>BEAN_bpwo</jsf>, MyBean.<jk>class</jk>.getName(), <js>"foo,bar"</js>) 981 * .build(); 982 * 983 * <jc>// Alternate using JSON object.</jc> 984 * WriterSerializer s = JsonSerializer 985 * .<jsm>create</jsm>() 986 * .addTo(<jsf>BEAN_bpwo</jsf>, <js>"{'org.apache.MyBean':'foo,bar'}"</js>) 987 * .build(); 988 * </p> 989 */ 990 public static final String BEAN_bpwo = PREFIX + ".bpwo.sms"; 991 992 /** 993 * Configuration property: Debug mode. 994 * 995 * <h5 class='section'>Property:</h5> 996 * <ul> 997 * <li><b>Name:</b> <js>"BeanContext.debug.b"</js> 998 * <li><b>Data type:</b> <c>Boolean</c> 999 * <li><b>Default:</b> <jk>false</jk> 1000 * <li><b>Session property:</b> <jk>true</jk> 1001 * <li><b>Methods:</b> 1002 * <ul> 1003 * <li class='jm'>{@link BeanContextBuilder#debug(boolean)} 1004 * <li class='jm'>{@link BeanContextBuilder#debug()} 1005 * <li class='jm'>{@link BeanSessionArgs#debug(Boolean)} 1006 * </ul> 1007 * </ul> 1008 * 1009 * <h5 class='section'>Description:</h5> 1010 * <p> 1011 * Enables the following additional information during serialization: 1012 * <ul class='spaced-list'> 1013 * <li> 1014 * When bean getters throws exceptions, the exception includes the object stack information 1015 * in order to determine how that method was invoked. 1016 * <li> 1017 * Enables {@link Serializer#BEANTRAVERSE_detectRecursions}. 1018 * </ul> 1019 * 1020 * <p> 1021 * Enables the following additional information during parsing: 1022 * <ul class='spaced-list'> 1023 * <li> 1024 * When bean setters throws exceptions, the exception includes the object stack information 1025 * in order to determine how that method was invoked. 1026 * </ul> 1027 * 1028 * <h5 class='section'>Example:</h5> 1029 * <p class='bcode w800'> 1030 * <jc>// Create a serializer with debug enabled.</jc> 1031 * WriterSerializer s = JsonSerializer 1032 * .<jsm>create</jsm>() 1033 * .debug() 1034 * .build(); 1035 * 1036 * <jc>// Same, but use property.</jc> 1037 * WriterSerializer s = JsonSerializer 1038 * .<jsm>create</jsm>() 1039 * .set(<jsf>BEAN_debug</jsf>, <jk>true</jk>) 1040 * .build(); 1041 * </p> 1042 */ 1043 public static final String BEAN_debug = PREFIX + ".debug.b"; 1044 1045 /** 1046 * Configuration property: POJO examples. 1047 * 1048 * <h5 class='section'>Property:</h5> 1049 * <ul> 1050 * <li><b>Name:</b> <js>"BeanContext.examples.smo"</js> 1051 * <li><b>Data type:</b> <c>Map<String,Object></c> 1052 * <li><b>Default:</b> <c>{}</c> 1053 * <li><b>Session property:</b> <jk>false</jk> 1054 * <li><b>Annotations:</b> 1055 * <ul> 1056 * <li class='ja'>{@link Example} 1057 * </ul> 1058 * <li><b>Methods:</b> 1059 * <ul> 1060 * <li class='jm'>{@link BeanContextBuilder#example(Class,Object)} 1061 * </ul> 1062 * </ul> 1063 * 1064 * <h5 class='section'>Description:</h5> 1065 * <p> 1066 * Specifies an example of the specified class. 1067 * 1068 * <p> 1069 * Examples are used in cases such as POJO examples in Swagger documents. 1070 * 1071 * <p> 1072 * Setting applies to specified class and all subclasses. 1073 * 1074 * <h5 class='section'>Example:</h5> 1075 * <p class='bcode w800'> 1076 * <jc>// Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class.</jc> 1077 * WriterSerializer s = JsonSerializer 1078 * .<jsm>create</jsm>() 1079 * .example(MyBean.<jk>class</jk>, <jk>new</jk> MyBean().foo(<js>"foo"</js>).bar(123)) 1080 * .build(); 1081 * 1082 * <jc>// Same, but use property.</jc> 1083 * WriterSerializer s = JsonSerializer 1084 * .<jsm>create</jsm>() 1085 * .addTo(<jsf>BEAN_examples</jsf>, MyBean.<jk>class</jk>.getName(), <jk>new</jk> MyBean().foo(<js>"foo"</js>).bar(123)) 1086 * .build(); 1087 * </p> 1088 * 1089 * <p> 1090 * POJO examples can also be defined on classes via the following: 1091 * <ul class='spaced-list'> 1092 * <li>A static field annotated with {@link Example @Example}. 1093 * <li>A static method annotated with {@link Example @Example} with zero arguments or one {@link BeanSession} argument. 1094 * <li>A static method with name <c>example</c> with no arguments or one {@link BeanSession} argument. 1095 * </ul> 1096 */ 1097 public static final String BEAN_examples = PREFIX + ".examples.smo"; 1098 1099 /** 1100 * Configuration property: Bean property excludes. 1101 * 1102 * @deprecated Use {@link #BEAN_bpx} 1103 */ 1104 @Deprecated public static final String BEAN_excludeProperties = BEAN_bpx; 1105 1106 /** 1107 * Configuration property: Find fluent setters. 1108 * 1109 * <h5 class='section'>Property:</h5> 1110 * <ul> 1111 * <li><b>Name:</b> <js>"BeanContext.fluentSetters.b"</js> 1112 * <li><b>Data type:</b> <c>Boolean</c> 1113 * <li><b>Default:</b> <jk>false</jk> 1114 * <li><b>Session property:</b> <jk>false</jk> 1115 * <li><b>Annotations:</b> 1116 * <ul> 1117 * <li class='ja'>{@link Bean#fluentSetters()} 1118 * </ul> 1119 * <li><b>Methods:</b> 1120 * <ul> 1121 * <li class='jm'>{@link BeanContextBuilder#fluentSetters(boolean)} 1122 * <li class='jm'>{@link BeanContextBuilder#fluentSetters()} 1123 * <li class='jm'>{@link BeanFilterBuilder#fluentSetters(boolean)} 1124 * <li class='jm'>{@link BeanFilterBuilder#fluentSetters()} 1125 * </ul> 1126 * </ul> 1127 * 1128 * <h5 class='section'>Description:</h5> 1129 * <p> 1130 * When enabled, fluent setters are detected on beans. 1131 * 1132 * <p> 1133 * Fluent setters must have the following attributes: 1134 * <ul> 1135 * <li>Public. 1136 * <li>Not static. 1137 * <li>Take in one parameter. 1138 * <li>Return the bean itself. 1139 * </ul> 1140 * 1141 * <h5 class='section'>Example:</h5> 1142 * <p class='bcode w800'> 1143 * <jc>// Create a serializer that finds fluent setters.</jc> 1144 * WriterSerializer s = JsonSerializer 1145 * .<jsm>create</jsm>() 1146 * .fluentSetters() 1147 * .build(); 1148 * 1149 * <jc>// Same, but use property.</jc> 1150 * WriterSerializer s = JsonSerializer 1151 * .<jsm>create</jsm>() 1152 * .set(<jsf>BEAN_fluentSetters</jsf>, <jk>true</jk>) 1153 * .build(); 1154 * </p> 1155 */ 1156 public static final String BEAN_fluentSetters = PREFIX + ".fluentSetters.b"; 1157 1158 /** 1159 * Configuration property: Ignore invocation errors on getters. 1160 * 1161 * <h5 class='section'>Property:</h5> 1162 * <ul> 1163 * <li><b>Name:</b> <js>"BeanContext.ignoreInvocationExceptionsOnGetters.b"</js> 1164 * <li><b>Data type:</b> <c>Boolean</c> 1165 * <li><b>Default:</b> <jk>false</jk> 1166 * <li><b>Session property:</b> <jk>false</jk> 1167 * <li><b>Methods:</b> 1168 * <ul> 1169 * <li class='jm'>{@link BeanContextBuilder#ignoreInvocationExceptionsOnGetters(boolean)} 1170 * <li class='jm'>{@link BeanContextBuilder#ignoreInvocationExceptionsOnGetters()} 1171 * </ul> 1172 * </ul> 1173 * 1174 * <h5 class='section'>Description:</h5> 1175 * <p> 1176 * If <jk>true</jk>, errors thrown when calling bean getter methods will silently be ignored. 1177 * <br>Otherwise, a {@code BeanRuntimeException} is thrown. 1178 * 1179 * <h5 class='section'>Example:</h5> 1180 * <p class='bcode w800'> 1181 * <jc>// Create a serializer that ignores bean getter exceptions.</jc> 1182 * WriterSerializer s = JsonSerializer 1183 * .<jsm>create</jsm>() 1184 * .ingoreInvocationExceptionsOnGetters() 1185 * .build(); 1186 * 1187 * <jc>// Same, but use property.</jc> 1188 * WriterSerializer s = JsonSerializer 1189 * .<jsm>create</jsm>() 1190 * .set(<jsf>BEAN_ignoreInvocationExceptionsOnGetters</jsf>, <jk>true</jk>) 1191 * .build(); 1192 * </p> 1193 */ 1194 public static final String BEAN_ignoreInvocationExceptionsOnGetters = PREFIX + ".ignoreInvocationExceptionsOnGetters.b"; 1195 1196 /** 1197 * Configuration property: Ignore invocation errors on setters. 1198 * 1199 * <h5 class='section'>Property:</h5> 1200 * <ul> 1201 * <li><b>Name:</b> <js>"BeanContext.ignoreInvocationExceptionsOnSetters.b"</js> 1202 * <li><b>Data type:</b> <c>Boolean</c> 1203 * <li><b>Default:</b> <jk>false</jk> 1204 * <li><b>Session property:</b> <jk>false</jk> 1205 * <li><b>Methods:</b> 1206 * <ul> 1207 * <li class='jm'>{@link BeanContextBuilder#ignoreInvocationExceptionsOnSetters(boolean)} 1208 * <li class='jm'>{@link BeanContextBuilder#ignoreInvocationExceptionsOnSetters()} 1209 * </ul> 1210 * </ul> 1211 * 1212 * <h5 class='section'>Description:</h5> 1213 * <p> 1214 * If <jk>true</jk>, errors thrown when calling bean setter methods will silently be ignored. 1215 * <br>Otherwise, a {@code BeanRuntimeException} is thrown. 1216 * 1217 * <h5 class='section'>Example:</h5> 1218 * <p class='bcode w800'> 1219 * <jc>// Create a parser that ignores bean setter exceptions.</jc> 1220 * ReaderParser p = JsonParser 1221 * .<jsm>create</jsm>() 1222 * .ignoreInvocationExceptionsOnSetters() 1223 * .build(); 1224 * 1225 * <jc>// Same, but use property.</jc> 1226 * ReaderParser p = JsonParser 1227 * .<jsm>create</jsm>() 1228 * .set(<jsf>BEAN_ignoreInvocationExceptionsOnSetters</jsf>, <jk>true</jk>) 1229 * .build(); 1230 * </p> 1231 */ 1232 public static final String BEAN_ignoreInvocationExceptionsOnSetters = PREFIX + ".ignoreInvocationExceptionsOnSetters.b"; 1233 1234 /** 1235 * Configuration property: Ignore properties without setters. 1236 * 1237 * <h5 class='section'>Property:</h5> 1238 * <ul> 1239 * <li><b>Name:</b> <js>"BeanContext.ignorePropertiesWithoutSetters.b"</js> 1240 * <li><b>Data type:</b> <c>Boolean</c> 1241 * <li><b>Default:</b> <jk>true</jk> 1242 * <li><b>Session property:</b> <jk>false</jk> 1243 * <li><b>Methods:</b> 1244 * <ul> 1245 * <li class='jm'>{@link BeanContextBuilder#ignorePropertiesWithoutSetters(boolean)} 1246 * </ul> 1247 * </ul> 1248 * 1249 * <h5 class='section'>Description:</h5> 1250 * <p> 1251 * If <jk>true</jk>, trying to set a value on a bean property without a setter will silently be ignored. 1252 * <br>Otherwise, a {@code RuntimeException} is thrown. 1253 * 1254 * <h5 class='section'>Example:</h5> 1255 * <p class='bcode w800'> 1256 * <jc>// Create a parser that throws an exception if a setter is not found but a getter is.</jc> 1257 * ReaderParser p = JsonParser 1258 * .<jsm>create</jsm>() 1259 * .ignorePropertiesWithoutSetters(<jk>false</jk>) 1260 * .build(); 1261 * 1262 * <jc>// Same, but use property.</jc> 1263 * ReaderParser p = JsonParser 1264 * .<jsm>create</jsm>() 1265 * .set(<jsf>BEAN_ignorePropertiesWithoutSetters</jsf>, <jk>false</jk>) 1266 * .build(); 1267 * </p> 1268 */ 1269 public static final String BEAN_ignorePropertiesWithoutSetters = PREFIX + ".ignorePropertiesWithoutSetters.b"; 1270 1271 /** 1272 * Configuration property: Ignore unknown properties. 1273 * 1274 * <h5 class='section'>Property:</h5> 1275 * <ul> 1276 * <li><b>Name:</b> <js>"BeanContext.ignoreUnknownBeanProperties.b"</js> 1277 * <li><b>Data type:</b> <c>Boolean</c> 1278 * <li><b>Default:</b> <jk>false</jk> 1279 * <li><b>Session property:</b> <jk>false</jk> 1280 * <li><b>Methods:</b> 1281 * <ul> 1282 * <li class='jm'>{@link BeanContextBuilder#ignoreUnknownBeanProperties(boolean)} 1283 * <li class='jm'>{@link BeanContextBuilder#ignoreUnknownBeanProperties()} 1284 * </ul> 1285 * </ul> 1286 * 1287 * <h5 class='section'>Description:</h5> 1288 * <p> 1289 * If <jk>true</jk>, trying to set a value on a non-existent bean property will silently be ignored. 1290 * <br>Otherwise, a {@code RuntimeException} is thrown. 1291 * 1292 * <h5 class='section'>Example:</h5> 1293 * <p class='bcode w800'> 1294 * <jc>// Create a parser that ignores missing bean properties.</jc> 1295 * ReaderParser p = JsonParser 1296 * .<jsm>create</jsm>() 1297 * .ignoreUnknownBeanProperties() 1298 * .build(); 1299 * 1300 * <jc>// Same, but use property.</jc> 1301 * ReaderParser p = JsonParser 1302 * .<jsm>create</jsm>() 1303 * .set(<jsf>BEAN_ignoreUnknownBeanProperties</jsf>, <jk>true</jk>) 1304 * .build(); 1305 * </p> 1306 */ 1307 public static final String BEAN_ignoreUnknownBeanProperties = PREFIX + ".ignoreUnknownBeanProperties.b"; 1308 1309 /** 1310 * Configuration property: Ignore unknown properties with null values. 1311 * 1312 * <h5 class='section'>Property:</h5> 1313 * <ul> 1314 * <li><b>Name:</b> <js>"BeanContext.ignoreUnknownNullBeanProperties.b"</js> 1315 * <li><b>Data type:</b> <c>Boolean</c> 1316 * <li><b>Default:</b> <jk>true</jk> 1317 * <li><b>Session property:</b> <jk>false</jk> 1318 * <li><b>Methods:</b> 1319 * <ul> 1320 * <li class='jm'>{@link BeanContextBuilder#ignoreUnknownNullBeanProperties(boolean)} 1321 * </ul> 1322 * </ul> 1323 * 1324 * <h5 class='section'>Description:</h5> 1325 * <p> 1326 * If <jk>true</jk>, trying to set a <jk>null</jk> value on a non-existent bean property will silently be ignored. 1327 * <br>Otherwise, a {@code RuntimeException} is thrown. 1328 * 1329 * <h5 class='section'>Example:</h5> 1330 * <p class='bcode w800'> 1331 * <jc>// Create a parser that throws an exception on an unknown property even if the value being set is null.</jc> 1332 * ReaderParser p = JsonParser 1333 * .<jsm>create</jsm>() 1334 * .ignoreUnknownNullBeanProperties(<jk>false</jk>) 1335 * .build(); 1336 * 1337 * <jc>// Same, but use property.</jc> 1338 * ReaderParser p = JsonParser 1339 * .<jsm>create</jsm>() 1340 * .set(<jsf>BEAN_ignoreUnknownNullBeanProperties</jsf>, <jk>false</jk>) 1341 * .build(); 1342 * </p> 1343 */ 1344 public static final String BEAN_ignoreUnknownNullBeanProperties = PREFIX + ".ignoreUnknownNullBeanProperties.b"; 1345 1346 /** 1347 * Configuration property: Implementation classes. 1348 * 1349 * <h5 class='section'>Property:</h5> 1350 * <ul> 1351 * <li><b>Name:</b> <js>"BeanContext.implClasses.smc"</js> 1352 * <li><b>Data type:</b> <c>Map<String,Class></c> 1353 * <li><b>Default:</b> empty map 1354 * <li><b>Session property:</b> <jk>false</jk> 1355 * <li><b>Methods:</b> 1356 * <ul> 1357 * <li class='jm'>{@link BeanContextBuilder#implClasses(Map)} 1358 * <li class='jm'>{@link BeanContextBuilder#implClass(Class, Class)} 1359 * </ul> 1360 * </ul> 1361 * 1362 * <h5 class='section'>Description:</h5> 1363 * <p> 1364 * For interfaces and abstract classes this method can be used to specify an implementation class for the 1365 * interface/abstract class so that instances of the implementation class are used when instantiated (e.g. during a 1366 * parse). 1367 * 1368 * <h5 class='section'>Example:</h5> 1369 * <p class='bcode w800'> 1370 * <jc>// Create a parser that instantiates MyBeanImpls when parsing MyBeanInterfaces.</jc> 1371 * ReaderParser p = JsonParser 1372 * .<jsm>create</jsm>() 1373 * .implClass(MyBeanInterface.<jk>class</jk>, MyBeanImpl.<jk>class</jk>) 1374 * .build(); 1375 * 1376 * <jc>// Same, but use property.</jc> 1377 * ReaderParser p = JsonParser 1378 * .<jsm>create</jsm>() 1379 * .addTo(<jsf>BEAN_implClasses</jsf>, MyBeanInterface.<jk>class</jk>.getName(), MyBeanImpl.<jk>class</jk>) 1380 * .build(); 1381 * </p> 1382 */ 1383 public static final String BEAN_implClasses = PREFIX + ".implClasses.smc"; 1384 1385 /** 1386 * Configuration property: Bean property includes. 1387 * 1388 * @deprecated Use {@link #BEAN_bpi} 1389 */ 1390 @Deprecated public static final String BEAN_includeProperties = BEAN_bpi; 1391 1392 /** 1393 * Configuration property: Locale. 1394 * 1395 * <h5 class='section'>Property:</h5> 1396 * <ul> 1397 * <li><b>Name:</b> <js>"BeanContext.locale.s"</js> 1398 * <li><b>Data type:</b> <c>String</c> ({@link Locale}) 1399 * <li><b>Default:</b> <jk>null</jk> (defaults to {@link Locale#getDefault()}) 1400 * <li><b>Session property:</b> <jk>true</jk> 1401 * <li><b>Methods:</b> 1402 * <ul> 1403 * <li class='jm'>{@link BeanContextBuilder#locale(Locale)} 1404 * <li class='jm'>{@link BeanSessionArgs#locale(Locale)} 1405 * </ul> 1406 * </ul> 1407 * 1408 * <h5 class='section'>Description:</h5> 1409 * <p> 1410 * Specifies the default locale for serializer and parser sessions. 1411 * 1412 * <h5 class='section'>Example:</h5> 1413 * <p class='bcode w800'> 1414 * <jc>// Create a serializer that uses the specified locale if it's not passed in through session args.</jc> 1415 * WriterSerializer s = JsonSerializer 1416 * .<jsm>create</jsm>() 1417 * .locale(Locale.<jsf>UK</jsf>) 1418 * .build(); 1419 * 1420 * <jc>// Same, but use property.</jc> 1421 * WriterSerializer s = JsonSerializer 1422 * .<jsm>create</jsm>() 1423 * .set(<jsf>BEAN_locale</jsf>, Locale.<jsf>UK</jsf>) 1424 * .build(); 1425 * 1426 * <jc>// Define on session-args instead.</jc> 1427 * SerializerSessionArgs sessionArgs = <jk>new</jk> SerializerSessionArgs().locale(Locale.<jsf>UK</jsf>); 1428 * <jk>try</jk> (WriterSerializerSession session = s.createSession(sessionArgs)) { 1429 * ... 1430 * } 1431 * </p> 1432 */ 1433 public static final String BEAN_locale = PREFIX + ".locale.s"; 1434 1435 /** 1436 * Configuration property: Media type. 1437 * 1438 * <h5 class='section'>Property:</h5> 1439 * <ul> 1440 * <li><b>Name:</b> <js>"BeanContext.mediaType.s"</js> 1441 * <li><b>Data type:</b> <c>String</c> ({@link MediaType}) 1442 * <li><b>Default:</b> <jk>null</jk> 1443 * <li><b>Session property:</b> <jk>true</jk> 1444 * <li><b>Methods:</b> 1445 * <ul> 1446 * <li class='jm'>{@link BeanContextBuilder#mediaType(MediaType)} 1447 * <li class='jm'>{@link BeanSessionArgs#mediaType(MediaType)} 1448 * </ul> 1449 * </ul> 1450 * 1451 * <h5 class='section'>Description:</h5> 1452 * <p> 1453 * Specifies the default media type value for serializer and parser sessions. 1454 * 1455 * <h5 class='section'>Example:</h5> 1456 * <p class='bcode w800'> 1457 * <jc>// Create a serializer that uses the specified media type if it's not passed in through session args.</jc> 1458 * WriterSerializer s = JsonSerializer 1459 * .<jsm>create</jsm>() 1460 * .mediaType(MediaType.<jsf>JSON</jsf>) 1461 * .build(); 1462 * 1463 * <jc>// Same, but use property.</jc> 1464 * WriterSerializer s = JsonSerializer 1465 * .<jsm>create</jsm>() 1466 * .set(<jsf>BEAN_mediaType</jsf>, MediaType.<jsf>JSON</jsf>) 1467 * .build(); 1468 * 1469 * <jc>// Define on session-args instead.</jc> 1470 * SerializerSessionArgs sessionArgs = <jk>new</jk> SerializerSessionArgs().mediaType(MediaType.<jsf>JSON</jsf>); 1471 * <jk>try</jk> (WriterSerializerSession session = s.createSession(sessionArgs)) { 1472 * ... 1473 * } 1474 * </p> 1475 */ 1476 public static final String BEAN_mediaType = PREFIX + ".mediaType.s"; 1477 1478 /** 1479 * Configuration property: Bean class exclusions. 1480 * 1481 * <h5 class='section'>Property:</h5> 1482 * <ul> 1483 * <li><b>Name:</b> <js>"BeanContext.notBeanClasses.sc"</js> 1484 * <li><b>Data type:</b> <c>Set<Class></c> 1485 * <li><b>Default:</b> empty set 1486 * <li><b>Session property:</b> <jk>false</jk> 1487 * <li><b>Annotations:</b> 1488 * <ul> 1489 * <li class='ja'>{@link BeanIgnore} 1490 * </ul> 1491 * <li><b>Methods:</b> 1492 * <ul> 1493 * <li class='jm'>{@link BeanContextBuilder#notBeanClasses(Class...)} 1494 * <li class='jm'>{@link BeanContextBuilder#notBeanClasses(Object...)} 1495 * <li class='jm'>{@link BeanContextBuilder#notBeanClassesReplace(Class...)} 1496 * <li class='jm'>{@link BeanContextBuilder#notBeanClassesReplace(Object...)} 1497 * <li class='jm'>{@link BeanContextBuilder#notBeanClassesRemove(Class...)} 1498 * <li class='jm'>{@link BeanContextBuilder#notBeanClassesRemove(Object...)} 1499 * </ul> 1500 * </ul> 1501 * 1502 * <h5 class='section'>Description:</h5> 1503 * <p> 1504 * List of classes that should not be treated as beans even if they appear to be bean-like. 1505 * <br>Not-bean classes are converted to <c>Strings</c> during serialization. 1506 * 1507 * <p> 1508 * Values can consist of any of the following types: 1509 * <ul> 1510 * <li>Classes. 1511 * <li>Arrays and collections of classes. 1512 * </ul> 1513 * 1514 * <h5 class='section'>Example:</h5> 1515 * <p class='bcode w800'> 1516 * <jc>// Create a serializer that doesn't treat MyBean as a bean class.</jc> 1517 * WriterSerializer s = JsonSerializer 1518 * .<jsm>create</jsm>() 1519 * .notBeanClasses(MyBean.<jk>class</jk>) 1520 * .build(); 1521 * 1522 * <jc>// Same, but use property.</jc> 1523 * WriterSerializer s = JsonSerializer 1524 * .<jsm>create</jsm>() 1525 * .addTo(<jsf>BEAN_notBeanClasses</jsf>, MyBean.<jk>class</jk>) 1526 * .build(); 1527 * </p> 1528 */ 1529 public static final String BEAN_notBeanClasses = PREFIX + ".notBeanClasses.sc"; 1530 1531 /** 1532 * Configuration property: Add to classes that should not be considered beans. 1533 */ 1534 public static final String BEAN_notBeanClasses_add = PREFIX + ".notBeanClasses.sc/add"; 1535 1536 /** 1537 * Configuration property: Remove from classes that should not be considered beans. 1538 */ 1539 public static final String BEAN_notBeanClasses_remove = PREFIX + ".notBeanClasses.sc/remove"; 1540 1541 /** 1542 * Configuration property: Bean package exclusions. 1543 * 1544 * <h5 class='section'>Property:</h5> 1545 * <ul> 1546 * <li><b>Name:</b> <js>"BeanContext.notBeanPackages.ss"</js> 1547 * <li><b>Data type:</b> <c>Set<String></c> 1548 * <li><b>Default:</b> 1549 * <ul> 1550 * <li><c>java.lang</c> 1551 * <li><c>java.lang.annotation</c> 1552 * <li><c>java.lang.ref</c> 1553 * <li><c>java.lang.reflect</c> 1554 * <li><c>java.io</c> 1555 * <li><c>java.net</c> 1556 * <li><c>java.nio.*</c> 1557 * <li><c>java.util.*</c> 1558 * </ul> 1559 * <li><b>Session property:</b> <jk>false</jk> 1560 * <li><b>Methods:</b> 1561 * <ul> 1562 * <li class='jm'>{@link BeanContextBuilder#notBeanPackages(Object...)} 1563 * <li class='jm'>{@link BeanContextBuilder#notBeanPackages(String...)} 1564 * <li class='jm'>{@link BeanContextBuilder#notBeanPackagesReplace(Object...)} 1565 * <li class='jm'>{@link BeanContextBuilder#notBeanPackagesReplace(String...)} 1566 * <li class='jm'>{@link BeanContextBuilder#notBeanPackagesRemove(Object...)} 1567 * <li class='jm'>{@link BeanContextBuilder#notBeanPackagesRemove(String...)} 1568 * </ul> 1569 * </ul> 1570 * 1571 * <h5 class='section'>Description:</h5> 1572 * <p> 1573 * When specified, the current list of ignore packages are appended to. 1574 * 1575 * <p> 1576 * Any classes within these packages will be serialized to strings using {@link Object#toString()}. 1577 * 1578 * <p> 1579 * Note that you can specify suffix patterns to include all subpackages. 1580 * 1581 * <p> 1582 * Values can consist of any of the following types: 1583 * <ul> 1584 * <li>Strings. 1585 * <li>Arrays and collections of strings. 1586 * </ul> 1587 * 1588 * <h5 class='section'>Example:</h5> 1589 * <p class='bcode w800'> 1590 * <jc>// Create a serializer that ignores beans in the specified packages.</jc> 1591 * WriterSerializer s = JsonSerializer 1592 * .<jsm>create</jsm>() 1593 * .notBeanPackages(<js>"org.apache.foo"</js>, <js>"org.apache.bar.*"</js>) 1594 * .build(); 1595 * 1596 * <jc>// Same, but use property.</jc> 1597 * WriterSerializer s = JsonSerializer 1598 * .<jsm>create</jsm>() 1599 * .addTo(<jsf>BEAN_notBeanPackages</jsf>, <js>"org.apache.foo"</js>) 1600 * .addTo(<jsf>BEAN_notBeanPackages</jsf>, <js>"org.apache.bar.*"</js>) 1601 * .build(); 1602 * </p> 1603 */ 1604 public static final String BEAN_notBeanPackages = PREFIX + ".notBeanPackages.ss"; 1605 1606 /** 1607 * Configuration property: Add to packages whose classes should not be considered beans. 1608 */ 1609 public static final String BEAN_notBeanPackages_add = PREFIX + ".notBeanPackages.ss/add"; 1610 1611 /** 1612 * Configuration property: Remove from packages whose classes should not be considered beans. 1613 */ 1614 public static final String BEAN_notBeanPackages_remove = PREFIX + ".notBeanPackages.ss/remove"; 1615 1616 /** 1617 * Configuration property: POJO swaps. 1618 * 1619 * <h5 class='section'>Property:</h5> 1620 * <ul> 1621 * <li><b>Name:</b> <js>"BeanContext.pojoSwaps.lo"</js> 1622 * <li><b>Data type:</b> <c>List<Object></c> 1623 * <li><b>Default:</b> empty list 1624 * <li><b>Session property:</b> <jk>false</jk> 1625 * <li><b>Annotations:</b> 1626 * <ul> 1627 * <li class='ja'>{@link Swap} 1628 * <li class='ja'>{@link Swaps} 1629 * </ul> 1630 * <li><b>Methods:</b> 1631 * <ul> 1632 * <li class='jm'>{@link BeanContextBuilder#pojoSwaps(Object...)} 1633 * <li class='jm'>{@link BeanContextBuilder#pojoSwaps(Class...)} 1634 * <li class='jm'>{@link BeanContextBuilder#pojoSwapsReplace(Object...)} 1635 * <li class='jm'>{@link BeanContextBuilder#pojoSwapsReplace(Class...)} 1636 * <li class='jm'>{@link BeanContextBuilder#pojoSwapsRemove(Object...)} 1637 * <li class='jm'>{@link BeanContextBuilder#pojoSwapsRemove(Class...)} 1638 * </ul> 1639 * </ul> 1640 * 1641 * <h5 class='section'>Description:</h5> 1642 * <p> 1643 * POJO swaps are used to "swap out" non-serializable classes with serializable equivalents during serialization, 1644 * and "swap in" the non-serializable class during parsing. 1645 * 1646 * <p> 1647 * An example of a POJO swap would be a <c>Calendar</c> object that gets swapped out for an ISO8601 string. 1648 * 1649 * <p> 1650 * Multiple POJO swaps can be associated with a single class. 1651 * <br>When multiple swaps are applicable to the same class, the media type pattern defined by 1652 * {@link PojoSwap#forMediaTypes()} or {@link Swap#mediaTypes() @Swap(mediaTypes)} are used to come up with the best match. 1653 * 1654 * <p> 1655 * Values can consist of any of the following types: 1656 * <ul> 1657 * <li>Any subclass of {@link PojoSwap}. 1658 * <li>Any instance of {@link PojoSwap}. 1659 * <li>Any surrogate class. A shortcut for defining a {@link SurrogateSwap}. 1660 * <li>Any array or collection of the objects above. 1661 * </ul> 1662 * 1663 * <h5 class='section'>Example:</h5> 1664 * <p class='bcode w800'> 1665 * <jc>// Sample swap for converting Dates to ISO8601 strings.</jc> 1666 * <jk>public class</jk> MyDateSwap <jk>extends</jk> StringSwap<Date> { 1667 * <jc>// ISO8601 formatter.</jc> 1668 * <jk>private</jk> DateFormat <jf>format</jf> = <jk>new</jk> SimpleDateFormat(<js>"yyyy-MM-dd'T'HH:mm:ssZ"</js>); 1669 * 1670 * <ja>@Override</ja> 1671 * <jk>public</jk> String swap(BeanSession session, Date o) { 1672 * <jk>return</jk> <jf>format</jf>.format(o); 1673 * } 1674 * 1675 * <ja>@Override</ja> 1676 * <jk>public</jk> Date unswap(BeanSession session, String o, ClassMeta hint) <jk>throws</jk> Exception { 1677 * <jk>return</jk> <jf>format</jf>.parse(o); 1678 * } 1679 * } 1680 * 1681 * <jc>// Sample bean with a Date field.</jc> 1682 * <jk>public class</jk> MyBean { 1683 * <jk>public</jk> Date <jf>date</jf> = <jk>new</jk> Date(112, 2, 3, 4, 5, 6); 1684 * } 1685 * 1686 * <jc>// Create a serializer that uses our date swap.</jc> 1687 * WriterSerializer s = JsonSerializer 1688 * .<jsm>create</jsm>() 1689 * .pojoSwaps(MyDateSwap.<jk>class</jk>) 1690 * .build(); 1691 * 1692 * <jc>// Same, but use property.</jc> 1693 * WriterSerializer s = JsonSerializer 1694 * .<jsm>create</jsm>() 1695 * .addTo(<jsf>BEAN_pojoSwaps</jsf>, MyDateSwap.<jk>class</jk>) 1696 * .build(); 1697 * 1698 * <jc>// Produces "{date:'2012-03-03T04:05:06-0500'}"</jc> 1699 * String json = s.serialize(<jk>new</jk> MyBean()); 1700 * 1701 * <jc>// Create a serializer that uses our date swap.</jc> 1702 * ReaderParser p = JsonParser 1703 * .<jsm>create</jsm>() 1704 * .pojoSwaps(MyDateSwap.<jk>class</jk>) 1705 * .build(); 1706 * 1707 * <jc>// Use our parser to parse a bean.</jc> 1708 * MyBean bean = p.parse(json, MyBean.<jk>class</jk>); 1709 * </p> 1710 * 1711 * <ul class='seealso'> 1712 * <li class='link'>{@doc juneau-marshall.Transforms.PojoSwaps} 1713 * <li class='link'>{@doc juneau-marshall.Transforms.PerMediaTypePojoSwaps} 1714 * <li class='link'>{@doc juneau-marshall.Transforms.OneWayPojoSwaps} 1715 * <li class='link'>{@doc juneau-marshall.Transforms.SwapAnnotation} 1716 * <li class='link'>{@doc juneau-marshall.Transforms.AutoPojoSwaps} 1717 * <li class='link'>{@doc juneau-marshall.Transforms.SurrogateClasses} 1718 * </ul> 1719 */ 1720 public static final String BEAN_pojoSwaps = PREFIX + ".pojoSwaps.lo"; 1721 1722 /** 1723 * Configuration property: Add to POJO swap classes. 1724 */ 1725 public static final String BEAN_pojoSwaps_add = PREFIX + ".pojoSwaps.lo/add"; 1726 1727 /** 1728 * Configuration property: Remove from POJO swap classes. 1729 */ 1730 public static final String BEAN_pojoSwaps_remove = PREFIX + ".pojoSwaps.lo/remove"; 1731 1732 /** 1733 * Configuration property: Bean property namer. 1734 * 1735 * <h5 class='section'>Property:</h5> 1736 * <ul> 1737 * <li><b>Name:</b> <js>"BeanContext.propertyNamer.c"</js> 1738 * <li><b>Data type:</b> <code>Class<? <jk>implements</jk> {@link PropertyNamer}></code> 1739 * <li><b>Default:</b> {@link PropertyNamerDefault} 1740 * <li><b>Session property:</b> <jk>false</jk> 1741 * <li><b>Annotations:</b> 1742 * <ul> 1743 * <li class='ja'>{@link Bean#propertyNamer()} 1744 * </ul> 1745 * <li><b>Methods:</b> 1746 * <ul> 1747 * <li class='jm'>{@link BeanContextBuilder#propertyNamer(Class)} 1748 * <li class='jm'>{@link BeanFilterBuilder#propertyNamer(Class)} 1749 * </ul> 1750 * </ul> 1751 * 1752 * <h5 class='section'>Description:</h5> 1753 * <p> 1754 * The class to use for calculating bean property names. 1755 * 1756 * <p> 1757 * Predefined classes: 1758 * <ul> 1759 * <li>{@link PropertyNamerDefault} - Default. 1760 * <li>{@link PropertyNamerDLC} - Dashed-lower-case names. 1761 * <li>{@link PropertyNamerULC} - Dashed-upper-case names. 1762 * </ul> 1763 * 1764 * <h5 class='section'>Example:</h5> 1765 * <p class='bcode w800'> 1766 * <jc>// Create a serializer that uses Dashed-Lower-Case property names.</jc> 1767 * <jc>// (e.g. "foo-bar-url" instead of "fooBarURL")</jc> 1768 * WriterSerializer s = JsonSerializer 1769 * .<jsm>create</jsm>() 1770 * .propertyNamer(PropertyNamerDLC.<jk>class</jk>) 1771 * .build(); 1772 * 1773 * <jc>// Same, but use property.</jc> 1774 * WriterSerializer s = JsonSerializer 1775 * .<jsm>create</jsm>() 1776 * .set(<jsf>BEAN_propertyNamer</jsf>, PropertyNamerDLC.<jk>class</jk>) 1777 * .build(); 1778 * </p> 1779 */ 1780 public static final String BEAN_propertyNamer = PREFIX + ".propertyNamer.c"; 1781 1782 /** 1783 * Configuration property: Sort bean properties. 1784 * 1785 * <h5 class='section'>Property:</h5> 1786 * <ul> 1787 * <li><b>Name:</b> <js>"BeanContext.sortProperties.b"</js> 1788 * <li><b>Data type:</b> <c>Boolean</c> 1789 * <li><b>Default:</b> <jk>false</jk> 1790 * <li><b>Session property:</b> <jk>false</jk> 1791 * <li><b>Annotations:</b> 1792 * <ul> 1793 * <li class='ja'>{@link Bean#sort()} 1794 * </ul> 1795 * <li><b>Methods:</b> 1796 * <ul> 1797 * <li class='jm'>{@link BeanContextBuilder#sortProperties(boolean)} 1798 * <li class='jm'>{@link BeanContextBuilder#sortProperties()} 1799 * <li class='jm'>{@link BeanFilterBuilder#sortProperties(boolean)} 1800 * <li class='jm'>{@link BeanFilterBuilder#sortProperties()} 1801 * </ul> 1802 * </ul> 1803 * 1804 * <h5 class='section'>Description:</h5> 1805 * <p> 1806 * When <jk>true</jk>, all bean properties will be serialized and access in alphabetical order. 1807 * <br>Otherwise, the natural order of the bean properties is used which is dependent on the JVM vendor. 1808 * <br>On IBM JVMs, the bean properties are ordered based on their ordering in the Java file. 1809 * <br>On Oracle JVMs, the bean properties are not ordered (which follows the official JVM specs). 1810 * 1811 * <p> 1812 * This property is disabled by default so that IBM JVM users don't have to use {@link Bean @Bean} annotations 1813 * to force bean properties to be in a particular order and can just alter the order of the fields/methods 1814 * in the Java file. 1815 * 1816 * <h5 class='section'>Example:</h5> 1817 * <p class='bcode w800'> 1818 * <jc>// Create a serializer that sorts bean properties.</jc> 1819 * WriterSerializer s = JsonSerializer 1820 * .<jsm>create</jsm>() 1821 * .sortProperties() 1822 * .build(); 1823 * 1824 * <jc>// Same, but use property.</jc> 1825 * WriterSerializer s = JsonSerializer 1826 * .<jsm>create</jsm>() 1827 * .set(<jsf>BEAN_sortProperties</jsf>, <jk>true</jk>) 1828 * .build(); 1829 * </p> 1830 */ 1831 public static final String BEAN_sortProperties = PREFIX + ".sortProperties.b"; 1832 1833 /** 1834 * Configuration property: Time zone. 1835 * 1836 * <h5 class='section'>Property:</h5> 1837 * <ul> 1838 * <li><b>Name:</b> <js>"BeanContext.timeZone.s"</js> 1839 * <li><b>Data type:</b> <c>String</c> ({@link TimeZone}) 1840 * <li><b>Default:</b> <jk>null</jk> 1841 * <li><b>Session property:</b> <jk>true</jk> 1842 * <li><b>Methods:</b> 1843 * <ul> 1844 * <li class='jm'>{@link BeanContextBuilder#timeZone(TimeZone)} 1845 * <li class='jm'>{@link BeanSessionArgs#timeZone(TimeZone)} 1846 * </ul> 1847 * </ul> 1848 * 1849 * <h5 class='section'>Description:</h5> 1850 * <p> 1851 * Specifies the default timezone for serializer and parser sessions. 1852 * 1853 * <h5 class='section'>Example:</h5> 1854 * <p class='bcode w800'> 1855 * <jc>// Create a serializer that uses GMT if the timezone is not specified in the session args.</jc> 1856 * WriterSerializer s = JsonSerializer 1857 * .<jsm>create</jsm>() 1858 * .timeZone(TimeZone.<jsf>GMT</jsf>) 1859 * .build(); 1860 * 1861 * <jc>// Same, but use property.</jc> 1862 * WriterSerializer s = JsonSerializer 1863 * .<jsm>create</jsm>() 1864 * .set(<jsf>BEAN_timeZone</jsf>, TimeZone.<jsf>GMT</jsf>) 1865 * .build(); 1866 * 1867 * <jc>// Define on session-args instead.</jc> 1868 * SerializerSessionArgs sessionArgs = <jk>new</jk> SerializerSessionArgs().timeZone(TimeZone.<jsf>GMT</jsf>); 1869 * <jk>try</jk> (WriterSerializerSession ss = JsonSerializer.<jsf>DEFAULT</jsf>.createSession(sessionArgs)) { 1870 * String json = s.serialize(<jk>new</jk> MyBean()); 1871 * } 1872 * </p> 1873 */ 1874 public static final String BEAN_timeZone = PREFIX + ".timeZone.s"; 1875 1876 /** 1877 * Configuration property: Use enum names. 1878 * 1879 * <h5 class='section'>Property:</h5> 1880 * <ul> 1881 * <li><b>Name:</b> <js>"BeanContext.useEnumNames.b"</js> 1882 * <li><b>Data type:</b> <c>Boolean</c> 1883 * <li><b>Default:</b> <jk>false</jk> 1884 * <li><b>Session property:</b> <jk>false</jk> 1885 * <li><b>Methods:</b> 1886 * <ul> 1887 * <li class='jm'>{@link BeanContextBuilder#useEnumNames()} 1888 * </ul> 1889 * </ul> 1890 * 1891 * <h5 class='section'>Description:</h5> 1892 * <p> 1893 * When enabled, enums are always serialized by name, not using {@link Object#toString()}. 1894 * 1895 * <h5 class='section'>Example:</h5> 1896 * <p class='bcode w800'> 1897 * <jc>// Create a serializer with debug enabled.</jc> 1898 * WriterSerializer s = JsonSerializer 1899 * .<jsm>create</jsm>() 1900 * .useEnumNames() 1901 * .build(); 1902 * 1903 * <jc>// Same, but use property.</jc> 1904 * WriterSerializer s = JsonSerializer 1905 * .<jsm>create</jsm>() 1906 * .set(<jsf>BEAN_useEnumNames</jsf>, <jk>true</jk>) 1907 * .build(); 1908 * 1909 * <jc>// Enum with overridden toString().</jc> 1910 * <jc>// Will be serialized as ONE/TWO/THREE even though there's a toString() method.. 1911 * <jk>public enum</jk> Option { 1912 * <jsf>ONE</jsf>(1), 1913 * <jsf>TWO</jsf>(2), 1914 * <jsf>THREE</jsf>(3); 1915 * 1916 * <jk>private int</jk> <jf>i</jf>; 1917 * 1918 * Option(<jk>int</jk> i) { 1919 * <jk>this</jk>.<jf>i</jf> = i; 1920 * } 1921 * 1922 * <ja>@Override</ja> 1923 * <jk>public</jk> String toString() { 1924 * <jk>return</jk> String.<jsm>valueOf</jsm>(<jf>i</jf>); 1925 * } 1926 * </p> 1927 */ 1928 public static final String BEAN_useEnumNames = PREFIX + ".useEnumNames.b"; 1929 1930 /** 1931 * Configuration property: Use interface proxies. 1932 * 1933 * <h5 class='section'>Property:</h5> 1934 * <ul> 1935 * <li><b>Name:</b> <js>"BeanContext.useInterfaceProxies.b"</js> 1936 * <li><b>Data type:</b> <c>Boolean</c> 1937 * <li><b>Default:</b> <jk>true</jk> 1938 * <li><b>Session property:</b> <jk>false</jk> 1939 * <li><b>Methods:</b> 1940 * <ul> 1941 * <li class='jm'>{@link BeanContextBuilder#useInterfaceProxies(boolean)} 1942 * </ul> 1943 * </ul> 1944 * 1945 * <h5 class='section'>Description:</h5> 1946 * <p> 1947 * If <jk>true</jk>, then interfaces will be instantiated as proxy classes through the use of an 1948 * {@link InvocationHandler} if there is no other way of instantiating them. 1949 * <br>Otherwise, throws a {@link BeanRuntimeException}. 1950 * 1951 * <h5 class='section'>Example:</h5> 1952 * <p class='bcode w800'> 1953 * <jc>// Create a parser that doesn't try to make interface proxies.</jc> 1954 * ReaderParser p = JsonParser 1955 * .<jsm>create</jsm>() 1956 * .useInterfaceProxies(<jk>false</jk>) 1957 * .build(); 1958 * 1959 * <jc>// Same, but use property.</jc> 1960 * ReaderParser p = JsonParser 1961 * .<jsm>create</jsm>() 1962 * .set(<jsf>BEAN_useInterfaceProxies</jsf>, <jk>false</jk>) 1963 * .build(); 1964 * </p> 1965 */ 1966 public static final String BEAN_useInterfaceProxies = PREFIX + ".useInterfaceProxies.b"; 1967 1968 /** 1969 * Configuration property: Use Java Introspector. 1970 * 1971 * <h5 class='section'>Property:</h5> 1972 * <ul> 1973 * <li><b>Name:</b> <js>"BeanContext.useJavaBeanIntrospector.b"</js> 1974 * <li><b>Data type:</b> <c>Boolean</c> 1975 * <li><b>Default:</b> <jk>false</jk> 1976 * <li><b>Session property:</b> <jk>false</jk> 1977 * <li><b>Methods:</b> 1978 * <ul> 1979 * <li class='jm'>{@link BeanContextBuilder#useJavaBeanIntrospector(boolean)} 1980 * <li class='jm'>{@link BeanContextBuilder#useJavaBeanIntrospector()} 1981 * </ul> 1982 * </ul> 1983 * 1984 * <h5 class='section'>Description:</h5> 1985 * <p> 1986 * Using the built-in Java bean introspector will not pick up fields or non-standard getters/setters. 1987 * <br>Most {@link Bean @Bean} annotations will be ignored. 1988 * 1989 * <h5 class='section'>Example:</h5> 1990 * <p class='bcode w800'> 1991 * <jc>// Create a serializer that only uses the built-in java bean introspector for finding properties.</jc> 1992 * WriterSerializer s = JsonSerializer 1993 * .<jsm>create</jsm>() 1994 * .useJavaBeanIntrospector(<jk>false</jk>) 1995 * .build(); 1996 * 1997 * <jc>// Same, but use property.</jc> 1998 * WriterSerializer s = JsonSerializer 1999 * .<jsm>create</jsm>() 2000 * .set(<jsf>BEAN_useJavaBeanIntrospector</jsf>, <jk>false</jk>) 2001 * .build(); 2002 * </p> 2003 */ 2004 public static final String BEAN_useJavaBeanIntrospector = PREFIX + ".useJavaBeanIntrospector.b"; 2005 2006 /* 2007 * The default package pattern exclusion list. 2008 * Any beans in packages in this list will not be considered beans. 2009 */ 2010 private static final String[] DEFAULT_NOTBEAN_PACKAGES = { 2011 "java.lang", 2012 "java.lang.annotation", 2013 "java.lang.ref", 2014 "java.lang.reflect", 2015 "java.io", 2016 "java.net", 2017 "java.nio.*", 2018 "java.util.*" 2019 }; 2020 2021 /* 2022 * The default bean class exclusion list. 2023 * Anything in this list will not be considered beans. 2024 */ 2025 private static final Class<?>[] DEFAULT_NOTBEAN_CLASSES = { 2026 Map.class, 2027 Collection.class, 2028 Reader.class, 2029 Writer.class, 2030 InputStream.class, 2031 OutputStream.class, 2032 Throwable.class 2033 }; 2034 2035 2036 // This map is important! 2037 // We may have many Context objects that have identical BeanContext properties. 2038 // This map ensures that if the BeanContext properties in the Context are the same, 2039 // then we reuse the same Class->ClassMeta cache map. 2040 // This significantly reduces the number of times we need to construct ClassMeta objects which can be expensive. 2041 private static final ConcurrentHashMap<Integer,Map<Class,ClassMeta>> cmCacheCache 2042 = new ConcurrentHashMap<>(); 2043 2044 /** Default config. All default settings. */ 2045 public static final BeanContext DEFAULT = BeanContext.create().build(); 2046 2047 /** Default config. All default settings except sort bean properties. */ 2048 public static final BeanContext DEFAULT_SORTED = BeanContext.create().sortProperties().build(); 2049 2050 private final boolean 2051 beansRequireDefaultConstructor, 2052 beansRequireSerializable, 2053 beansRequireSettersForGetters, 2054 beansRequireSomeProperties, 2055 beanMapPutReturnsOldValue, 2056 useInterfaceProxies, 2057 ignoreUnknownBeanProperties, 2058 ignoreUnknownNullBeanProperties, 2059 ignorePropertiesWithoutSetters, 2060 ignoreInvocationExceptionsOnGetters, 2061 ignoreInvocationExceptionsOnSetters, 2062 useJavaBeanIntrospector, 2063 useEnumNames, 2064 sortProperties, 2065 fluentSetters, 2066 debug; 2067 2068 private final Visibility 2069 beanConstructorVisibility, 2070 beanClassVisibility, 2071 beanMethodVisibility, 2072 beanFieldVisibility; 2073 2074 private final Class<?>[] notBeanClasses; 2075 private final List<Class<?>> beanDictionaryClasses; 2076 private final String[] notBeanPackageNames, notBeanPackagePrefixes; 2077 private final BeanFilter[] beanFilters; 2078 private final PojoSwap<?,?>[] pojoSwaps; 2079 private final Map<String,?> examples; 2080 private final BeanRegistry beanRegistry; 2081 private final Map<String,ClassInfo> implClasses; 2082 private final Locale locale; 2083 private final TimeZone timeZone; 2084 private final MediaType mediaType; 2085 private final Map<String,Set<String>> bpi, bpx, bpro, bpwo; 2086 private final PropertyNamer propertyNamer; 2087 private final String beanTypePropertyName; 2088 private final int beanHashCode; 2089 2090 final Map<Class,ClassMeta> cmCache; 2091 private final ClassMeta<Object> cmObject; // Reusable ClassMeta that represents general Objects. 2092 private final ClassMeta<String> cmString; // Reusable ClassMeta that represents general Strings. 2093 private final ClassMeta<Class> cmClass; // Reusable ClassMeta that represents general Classes. 2094 2095 2096 /** 2097 * Constructor. 2098 * 2099 * <p> 2100 * Typically only called from {@link ContextBuilder#build(Class)} method. 2101 * 2102 * @param ps The property store containing the unmodifiable configuration for this bean context. 2103 */ 2104 public BeanContext(PropertyStore ps) { 2105 super(ps, true); 2106 2107 if (ps == null) 2108 ps = PropertyStore.DEFAULT; 2109 2110 beanHashCode = ps.hashCode("BeanContext"); 2111 2112 beansRequireDefaultConstructor = getBooleanProperty(BEAN_beansRequireDefaultConstructor, false); 2113 beansRequireSerializable = getBooleanProperty(BEAN_beansRequireSerializable, false); 2114 beansRequireSettersForGetters = getBooleanProperty(BEAN_beansRequireSettersForGetters, false); 2115 beansRequireSomeProperties = getBooleanProperty(BEAN_beansRequireSomeProperties, true); 2116 beanMapPutReturnsOldValue = getBooleanProperty(BEAN_beanMapPutReturnsOldValue, false); 2117 useEnumNames = getBooleanProperty(BEAN_useEnumNames, false); 2118 useInterfaceProxies = getBooleanProperty(BEAN_useInterfaceProxies, true); 2119 ignoreUnknownBeanProperties = getBooleanProperty(BEAN_ignoreUnknownBeanProperties, false); 2120 ignoreUnknownNullBeanProperties = getBooleanProperty(BEAN_ignoreUnknownNullBeanProperties, true); 2121 ignorePropertiesWithoutSetters = getBooleanProperty(BEAN_ignorePropertiesWithoutSetters, true); 2122 ignoreInvocationExceptionsOnGetters = getBooleanProperty(BEAN_ignoreInvocationExceptionsOnGetters, false); 2123 ignoreInvocationExceptionsOnSetters = getBooleanProperty(BEAN_ignoreInvocationExceptionsOnSetters, false); 2124 useJavaBeanIntrospector = getBooleanProperty(BEAN_useJavaBeanIntrospector, false); 2125 sortProperties = getBooleanProperty(BEAN_sortProperties, false); 2126 fluentSetters = getBooleanProperty(BEAN_fluentSetters, false); 2127 beanTypePropertyName = getStringProperty(BEAN_beanTypePropertyName, "_type"); 2128 debug = getBooleanProperty(BEAN_debug, false); 2129 2130 beanConstructorVisibility = getProperty(BEAN_beanConstructorVisibility, Visibility.class, PUBLIC); 2131 beanClassVisibility = getProperty(BEAN_beanClassVisibility, Visibility.class, PUBLIC); 2132 beanMethodVisibility = getProperty(BEAN_beanMethodVisibility, Visibility.class, PUBLIC); 2133 beanFieldVisibility = getProperty(BEAN_beanFieldVisibility, Visibility.class, PUBLIC); 2134 2135 notBeanClasses = getClassArrayProperty(BEAN_notBeanClasses, DEFAULT_NOTBEAN_CLASSES); 2136 2137 propertyNamer = getInstanceProperty(BEAN_propertyNamer, PropertyNamer.class, PropertyNamerDefault.class); 2138 2139 List<String> l1 = new LinkedList<>(); 2140 List<String> l2 = new LinkedList<>(); 2141 for (String s : getArrayProperty(BEAN_notBeanPackages, String.class, DEFAULT_NOTBEAN_PACKAGES)) { 2142 if (s.endsWith(".*")) 2143 l2.add(s.substring(0, s.length()-2)); 2144 else 2145 l1.add(s); 2146 } 2147 notBeanPackageNames = l1.toArray(new String[l1.size()]); 2148 notBeanPackagePrefixes = l2.toArray(new String[l2.size()]); 2149 2150 LinkedList<BeanFilter> lbf = new LinkedList<>(); 2151 for (Class<?> c : getClassListProperty(BEAN_beanFilters)) { 2152 ClassInfo ci = ClassInfo.of(c); 2153 if (ci.isChildOf(BeanFilter.class)) 2154 lbf.add(castOrCreate(BeanFilter.class, c)); 2155 else if (ci.isChildOf(BeanFilterBuilder.class)) 2156 lbf.add(castOrCreate(BeanFilterBuilder.class, c).build()); 2157 else 2158 lbf.add(new InterfaceBeanFilterBuilder(c).build()); 2159 } 2160 beanFilters = lbf.toArray(new BeanFilter[0]); 2161 2162 LinkedList<PojoSwap<?,?>> lpf = new LinkedList<>(); 2163 for (Object o : getListProperty(BEAN_pojoSwaps, Object.class)) { 2164 if (o instanceof Class) { 2165 ClassInfo ci = ClassInfo.of((Class<?>)o); 2166 if (ci.isChildOf(PojoSwap.class)) 2167 lpf.add(castOrCreate(PojoSwap.class, ci.inner())); 2168 else if (ci.isChildOf(Surrogate.class)) 2169 lpf.addAll(SurrogateSwap.findPojoSwaps(ci.inner())); 2170 else 2171 throw new FormattedRuntimeException("Invalid class {0} specified in BeanContext.pojoSwaps property. Must be a subclass of PojoSwap or Surrogate.", ci.inner()); 2172 } else if (o instanceof PojoSwap) { 2173 lpf.add((PojoSwap)o); 2174 } 2175 } 2176 pojoSwaps = lpf.toArray(new PojoSwap[lpf.size()]); 2177 2178 examples = getMapProperty(BEAN_examples, Object.class); 2179 2180 Map<String,ClassInfo> icm = new LinkedHashMap<>(); 2181 for (Map.Entry<String,Class<?>> e : getClassMapProperty(BEAN_implClasses).entrySet()) 2182 icm.put(e.getKey(), ClassInfo.of(e.getValue())); 2183 implClasses = unmodifiableMap(icm); 2184 2185 Map<String,Set<String>> m2 = new HashMap<>(); 2186 for (Map.Entry<String,String> e : getMapProperty(BEAN_bpi, String.class).entrySet()) 2187 m2.put(e.getKey(), newUnmodifiableLinkedHashSet(split(e.getValue()))); 2188 bpi = unmodifiableMap(m2); 2189 2190 m2 = new HashMap<>(); 2191 for (Map.Entry<String,String> e : getMapProperty(BEAN_bpx, String.class).entrySet()) 2192 m2.put(e.getKey(), newUnmodifiableLinkedHashSet(split(e.getValue()))); 2193 bpx = unmodifiableMap(m2); 2194 2195 m2 = new HashMap<>(); 2196 for (Map.Entry<String,String> e : getMapProperty(BEAN_bpro, String.class).entrySet()) 2197 m2.put(e.getKey(), newUnmodifiableLinkedHashSet(split(e.getValue()))); 2198 bpro = unmodifiableMap(m2); 2199 2200 m2 = new HashMap<>(); 2201 for (Map.Entry<String,String> e : getMapProperty(BEAN_bpwo, String.class).entrySet()) 2202 m2.put(e.getKey(), newUnmodifiableLinkedHashSet(split(e.getValue()))); 2203 bpwo = unmodifiableMap(m2); 2204 2205 locale = getInstanceProperty(BEAN_locale, Locale.class, Locale.getDefault()); 2206 timeZone = getInstanceProperty(BEAN_timeZone, TimeZone.class, null); 2207 mediaType = getInstanceProperty(BEAN_mediaType, MediaType.class, null); 2208 2209 if (! cmCacheCache.containsKey(beanHashCode)) { 2210 ConcurrentHashMap<Class,ClassMeta> cm = new ConcurrentHashMap<>(); 2211 cm.putIfAbsent(String.class, new ClassMeta(String.class, this, null, null, findPojoSwaps(String.class), findChildPojoSwaps(String.class), findExample(String.class))); 2212 cm.putIfAbsent(Object.class, new ClassMeta(Object.class, this, null, null, findPojoSwaps(Object.class), findChildPojoSwaps(Object.class), findExample(Object.class))); 2213 cmCacheCache.putIfAbsent(beanHashCode, cm); 2214 } 2215 cmCache = cmCacheCache.get(beanHashCode); 2216 cmString = cmCache.get(String.class); 2217 cmObject = cmCache.get(Object.class); 2218 cmClass = cmCache.get(Class.class); 2219 2220 beanDictionaryClasses = unmodifiableList(Arrays.asList(getClassArrayProperty(BEAN_beanDictionary))); 2221 beanRegistry = new BeanRegistry(this, null); 2222 } 2223 2224 @Override /* Context */ 2225 public BeanContextBuilder builder() { 2226 return new BeanContextBuilder(getPropertyStore()); 2227 } 2228 2229 /** 2230 * Instantiates a new clean-slate {@link BeanContextBuilder} object. 2231 * 2232 * <p> 2233 * This is equivalent to simply calling <code><jk>new</jk> BeanContextBuilder()</code>. 2234 * 2235 * @return A new {@link JsonSerializerBuilder} object. 2236 */ 2237 public static BeanContextBuilder create() { 2238 return new BeanContextBuilder(); 2239 } 2240 2241 /** 2242 * Create a new bean session based on the properties defined on this context. 2243 * 2244 * <p> 2245 * Use this method for creating sessions if you don't need to override any 2246 * properties or locale/timezone currently set on this context. 2247 * 2248 * @return A new session object. 2249 */ 2250 @Override /* Context */ 2251 public BeanSession createSession() { 2252 return createBeanSession(createDefaultSessionArgs()); 2253 } 2254 2255 /** 2256 * Create a new bean session based on the properties defined on this context combined with the specified 2257 * runtime args. 2258 * 2259 * <p> 2260 * Use this method for creating sessions if you don't need to override any 2261 * properties or locale/timezone currently set on this context. 2262 * 2263 * @param args 2264 * The session arguments. 2265 * @return A new session object. 2266 */ 2267 public BeanSession createSession(BeanSessionArgs args) { 2268 return createBeanSession(args); 2269 } 2270 2271 @Override /* Context */ 2272 public final Session createSession(SessionArgs args) { 2273 throw new NoSuchMethodError(); 2274 } 2275 2276 /** 2277 * Same as {@link #createSession(BeanSessionArgs)} except always returns a {@link BeanSession} object unlike {@link #createSession(BeanSessionArgs)} 2278 * which is meant to be overridden by subclasses. 2279 * 2280 * @param args The session arguments. 2281 * @return A new session object. 2282 */ 2283 public final BeanSession createBeanSession(BeanSessionArgs args) { 2284 return new BeanSession(this, args); 2285 } 2286 2287 /** 2288 * Same as {@link #createSession()} except always returns a {@link BeanSession} object unlike {@link #createSession()} 2289 * which is meant to be overridden by subclasses. 2290 * 2291 * @return A new session object. 2292 */ 2293 public final BeanSession createBeanSession() { 2294 return new BeanSession(this, createDefaultBeanSessionArgs()); 2295 } 2296 2297 @Override /* Context */ 2298 public BeanSessionArgs createDefaultSessionArgs() { 2299 return createDefaultBeanSessionArgs(); 2300 } 2301 2302 /** 2303 * Same as {@link #createDefaultSessionArgs()} except always returns a {@link BeanSessionArgs} unlike 2304 * {@link #createDefaultBeanSessionArgs()} which is meant to be overridden by subclasses. 2305 * 2306 * @return A new session arguments object. 2307 */ 2308 public final BeanSessionArgs createDefaultBeanSessionArgs() { 2309 return new BeanSessionArgs(); 2310 } 2311 2312 /** 2313 * Returns <jk>true</jk> if the specified bean context shares the same cache as this bean context. 2314 * 2315 * <p> 2316 * Useful for testing purposes. 2317 * 2318 * @param bc The bean context to compare to. 2319 * @return <jk>true</jk> if the bean contexts have equivalent settings and thus share caches. 2320 */ 2321 public final boolean hasSameCache(BeanContext bc) { 2322 return bc.cmCache == this.cmCache; 2323 } 2324 2325 /** 2326 * Determines whether the specified class is ignored as a bean class based on the various exclusion parameters 2327 * specified on this context class. 2328 * 2329 * @param c The class type being tested. 2330 * @return <jk>true</jk> if the specified class matches any of the exclusion parameters. 2331 */ 2332 protected final boolean isNotABean(Class<?> c) { 2333 if (c.isArray() || c.isPrimitive() || c.isEnum() || c.isAnnotation()) 2334 return true; 2335 Package p = c.getPackage(); 2336 if (p != null) { 2337 for (String p2 : notBeanPackageNames) 2338 if (p.getName().equals(p2)) 2339 return true; 2340 for (String p2 : notBeanPackagePrefixes) 2341 if (p.getName().startsWith(p2)) 2342 return true; 2343 } 2344 ClassInfo ci = ClassInfo.of(c); 2345 for (Class exclude : notBeanClasses) 2346 if (ci.isChildOf(exclude)) 2347 return true; 2348 return false; 2349 } 2350 2351 /** 2352 * Returns <jk>true</jk> if the specified object is a bean. 2353 * 2354 * @param o The object to test. 2355 * @return <jk>true</jk> if the specified object is a bean. <jk>false</jk> if the bean is <jk>null</jk>. 2356 */ 2357 public boolean isBean(Object o) { 2358 if (o == null) 2359 return false; 2360 return getClassMetaForObject(o).isBean(); 2361 } 2362 2363 /** 2364 * Prints meta cache statistics to <c>System.out</c>. 2365 */ 2366 protected static void dumpCacheStats() { 2367 try { 2368 int ctCount = 0; 2369 for (Map<Class,ClassMeta> cm : cmCacheCache.values()) 2370 ctCount += cm.size(); 2371 System.out.println(format("ClassMeta cache: {0} instances in {1} caches", ctCount, cmCacheCache.size())); // NOT DEBUG 2372 } catch (Exception e) { 2373 e.printStackTrace(); 2374 } 2375 } 2376 2377 /** 2378 * Returns the {@link BeanMeta} class for the specified class. 2379 * 2380 * @param <T> The class type to get the meta-data on. 2381 * @param c The class to get the meta-data on. 2382 * @return 2383 * The {@link BeanMeta} for the specified class, or <jk>null</jk> if the class is not a bean per the settings on 2384 * this context. 2385 */ 2386 public final <T> BeanMeta<T> getBeanMeta(Class<T> c) { 2387 if (c == null) 2388 return null; 2389 return getClassMeta(c).getBeanMeta(); 2390 } 2391 2392 /** 2393 * Construct a {@code ClassMeta} wrapper around a {@link Class} object. 2394 * 2395 * @param <T> The class type being wrapped. 2396 * @param type The class to resolve. 2397 * @return 2398 * If the class is not an array, returns a cached {@link ClassMeta} object. 2399 * Otherwise, returns a new {@link ClassMeta} object every time. 2400 */ 2401 public final <T> ClassMeta<T> getClassMeta(Class<T> type) { 2402 return getClassMeta(type, true); 2403 } 2404 2405 /** 2406 * Construct a {@code ClassMeta} wrapper around a {@link Class} object. 2407 * 2408 * @param <T> The class type being wrapped. 2409 * @param type The class to resolve. 2410 * @param waitForInit 2411 * If <jk>true</jk>, wait for the ClassMeta constructor to finish before returning. 2412 * @return 2413 * If the class is not an array, returns a cached {@link ClassMeta} object. 2414 * Otherwise, returns a new {@link ClassMeta} object every time. 2415 */ 2416 final <T> ClassMeta<T> getClassMeta(Class<T> type, boolean waitForInit) { 2417 2418 // If this is an array, then we want it wrapped in an uncached ClassMeta object. 2419 // Note that if it has a pojo swap, we still want to cache it so that 2420 // we can cache something like byte[] with ByteArraySwap.Base64. 2421 if (type.isArray() && findPojoSwaps(type) == null) 2422 return new ClassMeta(type, this, findImplClass(type), findBeanFilter(type), findPojoSwaps(type), findChildPojoSwaps(type), findExample(type)); 2423 2424 // This can happen if we have transforms defined against String or Object. 2425 if (cmCache == null) 2426 return null; 2427 2428 ClassMeta<T> cm = cmCache.get(type); 2429 if (cm == null) { 2430 2431 synchronized (this) { 2432 // Make sure someone didn't already set it while this thread was blocked. 2433 cm = cmCache.get(type); 2434 if (cm == null) 2435 cm = new ClassMeta<>(type, this, findImplClass(type), findBeanFilter(type), findPojoSwaps(type), findChildPojoSwaps(type), findExample(type)); 2436 } 2437 } 2438 if (waitForInit) 2439 cm.waitForInit(); 2440 return cm; 2441 } 2442 2443 /** 2444 * Used to resolve <c>ClassMetas</c> of type <c>Collection</c> and <c>Map</c> that have 2445 * <c>ClassMeta</c> values that themselves could be collections or maps. 2446 * 2447 * <p> 2448 * <c>Collection</c> meta objects are assumed to be followed by zero or one meta objects indicating the element type. 2449 * 2450 * <p> 2451 * <c>Map</c> meta objects are assumed to be followed by zero or two meta objects indicating the key and value types. 2452 * 2453 * <p> 2454 * The array can be arbitrarily long to indicate arbitrarily complex data structures. 2455 * 2456 * <h5 class='section'>Examples:</h5> 2457 * <ul> 2458 * <li><code>getClassMeta(String.<jk>class</jk>);</code> - A normal type. 2459 * <li><code>getClassMeta(List.<jk>class</jk>);</code> - A list containing objects. 2460 * <li><code>getClassMeta(List.<jk>class</jk>, String.<jk>class</jk>);</code> - A list containing strings. 2461 * <li><code>getClassMeta(LinkedList.<jk>class</jk>, String.<jk>class</jk>);</code> - A linked-list containing 2462 * strings. 2463 * <li><code>getClassMeta(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);</code> - 2464 * A linked-list containing linked-lists of strings. 2465 * <li><code>getClassMeta(Map.<jk>class</jk>);</code> - A map containing object keys/values. 2466 * <li><code>getClassMeta(Map.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);</code> - A map 2467 * containing string keys/values. 2468 * <li><code>getClassMeta(Map.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);</code> - 2469 * A map containing string keys and values of lists containing beans. 2470 * </ul> 2471 * 2472 * @param type 2473 * The class to resolve. 2474 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 2475 * @param args 2476 * The type arguments of the class if it's a collection or map. 2477 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 2478 * <br>Ignored if the main type is not a map or collection. 2479 * @return The resolved class meta. 2480 */ 2481 public final <T> ClassMeta<T> getClassMeta(Type type, Type...args) { 2482 if (type == null) 2483 return null; 2484 ClassMeta<T> cm = type instanceof Class ? getClassMeta((Class)type) : resolveClassMeta(type, null); 2485 if (args.length == 0) 2486 return cm; 2487 ClassMeta<?>[] cma = new ClassMeta[args.length+1]; 2488 cma[0] = cm; 2489 for (int i = 0; i < Array.getLength(args); i++) { 2490 Type arg = (Type)Array.get(args, i); 2491 cma[i+1] = arg instanceof Class ? getClassMeta((Class)arg) : resolveClassMeta(arg, null); 2492 } 2493 return (ClassMeta<T>) getTypedClassMeta(cma, 0); 2494 } 2495 2496 /* 2497 * Resolves the 'genericized' class meta at the specified position in the ClassMeta array. 2498 */ 2499 private ClassMeta<?> getTypedClassMeta(ClassMeta<?>[] c, int pos) { 2500 ClassMeta<?> cm = c[pos++]; 2501 if (cm.isCollection() || cm.isOptional()) { 2502 ClassMeta<?> ce = c.length == pos ? object() : getTypedClassMeta(c, pos); 2503 return (ce.isObject() ? cm : new ClassMeta(cm, null, null, ce)); 2504 } else if (cm.isMap()) { 2505 ClassMeta<?> ck = c.length == pos ? object() : c[pos++]; 2506 ClassMeta<?> cv = c.length == pos ? object() : getTypedClassMeta(c, pos); 2507 return (ck.isObject() && cv.isObject() ? cm : new ClassMeta(cm, ck, cv, null)); 2508 } 2509 return cm; 2510 } 2511 2512 final ClassMeta resolveClassMeta(Type o, Map<Class<?>,Class<?>[]> typeVarImpls) { 2513 if (o == null) 2514 return null; 2515 2516 if (o instanceof ClassMeta) { 2517 ClassMeta<?> cm = (ClassMeta)o; 2518 2519 // This classmeta could have been created by a different context. 2520 // Need to re-resolve it to pick up PojoSwaps and stuff on this context. 2521 if (cm.getBeanContext() == this) 2522 return cm; 2523 if (cm.isMap()) 2524 return getClassMeta(cm.innerClass, cm.getKeyType(), cm.getValueType()); 2525 if (cm.isCollection() || cm.isOptional()) 2526 return getClassMeta(cm.innerClass, cm.getElementType()); 2527 return getClassMeta(cm.innerClass); 2528 } 2529 2530 Class c = resolve(o, typeVarImpls); 2531 2532 // This can happen when trying to resolve the "E getFirst()" method on LinkedList, whose type is a TypeVariable 2533 // These should just resolve to Object. 2534 if (c == null) 2535 return object(); 2536 2537 ClassMeta rawType = getClassMeta(c); 2538 2539 // If this is a Map or Collection, and the parameter types aren't part 2540 // of the class definition itself (e.g. class AddressBook extends List<Person>), 2541 // then we need to figure out the parameters. 2542 if (rawType.isMap() || rawType.isCollection() || rawType.isOptional()) { 2543 ClassMeta[] params = findParameters(o, c); 2544 if (params == null) 2545 return rawType; 2546 if (rawType.isMap()) { 2547 if (params.length != 2) 2548 return rawType; 2549 if (params[0].isObject() && params[1].isObject()) 2550 return rawType; 2551 return new ClassMeta(rawType, params[0], params[1], null); 2552 } 2553 if (rawType.isCollection() || rawType.isOptional()) { 2554 if (params.length != 1) 2555 return rawType; 2556 if (params[0].isObject()) 2557 return rawType; 2558 return new ClassMeta(rawType, null, null, params[0]); 2559 } 2560 } 2561 2562 if (rawType.isArray()) { 2563 if (o instanceof GenericArrayType) { 2564 GenericArrayType gat = (GenericArrayType)o; 2565 ClassMeta elementType = resolveClassMeta(gat.getGenericComponentType(), typeVarImpls); 2566 return new ClassMeta(rawType, null, null, elementType); 2567 } 2568 } 2569 2570 return rawType; 2571 } 2572 2573 /** 2574 * Convert a Type to a Class if possible. 2575 * Return null if not possible. 2576 */ 2577 final Class resolve(Type t, Map<Class<?>,Class<?>[]> typeVarImpls) { 2578 2579 if (t instanceof Class) 2580 return (Class)t; 2581 2582 if (t instanceof ParameterizedType) 2583 // A parameter (e.g. <String>. 2584 return (Class)((ParameterizedType)t).getRawType(); 2585 2586 if (t instanceof GenericArrayType) { 2587 // An array parameter (e.g. <byte[]>). 2588 Type gatct = ((GenericArrayType)t).getGenericComponentType(); 2589 2590 if (gatct instanceof Class) 2591 return Array.newInstance((Class)gatct, 0).getClass(); 2592 2593 if (gatct instanceof ParameterizedType) 2594 return Array.newInstance((Class)((ParameterizedType)gatct).getRawType(), 0).getClass(); 2595 2596 if (gatct instanceof GenericArrayType) 2597 return Array.newInstance(resolve(gatct, typeVarImpls), 0).getClass(); 2598 2599 return null; 2600 2601 } else if (t instanceof TypeVariable) { 2602 if (typeVarImpls != null) { 2603 TypeVariable tv = (TypeVariable)t; 2604 String varName = tv.getName(); 2605 int varIndex = -1; 2606 Class gc = (Class)tv.getGenericDeclaration(); 2607 TypeVariable[] tvv = gc.getTypeParameters(); 2608 for (int i = 0; i < tvv.length; i++) { 2609 if (tvv[i].getName().equals(varName)) { 2610 varIndex = i; 2611 } 2612 } 2613 if (varIndex != -1) { 2614 2615 // If we couldn't find a type variable implementation, that means 2616 // the type was defined at runtime (e.g. Bean b = new Bean<Foo>();) 2617 // in which case the type is lost through erasure. 2618 // Assume java.lang.Object as the type. 2619 if (! typeVarImpls.containsKey(gc)) 2620 return null; 2621 2622 return typeVarImpls.get(gc)[varIndex]; 2623 } 2624 } 2625 } 2626 return null; 2627 } 2628 2629 final ClassMeta[] findParameters(Type o, Class c) { 2630 if (o == null) 2631 o = c; 2632 2633 // Loop until we find a ParameterizedType 2634 if (! (o instanceof ParameterizedType)) { 2635 loop: do { 2636 o = c.getGenericSuperclass(); 2637 if (o instanceof ParameterizedType) 2638 break loop; 2639 for (Type t : c.getGenericInterfaces()) { 2640 o = t; 2641 if (o instanceof ParameterizedType) 2642 break loop; 2643 } 2644 c = c.getSuperclass(); 2645 } while (c != null); 2646 } 2647 2648 if (o instanceof ParameterizedType) { 2649 ParameterizedType pt = (ParameterizedType)o; 2650 if (! pt.getRawType().equals(Enum.class)) { 2651 List<ClassMeta<?>> l = new LinkedList<>(); 2652 for (Type pt2 : pt.getActualTypeArguments()) { 2653 if (pt2 instanceof WildcardType || pt2 instanceof TypeVariable) 2654 return null; 2655 l.add(resolveClassMeta(pt2, null)); 2656 } 2657 if (l.isEmpty()) 2658 return null; 2659 return l.toArray(new ClassMeta[l.size()]); 2660 } 2661 } 2662 2663 return null; 2664 } 2665 2666 /** 2667 * Shortcut for calling {@code getClassMeta(o.getClass())}. 2668 * 2669 * @param <T> The class of the object being passed in. 2670 * @param o The class to find the class type for. 2671 * @return The ClassMeta object, or <jk>null</jk> if {@code o} is <jk>null</jk>. 2672 */ 2673 public final <T> ClassMeta<T> getClassMetaForObject(T o) { 2674 if (o == null) 2675 return null; 2676 return (ClassMeta<T>)getClassMeta(o.getClass()); 2677 } 2678 2679 2680 /** 2681 * Used for determining the class type on a method or field where a {@code @Beanp} annotation may be present. 2682 * 2683 * @param <T> The class type we're wrapping. 2684 * @param px The property annotation on the type if there is one. 2685 * @param p The property annotation on the type if there is one. 2686 * @param t The type. 2687 * @param typeVarImpls 2688 * Contains known resolved type parameters on the specified class so that we can result 2689 * {@code ParameterizedTypes} and {@code TypeVariables}. 2690 * Can be <jk>null</jk> if the information is not known. 2691 * @return The new {@code ClassMeta} object wrapped around the {@code Type} object. 2692 */ 2693 @SuppressWarnings("deprecation") 2694 protected final <T> ClassMeta<T> resolveClassMeta(BeanProperty px, Beanp p, Type t, Map<Class<?>,Class<?>[]> typeVarImpls) { 2695 ClassMeta<T> cm = resolveClassMeta(t, typeVarImpls); 2696 ClassMeta<T> cm2 = cm; 2697 if (px != null) { 2698 2699 if (px.type() != Object.class) 2700 cm2 = resolveClassMeta(px.type(), typeVarImpls); 2701 2702 if (cm2.isMap()) { 2703 Class<?>[] pParams = (px.params().length == 0 ? new Class[]{Object.class, Object.class} : px.params()); 2704 if (pParams.length != 2) 2705 throw new FormattedRuntimeException("Invalid number of parameters specified for Map (must be 2): {0}", pParams.length); 2706 ClassMeta<?> keyType = resolveType(pParams[0], cm2.getKeyType(), cm.getKeyType()); 2707 ClassMeta<?> valueType = resolveType(pParams[1], cm2.getValueType(), cm.getValueType()); 2708 if (keyType.isObject() && valueType.isObject()) 2709 return cm2; 2710 return new ClassMeta<>(cm2, keyType, valueType, null); 2711 } 2712 2713 if (cm2.isCollection() || cm2.isOptional()) { 2714 Class<?>[] pParams = (px.params().length == 0 ? new Class[]{Object.class} : px.params()); 2715 if (pParams.length != 1) 2716 throw new FormattedRuntimeException("Invalid number of parameters specified for "+(cm2.isCollection() ? "Collection" : cm2.isOptional() ? "Optional" : "Array")+" (must be 1): {0}", pParams.length); 2717 ClassMeta<?> elementType = resolveType(pParams[0], cm2.getElementType(), cm.getElementType()); 2718 if (elementType.isObject()) 2719 return cm2; 2720 return new ClassMeta<>(cm2, null, null, elementType); 2721 } 2722 2723 return cm2; 2724 } 2725 2726 if (p != null) { 2727 2728 if (p.type() != Object.class) 2729 cm2 = resolveClassMeta(p.type(), typeVarImpls); 2730 2731 if (cm2.isMap()) { 2732 Class<?>[] pParams = (p.params().length == 0 ? new Class[]{Object.class, Object.class} : p.params()); 2733 if (pParams.length != 2) 2734 throw new FormattedRuntimeException("Invalid number of parameters specified for Map (must be 2): {0}", pParams.length); 2735 ClassMeta<?> keyType = resolveType(pParams[0], cm2.getKeyType(), cm.getKeyType()); 2736 ClassMeta<?> valueType = resolveType(pParams[1], cm2.getValueType(), cm.getValueType()); 2737 if (keyType.isObject() && valueType.isObject()) 2738 return cm2; 2739 return new ClassMeta<>(cm2, keyType, valueType, null); 2740 } 2741 2742 if (cm2.isCollection() || cm2.isOptional()) { 2743 Class<?>[] pParams = (p.params().length == 0 ? new Class[]{Object.class} : p.params()); 2744 if (pParams.length != 1) 2745 throw new FormattedRuntimeException("Invalid number of parameters specified for "+(cm2.isCollection() ? "Collection" : cm2.isOptional() ? "Optional" : "Array")+" (must be 1): {0}", pParams.length); 2746 ClassMeta<?> elementType = resolveType(pParams[0], cm2.getElementType(), cm.getElementType()); 2747 if (elementType.isObject()) 2748 return cm2; 2749 return new ClassMeta<>(cm2, null, null, elementType); 2750 } 2751 2752 return cm2; 2753 } 2754 2755 return cm; 2756 } 2757 2758 private ClassMeta<?> resolveType(Type...t) { 2759 for (Type tt : t) { 2760 if (tt != null) { 2761 ClassMeta<?> cm = getClassMeta(tt); 2762 if (tt != cmObject) 2763 return cm; 2764 } 2765 } 2766 return cmObject; 2767 } 2768 2769 /** 2770 * Returns the {@link PojoSwap} associated with the specified class, or <jk>null</jk> if there is no POJO swap 2771 * associated with the class. 2772 * 2773 * @param <T> The class associated with the swap. 2774 * @param c The class associated with the swap. 2775 * @return The swap associated with the class, or null if there is no association. 2776 */ 2777 private final <T> PojoSwap[] findPojoSwaps(Class<T> c) { 2778 // Note: On first 2779 if (c != null) { 2780 List<PojoSwap> l = new ArrayList<>(); 2781 for (PojoSwap f : pojoSwaps) 2782 if (f.getNormalClass().isParentOf(c)) 2783 l.add(f); 2784 return l.size() == 0 ? null : l.toArray(new PojoSwap[l.size()]); 2785 } 2786 return null; 2787 } 2788 2789 private final Object findExample(Class<?> c) { 2790 if (c != null) { 2791 Object o = examples.get(c.getName()); 2792 if (o != null) 2793 return o; 2794 o = examples.get(c.getSimpleName()); 2795 if (o != null) 2796 return o; 2797 Class<?> c2 = findImplClass(c); 2798 if (c2 == null) 2799 return null; 2800 o = examples.get(c2.getName()); 2801 if (o != null) 2802 return o; 2803 o = examples.get(c2.getSimpleName()); 2804 return o; 2805 } 2806 return null; 2807 } 2808 2809 /** 2810 * Checks whether a class has a {@link PojoSwap} associated with it in this bean context. 2811 * 2812 * @param c The class to check. 2813 * @return <jk>true</jk> if the specified class or one of its subclasses has a {@link PojoSwap} associated with it. 2814 */ 2815 private final PojoSwap[] findChildPojoSwaps(Class<?> c) { 2816 if (c == null || pojoSwaps.length == 0) 2817 return null; 2818 List<PojoSwap> l = null; 2819 for (PojoSwap f : pojoSwaps) { 2820 if (f.getNormalClass().isChildOf(c)) { 2821 if (l == null) 2822 l = new ArrayList<>(); 2823 l.add(f); 2824 } 2825 } 2826 return l == null ? null : l.toArray(new PojoSwap[l.size()]); 2827 } 2828 2829 /** 2830 * Returns the {@link BeanFilter} associated with the specified class, or <jk>null</jk> if there is no bean filter 2831 * associated with the class. 2832 * 2833 * @param <T> The class associated with the bean filter. 2834 * @param c The class associated with the bean filter. 2835 * @return The bean filter associated with the class, or null if there is no association. 2836 */ 2837 private final <T> BeanFilter findBeanFilter(Class<T> c) { 2838 if (c != null) 2839 for (BeanFilter f : beanFilters) 2840 if (ClassInfo.of(f.getBeanClass()).isParentOf(c)) 2841 return f; 2842 return null; 2843 } 2844 2845 /** 2846 * Gets the no-arg constructor for the specified class. 2847 * 2848 * @param <T> The class to check. 2849 * @param c The class to check. 2850 * @param v The minimum visibility for the constructor. 2851 * @return The no arg constructor, or <jk>null</jk> if the class has no no-arg constructor. 2852 */ 2853 protected final <T> ConstructorInfo getImplClassConstructor(Class<T> c, Visibility v) { 2854 if (implClasses.isEmpty()) 2855 return null; 2856 Class cc = c; 2857 while (cc != null) { 2858 ClassInfo implClass = implClasses.get(cc.getName()); 2859 if (implClass != null) 2860 return implClass.getNoArgConstructor(v); 2861 for (Class ic : cc.getInterfaces()) { 2862 implClass = implClasses.get(ic.getName()); 2863 if (implClass != null) 2864 return implClass.getNoArgConstructor(v); 2865 } 2866 cc = cc.getSuperclass(); 2867 } 2868 return null; 2869 } 2870 2871 private final <T> Class<T> findImplClass(Class<T> c) { 2872 if (implClasses.isEmpty()) 2873 return null; 2874 Class cc = c; 2875 while (cc != null) { 2876 ClassInfo implClass = implClasses.get(cc.getName()); 2877 if (implClass != null) 2878 return implClass.<T>inner(); 2879 for (Class ic : cc.getInterfaces()) { 2880 implClass = implClasses.get(ic.getName()); 2881 if (implClass != null) 2882 return implClass.<T>inner(); 2883 } 2884 cc = cc.getSuperclass(); 2885 } 2886 return null; 2887 } 2888 2889 /** 2890 * Returns a reusable {@link ClassMeta} representation for the class <c>Object</c>. 2891 * 2892 * <p> 2893 * This <c>ClassMeta</c> is often used to represent "any object type" when an object type is not known. 2894 * 2895 * <p> 2896 * This method is identical to calling <code>getClassMeta(Object.<jk>class</jk>)</code> but uses a cached copy to 2897 * avoid a hashmap lookup. 2898 * 2899 * @return The {@link ClassMeta} object associated with the <c>Object</c> class. 2900 */ 2901 protected final ClassMeta<Object> object() { 2902 return cmObject; 2903 } 2904 2905 /** 2906 * Returns a reusable {@link ClassMeta} representation for the class <c>String</c>. 2907 * 2908 * <p> 2909 * This <c>ClassMeta</c> is often used to represent key types in maps. 2910 * 2911 * <p> 2912 * This method is identical to calling <code>getClassMeta(String.<jk>class</jk>)</code> but uses a cached copy to 2913 * avoid a hashmap lookup. 2914 * 2915 * @return The {@link ClassMeta} object associated with the <c>String</c> class. 2916 */ 2917 protected final ClassMeta<String> string() { 2918 return cmString; 2919 } 2920 2921 /** 2922 * Returns a reusable {@link ClassMeta} representation for the class <c>Class</c>. 2923 * 2924 * <p> 2925 * This <c>ClassMeta</c> is often used to represent key types in maps. 2926 * 2927 * <p> 2928 * This method is identical to calling <code>getClassMeta(Class.<jk>class</jk>)</code> but uses a cached copy to 2929 * avoid a hashmap lookup. 2930 * 2931 * @return The {@link ClassMeta} object associated with the <c>String</c> class. 2932 */ 2933 protected final ClassMeta<Class> _class() { 2934 return cmClass; 2935 } 2936 2937 /** 2938 * Returns the lookup table for resolving bean types by name. 2939 * 2940 * @return The lookup table for resolving bean types by name. 2941 */ 2942 protected final BeanRegistry getBeanRegistry() { 2943 return beanRegistry; 2944 } 2945 2946 //----------------------------------------------------------------------------------------------------------------- 2947 // Properties 2948 //----------------------------------------------------------------------------------------------------------------- 2949 2950 /** 2951 * Configuration property: Minimum bean class visibility. 2952 * 2953 * @see #BEAN_beanClassVisibility 2954 * @return 2955 * Classes are not considered beans unless they meet the minimum visibility requirements. 2956 */ 2957 protected final Visibility getBeanClassVisibility() { 2958 return beanClassVisibility; 2959 } 2960 2961 /** 2962 * Configuration property: Minimum bean constructor visibility. 2963 * 2964 * @see #BEAN_beanConstructorVisibility 2965 * @return 2966 * Only look for constructors with this specified minimum visibility. 2967 */ 2968 protected final Visibility getBeanConstructorVisibility() { 2969 return beanConstructorVisibility; 2970 } 2971 2972 /** 2973 * Configuration property: Bean dictionary. 2974 * 2975 * @see #BEAN_beanDictionary 2976 * @return 2977 * The list of classes that make up the bean dictionary in this bean context. 2978 */ 2979 protected final List<Class<?>> getBeanDictionaryClasses() { 2980 return beanDictionaryClasses; 2981 } 2982 2983 /** 2984 * Configuration property: Minimum bean field visibility. 2985 * 2986 * 2987 * @see #BEAN_beanFieldVisibility 2988 * @return 2989 * Only look for bean fields with this specified minimum visibility. 2990 */ 2991 protected final Visibility getBeanFieldVisibility() { 2992 return beanFieldVisibility; 2993 } 2994 2995 /** 2996 * Configuration property: Bean filters. 2997 * 2998 * 2999 * @see BeanContext#BEAN_beanFilters 3000 * @return 3001 * Only look for bean fields with this specified minimum visibility. 3002 */ 3003 protected final BeanFilter[] getBeanFilters() { 3004 return beanFilters; 3005 } 3006 3007 /** 3008 * Configuration property: BeanMap.put() returns old property value. 3009 * 3010 * @see #BEAN_beanMapPutReturnsOldValue 3011 * @return 3012 * <jk>true</jk> if the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property values. 3013 * <br>Otherwise, it returns <jk>null</jk>. 3014 */ 3015 protected final boolean isBeanMapPutReturnsOldValue() { 3016 return beanMapPutReturnsOldValue; 3017 } 3018 3019 /** 3020 * Configuration property: Minimum bean method visibility. 3021 * 3022 * @see #BEAN_beanMethodVisibility 3023 * @return 3024 * Only look for bean methods with this specified minimum visibility. 3025 */ 3026 protected final Visibility getBeanMethodVisibility() { 3027 return beanMethodVisibility; 3028 } 3029 3030 /** 3031 * Configuration property: Beans require no-arg constructors. 3032 * 3033 * @see #BEAN_beansRequireDefaultConstructor 3034 * @return 3035 * <jk>true</jk> if a Java class must implement a default no-arg constructor to be considered a bean. 3036 * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 3037 */ 3038 protected final boolean isBeansRequireDefaultConstructor() { 3039 return beansRequireDefaultConstructor; 3040 } 3041 3042 /** 3043 * Configuration property: Beans require Serializable interface. 3044 * 3045 * @see #BEAN_beansRequireSerializable 3046 * @return 3047 * <jk>true</jk> if a Java class must implement the {@link Serializable} interface to be considered a bean. 3048 * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 3049 */ 3050 protected final boolean isBeansRequireSerializable() { 3051 return beansRequireSerializable; 3052 } 3053 3054 /** 3055 * Configuration property: Beans require setters for getters. 3056 * 3057 * @see #BEAN_beansRequireSettersForGetters 3058 * @return 3059 * <jk>true</jk> if only getters that have equivalent setters will be considered as properties on a bean. 3060 * <br>Otherwise, they are ignored. 3061 */ 3062 protected final boolean isBeansRequireSettersForGetters() { 3063 return beansRequireSettersForGetters; 3064 } 3065 3066 /** 3067 * Configuration property: Beans require at least one property. 3068 * 3069 * @see #BEAN_beansRequireSomeProperties 3070 * @return 3071 * <jk>true</jk> if a Java class must contain at least 1 property to be considered a bean. 3072 * <br>Otherwise, the bean is serialized as a string using the {@link Object#toString()} method. 3073 */ 3074 protected final boolean isBeansRequireSomeProperties() { 3075 return beansRequireSomeProperties; 3076 } 3077 3078 /** 3079 * Configuration property: Bean type property name. 3080 * 3081 * @see #BEAN_beanTypePropertyName 3082 * @return 3083 * 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. 3084 */ 3085 protected final String getBeanTypePropertyName() { 3086 return beanTypePropertyName; 3087 } 3088 3089 /** 3090 * Configuration property: Bean property includes. 3091 * 3092 * @see #BEAN_bpi 3093 * @return 3094 * Include properties keyed by class name. 3095 */ 3096 protected final Map<String,Set<String>> getBpi() { 3097 return bpi; 3098 } 3099 3100 /** 3101 * Returns the {@link #BEAN_bpi} setting for the specified class. 3102 * 3103 * @param c The class. 3104 * @return The properties to include for the specified class, or an empty set if it's not defined for the class. 3105 */ 3106 protected Set<String> getBpi(Class<?> c) { 3107 if (bpi.isEmpty()) 3108 return emptySet(); 3109 ClassInfo ci = ClassInfo.of(c); 3110 for (ClassInfo c2 : ci.getAllParents()) { 3111 for (String n : c2.getNames()) { 3112 Set<String> s = bpi.get(n); 3113 if (s != null) 3114 return s; 3115 } 3116 } 3117 if (bpi.containsKey("*")) 3118 return bpi.get("*"); 3119 return emptySet(); 3120 } 3121 3122 /** 3123 * Configuration property: Bean property excludes. 3124 * 3125 * @see #BEAN_bpx 3126 * @return 3127 * The list of property names to exclude keyed by class name. 3128 */ 3129 protected final Map<String,Set<String>> getBpx() { 3130 return bpx; 3131 } 3132 3133 /** 3134 * Returns the {@link #BEAN_bpx} setting for the specified class. 3135 * 3136 * @param c The class. 3137 * @return The properties to exclude for the specified class, or an empty set if it's not defined for the class. 3138 */ 3139 protected Set<String> getBpx(Class<?> c) { 3140 if (bpx.isEmpty()) 3141 return emptySet(); 3142 ClassInfo ci = ClassInfo.of(c); 3143 for (ClassInfo c2 : ci.getAllParents()) { 3144 for (String n : c2.getNames()) { 3145 Set<String> s = bpx.get(n); 3146 if (s != null) 3147 return s; 3148 } 3149 } 3150 if (bpx.containsKey("*")) 3151 return bpx.get("*"); 3152 return emptySet(); 3153 } 3154 3155 /** 3156 * Configuration property: Read-only bean properties. 3157 * 3158 * @see #BEAN_bpro 3159 * @return 3160 * The list of read-only property names keyed by class name. 3161 */ 3162 protected final Map<String,Set<String>> getBpro() { 3163 return bpro; 3164 } 3165 3166 /** 3167 * Returns the {@link #BEAN_bpro} setting for the specified class. 3168 * 3169 * @param c The class. 3170 * @return The read-only properties for the specified class, or an empty set if it's not defined for the class. 3171 */ 3172 protected Set<String> getBpro(Class<?> c) { 3173 if (bpro.isEmpty()) 3174 return emptySet(); 3175 ClassInfo ci = ClassInfo.of(c); 3176 for (ClassInfo c2 : ci.getAllParents()) { 3177 for (String n : c2.getNames()) { 3178 Set<String> s = bpro.get(n); 3179 if (s != null) 3180 return s; 3181 } 3182 } 3183 if (bpro.containsKey("*")) 3184 return bpro.get("*"); 3185 return emptySet(); 3186 } 3187 3188 /** 3189 * Configuration property: Write-only bean properties. 3190 * 3191 * @see #BEAN_bpwo 3192 * @return 3193 * The list of write-only property names keyed by class name. 3194 */ 3195 protected final Map<String,Set<String>> getBpwo() { 3196 return bpwo; 3197 } 3198 3199 /** 3200 * Returns the {@link #BEAN_bpwo} setting for the specified class. 3201 * 3202 * @param c The class. 3203 * @return The write-only properties for the specified class, or an empty set if it's not defined for the class. 3204 */ 3205 protected Set<String> getBpwo(Class<?> c) { 3206 if (bpwo.isEmpty()) 3207 return emptySet(); 3208 ClassInfo ci = ClassInfo.of(c); 3209 for (ClassInfo c2 : ci.getAllParents()) { 3210 for (String n : c2.getNames()) { 3211 Set<String> s = bpwo.get(n); 3212 if (s != null) 3213 return s; 3214 } 3215 } 3216 if (bpwo.containsKey("*")) 3217 return bpwo.get("*"); 3218 return emptySet(); 3219 } 3220 3221 /** 3222 * Configuration property: Debug mode. 3223 * 3224 * @see #BEAN_debug 3225 * @return 3226 * <jk>true</jk> if debug mode is enabled. 3227 */ 3228 protected boolean isDebug() { 3229 return debug; 3230 } 3231 3232 /** 3233 * Configuration property: POJO examples. 3234 * 3235 * @see #BEAN_examples 3236 * @return 3237 * A map of POJO examples keyed by class name. 3238 */ 3239 protected final Map<String,?> getExamples() { 3240 return examples; 3241 } 3242 3243 /** 3244 * Configuration property: Find fluent setters. 3245 * 3246 * <h5 class='section'>Description:</h5> 3247 * <p> 3248 * 3249 * @see #BEAN_fluentSetters 3250 * @return 3251 * <jk>true</jk> if fluent setters are detected on beans. 3252 */ 3253 protected final boolean isFluentSetters() { 3254 return fluentSetters; 3255 } 3256 3257 /** 3258 * Configuration property: Ignore invocation errors on getters. 3259 * 3260 * @see #BEAN_ignoreInvocationExceptionsOnGetters 3261 * @return 3262 * <jk>true</jk> if errors thrown when calling bean getter methods are silently ignored. 3263 */ 3264 protected final boolean isIgnoreInvocationExceptionsOnGetters() { 3265 return ignoreInvocationExceptionsOnGetters; 3266 } 3267 3268 /** 3269 * Configuration property: Ignore invocation errors on setters. 3270 * 3271 * @see #BEAN_ignoreInvocationExceptionsOnSetters 3272 * @return 3273 * <jk>true</jk> if errors thrown when calling bean setter methods are silently ignored. 3274 */ 3275 protected final boolean isIgnoreInvocationExceptionsOnSetters() { 3276 return ignoreInvocationExceptionsOnSetters; 3277 } 3278 3279 /** 3280 * Configuration property: Ignore properties without setters. 3281 * 3282 * <br>Otherwise, a {@code RuntimeException} is thrown. 3283 * 3284 * @see #BEAN_ignorePropertiesWithoutSetters 3285 * @return 3286 * <jk>true</jk> if trying to set a value on a bean property without a setter is silently ignored. 3287 */ 3288 protected final boolean isIgnorePropertiesWithoutSetters() { 3289 return ignorePropertiesWithoutSetters; 3290 } 3291 3292 /** 3293 * Configuration property: Ignore unknown properties. 3294 * 3295 * @see #BEAN_ignoreUnknownBeanProperties 3296 * @return 3297 * <jk>true</jk> if trying to set a value on a non-existent bean property is silently ignored. 3298 * <br>Otherwise, a {@code RuntimeException} is thrown. 3299 */ 3300 protected final boolean isIgnoreUnknownBeanProperties() { 3301 return ignoreUnknownBeanProperties; 3302 } 3303 3304 /** 3305 * Configuration property: Ignore unknown properties with null values. 3306 * 3307 * @see #BEAN_ignoreUnknownNullBeanProperties 3308 * @return 3309 * <jk>true</jk> if trying to set a <jk>null</jk> value on a non-existent bean property is silently ignored. 3310 */ 3311 protected final boolean isIgnoreUnknownNullBeanProperties() { 3312 return ignoreUnknownNullBeanProperties; 3313 } 3314 3315 /** 3316 * Configuration property: Implementation classes. 3317 * 3318 * @see #BEAN_implClasses 3319 * @return 3320 * Implementation classes keyed by interface class names. 3321 */ 3322 protected final Map<String,ClassInfo> getImplClasses() { 3323 return implClasses; 3324 } 3325 3326 /** 3327 * Configuration property: Locale. 3328 * 3329 * @see #BEAN_locale 3330 * @return 3331 * The default locale for serializer and parser sessions. 3332 */ 3333 protected final Locale getLocale() { 3334 return locale; 3335 } 3336 3337 /** 3338 * Configuration property: Media type. 3339 * 3340 * @see #BEAN_mediaType 3341 * @return 3342 * The default media type value for serializer and parser sessions. 3343 */ 3344 protected final MediaType getMediaType() { 3345 return mediaType; 3346 } 3347 3348 /** 3349 * Configuration property: Bean class exclusions. 3350 * 3351 * @see #BEAN_notBeanClasses 3352 * @return 3353 * The list of classes that are explicitly not beans. 3354 */ 3355 protected final Class<?>[] getNotBeanClasses() { 3356 return notBeanClasses; 3357 } 3358 3359 /** 3360 * Configuration property: Bean package exclusions. 3361 * 3362 * @see #BEAN_notBeanPackages 3363 * @return 3364 * The list of fully-qualified package names to exclude from being classified as beans. 3365 */ 3366 protected final String[] getNotBeanPackagesNames() { 3367 return notBeanPackageNames; 3368 } 3369 3370 /** 3371 * Configuration property: Bean package exclusions. 3372 * 3373 * @see #BEAN_notBeanPackages 3374 * @return 3375 * The list of package name prefixes to exclude from being classified as beans. 3376 */ 3377 protected final String[] getNotBeanPackagesPrefixes() { 3378 return notBeanPackagePrefixes; 3379 } 3380 3381 /** 3382 * Configuration property: POJO swaps. 3383 * 3384 * @see #BEAN_pojoSwaps 3385 * @return 3386 * The list POJO swaps defined. 3387 */ 3388 protected final PojoSwap<?,?>[] getPojoSwaps() { 3389 return pojoSwaps; 3390 } 3391 3392 /** 3393 * Configuration property: Bean property namer. 3394 * 3395 * @see #BEAN_propertyNamer 3396 * @return 3397 * The interface used to calculate bean property names. 3398 */ 3399 protected final PropertyNamer getPropertyNamer() { 3400 return propertyNamer; 3401 } 3402 3403 /** 3404 * Configuration property: Sort bean properties. 3405 * 3406 * @see #BEAN_sortProperties 3407 * @return 3408 * <jk>true</jk> if all bean properties will be serialized and access in alphabetical order. 3409 */ 3410 protected final boolean isSortProperties() { 3411 return sortProperties; 3412 } 3413 3414 /** 3415 * Configuration property: Time zone. 3416 * 3417 * @see #BEAN_timeZone 3418 * @return 3419 * The default timezone for serializer and parser sessions. 3420 */ 3421 protected final TimeZone getTimeZone() { 3422 return timeZone; 3423 } 3424 3425 /** 3426 * Configuration property: Use enum names. 3427 * 3428 * @see #BEAN_useEnumNames 3429 * @return 3430 * <jk>true</jk> if enums are always serialized by name, not using {@link Object#toString()}. 3431 */ 3432 protected final boolean isUseEnumNames() { 3433 return useEnumNames; 3434 } 3435 3436 /** 3437 * Configuration property: Use interface proxies. 3438 * 3439 * @see #BEAN_useInterfaceProxies 3440 * @return 3441 * <jk>true</jk> if interfaces will be instantiated as proxy classes through the use of an 3442 * {@link InvocationHandler} if there is no other way of instantiating them. 3443 */ 3444 protected final boolean isUseInterfaceProxies() { 3445 return useInterfaceProxies; 3446 } 3447 3448 /** 3449 * Configuration property: Use Java Introspector. 3450 * 3451 * @see #BEAN_useJavaBeanIntrospector 3452 * @return 3453 * <jk>true</jk> if the built-in Java bean introspector should be used for bean introspection. 3454 */ 3455 protected final boolean isUseJavaBeanIntrospector() { 3456 return useJavaBeanIntrospector; 3457 } 3458 3459 //----------------------------------------------------------------------------------------------------------------- 3460 // Other methods 3461 //----------------------------------------------------------------------------------------------------------------- 3462 3463 @Override /* Context */ 3464 public ObjectMap toMap() { 3465 return super.toMap() 3466 .append("BeanContext", new DefaultFilteringObjectMap() 3467 .append("id", System.identityHashCode(this)) 3468 .append("beanClassVisibility", beanClassVisibility) 3469 .append("beanConstructorVisibility", beanConstructorVisibility) 3470 .append("beanDictionaryClasses", beanDictionaryClasses) 3471 .append("beanFieldVisibility", beanFieldVisibility) 3472 .append("beanFilters", beanFilters) 3473 .append("beanMapPutReturnsOldValue", beanMapPutReturnsOldValue) 3474 .append("beanMethodVisibility", beanMethodVisibility) 3475 .append("beansRequireDefaultConstructor", beansRequireDefaultConstructor) 3476 .append("beansRequireSerializable", beansRequireSerializable) 3477 .append("beansRequireSettersForGetters", beansRequireSettersForGetters) 3478 .append("beansRequireSomeProperties", beansRequireSomeProperties) 3479 .append("bpi", bpi) 3480 .append("bpx", bpx) 3481 .append("ignoreInvocationExceptionsOnGetters", ignoreInvocationExceptionsOnGetters) 3482 .append("ignoreInvocationExceptionsOnSetters", ignoreInvocationExceptionsOnSetters) 3483 .append("ignorePropertiesWithoutSetters", ignorePropertiesWithoutSetters) 3484 .append("ignoreUnknownBeanProperties", ignoreUnknownBeanProperties) 3485 .append("ignoreUnknownNullBeanProperties", ignoreUnknownNullBeanProperties) 3486 .append("implClasses", implClasses) 3487 .append("locale", locale) 3488 .append("mediaType", mediaType) 3489 .append("notBeanClasses", notBeanClasses) 3490 .append("notBeanPackageNames", notBeanPackageNames) 3491 .append("notBeanPackagePrefixes", notBeanPackagePrefixes) 3492 .append("pojoSwaps", pojoSwaps) 3493 .append("sortProperties", sortProperties) 3494 .append("timeZone", timeZone) 3495 .append("useEnumNames", useEnumNames) 3496 .append("useInterfaceProxies", useInterfaceProxies) 3497 .append("useJavaBeanIntrospector", useJavaBeanIntrospector) 3498 ); 3499 } 3500}