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