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.internal.ClassUtils.*; 016import static org.apache.juneau.internal.StringUtils.*; 017import static org.apache.juneau.internal.ThrowableUtils.*; 018 019import java.io.*; 020import java.lang.reflect.*; 021import java.util.*; 022import java.util.Date; 023import java.util.concurrent.atomic.*; 024 025import org.apache.juneau.http.*; 026import org.apache.juneau.httppart.*; 027import org.apache.juneau.internal.*; 028import org.apache.juneau.json.*; 029import org.apache.juneau.parser.*; 030import org.apache.juneau.serializer.*; 031import org.apache.juneau.transform.*; 032 033/** 034 * Session object that lives for the duration of a single use of {@link Serializer} or {@link Parser}. 035 * 036 * <p> 037 * This class is NOT thread safe. It is meant to be discarded after one-time use. 038 */ 039@SuppressWarnings({"unchecked","rawtypes"}) 040public class BeanSession extends Session { 041 042 private final BeanContext ctx; 043 private final Locale locale; 044 private final TimeZone timeZone; 045 private final MediaType mediaType; 046 private final boolean debug; 047 private final HttpPartSchema schema; 048 private Stack<StringBuilder> sbStack = new Stack<>(); 049 050 /** 051 * Create a new session using properties specified in the context. 052 * 053 * @param ctx 054 * The context creating this session object. 055 * The context contains all the configuration settings for this object. 056 * @param args 057 * Runtime session arguments. 058 */ 059 protected BeanSession(BeanContext ctx, BeanSessionArgs args) { 060 super(args); 061 this.ctx = ctx; 062 locale = ObjectUtils.firstNonNull(args.locale, ctx.getLocale(), Locale.getDefault()); 063 timeZone = ObjectUtils.firstNonNull(args.timeZone, ctx.getTimeZone()); 064 debug = ObjectUtils.firstNonNull(args.debug, ctx.isDebug(), false); 065 schema = args.schema; 066 mediaType = ObjectUtils.firstNonNull(args.mediaType, ctx.getMediaType()); 067 } 068 069 @Override /* Session */ 070 public ObjectMap asMap() { 071 return super.asMap() 072 .appendAll(ctx.asMap()) 073 .append("BeanSession", new ObjectMap() 074 .append("debug", debug) 075 .append("locale", locale) 076 .append("schema", schema) 077 .append("mediaType", mediaType) 078 .append("timeZone", timeZone) 079 ); 080 } 081 082 /** 083 * Converts the specified value to the specified class type. 084 * 085 * <p> 086 * See {@link #convertToType(Object, ClassMeta)} for the list of valid conversions. 087 * 088 * @param <T> The class type to convert the value to. 089 * @param value The value to convert. 090 * @param type The class type to convert the value to. 091 * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. 092 * @return The converted value. 093 */ 094 public final <T> T convertToType(Object value, Class<T> type) throws InvalidDataConversionException { 095 // Shortcut for most common case. 096 if (value != null && value.getClass() == type) 097 return (T)value; 098 return convertToMemberType(null, value, getClassMeta(type)); 099 } 100 101 /** 102 * Same as {@link #convertToType(Object, Class)}, except used for instantiating inner member classes that must 103 * be instantiated within another class instance. 104 * 105 * @param <T> The class type to convert the value to. 106 * @param outer 107 * If class is a member class, this is the instance of the containing class. 108 * Should be <jk>null</jk> if not a member class. 109 * @param value The value to convert. 110 * @param type The class type to convert the value to. 111 * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. 112 * @return The converted value. 113 */ 114 public final <T> T convertToMemberType(Object outer, Object value, Class<T> type) throws InvalidDataConversionException { 115 return convertToMemberType(outer, value, getClassMeta(type)); 116 } 117 118 /** 119 * Casts the specified value into the specified type. 120 * 121 * <p> 122 * If the value isn't an instance of the specified type, then converts the value if possible. 123 * 124 * <p> 125 * The following conversions are valid: 126 * <table class='styled'> 127 * <tr><th>Convert to type</th><th>Valid input value types</th><th>Notes</th></tr> 128 * <tr> 129 * <td> 130 * A class that is the normal type of a registered {@link PojoSwap}. 131 * </td> 132 * <td> 133 * A value whose class matches the transformed type of that registered {@link PojoSwap}. 134 * </td> 135 * <td> </td> 136 * </tr> 137 * <tr> 138 * <td> 139 * A class that is the transformed type of a registered {@link PojoSwap}. 140 * </td> 141 * <td> 142 * A value whose class matches the normal type of that registered {@link PojoSwap}. 143 * </td> 144 * <td> </td> 145 * </tr> 146 * <tr> 147 * <td> 148 * {@code Number} (e.g. {@code Integer}, {@code Short}, {@code Float},...) 149 * <br><code>Number.<jsf>TYPE</jsf></code> (e.g. <code>Integer.<jsf>TYPE</jsf></code>, 150 * <code>Short.<jsf>TYPE</jsf></code>, <code>Float.<jsf>TYPE</jsf></code>,...) 151 * </td> 152 * <td> 153 * {@code Number}, {@code String}, <jk>null</jk> 154 * </td> 155 * <td> 156 * For primitive {@code TYPES}, <jk>null</jk> returns the JVM default value for that type. 157 * </td> 158 * </tr> 159 * <tr> 160 * <td> 161 * {@code Map} (e.g. {@code Map}, {@code HashMap}, {@code TreeMap}, {@code ObjectMap}) 162 * </td> 163 * <td> 164 * {@code Map} 165 * </td> 166 * <td> 167 * If {@code Map} is not constructible, a {@code ObjectMap} is created. 168 * </td> 169 * </tr> 170 * <tr> 171 * <td> 172 * {@code Collection} (e.g. {@code List}, {@code LinkedList}, {@code HashSet}, {@code ObjectList}) 173 * </td> 174 * <td> 175 * {@code Collection<Object>} 176 * <br>{@code Object[]} 177 * </td> 178 * <td> 179 * If {@code Collection} is not constructible, a {@code ObjectList} is created. 180 * </td> 181 * </tr> 182 * <tr> 183 * <td> 184 * {@code X[]} (array of any type X) 185 * </td> 186 * <td> 187 * {@code List<X>} 188 * </td> 189 * <td> </td> 190 * </tr> 191 * <tr> 192 * <td> 193 * {@code X[][]} (multi-dimensional arrays) 194 * </td> 195 * <td> 196 * {@code List<List<X>>} 197 * <br>{@code List<X[]>} 198 * <br>{@code List[]<X>} 199 * </td> 200 * <td> </td> 201 * </tr> 202 * <tr> 203 * <td> 204 * {@code Enum} 205 * </td> 206 * <td> 207 * {@code String} 208 * </td> 209 * <td> </td> 210 * </tr> 211 * <tr> 212 * <td> 213 * Bean 214 * </td> 215 * <td> 216 * {@code Map} 217 * </td> 218 * <td> </td> 219 * </tr> 220 * <tr> 221 * <td> 222 * {@code String} 223 * </td> 224 * <td> 225 * Anything 226 * </td> 227 * <td> 228 * Arrays are converted to JSON arrays 229 * </td> 230 * </tr> 231 * <tr> 232 * <td> 233 * Anything with one of the following methods: 234 * <br><code><jk>public static</jk> T fromString(String)</code> 235 * <br><code><jk>public static</jk> T valueOf(String)</code> 236 * <br><code><jk>public</jk> T(String)</code> 237 * </td> 238 * <td> 239 * <code>String</code> 240 * </td> 241 * <td> 242 * <br> 243 * </td> 244 * </tr> 245 * </table> 246 * 247 * @param <T> The class type to convert the value to. 248 * @param value The value to be converted. 249 * @param type The target object type. 250 * @return The converted type. 251 * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. 252 */ 253 public final <T> T convertToType(Object value, ClassMeta<T> type) throws InvalidDataConversionException { 254 return convertToMemberType(null, value, type); 255 } 256 257 /** 258 * Same as {@link #convertToType(Object, Class)}, but allows for complex data types consisting of collections or maps. 259 * 260 * @param <T> The class type to convert the value to. 261 * @param value The value to be converted. 262 * @param type The target object type. 263 * @param args The target object parameter types. 264 * @return The converted type. 265 * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. 266 */ 267 public final <T> T convertToType(Object value, Type type, Type...args) throws InvalidDataConversionException { 268 return (T)convertToMemberType(null, value, getClassMeta(type, args)); 269 } 270 271 /** 272 * Same as {@link #convertToType(Object, ClassMeta)}, except used for instantiating inner member classes that must 273 * be instantiated within another class instance. 274 * 275 * @param <T> The class type to convert the value to. 276 * @param outer 277 * If class is a member class, this is the instance of the containing class. 278 * Should be <jk>null</jk> if not a member class. 279 * @param value The value to convert. 280 * @param to The class type to convert the value to. 281 * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. 282 * @return The converted value. 283 */ 284 protected final <T> T convertToMemberType(Object outer, Object value, ClassMeta<T> to) throws InvalidDataConversionException { 285 if (to == null) 286 to = (ClassMeta<T>)object(); 287 288 try { 289 // Handle the case of a null value. 290 if (value == null) { 291 292 // If it's a primitive, then use the converters to get the default value for the primitive type. 293 if (to.isPrimitive()) 294 return to.getPrimitiveDefault(); 295 296 // Otherwise, just return null. 297 return null; 298 } 299 300 Class<T> tc = to.getInnerClass(); 301 302 // If no conversion needed, then just return the value. 303 // Don't include maps or collections, because child elements may need conversion. 304 if (tc.isInstance(value)) 305 if (! ((to.isMap() && to.getValueType().isNotObject()) || (to.isCollection() && to.getElementType().isNotObject()))) 306 return (T)value; 307 308 PojoSwap swap = to.getPojoSwap(this); 309 if (swap != null) { 310 Class<?> nc = swap.getNormalClass(), fc = swap.getSwapClass(); 311 if (isParentClass(nc, tc) && isParentClass(fc, value.getClass())) 312 return (T)swap.unswap(this, value, to); 313 } 314 315 ClassMeta<?> from = getClassMetaForObject(value); 316 swap = from.getPojoSwap(this); 317 if (swap != null) { 318 Class<?> nc = swap.getNormalClass(), fc = swap.getSwapClass(); 319 if (isParentClass(nc, from.getInnerClass()) && isParentClass(fc, tc)) 320 return (T)swap.swap(this, value); 321 } 322 323 if (to.isPrimitive()) { 324 if (to.isNumber()) { 325 if (from.isNumber()) { 326 Number n = (Number)value; 327 if (tc == Integer.TYPE) 328 return (T)Integer.valueOf(n.intValue()); 329 if (tc == Short.TYPE) 330 return (T)Short.valueOf(n.shortValue()); 331 if (tc == Long.TYPE) 332 return (T)Long.valueOf(n.longValue()); 333 if (tc == Float.TYPE) 334 return (T)Float.valueOf(n.floatValue()); 335 if (tc == Double.TYPE) 336 return (T)Double.valueOf(n.doubleValue()); 337 if (tc == Byte.TYPE) 338 return (T)Byte.valueOf(n.byteValue()); 339 } else if (from.isBoolean()) { 340 Boolean b = (Boolean)value; 341 if (tc == Integer.TYPE) 342 return (T)(Integer.valueOf(b ? 1 : 0)); 343 if (tc == Short.TYPE) 344 return (T)(Short.valueOf(b ? (short)1 : 0)); 345 if (tc == Long.TYPE) 346 return (T)(Long.valueOf(b ? 1l : 0)); 347 if (tc == Float.TYPE) 348 return (T)(Float.valueOf(b ? 1f : 0)); 349 if (tc == Double.TYPE) 350 return (T)(Double.valueOf(b ? 1d : 0)); 351 if (tc == Byte.TYPE) 352 return (T)(Byte.valueOf(b ? (byte)1 : 0)); 353 } else if (isNullOrEmpty(value)) { 354 return (T)getPrimitiveDefault(to.innerClass); 355 } else { 356 String s = value.toString(); 357 int multiplier = (tc == Integer.TYPE || tc == Short.TYPE || tc == Long.TYPE) ? getMultiplier(s) : 1; 358 if (multiplier != 1) { 359 s = s.substring(0, s.length()-1).trim(); 360 Long l = Long.valueOf(s) * multiplier; 361 if (tc == Integer.TYPE) 362 return (T)Integer.valueOf(l.intValue()); 363 if (tc == Short.TYPE) 364 return (T)Short.valueOf(l.shortValue()); 365 if (tc == Long.TYPE) 366 return (T)Long.valueOf(l.longValue()); 367 } else { 368 if (tc == Integer.TYPE) 369 return (T)Integer.valueOf(s); 370 if (tc == Short.TYPE) 371 return (T)Short.valueOf(s); 372 if (tc == Long.TYPE) 373 return (T)Long.valueOf(s); 374 if (tc == Float.TYPE) 375 return (T)new Float(s); 376 if (tc == Double.TYPE) 377 return (T)new Double(s); 378 if (tc == Byte.TYPE) 379 return (T)Byte.valueOf(s); 380 } 381 } 382 } else if (to.isChar()) { 383 if (isNullOrEmpty(value)) 384 return (T)getPrimitiveDefault(to.innerClass); 385 return (T)parseCharacter(value); 386 } else if (to.isBoolean()) { 387 if (from.isNumber()) { 388 int i = ((Number)value).intValue(); 389 return (T)(i == 0 ? Boolean.FALSE : Boolean.TRUE); 390 } else if (isNullOrEmpty(value)) { 391 return (T)getPrimitiveDefault(to.innerClass); 392 } else { 393 return (T)Boolean.valueOf(value.toString()); 394 } 395 } 396 } 397 398 if (to.isNumber()) { 399 if (from.isNumber()) { 400 Number n = (Number)value; 401 if (tc == Integer.class) 402 return (T)Integer.valueOf(n.intValue()); 403 if (tc == Short.class) 404 return (T)Short.valueOf(n.shortValue()); 405 if (tc == Long.class) 406 return (T)Long.valueOf(n.longValue()); 407 if (tc == Float.class) 408 return (T)Float.valueOf(n.floatValue()); 409 if (tc == Double.class) 410 return (T)Double.valueOf(n.doubleValue()); 411 if (tc == Byte.class) 412 return (T)Byte.valueOf(n.byteValue()); 413 if (tc == AtomicInteger.class) 414 return (T)new AtomicInteger(n.intValue()); 415 if (tc == AtomicLong.class) 416 return (T)new AtomicLong(n.intValue()); 417 } else if (from.isBoolean()) { 418 Boolean b = (Boolean)value; 419 if (tc == Integer.class) 420 return (T)Integer.valueOf(b ? 1 : 0); 421 if (tc == Short.class) 422 return (T)Short.valueOf(b ? (short)1 : 0); 423 if (tc == Long.class) 424 return (T)Long.valueOf(b ? 1 : 0); 425 if (tc == Float.class) 426 return (T)Float.valueOf(b ? 1 : 0); 427 if (tc == Double.class) 428 return (T)Double.valueOf(b ? 1 : 0); 429 if (tc == Byte.class) 430 return (T)Byte.valueOf(b ? (byte)1 : 0); 431 if (tc == AtomicInteger.class) 432 return (T)new AtomicInteger(b ? 1 : 0); 433 if (tc == AtomicLong.class) 434 return (T)new AtomicLong(b ? 1 : 0); 435 } else if (isNullOrEmpty(value)) { 436 return null; 437 } else if (! hasTransform(from, to)) { 438 String s = value.toString(); 439 440 int multiplier = (tc == Integer.class || tc == Short.class || tc == Long.class) ? getMultiplier(s) : 1; 441 if (multiplier != 1) { 442 s = s.substring(0, s.length()-1).trim(); 443 Long l = Long.valueOf(s) * multiplier; 444 if (tc == Integer.TYPE) 445 return (T)Integer.valueOf(l.intValue()); 446 if (tc == Short.TYPE) 447 return (T)Short.valueOf(l.shortValue()); 448 if (tc == Long.TYPE) 449 return (T)Long.valueOf(l.longValue()); 450 } else { 451 if (tc == Integer.class) 452 return (T)Integer.valueOf(s); 453 if (tc == Short.class) 454 return (T)Short.valueOf(s); 455 if (tc == Long.class) 456 return (T)Long.valueOf(s); 457 if (tc == Float.class) 458 return (T)new Float(s); 459 if (tc == Double.class) 460 return (T)new Double(s); 461 if (tc == Byte.class) 462 return (T)Byte.valueOf(s); 463 if (tc == AtomicInteger.class) 464 return (T)new AtomicInteger(Integer.valueOf(s)); 465 if (tc == AtomicLong.class) 466 return (T)new AtomicLong(Long.valueOf(s)); 467 if (tc == Number.class) 468 return (T)StringUtils.parseNumber(s, Number.class); 469 } 470 } 471 } 472 473 if (to.isChar()) { 474 if (isNullOrEmpty(value)) 475 return null; 476 String s = value.toString(); 477 if (s.length() == 1) 478 return (T)Character.valueOf(s.charAt(0)); 479 } 480 481 if (to.isByteArray()) { 482 if (from.isInputStream()) 483 return (T)IOUtils.readBytes((InputStream)value, 1024); 484 if (from.isReader()) 485 return (T)IOUtils.read((Reader)value).getBytes(); 486 } 487 488 // Handle setting of array properties 489 if (to.isArray()) { 490 if (from.isCollection()) 491 return (T)toArray(to, (Collection)value); 492 else if (from.isArray()) 493 return (T)toArray(to, Arrays.asList((Object[])value)); 494 else if (startsWith(value.toString(), '[')) 495 return (T)toArray(to, new ObjectList(value.toString()).setBeanSession(this)); 496 else if (to.hasTransformFrom(from)) 497 return to.transformFrom(value); 498 else if (from.hasTransformTo(to)) 499 return from.transformTo(value, to); 500 else 501 return (T)toArray(to, new ObjectList((Object[])StringUtils.split(value.toString())).setBeanSession(this)); 502 } 503 504 // Target type is some sort of Map that needs to be converted. 505 if (to.isMap()) { 506 try { 507 if (from.isMap()) { 508 Map m = to.canCreateNewInstance(outer) ? (Map)to.newInstance(outer) : new ObjectMap(this); 509 ClassMeta keyType = to.getKeyType(), valueType = to.getValueType(); 510 for (Map.Entry e : (Set<Map.Entry>)((Map)value).entrySet()) { 511 Object k = e.getKey(); 512 if (keyType.isNotObject()) { 513 if (keyType.isString() && k.getClass() != Class.class) 514 k = k.toString(); 515 else 516 k = convertToMemberType(m, k, keyType); 517 } 518 Object v = e.getValue(); 519 if (valueType.isNotObject()) 520 v = convertToMemberType(m, v, valueType); 521 m.put(k, v); 522 } 523 return (T)m; 524 } else if (!to.canCreateNewInstanceFromString(outer)) { 525 ObjectMap m = new ObjectMap(value.toString()); 526 m.setBeanSession(this); 527 return convertToMemberType(outer, m, to); 528 } 529 } catch (Exception e) { 530 throw new InvalidDataConversionException(value.getClass(), to, e); 531 } 532 } 533 534 // Target type is some sort of Collection 535 if (to.isCollection()) { 536 try { 537 Collection l = to.canCreateNewInstance(outer) ? (Collection)to.newInstance(outer) : to.isSet() ? new LinkedHashSet<>() : new ObjectList(this); 538 ClassMeta elementType = to.getElementType(); 539 540 if (from.isArray()) 541 for (Object o : (Object[])value) 542 l.add(elementType.isObject() ? o : convertToMemberType(l, o, elementType)); 543 else if (from.isCollection()) 544 for (Object o : (Collection)value) 545 l.add(elementType.isObject() ? o : convertToMemberType(l, o, elementType)); 546 else if (from.isMap()) 547 l.add(elementType.isObject() ? value : convertToMemberType(l, value, elementType)); 548 else if (isNullOrEmpty(value)) 549 return null; 550 else if (from.isString()) { 551 String s = value.toString(); 552 if (isObjectList(s, false)) { 553 ObjectList l2 = new ObjectList(s); 554 l2.setBeanSession(this); 555 for (Object o : l2) 556 l.add(elementType.isObject() ? o : convertToMemberType(l, o, elementType)); 557 } else { 558 throw new InvalidDataConversionException(value.getClass(), to, null); 559 } 560 } 561 else 562 throw new InvalidDataConversionException(value.getClass(), to, null); 563 return (T)l; 564 } catch (InvalidDataConversionException e) { 565 throw e; 566 } catch (Exception e) { 567 throw new InvalidDataConversionException(value.getClass(), to, e); 568 } 569 } 570 571 if (to.isEnum()) { 572 if (to.canCreateNewInstanceFromString(outer)) 573 return to.newInstanceFromString(outer, value.toString()); 574 if (isNullOrEmpty(value)) 575 return null; 576 return (T)Enum.valueOf((Class<? extends Enum>)tc, value.toString()); 577 } 578 579 if (to.isString()) { 580 if (from.isByteArray()) { 581 return (T) new String((byte[])value); 582 } else if (from.isMapOrBean() || from.isCollectionOrArray()) { 583 if (SimpleJsonSerializer.DEFAULT != null) 584 return (T)SimpleJsonSerializer.DEFAULT.serialize(value); 585 } else if (from.isClass()) { 586 return (T)((Class<?>)value).getName(); 587 } 588 return (T)value.toString(); 589 } 590 591 if (to.isCharSequence()) { 592 Class<?> c = value.getClass(); 593 if (c.isArray()) { 594 if (c.getComponentType().isPrimitive()) { 595 ObjectList l = new ObjectList(this); 596 int size = Array.getLength(value); 597 for (int i = 0; i < size; i++) 598 l.add(Array.get(value, i)); 599 value = l; 600 } 601 value = new ObjectList((Object[])value).setBeanSession(this); 602 } 603 604 return to.newInstanceFromString(outer, value.toString()); 605 } 606 607 if (to.isBoolean()) { 608 if (from.isNumber()) 609 return (T)(Boolean.valueOf(((Number)value).intValue() != 0)); 610 if (isNullOrEmpty(value)) 611 return null; 612 if (! hasTransform(from, to)) 613 return (T)Boolean.valueOf(value.toString()); 614 } 615 616 // It's a bean being initialized with a Map 617 if (to.isBean() && value instanceof Map) { 618 BuilderSwap<T,Object> builder = (BuilderSwap<T,Object>)to.getBuilderSwap(this); 619 620 if (value instanceof ObjectMap && builder == null) { 621 ObjectMap m2 = (ObjectMap)value; 622 String typeName = m2.getString(getBeanTypePropertyName(to)); 623 if (typeName != null) { 624 ClassMeta cm = to.getBeanRegistry().getClassMeta(typeName); 625 if (cm != null && isParentClass(to.innerClass, cm.innerClass)) 626 return (T)m2.cast(cm); 627 } 628 } 629 if (builder != null) { 630 BeanMap m = toBeanMap(builder.create(this, to)); 631 m.load((Map<?,?>) value); 632 return builder.build(this, m.getBean(), to); 633 } 634 return newBeanMap(tc).load((Map<?,?>) value).getBean(); 635 } 636 637 if (to.isInputStream()) { 638 if (from.isByteArray()) { 639 byte[] b = (byte[])value; 640 return (T) new ByteArrayInputStream(b, 0, b.length); 641 } 642 byte[] b = value.toString().getBytes(); 643 return (T)new ByteArrayInputStream(b, 0, b.length); 644 } 645 646 if (to.isReader()) { 647 if (from.isByteArray()) { 648 byte[] b = (byte[])value; 649 return (T) new StringReader(new String(b)); 650 } 651 return (T)new StringReader(value.toString()); 652 } 653 654 if (to.isCalendar()) { 655 if (from.isCalendar()) { 656 Calendar c = (Calendar)value; 657 if (value instanceof GregorianCalendar) { 658 GregorianCalendar c2 = new GregorianCalendar(c.getTimeZone()); 659 c2.setTime(c.getTime()); 660 return (T)c2; 661 } 662 } 663 if (from.isDate()) { 664 Date d = (Date)value; 665 if (value instanceof GregorianCalendar) { 666 GregorianCalendar c2 = new GregorianCalendar(TimeZone.getDefault()); 667 c2.setTime(d); 668 return (T)c2; 669 } 670 } 671 } 672 673 if (to.isDate() && to.getInnerClass() == Date.class) { 674 if (from.isCalendar()) 675 return (T)((Calendar)value).getTime(); 676 } 677 678 if (to.hasTransformFrom(from)) 679 return to.transformFrom(value); 680 681 if (from.hasTransformTo(to)) 682 return from.transformTo(value, to); 683 684 if (to.isBean()) 685 return newBeanMap(to.getInnerClass()).load(value.toString()).getBean(); 686 687 if (to.canCreateNewInstanceFromNumber(outer) && value instanceof Number) 688 return to.newInstanceFromNumber(this, outer, (Number)value); 689 690 if (to.canCreateNewInstanceFromString(outer)) 691 return to.newInstanceFromString(outer, value.toString()); 692 693 } catch (Exception e) { 694 throw new InvalidDataConversionException(value, to, e); 695 } 696 697 throw new InvalidDataConversionException(value, to, null); 698 } 699 700 private static boolean hasTransform(ClassMeta<?> from, ClassMeta<?> to) { 701 return to.hasTransformFrom(from) || from.hasTransformTo(to); 702 } 703 704 private static final boolean isNullOrEmpty(Object o) { 705 return o == null || o.toString().equals("") || o.toString().equals("null"); 706 } 707 708 private static int getMultiplier(String s) { 709 if (s.endsWith("G")) 710 return 1024*1024*1024; 711 if (s.endsWith("M")) 712 return 1024*1024; 713 if (s.endsWith("K")) 714 return 1024; 715 return 1; 716 } 717 718 /** 719 * Converts the contents of the specified list into an array. 720 * 721 * <p> 722 * Works on both object and primitive arrays. 723 * 724 * <p> 725 * In the case of multi-dimensional arrays, the incoming list must contain elements of type n-1 dimension. 726 * i.e. if {@code type} is <code><jk>int</jk>[][]</code> then {@code list} must have entries of type 727 * <code><jk>int</jk>[]</code>. 728 * 729 * @param type The type to convert to. Must be an array type. 730 * @param list The contents to populate the array with. 731 * @return A new object or primitive array. 732 */ 733 protected final Object toArray(ClassMeta<?> type, Collection<?> list) { 734 if (list == null) 735 return null; 736 ClassMeta<?> componentType = type.isArgs() ? object() : type.getElementType(); 737 Object array = Array.newInstance(componentType.getInnerClass(), list.size()); 738 int i = 0; 739 for (Object o : list) { 740 if (! type.getInnerClass().isInstance(o)) { 741 if (componentType.isArray() && o instanceof Collection) 742 o = toArray(componentType, (Collection<?>)o); 743 else if (o == null && componentType.isPrimitive()) 744 o = componentType.getPrimitiveDefault(); 745 else 746 o = convertToType(o, componentType); 747 } 748 try { 749 Array.set(array, i++, o); 750 } catch (IllegalArgumentException e) { 751 e.printStackTrace(); 752 throw e; 753 } 754 } 755 return array; 756 } 757 758 /** 759 * Wraps an object inside a {@link BeanMap} object (a modifiable {@link Map}). 760 * 761 * <p> 762 * If object is not a true bean, then throws a {@link BeanRuntimeException} with an explanation of why it's not a 763 * bean. 764 * 765 * <h5 class='section'>Example:</h5> 766 * <p class='bcode w800'> 767 * <jc>// Construct a bean map around a bean instance</jc> 768 * BeanMap<Person> bm = BeanContext.<jsf>DEFAULT</jsf>.forBean(<jk>new</jk> Person()); 769 * </p> 770 * 771 * @param <T> The class of the object being wrapped. 772 * @param o The object to wrap in a map interface. Must not be null. 773 * @return The wrapped object. 774 */ 775 public final <T> BeanMap<T> toBeanMap(T o) { 776 return this.toBeanMap(o, (Class<T>)o.getClass()); 777 } 778 779 /** 780 * Determines whether the specified object matches the requirements on this context of being a bean. 781 * 782 * @param o The object being tested. 783 * @return <jk>true</jk> if the specified object is considered a bean. 784 */ 785 public final boolean isBean(Object o) { 786 if (o == null) 787 return false; 788 return isBean(o.getClass()); 789 } 790 791 /** 792 * Determines whether the specified class matches the requirements on this context of being a bean. 793 * 794 * @param c The class being tested. 795 * @return <jk>true</jk> if the specified class is considered a bean. 796 */ 797 public final boolean isBean(Class<?> c) { 798 return getBeanMeta(c) != null; 799 } 800 801 /** 802 * Wraps an object inside a {@link BeanMap} object (i.e.: a modifiable {@link Map}) defined as a bean for one of its 803 * class, a super class, or an implemented interface. 804 * 805 * <p> 806 * If object is not a true bean, throws a {@link BeanRuntimeException} with an explanation of why it's not a bean. 807 * 808 * <h5 class='section'>Example:</h5> 809 * <p class='bcode w800'> 810 * <jc>// Construct a bean map for new bean using only properties defined in a superclass</jc> 811 * BeanMap<MySubBean> bm = BeanContext.<jsf>DEFAULT</jsf>.forBean(<jk>new</jk> MySubBean(), MySuperBean.<jk>class</jk>); 812 * 813 * <jc>// Construct a bean map for new bean using only properties defined in an interface</jc> 814 * BeanMap<MySubBean> bm = BeanContext.<jsf>DEFAULT</jsf>.forBean(<jk>new</jk> MySubBean(), MySuperInterface.<jk>class</jk>); 815 * </p> 816 * 817 * @param <T> The class of the object being wrapped. 818 * @param o The object to wrap in a bean interface. Must not be null. 819 * @param c The superclass to narrow the bean properties to. Must not be null. 820 * @return The bean representation, or <jk>null</jk> if the object is not a true bean. 821 * @throws NullPointerException If either parameter is null. 822 * @throws IllegalArgumentException If the specified object is not an an instance of the specified class. 823 * @throws 824 * BeanRuntimeException If specified object is not a bean according to the bean rules specified in this context 825 * class. 826 */ 827 public final <T> BeanMap<T> toBeanMap(T o, Class<? super T> c) throws BeanRuntimeException { 828 assertFieldNotNull(o, "o"); 829 assertFieldNotNull(c, "c"); 830 831 if (! c.isInstance(o)) 832 illegalArg("The specified object is not an instance of the specified class. class=''{0}'', objectClass=''{1}'', object=''{2}''", c.getName(), o.getClass().getName(), 0); 833 834 ClassMeta cm = getClassMeta(c); 835 836 BeanMeta m = cm.getBeanMeta(); 837 if (m == null) 838 throw new BeanRuntimeException(c, "Class is not a bean. Reason=''{0}''", cm.getNotABeanReason()); 839 return new BeanMap<>(this, o, m); 840 } 841 842 /** 843 * Creates a new {@link BeanMap} object (a modifiable {@link Map}) of the given class with uninitialized 844 * property values. 845 * 846 * <p> 847 * If object is not a true bean, then throws a {@link BeanRuntimeException} with an explanation of why it's not a 848 * bean. 849 * 850 * <h5 class='section'>Example:</h5> 851 * <p class='bcode w800'> 852 * <jc>// Construct a new bean map wrapped around a new Person object</jc> 853 * BeanMap<Person> bm = BeanContext.<jsf>DEFAULT</jsf>.newBeanMap(Person.<jk>class</jk>); 854 * </p> 855 * 856 * @param <T> The class of the object being wrapped. 857 * @param c The name of the class to create a new instance of. 858 * @return A new instance of the class. 859 */ 860 public final <T> BeanMap<T> newBeanMap(Class<T> c) { 861 return newBeanMap(null, c); 862 } 863 864 /** 865 * Same as {@link #newBeanMap(Class)}, except used for instantiating inner member classes that must be instantiated 866 * within another class instance. 867 * 868 * @param <T> The class of the object being wrapped. 869 * @param c The name of the class to create a new instance of. 870 * @param outer 871 * If class is a member class, this is the instance of the containing class. 872 * Should be <jk>null</jk> if not a member class. 873 * @return A new instance of the class. 874 */ 875 public final <T> BeanMap<T> newBeanMap(Object outer, Class<T> c) { 876 BeanMeta m = getBeanMeta(c); 877 if (m == null) 878 return null; 879 T bean = null; 880 if (m.constructorArgs.length == 0) 881 bean = newBean(outer, c); 882 return new BeanMap<>(this, bean, m); 883 } 884 885 /** 886 * Creates a new empty bean of the specified type, except used for instantiating inner member classes that must 887 * be instantiated within another class instance. 888 * 889 * <h5 class='section'>Example:</h5> 890 * <p class='bcode w800'> 891 * <jc>// Construct a new instance of the specified bean class</jc> 892 * Person p = BeanContext.<jsf>DEFAULT</jsf>.newBean(Person.<jk>class</jk>); 893 * </p> 894 * 895 * @param <T> The class type of the bean being created. 896 * @param c The class type of the bean being created. 897 * @return A new bean object. 898 * @throws BeanRuntimeException If the specified class is not a valid bean. 899 */ 900 public final <T> T newBean(Class<T> c) throws BeanRuntimeException { 901 return newBean(null, c); 902 } 903 904 /** 905 * Same as {@link #newBean(Class)}, except used for instantiating inner member classes that must be instantiated 906 * within another class instance. 907 * 908 * @param <T> The class type of the bean being created. 909 * @param c The class type of the bean being created. 910 * @param outer 911 * If class is a member class, this is the instance of the containing class. 912 * Should be <jk>null</jk> if not a member class. 913 * @return A new bean object. 914 * @throws BeanRuntimeException If the specified class is not a valid bean. 915 */ 916 public final <T> T newBean(Object outer, Class<T> c) throws BeanRuntimeException { 917 ClassMeta<T> cm = getClassMeta(c); 918 BeanMeta m = cm.getBeanMeta(); 919 if (m == null) 920 return null; 921 try { 922 T o = (T)m.newBean(outer); 923 if (o == null) 924 throw new BeanRuntimeException(c, "Class does not have a no-arg constructor."); 925 return o; 926 } catch (BeanRuntimeException e) { 927 throw e; 928 } catch (Exception e) { 929 throw new BeanRuntimeException(e); 930 } 931 } 932 933 /** 934 * Returns the {@link BeanMeta} class for the specified class. 935 * 936 * @param <T> The class type to get the meta-data on. 937 * @param c The class to get the meta-data on. 938 * @return 939 * The {@link BeanMeta} for the specified class, or <jk>null</jk> if the class 940 * is not a bean per the settings on this context. 941 */ 942 public final <T> BeanMeta<T> getBeanMeta(Class<T> c) { 943 if (c == null) 944 return null; 945 return getClassMeta(c).getBeanMeta(); 946 } 947 948 /** 949 * Returns a {@code ClassMeta} wrapper around a {@link Class} object. 950 * 951 * @param <T> The class type being wrapped. 952 * @param c The class being wrapped. 953 * @return The class meta object containing information about the class. 954 */ 955 public final <T> ClassMeta<T> getClassMeta(Class<T> c) { 956 return ctx.getClassMeta(c); 957 } 958 959 /** 960 * Used to resolve <code>ClassMetas</code> of type <code>Collection</code> and <code>Map</code> that have 961 * <code>ClassMeta</code> values that themselves could be collections or maps. 962 * 963 * <p> 964 * <code>Collection</code> meta objects are assumed to be followed by zero or one meta objects indicating the 965 * element type. 966 * 967 * <p> 968 * <code>Map</code> meta objects are assumed to be followed by zero or two meta objects indicating the key and value 969 * types. 970 * 971 * <p> 972 * The array can be arbitrarily long to indicate arbitrarily complex data structures. 973 * 974 * <h5 class='section'>Examples:</h5> 975 * <ul> 976 * <li><code>getClassMeta(String.<jk>class</jk>);</code> - A normal type. 977 * <li><code>getClassMeta(List.<jk>class</jk>);</code> - A list containing objects. 978 * <li><code>getClassMeta(List.<jk>class</jk>, String.<jk>class</jk>);</code> - A list containing strings. 979 * <li><code>getClassMeta(LinkedList.<jk>class</jk>, String.<jk>class</jk>);</code> - A linked-list containing 980 * strings. 981 * <li><code>getClassMeta(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);</code> - 982 * A linked-list containing linked-lists of strings. 983 * <li><code>getClassMeta(Map.<jk>class</jk>);</code> - A map containing object keys/values. 984 * <li><code>getClassMeta(Map.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);</code> - A map 985 * containing string keys/values. 986 * <li><code>getClassMeta(Map.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);</code> - 987 * A map containing string keys and values of lists containing beans. 988 * </ul> 989 * 990 * @param type 991 * The class to resolve. 992 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 993 * @param args 994 * The type arguments of the class if it's a collection or map. 995 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 996 * <br>Ignored if the main type is not a map or collection. 997 * @return The class meta. 998 */ 999 public final <T> ClassMeta<T> getClassMeta(Type type, Type...args) { 1000 return ctx.getClassMeta(type, args); 1001 } 1002 1003 /** 1004 * Given an array of {@link Type} objects, returns a {@link ClassMeta} representing those arguments. 1005 * 1006 * <p> 1007 * Constructs a new meta on each call. 1008 * 1009 * @param classes The array of classes to get class metas for. 1010 * @return The args {@link ClassMeta} object corresponding to the classes. Never <jk>null</jk>. 1011 */ 1012 protected final ClassMeta<Object[]> getArgsClassMeta(Type[] classes) { 1013 assertFieldNotNull(classes, "classes"); 1014 ClassMeta[] cm = new ClassMeta<?>[classes.length]; 1015 for (int i = 0; i < classes.length; i++) 1016 cm[i] = getClassMeta(classes[i]); 1017 return new ClassMeta(cm); 1018 } 1019 1020 /** 1021 * Shortcut for calling {@code getClassMeta(o.getClass())}. 1022 * 1023 * @param <T> The class of the object being passed in. 1024 * @param o The class to find the class type for. 1025 * @return The ClassMeta object, or <jk>null</jk> if {@code o} is <jk>null</jk>. 1026 */ 1027 public final <T> ClassMeta<T> getClassMetaForObject(T o) { 1028 if (o == null) 1029 return null; 1030 return (ClassMeta<T>)getClassMeta(o.getClass()); 1031 } 1032 1033 /** 1034 * Returns the type property name as defined by {@link BeanContext#BEAN_beanTypePropertyName}. 1035 * 1036 * @param cm 1037 * The class meta of the type we're trying to resolve the type name for. 1038 * Can be <jk>null</jk>. 1039 * @return The type property name. Never <jk>null</jk>. 1040 */ 1041 public final String getBeanTypePropertyName(ClassMeta cm) { 1042 String s = cm == null ? null : cm.getBeanTypePropertyName(); 1043 return s == null ? getBeanTypePropertyName() : s; 1044 } 1045 1046 /** 1047 * Returns the bean registry defined in this bean context defined by {@link BeanContext#BEAN_beanDictionary}. 1048 * 1049 * @return The bean registry defined in this bean context. Never <jk>null</jk>. 1050 */ 1051 protected final BeanRegistry getBeanRegistry() { 1052 return ctx.getBeanRegistry(); 1053 } 1054 1055 /** 1056 * Creates an instance of the specified class. 1057 * 1058 * @param c 1059 * The class to cast to. 1060 * @param c2 1061 * The class to instantiate. 1062 * Can also be an instance of the class. 1063 * @return 1064 * The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface. 1065 * @throws 1066 * RuntimeException if constructor could not be found or called. 1067 */ 1068 public <T> T newInstance(Class<T> c, Object c2) { 1069 return ctx.newInstance(c, c2); 1070 } 1071 1072 /** 1073 * Creates an instance of the specified class. 1074 * 1075 * @param c 1076 * The class to cast to. 1077 * @param c2 1078 * The class to instantiate. 1079 * Can also be an instance of the class. 1080 * @param fuzzyArgs 1081 * Use fuzzy constructor arg matching. 1082 * <br>When <jk>true</jk>, constructor args can be in any order and extra args are ignored. 1083 * <br>No-arg constructors are also used if no other constructors are found. 1084 * @param args 1085 * The arguments to pass to the constructor. 1086 * @return 1087 * The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface. 1088 * @throws 1089 * RuntimeException if constructor could not be found or called. 1090 */ 1091 public <T> T newInstance(Class<T> c, Object c2, boolean fuzzyArgs, Object...args) { 1092 return ctx.newInstance(c, c2, fuzzyArgs, args); 1093 } 1094 1095 /** 1096 * Creates an instance of the specified class from within the context of another object. 1097 * 1098 * @param outer 1099 * The outer object. 1100 * Can be <jk>null</jk>. 1101 * @param c 1102 * The class to cast to. 1103 * @param c2 1104 * The class to instantiate. 1105 * Can also be an instance of the class. 1106 * @param fuzzyArgs 1107 * Use fuzzy constructor arg matching. 1108 * <br>When <jk>true</jk>, constructor args can be in any order and extra args are ignored. 1109 * <br>No-arg constructors are also used if no other constructors are found. 1110 * @param args 1111 * The arguments to pass to the constructor. 1112 * @return 1113 * The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface. 1114 * @throws 1115 * RuntimeException if constructor could not be found or called. 1116 */ 1117 public <T> T newInstanceFromOuter(Object outer, Class<T> c, Object c2, boolean fuzzyArgs, Object...args) { 1118 return ctx.newInstanceFromOuter(outer, c, c2, fuzzyArgs, args); 1119 } 1120 1121 /** 1122 * Creates a reusable {@link StringBuilder} object from an internal pool. 1123 * 1124 * <p> 1125 * String builders are returned to the pool by calling {@link #returnStringBuilder(StringBuilder)}. 1126 * 1127 * @return A new or previously returned string builder. 1128 */ 1129 protected final StringBuilder getStringBuilder() { 1130 if (sbStack.isEmpty()) 1131 return new StringBuilder(); 1132 return sbStack.pop(); 1133 } 1134 1135 /** 1136 * Returns a {@link StringBuilder} object back into the internal reuse pool. 1137 * 1138 * @param sb The string builder to return to the pool. No-op if <jk>null</jk>. 1139 */ 1140 protected final void returnStringBuilder(StringBuilder sb) { 1141 if (sb == null) 1142 return; 1143 sb.setLength(0); 1144 sbStack.push(sb); 1145 } 1146 1147 /** 1148 * Returns a reusable {@link ClassMeta} representation for the class <code>Object</code>. 1149 * 1150 * <p> 1151 * This <code>ClassMeta</code> is often used to represent "any object type" when an object type is not known. 1152 * 1153 * <p> 1154 * This method is identical to calling <code>getClassMeta(Object.<jk>class</jk>)</code> but uses a cached copy to 1155 * avoid a hashmap lookup. 1156 * 1157 * @return The {@link ClassMeta} object associated with the <code>Object</code> class. 1158 */ 1159 public final ClassMeta<Object> object() { 1160 return ctx.object(); 1161 } 1162 1163 /** 1164 * Returns a reusable {@link ClassMeta} representation for the class <code>String</code>. 1165 * 1166 * <p> 1167 * This <code>ClassMeta</code> is often used to represent key types in maps. 1168 * 1169 * <p> 1170 * This method is identical to calling <code>getClassMeta(String.<jk>class</jk>)</code> but uses a cached copy to 1171 * avoid a hashmap lookup. 1172 * 1173 * @return The {@link ClassMeta} object associated with the <code>String</code> class. 1174 */ 1175 public final ClassMeta<String> string() { 1176 return ctx.string(); 1177 } 1178 1179 /** 1180 * Returns a reusable {@link ClassMeta} representation for the class <code>Class</code>. 1181 * 1182 * <p> 1183 * This <code>ClassMeta</code> is often used to represent key types in maps. 1184 * 1185 * <p> 1186 * This method is identical to calling <code>getClassMeta(Class.<jk>class</jk>)</code> but uses a cached copy to 1187 * avoid a hashmap lookup. 1188 * 1189 * @return The {@link ClassMeta} object associated with the <code>String</code> class. 1190 */ 1191 public final ClassMeta<Class> _class() { 1192 return ctx._class(); 1193 } 1194 1195 //----------------------------------------------------------------------------------------------------------------- 1196 // Properties 1197 //----------------------------------------------------------------------------------------------------------------- 1198 1199 /** 1200 * Configuration property: Beans require no-arg constructors. 1201 * 1202 * @see BeanContext#BEAN_beansRequireDefaultConstructor 1203 * @return 1204 * <jk>true</jk> if a Java class must implement a default no-arg constructor to be considered a bean. 1205 * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 1206 */ 1207 protected final boolean isBeansRequireDefaultConstructor() { 1208 return ctx.isBeansRequireDefaultConstructor(); 1209 } 1210 1211 /** 1212 * Configuration property: Beans require Serializable interface. 1213 * 1214 * @see BeanContext#BEAN_beansRequireSerializable 1215 * @return 1216 * <jk>true</jk> if a Java class must implement the {@link Serializable} interface to be considered a bean. 1217 * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. 1218 */ 1219 protected final boolean isBeansRequireSerializable() { 1220 return ctx.isBeansRequireSerializable(); 1221 } 1222 1223 /** 1224 * Configuration property: Beans require setters for getters. 1225 * 1226 * @see BeanContext#BEAN_beansRequireSettersForGetters 1227 * @return 1228 * <jk>true</jk> if only getters that have equivalent setters will be considered as properties on a bean. 1229 * <br>Otherwise, they are ignored. 1230 */ 1231 protected final boolean isBeansRequireSettersForGetters() { 1232 return ctx.isBeansRequireSettersForGetters(); 1233 } 1234 1235 /** 1236 * Configuration property: Beans require at least one property. 1237 * 1238 * @see BeanContext#BEAN_beansRequireSomeProperties 1239 * @return 1240 * <jk>true</jk> if a Java class must contain at least 1 property to be considered a bean. 1241 * <br>Otherwise, the bean is serialized as a string using the {@link Object#toString()} method. 1242 */ 1243 protected final boolean isBeansRequireSomeProperties() { 1244 return ctx.isBeansRequireSomeProperties(); 1245 } 1246 1247 /** 1248 * Configuration property: BeanMap.put() returns old property value. 1249 * 1250 * @see BeanContext#BEAN_beanMapPutReturnsOldValue 1251 * @return 1252 * <jk>true</jk> if the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property values. 1253 * <br>Otherwise, it returns <jk>null</jk>. 1254 */ 1255 protected final boolean isBeanMapPutReturnsOldValue() { 1256 return ctx.isBeanMapPutReturnsOldValue(); 1257 } 1258 1259 /** 1260 * Configuration property: Use interface proxies. 1261 * 1262 * @see BeanContext#BEAN_useInterfaceProxies 1263 * @return 1264 * <jk>true</jk> if interfaces will be instantiated as proxy classes through the use of an 1265 * {@link InvocationHandler} if there is no other way of instantiating them. 1266 */ 1267 protected final boolean isUseInterfaceProxies() { 1268 return ctx.isUseInterfaceProxies(); 1269 } 1270 1271 /** 1272 * Configuration property: Ignore unknown properties. 1273 * 1274 * @see BeanContext#BEAN_ignoreUnknownBeanProperties 1275 * @return 1276 * <jk>true</jk> if trying to set a value on a non-existent bean property is silently ignored. 1277 * <br>Otherwise, a {@code RuntimeException} is thrown. 1278 */ 1279 protected final boolean isIgnoreUnknownBeanProperties() { 1280 return ctx.isIgnoreUnknownBeanProperties(); 1281 } 1282 1283 /** 1284 * Configuration property: Ignore unknown properties with null values. 1285 * 1286 * @see BeanContext#BEAN_ignoreUnknownNullBeanProperties 1287 * @return 1288 * <jk>true</jk> if trying to set a <jk>null</jk> value on a non-existent bean property is silently ignored. 1289 */ 1290 protected final boolean isIgnoreUnknownNullBeanProperties() { 1291 return ctx.isIgnoreUnknownNullBeanProperties(); 1292 } 1293 1294 /** 1295 * Configuration property: Ignore properties without setters. 1296 * 1297 * <br>Otherwise, a {@code RuntimeException} is thrown. 1298 * 1299 * @see BeanContext#BEAN_ignorePropertiesWithoutSetters 1300 * @return 1301 * <jk>true</jk> if trying to set a value on a bean property without a setter is silently ignored. 1302 */ 1303 protected final boolean isIgnorePropertiesWithoutSetters() { 1304 return ctx.isIgnorePropertiesWithoutSetters(); 1305 } 1306 1307 /** 1308 * Configuration property: Ignore invocation errors on getters. 1309 * 1310 * @see BeanContext#BEAN_ignoreInvocationExceptionsOnGetters 1311 * @return 1312 * <jk>true</jk> if errors thrown when calling bean getter methods are silently ignored. 1313 */ 1314 protected final boolean isIgnoreInvocationExceptionsOnGetters() { 1315 return ctx.isIgnoreInvocationExceptionsOnGetters(); 1316 } 1317 1318 /** 1319 * Configuration property: Ignore invocation errors on setters. 1320 * 1321 * @see BeanContext#BEAN_ignoreInvocationExceptionsOnSetters 1322 * @return 1323 * <jk>true</jk> if errors thrown when calling bean setter methods are silently ignored. 1324 */ 1325 protected final boolean isIgnoreInvocationExceptionsOnSetters() { 1326 return ctx.isIgnoreInvocationExceptionsOnSetters(); 1327 } 1328 1329 /** 1330 * Configuration property: Use Java Introspector. 1331 * 1332 * @see BeanContext#BEAN_useJavaBeanIntrospector 1333 * @return 1334 * <jk>true</jk> if the built-in Java bean introspector should be used for bean introspection. 1335 */ 1336 protected final boolean isUseJavaBeanIntrospector() { 1337 return ctx.isUseJavaBeanIntrospector(); 1338 } 1339 1340 /** 1341 * Configuration property: Use enum names. 1342 * 1343 * @see BeanContext#BEAN_useEnumNames 1344 * @return 1345 * <jk>true</jk> if enums are always serialized by name, not using {@link Object#toString()}. 1346 */ 1347 protected final boolean isUseEnumNames() { 1348 return ctx.isUseEnumNames(); 1349 } 1350 1351 /** 1352 * Configuration property: Sort bean properties. 1353 * 1354 * @see BeanContext#BEAN_sortProperties 1355 * @return 1356 * <jk>true</jk> if all bean properties will be serialized and access in alphabetical order. 1357 */ 1358 protected final boolean isSortProperties() { 1359 return ctx.isSortProperties(); 1360 } 1361 1362 /** 1363 * Configuration property: Find fluent setters. 1364 * 1365 * <h5 class='section'>Description:</h5> 1366 * <p> 1367 * 1368 * @see BeanContext#BEAN_fluentSetters 1369 * @return 1370 * <jk>true</jk> if fluent setters are detected on beans. 1371 */ 1372 protected final boolean isFluentSetters() { 1373 return ctx.isFluentSetters(); 1374 } 1375 1376 /** 1377 * Configuration property: Minimum bean constructor visibility. 1378 * 1379 * @see BeanContext#BEAN_beanConstructorVisibility 1380 * @return 1381 * Only look for constructors with this specified minimum visibility. 1382 */ 1383 protected final Visibility getBeanConstructorVisibility() { 1384 return ctx.getBeanConstructorVisibility(); 1385 } 1386 1387 /** 1388 * Configuration property: Minimum bean class visibility. 1389 * 1390 * @see BeanContext#BEAN_beanClassVisibility 1391 * @return 1392 * Classes are not considered beans unless they meet the minimum visibility requirements. 1393 */ 1394 protected final Visibility getBeanClassVisibility() { 1395 return ctx.getBeanClassVisibility(); 1396 } 1397 1398 /** 1399 * Configuration property: Minimum bean method visibility. 1400 * 1401 * @see BeanContext#BEAN_beanMethodVisibility 1402 * @return 1403 * Only look for bean methods with this specified minimum visibility. 1404 */ 1405 protected final Visibility getBeanMethodVisibility() { 1406 return ctx.getBeanMethodVisibility(); 1407 } 1408 1409 /** 1410 * Configuration property: Minimum bean field visibility. 1411 * 1412 * 1413 * @see BeanContext#BEAN_beanFieldVisibility 1414 * @return 1415 * Only look for bean fields with this specified minimum visibility. 1416 */ 1417 protected final Visibility getBeanFieldVisibility() { 1418 return ctx.getBeanFieldVisibility(); 1419 } 1420 1421 /** 1422 * Configuration property: Bean dictionary. 1423 * 1424 * @see BeanContext#BEAN_beanDictionary 1425 * @return 1426 * The list of classes that make up the bean dictionary in this bean context. 1427 */ 1428 protected final List<Class<?>> getBeanDictionaryClasses() { 1429 return ctx.getBeanDictionaryClasses(); 1430 } 1431 1432 /** 1433 * Configuration property: Bean property namer. 1434 * 1435 * @see BeanContext#BEAN_propertyNamer 1436 * @return 1437 * The interface used to calculate bean property names. 1438 */ 1439 protected final PropertyNamer getPropertyNamer() { 1440 return ctx.getPropertyNamer(); 1441 } 1442 1443 /** 1444 * Configuration property: Bean type property name. 1445 * 1446 * @see BeanContext#BEAN_beanTypePropertyName 1447 * @return 1448 * 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. 1449 */ 1450 protected final String getBeanTypePropertyName() { 1451 return ctx.getBeanTypePropertyName(); 1452 } 1453 1454 /** 1455 * Configuration property: Debug mode. 1456 * 1457 * @see BeanContext#BEAN_debug 1458 * @return 1459 * <jk>true</jk> if debug mode is enabled. 1460 */ 1461 protected final boolean isDebug() { 1462 return debug; 1463 } 1464 1465 /** 1466 * Configuration property: Locale. 1467 * 1468 * <p> 1469 * The locale is determined in the following order: 1470 * <ol> 1471 * <li><code>locale</code> parameter passed in through constructor. 1472 * <li>{@link BeanContext#BEAN_locale} entry in parameter passed in through constructor. 1473 * <li>{@link BeanContext#BEAN_locale} setting on bean context. 1474 * <li>Locale returned by {@link Locale#getDefault()}. 1475 * </ol> 1476 * 1477 * @see BeanContext#BEAN_locale 1478 * @return The session locale. 1479 */ 1480 public final Locale getLocale() { 1481 return locale; 1482 } 1483 1484 /** 1485 * Configuration property: Time zone. 1486 * 1487 * <p> 1488 * The timezone is determined in the following order: 1489 * <ol> 1490 * <li><code>timeZone</code> parameter passed in through constructor. 1491 * <li>{@link BeanContext#BEAN_timeZone} entry in parameter passed in through constructor. 1492 * <li>{@link BeanContext#BEAN_timeZone} setting on bean context. 1493 * </ol> 1494 * 1495 * @see BeanContext#BEAN_timeZone 1496 * @return The session timezone, or <jk>null</jk> if timezone not specified. 1497 */ 1498 public final TimeZone getTimeZone() { 1499 return timeZone; 1500 } 1501 1502 /** 1503 * Configuration property: Media type. 1504 * 1505 * <p> 1506 * For example, <js>"application/json"</js>. 1507 * 1508 * @see BeanContext#BEAN_mediaType 1509 * @return The media type for this session, or <jk>null</jk> if not specified. 1510 */ 1511 public final MediaType getMediaType() { 1512 return mediaType; 1513 } 1514 1515 /** 1516 * HTTP part schema of object being serialized or parsed. 1517 * 1518 * @return HTTP part schema of object being serialized or parsed, or <jk>null</jk> if not specified. 1519 */ 1520 public final HttpPartSchema getSchema() { 1521 return schema; 1522 } 1523 1524 @Override /* Session */ 1525 public void checkForWarnings() { 1526 if (debug) 1527 super.checkForWarnings(); 1528 } 1529}