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