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