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>&nbsp;</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>&nbsp;</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>&nbsp;</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>&nbsp;</td>
201    *    </tr>
202    *    <tr>
203    *       <td>
204    *          {@code Enum}
205    *       </td>
206    *       <td>
207    *          {@code String}
208    *       </td>
209    *       <td>&nbsp;</td>
210    *    </tr>
211    *    <tr>
212    *       <td>
213    *          Bean
214    *       </td>
215    *       <td>
216    *          {@code Map}
217    *       </td>
218    *       <td>&nbsp;</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&lt;Person&gt; 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&lt;MySubBean&gt; 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&lt;MySubBean&gt; 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&lt;Person&gt; 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}