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