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