Open Source Repository

Home /json/json-lib-2.4-jdk15 | Repository Home



net/sf/json/JSONArray.java
/*
 * Copyright 2002-2009 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.sf.json;

import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

import net.sf.ezmorph.Morpher;
import net.sf.ezmorph.object.IdentityObjectMorpher;
import net.sf.json.processors.JsonValueProcessor;
import net.sf.json.processors.JsonVerifier;
import net.sf.json.util.JSONTokener;
import net.sf.json.util.JSONUtils;

import org.apache.commons.lang.StringUtils;

/**
 * A JSONArray is an ordered sequence of values. Its external text form is a
 * string wrapped in square brackets with commas separating the values. The
 * internal form is an object having <code>get</code> and <code>opt</code>
 * methods for accessing the values by index, and <code>element</code> methods
 * for adding or replacing values. The values can be any of these types:
 <code>Boolean</code><code>JSONArray</code><code>JSONObject</code>,
 <code>Number</code><code>String</code>, or the
 <code>JSONNull object</code>.
 <p>
 * The constructor can convert a JSON text into a Java object. The
 <code>toString</code> method converts to JSON text.
 <p>
 * A <code>get</code> method returns a value if one can be found, and throws
 * an exception if one cannot be found. An <code>opt</code> method returns a
 * default value instead of throwing an exception, and so is useful for
 * obtaining optional values.
 <p>
 * The generic <code>get()</code> and <code>opt()</code> methods return an
 * object which you can cast or query for type. There are also typed
 <code>get</code> and <code>opt</code> methods that do type checking and
 * type coersion for you.
 <p>
 * The texts produced by the <code>toString</code> methods strictly conform to
 * JSON syntax rules. The constructors are more forgiving in the texts they will
 * accept:
 <ul>
 <li>An extra <code>,</code>&nbsp;<small>(comma)</small> may appear just
 * before the closing bracket.</li>
 <li>The <code>null</code> value will be inserted when there is
 <code>,</code>&nbsp;<small>(comma)</small> elision.</li>
 <li>Strings may be quoted with <code>'</code>&nbsp;<small>(single quote)</small>.</li>
 <li>Strings do not need to be quoted at all if they do not begin with a
 * quote or single quote, and if they do not contain leading or trailing spaces,
 * and if they do not contain any of these characters:
 <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers and
 * if they are not the reserved words <code>true</code><code>false</code>,
 * or <code>null</code>.</li>
 <li>Values can be separated by <code>;</code> <small>(semicolon)</small>
 * as well as by <code>,</code> <small>(comma)</small>.</li>
 <li>Numbers may have the <code>0-</code> <small>(octal)</small> or
 <code>0x-</code> <small>(hex)</small> prefix.</li>
 <li>Comments written in the slashshlash, slashstar, and hash conventions
 * will be ignored.</li>
 </ul>
 *
 @author JSON.org
 */
public final class JSONArray extends AbstractJSON implements JSON, List, Comparable {
   /**
    * Creates a JSONArray.<br>
    * Inspects the object type to call the correct JSONArray factory method.
    * Accepts JSON formatted strings, arrays, Collections and Enums.
    *
    @param object
    @throws JSONException if the object can not be converted to a proper
    *         JSONArray.
    */
   public static JSONArray fromObjectObject object ) {
      return fromObjectobject, new JsonConfig() );
   }

   /**
    * Creates a JSONArray.<br>
    * Inspects the object type to call the correct JSONArray factory method.
    * Accepts JSON formatted strings, arrays, Collections and Enums.
    *
    @param object
    @throws JSONException if the object can not be converted to a proper
    *         JSONArray.
    */
   public static JSONArray fromObjectObject object, JsonConfig jsonConfig ) {
      ifobject instanceof JSONString ){
         return _fromJSONString( (JSONStringobject, jsonConfig );
      }else ifobject instanceof JSONArray ){
         return _fromJSONArray( (JSONArrayobject, jsonConfig );
      }else ifobject instanceof Collection ){
         return _fromCollection( (Collectionobject, jsonConfig );
      }else ifobject instanceof JSONTokener ){
         return _fromJSONTokener( (JSONTokenerobject, jsonConfig );
      }else ifobject instanceof String ){
         return _fromString( (Stringobject, jsonConfig );
      }else ifobject != null && object.getClass()
            .isArray() ){
         Class type = object.getClass()
               .getComponentType();
         if!type.isPrimitive() ){
            return _fromArray( (Object[]) object, jsonConfig );
         }else{
            iftype == Boolean.TYPE ){
               return _fromArray( (boolean[]) object, jsonConfig );
            }else iftype == Byte.TYPE ){
               return _fromArray( (byte[]) object, jsonConfig );
            }else iftype == Short.TYPE ){
               return _fromArray( (short[]) object, jsonConfig );
            }else iftype == Integer.TYPE ){
               return _fromArray( (int[]) object, jsonConfig );
            }else iftype == Long.TYPE ){
               return _fromArray( (long[]) object, jsonConfig );
            }else iftype == Float.TYPE ){
               return _fromArray( (float[]) object, jsonConfig );
            }else iftype == Double.TYPE ){
               return _fromArray( (double[]) object, jsonConfig );
            }else iftype == Character.TYPE ){
               return _fromArray( (char[]) object, jsonConfig );
            }else{
               throw new JSONException"Unsupported type" );
            }
         }
      }else ifJSONUtils.isBooleanobject || JSONUtils.isFunctionobject )
            || JSONUtils.isNumberobject || JSONUtils.isNullobject )
            || JSONUtils.isStringobject || object instanceof JSON ){
         fireArrayStartEventjsonConfig );
         JSONArray jsonArray = new JSONArray().elementobject, jsonConfig );
         fireElementAddedEvent0, jsonArray.get), jsonConfig );
         fireArrayStartEventjsonConfig );
         return jsonArray;
      }else ifobject instanceof Enum ){
         return _fromArray( (Enumobject, jsonConfig );
      }else ifobject instanceof Annotation || (object != null && object.getClass()
            .isAnnotation()) ){
         throw new JSONException"Unsupported type" );
      }else ifJSONUtils.isObjectobject ) ){
         fireArrayStartEventjsonConfig );
         JSONArray jsonArray = new JSONArray().elementJSONObject.fromObjectobject, jsonConfig ) );
         fireElementAddedEvent0, jsonArray.get), jsonConfig );
         fireArrayStartEventjsonConfig );
         return jsonArray;
      }else{
         throw new JSONException"Unsupported type" );
      }
   }

   /**
    * Get the collection type from a getter or setter, or null if no type was
    * found.<br/>
    * Contributed by [Matt Small @ WaveMaker].
    */
   public static Class[] getCollectionTypePropertyDescriptor pd, boolean useGetter )
         throws JSONException {

      Type type;
      ifuseGetter ){
         Method m = pd.getReadMethod();
         type = m.getGenericReturnType();
      }else{
         Method m = pd.getWriteMethod();
         Type[] gpts = m.getGenericParameterTypes();

         if!= gpts.length ){
            throw new JSONException"method " + m + " is not a standard setter" );
         }
         type = gpts[0];
      }

      if!(type instanceof ParameterizedType) ){
         return null;
         // throw new JSONException("type not instanceof ParameterizedType:
         // "+type.getClass());
      }

      ParameterizedType pType = (ParameterizedTypetype;
      Type[] actualTypes = pType.getActualTypeArguments();

      Class[] ret = new Class[actualTypes.length];
      forint i = 0; i < ret.length; i++ ){
         ret[i(ClassactualTypes[i];
      }

      return ret;
   }

   /**
    * Returns the number of dimensions suited for a java array.
    */
   public static int[] getDimensionsJSONArray jsonArray ) {
      // short circuit for empty arrays
      ifjsonArray == null || jsonArray.isEmpty() ){
         return new int[] { };
      }

      List dims = new ArrayList();
      processArrayDimensionsjsonArray, dims, );
      int[] dimensions = new int[dims.size()];
      int j = 0;
      forIterator i = dims.iterator(); i.hasNext()){
         dimensions[j++((Integeri.next()).intValue();
      }
      return dimensions;
   }

   /**
    * Creates a java array from a JSONArray.
    */
   public static Object toArrayJSONArray jsonArray ) {
      return toArrayjsonArray, new JsonConfig() );
   }

   /**
    * Creates a java array from a JSONArray.
    */
   public static Object toArrayJSONArray jsonArray, Class objectClass ) {
      JsonConfig jsonConfig = new JsonConfig();
      jsonConfig.setRootClassobjectClass );
      return toArrayjsonArray, jsonConfig );
   }

   /**
    * Creates a java array from a JSONArray.<br>
    * Any attribute is a JSONObject and matches a key in the classMap, it will
    * be converted to that target class.<br>
    * The classMap has the following conventions:
    <ul>
    <li>Every key must be an String.</li>
    <li>Every value must be a Class.</li>
    <li>A key may be a regular expression.</li>
    </ul>
    */
   public static Object toArrayJSONArray jsonArray, Class objectClass, Map classMap ) {
      JsonConfig jsonConfig = new JsonConfig();
      jsonConfig.setRootClassobjectClass );
      jsonConfig.setClassMapclassMap );
      return toArrayjsonArray, jsonConfig );
   }

   /**
    * Creates a java array from a JSONArray.<br>
    */
   public static Object toArrayJSONArray jsonArray, JsonConfig jsonConfig ) {
      Class objectClass = jsonConfig.getRootClass();
      Map classMap = jsonConfig.getClassMap();

      ifjsonArray.size() == ){
         return Array.newInstanceobjectClass == null ? Object.class : objectClass, );
      }

      int[] dimensions = JSONArray.getDimensionsjsonArray );
      Object array = Array.newInstanceobjectClass == null ? Object.class : objectClass,
            dimensions );
      int size = jsonArray.size();
      forint i = 0; i < size; i++ ){
         Object value = jsonArray.get);
         ifJSONUtils.isNullvalue ) ){
            Array.setarray, i, null );
         }else{
            Class type = value.getClass();
            ifJSONArray.class.isAssignableFromtype ) ){
               Array.setarray, i, toArray( (JSONArrayvalue, objectClass, classMap ) );
            }else ifString.class.isAssignableFromtype )
                  || Boolean.class.isAssignableFromtype )
                  || Character.class.isAssignableFromtype )
                  || JSONFunction.class.isAssignableFromtype ) ){
               ifobjectClass != null && !objectClass.isAssignableFromtype ) ){
                  value = JSONUtils.getMorpherRegistry()
                        .morphobjectClass, value );
               }
               Array.setarray, i, value );
            }else ifJSONUtils.isNumbertype ) ){
               ifobjectClass != null
                     && (Byte.class.isAssignableFromobjectClass || Byte.TYPE.isAssignableFromobjectClass )) ){
                  Array.setarray, i, Byte.valueOfString.valueOfvalue ) ) );
               }else ifobjectClass != null
                     && (Short.class.isAssignableFromobjectClass || Short.TYPE.isAssignableFromobjectClass )) ){
                  Array.setarray, i, Short.valueOfString.valueOfvalue ) ) );
               }else{
                  Array.setarray, i, value );
               }
            }else{
               ifobjectClass != null ){
                  JsonConfig jsc = jsonConfig.copy();
                  jsc.setRootClassobjectClass );
                  jsc.setClassMapclassMap );
                  Array.setarray, i, JSONObject.toBean( (JSONObjectvalue, jsc ) );
               }else{
                  Array.setarray, i, JSONObject.toBean( (JSONObjectvalue ) );
               }
            }
         }
      }
      return array;
   }

   /**
    * Creates a java array from a JSONArray.<br>
    */
   public static Object toArrayJSONArray jsonArray, Object root, JsonConfig jsonConfig ) {
      Class objectClass = root.getClass();
      ifjsonArray.size() == ){
         return Array.newInstanceobjectClass, );
      }

      int[] dimensions = JSONArray.getDimensionsjsonArray );
      Object array = Array.newInstanceobjectClass == null ? Object.class : objectClass,
            dimensions );
      int size = jsonArray.size();
      forint i = 0; i < size; i++ ){
         Object value = jsonArray.get);
         ifJSONUtils.isNullvalue ) ){
            Array.setarray, i, null );
         }else{
            Class type = value.getClass();
            ifJSONArray.class.isAssignableFromtype ) ){
               Array.setarray, i, toArray( (JSONArrayvalue, root, jsonConfig ) );
            }else ifString.class.isAssignableFromtype )
                  || Boolean.class.isAssignableFromtype || JSONUtils.isNumbertype )
                  || Character.class.isAssignableFromtype )
                  || JSONFunction.class.isAssignableFromtype ) ){
               ifobjectClass != null && !objectClass.isAssignableFromtype ) ){
                  value = JSONUtils.getMorpherRegistry()
                        .morphobjectClass, value );
               }
               Array.setarray, i, value );
            }else{
               try{
                  Object newRoot = jsonConfig.getNewBeanInstanceStrategy()
                        .newInstanceroot.getClass()null );
                  Array.setarray, i, JSONObject.toBean( (JSONObjectvalue, newRoot, jsonConfig ) );
               }catchJSONException jsone ){
                  throw jsone;
               }catchException e ){
                  throw new JSONException);
               }
            }
         }
      }
      return array;
   }

   /**
    * Returns a List or a Set taking generics into account.<br/>
    */
   public static Collection toCollectionJSONArray jsonArray ) {
      return toCollectionjsonArray, new JsonConfig() );
   }

   /**
    * Returns a List or a Set taking generics into account.<br/>
    */
   public static Collection toCollectionJSONArray jsonArray, Class objectClass ) {
      JsonConfig jsonConfig = new JsonConfig();
      jsonConfig.setRootClassobjectClass );
      return toCollectionjsonArray, jsonConfig );
   }

   /**
    * Returns a List or a Set taking generics into account.<br/>
    * Contributed by [Matt Small @ WaveMaker].
    */
   public static Collection toCollectionJSONArray jsonArray, JsonConfig jsonConfig ) {
      Collection collection = null;
      Class collectionType = jsonConfig.getCollectionType();

      ifcollectionType.isInterface() ){
         ifcollectionType.equalsList.class ) ){
            collection = new ArrayList();
         }else ifcollectionType.equalsSet.class ) ){
            collection = new HashSet();
         }else{
            throw new JSONException"unknown interface: " + collectionType );
         }
      }else{
         try{
            collection = (CollectioncollectionType.newInstance();
         }catchInstantiationException e ){
            throw new JSONException);
         }catchIllegalAccessException e ){
            throw new JSONException);
         }
      }

      Class objectClass = jsonConfig.getRootClass();
      Map classMap = jsonConfig.getClassMap();

      int size = jsonArray.size();
      forint i = 0; i < size; i++ ){
         Object value = jsonArray.get);

         ifJSONUtils.isNullvalue ) ){
            collection.addnull );
         }else{
            Class type = value.getClass();
            ifJSONArray.class.isAssignableFromvalue.getClass() ) ){
               collection.addtoCollection( (JSONArrayvalue, jsonConfig ) );
            }else ifString.class.isAssignableFromtype )
                  || Boolean.class.isAssignableFromtype || JSONUtils.isNumbertype )
                  || Character.class.isAssignableFromtype )
                  || JSONFunction.class.isAssignableFromtype ) ){

               ifobjectClass != null && !objectClass.isAssignableFromtype ) ){
                  value = JSONUtils.getMorpherRegistry()
                     .morphobjectClass, value );
               }
               collection.addvalue );
            }else{
               ifobjectClass != null ){
                  JsonConfig jsc = jsonConfig.copy();
                  jsc.setRootClassobjectClass );
                  jsc.setClassMapclassMap );
                  collection.addJSONObject.toBean( (JSONObjectvalue, jsc ) );
               }else{
                  collection.addJSONObject.toBean( (JSONObjectvalue ) );
               }
            }
         }
      }

      return collection;
   }
   /*
   public static Collection toCollection( JSONArray jsonArray, JsonConfig jsonConfig ) {
      Collection collection = null;
      Class collectionType = jsonConfig.getCollectionType();
      Class enclosedType = jsonConfig.getEnclosedType();

      if( collectionType.isInterface() ){
         if( collectionType.equals( List.class ) ){
            collection = new ArrayList();
         }else if( collectionType.equals( Set.class ) ){
            collection = new HashSet();
         }else{
            throw new JSONException( "unknown interface: " + collectionType );
         }
      }else{
         try{
            collection = (Collection) collectionType.newInstance();
         }catch( InstantiationException e ){
            throw new JSONException( e );
         }catch( IllegalAccessException e ){
            throw new JSONException( e );
         }
      }

      Class objectClass = jsonConfig.getRootClass();
      Map classMap = jsonConfig.getClassMap();

      int size = jsonArray.size();
      for( int i = 0; i < size; i++ ){
         Object value = jsonArray.get( i );
         Class enclosedTypeE = enclosedType;

         if( null == enclosedTypeE ){
            enclosedTypeE = value.getClass();
         }

         if( JSONUtils.isNull( value ) ){
            collection.add( null );
         }else{
            if( JSONArray.class.isAssignableFrom( value.getClass() ) ){
               //throw new RuntimeException( "can't have nested collections" );
                collection.add( toCollection( (JSONArray) value, jsonConfig ) );
            }else if( String.class.isAssignableFrom( enclosedTypeE )
                  || Boolean.class.isAssignableFrom( enclosedTypeE )
                  || JSONUtils.isNumber( enclosedTypeE )
                  || Character.class.isAssignableFrom( enclosedTypeE )
                  || JSONFunction.class.isAssignableFrom( enclosedTypeE ) ){

               if( !value.getClass()
                     .isAssignableFrom( enclosedTypeE ) ){
                  throw new JSONException( "can't assign value " + value + " of type "
                        + value.getClass() + " to Collection of type " + enclosedTypeE );
               }
               collection.add( value );
            }else{
               try{
                  if( JSON.class.isAssignableFrom( enclosedTypeE ) ){
                     ret.add( JSONObject.toBean( (JSONObject) value ) );
                  }else{
                     Object newRoot = enclosedTypeE.newInstance();
                     ret.add( JSONObject.toBean( (JSONObject) value, newRoot, jsonConfig ) );
                  }
               }catch( JSONException jsone ){
                  throw jsone;
               }catch( Exception e ){
                  throw new JSONException( e );
               }
               if( objectClass != null ){
                  JsonConfig jsc = jsonConfig.copy();
                  jsc.setRootClass( objectClass );
                  jsc.setClassMap( classMap );
                  collection.add( JSONObject.toBean( (JSONObject) value, jsc ) );
               }else{
                  collection.add( JSONObject.toBean( (JSONObject) value ) );
               }
            }
         }
      }

      return collection;
   }
   */

   /**
    * Creates a List from a JSONArray.<br>
    *
    @deprecated replaced by toCollection
    @see #toCollection(JSONArray)
    */
   public static List toListJSONArray jsonArray ) {
      return toListjsonArray, new JsonConfig() );
   }

   /**
    * Creates a List from a JSONArray.
    *
    @deprecated replaced by toCollection
    @see #toCollection(JSONArray,Class)
    */
   public static List toListJSONArray jsonArray, Class objectClass ) {
      JsonConfig jsonConfig = new JsonConfig();
      jsonConfig.setRootClassobjectClass );
      return toListjsonArray, jsonConfig );
   }

   /**
    * Creates a List from a JSONArray.<br>
    * Any attribute is a JSONObject and matches a key in the classMap, it will
    * be converted to that target class.<br>
    * The classMap has the following conventions:
    <ul>
    <li>Every key must be an String.</li>
    <li>Every value must be a Class.</li>
    <li>A key may be a regular expression.</li>
    </ul>
    *
    @deprecated replaced by toCollection
    @see #toCollection(JSONArray,Class,Map)
    */
   public static List toListJSONArray jsonArray, Class objectClass, Map classMap ) {
      JsonConfig jsonConfig = new JsonConfig();
      jsonConfig.setRootClassobjectClass );
      jsonConfig.setClassMapclassMap );
      return toListjsonArray, jsonConfig );
   }

   /**
    * Creates a List from a JSONArray.<br>
    *
    @deprecated replaced by toCollection
    @see #toCollection(JSONArray,JsonConfig)
    */
   public static List toListJSONArray jsonArray, JsonConfig jsonConfig ) {
      ifjsonArray.size() == ){
         return new ArrayList();
      }

      Class objectClass = jsonConfig.getRootClass();
      Map classMap = jsonConfig.getClassMap();

      List list = new ArrayList();
      int size = jsonArray.size();
      forint i = 0; i < size; i++ ){
         Object value = jsonArray.get);
         ifJSONUtils.isNullvalue ) ){
            list.addnull );
         }else{
            Class type = value.getClass();
            ifJSONArray.class.isAssignableFromtype ) ){
               list.addtoList( (JSONArrayvalue, objectClass, classMap ) );
            }else ifString.class.isAssignableFromtype )
                  || Boolean.class.isAssignableFromtype || JSONUtils.isNumbertype )
                  || Character.class.isAssignableFromtype )
                  || JSONFunction.class.isAssignableFromtype ) ){
               ifobjectClass != null && !objectClass.isAssignableFromtype ) ){
                  value = JSONUtils.getMorpherRegistry()
                        .morphobjectClass, value );
               }
               list.addvalue );
            }else{
               ifobjectClass != null ){
                  JsonConfig jsc = jsonConfig.copy();
                  jsc.setRootClassobjectClass );
                  jsc.setClassMapclassMap );
                  list.addJSONObject.toBean( (JSONObjectvalue, jsc ) );
               }else{
                  list.addJSONObject.toBean( (JSONObjectvalue ) );
               }
            }
         }
      }
      return list;
   }

   /**
    * Creates a List from a JSONArray.<br>
    */
   public static List toListJSONArray jsonArray, Object root, JsonConfig jsonConfig ) {
      ifjsonArray.size() == || root == null ){
         return new ArrayList();
      }

      List list = new ArrayList();
      int size = jsonArray.size();
      forint i = 0; i < size; i++ ){
         Object value = jsonArray.get);
         ifJSONUtils.isNullvalue ) ){
            list.addnull );
         }else{
            Class type = value.getClass();
            ifJSONArray.class.isAssignableFromtype ) ){
               list.addtoList( (JSONArrayvalue, root, jsonConfig ) );
            }else ifString.class.isAssignableFromtype )
                  || Boolean.class.isAssignableFromtype || JSONUtils.isNumbertype )
                  || Character.class.isAssignableFromtype )
                  || JSONFunction.class.isAssignableFromtype ) ){
               list.addvalue );
            }else{
               try{
                  Object newRoot = jsonConfig.getNewBeanInstanceStrategy()
                        .newInstanceroot.getClass()null );
                  list.addJSONObject.toBean( (JSONObjectvalue, newRoot, jsonConfig ) );
               }catchJSONException jsone ){
                  throw jsone;
               }catchException e ){
                  throw new JSONException);
               }
            }
         }
      }
      return list;
   }

   /**
    * Construct a JSONArray from an boolean[].<br>
    *
    @param array An boolean[] array.
    */
   private static JSONArray _fromArrayboolean[] array, JsonConfig jsonConfig ) {
      if!addInstancearray ) ){
         try{
            return jsonConfig.getCycleDetectionStrategy()
                  .handleRepeatedReferenceAsArrayarray );
         }catchJSONException jsone ){
            removeInstancearray );
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }catchRuntimeException e ){
            removeInstancearray );
            JSONException jsone = new JSONException);
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }
      }
      fireArrayStartEventjsonConfig );
      JSONArray jsonArray = new JSONArray();
      forint i = 0; i < array.length; i++ ){
         Boolean b = array[i? Boolean.TRUE : Boolean.FALSE;
         jsonArray.addValueb, jsonConfig );
         fireElementAddedEventi, b, jsonConfig );
      }

      removeInstancearray );
      fireArrayEndEventjsonConfig );
      return jsonArray;
   }

   /**
    * Construct a JSONArray from an byte[].<br>
    *
    @param array An byte[] array.
    */
   private static JSONArray _fromArraybyte[] array, JsonConfig jsonConfig ) {
      if!addInstancearray ) ){
         try{
            return jsonConfig.getCycleDetectionStrategy()
                  .handleRepeatedReferenceAsArrayarray );
         }catchJSONException jsone ){
            removeInstancearray );
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }catchRuntimeException e ){
            removeInstancearray );
            JSONException jsone = new JSONException);
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }
      }
      fireArrayStartEventjsonConfig );
      JSONArray jsonArray = new JSONArray();
      forint i = 0; i < array.length; i++ ){
         Number n = JSONUtils.transformNumbernew Bytearray[i] ) );
         jsonArray.addValuen, jsonConfig );
         fireElementAddedEventi, n, jsonConfig );
      }

      removeInstancearray );
      fireArrayEndEventjsonConfig );
      return jsonArray;
   }

   /**
    * Construct a JSONArray from an char[].<br>
    *
    @param array An char[] array.
    */
   private static JSONArray _fromArraychar[] array, JsonConfig jsonConfig ) {
      if!addInstancearray ) ){
         try{
            return jsonConfig.getCycleDetectionStrategy()
                  .handleRepeatedReferenceAsArrayarray );
         }catchJSONException jsone ){
            removeInstancearray );
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }catchRuntimeException e ){
            removeInstancearray );
            JSONException jsone = new JSONException);
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }
      }
      fireArrayStartEventjsonConfig );
      JSONArray jsonArray = new JSONArray();
      forint i = 0; i < array.length; i++ ){
         Character c = new Characterarray[i] );
         jsonArray.addValuec, jsonConfig );
         fireElementAddedEventi, c, jsonConfig );
      }

      removeInstancearray );
      fireArrayEndEventjsonConfig );
      return jsonArray;
   }

   /**
    * Construct a JSONArray from an double[].<br>
    *
    @param array An double[] array.
    */
   private static JSONArray _fromArraydouble[] array, JsonConfig jsonConfig ) {
      if!addInstancearray ) ){
         try{
            return jsonConfig.getCycleDetectionStrategy()
                  .handleRepeatedReferenceAsArrayarray );
         }catchJSONException jsone ){
            removeInstancearray );
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }catchRuntimeException e ){
            removeInstancearray );
            JSONException jsone = new JSONException);
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }
      }
      fireArrayStartEventjsonConfig );
      JSONArray jsonArray = new JSONArray();
      try{
         forint i = 0; i < array.length; i++ ){
            Double d = new Doublearray[i] );
            JSONUtils.testValidity);
            jsonArray.addValued, jsonConfig );
            fireElementAddedEventi, d, jsonConfig );
         }
      }catchJSONException jsone ){
         removeInstancearray );
         fireErrorEventjsone, jsonConfig );
         throw jsone;
      }

      removeInstancearray );
      fireArrayEndEventjsonConfig );
      return jsonArray;
   }

   /**
    * Construct a JSONArray from an Enum value.
    *
    @param e A enum value.
    @throws JSONException If there is a syntax error.
    */
   private static JSONArray _fromArrayEnum e, JsonConfig jsonConfig ) {
      if!addInstance) ){
         try{
            return jsonConfig.getCycleDetectionStrategy()
                  .handleRepeatedReferenceAsArray);
         }catchJSONException jsone ){
            removeInstance);
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }catchRuntimeException re ){
            removeInstance);
            JSONException jsone = new JSONExceptionre );
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }
      }
      fireArrayStartEventjsonConfig );
      JSONArray jsonArray = new JSONArray();
      ife != null ){
         jsonArray.addValuee, jsonConfig );
         fireElementAddedEvent0, jsonArray.get), jsonConfig );
      }else{
         JSONException jsone = new JSONException"enum value is null" );
         removeInstance);
         fireErrorEventjsone, jsonConfig );
         throw jsone;
      }

      removeInstance);
      fireArrayEndEventjsonConfig );
      return jsonArray;
   }

   /**
    * Construct a JSONArray from an float[].<br>
    *
    @param array An float[] array.
    */
   private static JSONArray _fromArrayfloat[] array, JsonConfig jsonConfig ) {
      if!addInstancearray ) ){
         try{
            return jsonConfig.getCycleDetectionStrategy()
                  .handleRepeatedReferenceAsArrayarray );
         }catchJSONException jsone ){
            removeInstancearray );
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }catchRuntimeException e ){
            removeInstancearray );
            JSONException jsone = new JSONException);
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }
      }
      fireArrayStartEventjsonConfig );
      JSONArray jsonArray = new JSONArray();
      try{
         forint i = 0; i < array.length; i++ ){
            Float f = new Floatarray[i] );
            JSONUtils.testValidity);
            jsonArray.addValuef, jsonConfig );
            fireElementAddedEventi, f, jsonConfig );
         }
      }catchJSONException jsone ){
         removeInstancearray );
         fireErrorEventjsone, jsonConfig );
         throw jsone;
      }

      removeInstancearray );
      fireArrayEndEventjsonConfig );
      return jsonArray;
   }

   /**
    * Construct a JSONArray from an int[].<br>
    *
    @param array An int[] array.
    */
   private static JSONArray _fromArrayint[] array, JsonConfig jsonConfig ) {
      if!addInstancearray ) ){
         try{
            return jsonConfig.getCycleDetectionStrategy()
                  .handleRepeatedReferenceAsArrayarray );
         }catchJSONException jsone ){
            removeInstancearray );
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }catchRuntimeException e ){
            removeInstancearray );
            JSONException jsone = new JSONException);
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }
      }
      fireArrayStartEventjsonConfig );
      JSONArray jsonArray = new JSONArray();
      forint i = 0; i < array.length; i++ ){
         Number n = new Integerarray[i] );
         jsonArray.addValuen, jsonConfig );
         fireElementAddedEventi, n, jsonConfig );
      }

      removeInstancearray );
      fireArrayEndEventjsonConfig );
      return jsonArray;
   }

   /**
    * Construct a JSONArray from an long[].<br>
    *
    @param array An long[] array.
    */
   private static JSONArray _fromArraylong[] array, JsonConfig jsonConfig ) {
      if!addInstancearray ) ){
         try{
            return jsonConfig.getCycleDetectionStrategy()
                  .handleRepeatedReferenceAsArrayarray );
         }catchJSONException jsone ){
            removeInstancearray );
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }catchRuntimeException e ){
            removeInstancearray );
            JSONException jsone = new JSONException);
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }
      }
      fireArrayStartEventjsonConfig );
      JSONArray jsonArray = new JSONArray();
      forint i = 0; i < array.length; i++ ){
         Number n = JSONUtils.transformNumbernew Longarray[i] ) );
         jsonArray.addValuen, jsonConfig );
         fireElementAddedEventi, n, jsonConfig );
      }

      removeInstancearray );
      fireArrayEndEventjsonConfig );
      return jsonArray;
   }

   // ------------------------------------------------------

   private static JSONArray _fromArrayObject[] array, JsonConfig jsonConfig ) {
      if!addInstancearray ) ){
         try{
            return jsonConfig.getCycleDetectionStrategy()
                  .handleRepeatedReferenceAsArrayarray );
         }catchJSONException jsone ){
            removeInstancearray );
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }catchRuntimeException e ){
            removeInstancearray );
            JSONException jsone = new JSONException);
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }
      }
      fireArrayStartEventjsonConfig );
      JSONArray jsonArray = new JSONArray();
      try{
         forint i = 0; i < array.length; i++ ){
            Object element = array[i];
            jsonArray.addValueelement, jsonConfig );
            fireElementAddedEventi, jsonArray.get), jsonConfig );
         }
      }catchJSONException jsone ){
         removeInstancearray );
         fireErrorEventjsone, jsonConfig );
         throw jsone;
      }catchRuntimeException e ){
         removeInstancearray );
         JSONException jsone = new JSONException);
         fireErrorEventjsone, jsonConfig );
         throw jsone;
      }

      removeInstancearray );
      fireArrayEndEventjsonConfig );
      return jsonArray;
   }

   /**
    * Construct a JSONArray from an short[].<br>
    *
    @param array An short[] array.
    */
   private static JSONArray _fromArrayshort[] array, JsonConfig jsonConfig ) {
      if!addInstancearray ) ){
         try{
            return jsonConfig.getCycleDetectionStrategy()
                  .handleRepeatedReferenceAsArrayarray );
         }catchJSONException jsone ){
            removeInstancearray );
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }catchRuntimeException e ){
            removeInstancearray );
            JSONException jsone = new JSONException);
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }
      }
      fireArrayStartEventjsonConfig );
      JSONArray jsonArray = new JSONArray();
      forint i = 0; i < array.length; i++ ){
         Number n = JSONUtils.transformNumbernew Shortarray[i] ) );
         jsonArray.addValuen, jsonConfig );
         fireElementAddedEventi, n, jsonConfig );
      }

      removeInstancearray );
      fireArrayEndEventjsonConfig );
      return jsonArray;
   }

   private static JSONArray _fromCollectionCollection collection, JsonConfig jsonConfig ) {
      if!addInstancecollection ) ){
         try{
            return jsonConfig.getCycleDetectionStrategy()
                  .handleRepeatedReferenceAsArraycollection );
         }catchJSONException jsone ){
            removeInstancecollection );
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }catchRuntimeException e ){
            removeInstancecollection );
            JSONException jsone = new JSONException);
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }
      }
      fireArrayStartEventjsonConfig );
      JSONArray jsonArray = new JSONArray();
      try{
         int i = 0;
         forIterator elements = collection.iterator(); elements.hasNext()){
            Object element = elements.next();
            jsonArray.addValueelement, jsonConfig );
            fireElementAddedEventi, jsonArray.geti++ ), jsonConfig );
         }
      }catchJSONException jsone ){
         removeInstancecollection );
         fireErrorEventjsone, jsonConfig );
         throw jsone;
      }catchRuntimeException e ){
         removeInstancecollection );
         JSONException jsone = new JSONException);
         fireErrorEventjsone, jsonConfig );
         throw jsone;
      }

      removeInstancecollection );
      fireArrayEndEventjsonConfig );
      return jsonArray;
   }

   private static JSONArray _fromJSONArrayJSONArray array, JsonConfig jsonConfig ) {
      if!addInstancearray ) ){
         try{
            return jsonConfig.getCycleDetectionStrategy()
                  .handleRepeatedReferenceAsArrayarray );
         }catchJSONException jsone ){
            removeInstancearray );
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }catchRuntimeException e ){
            removeInstancearray );
            JSONException jsone = new JSONException);
            fireErrorEventjsone, jsonConfig );
            throw jsone;
         }
      }
      fireArrayStartEventjsonConfig );
      JSONArray jsonArray = new JSONArray();
      int index = 0;
      forIterator elements = array.iterator(); elements.hasNext()){
         Object element = elements.next();
         jsonArray.addValueelement, jsonConfig );
         fireElementAddedEventindex++, element, jsonConfig );
      }

      removeInstancearray );
      fireArrayEndEventjsonConfig );
      return jsonArray;
   }

   private static JSONArray _fromJSONStringJSONString string, JsonConfig jsonConfig ) {
      return _fromJSONTokenernew JSONTokenerstring.toJSONString() ), jsonConfig );
   }

   private static JSONArray _fromJSONTokenerJSONTokener tokener, JsonConfig jsonConfig ) {

      JSONArray jsonArray = new JSONArray();
      int index = 0;

      try{
         iftokener.nextClean() != '[' ){
            throw tokener.syntaxError"A JSONArray text must start with '['" );
         }
         fireArrayStartEventjsonConfig );
         iftokener.nextClean() == ']' ){
            fireArrayEndEventjsonConfig );
            return jsonArray;
         }
         tokener.back();
         for;; ){
            iftokener.nextClean() == ',' ){
               tokener.back();
               jsonArray.elements.addJSONNull.getInstance() );
               fireElementAddedEventindex, jsonArray.getindex++ ), jsonConfig );
            }else{
               tokener.back();
               Object v = tokener.nextValuejsonConfig );
               if!JSONUtils.isFunctionHeader) ){
                  ifinstanceof String && JSONUtils.mayBeJSON( (String) ){
                     jsonArray.addValueJSONUtils.DOUBLE_QUOTE + v + JSONUtils.DOUBLE_QUOTE,
                           jsonConfig );
                  }else{
                     jsonArray.addValuev, jsonConfig );
                  }
                  fireElementAddedEventindex, jsonArray.getindex++ ), jsonConfig );
               }else{
                  // read params if any
                  String params = JSONUtils.getFunctionParams( (String);
                  // read function text
                  int i = 0;
                  StringBuffer sb = new StringBuffer();
                  for;; ){
                     char ch = tokener.next();
                     ifch == ){
                        break;
                     }
                     ifch == '{' ){
                        i++;
                     }
                     ifch == '}' ){
                        i--;
                     }
                     sb.appendch );
                     ifi == ){
                        break;
                     }
                  }
                  ifi != ){
                     throw tokener.syntaxError"Unbalanced '{' or '}' on prop: " + v );
                  }
                  // trim '{' at start and '}' at end
                  String text = sb.toString();
                  text = text.substring1, text.length() )
                        .trim();
                  jsonArray.addValuenew JSONFunction( (params != null? StringUtils.split(
                        params, "," : null, text ), jsonConfig );
                  fireElementAddedEventindex, jsonArray.getindex++ ), jsonConfig );
               }
            }
            switchtokener.nextClean() ){
               case ';':
               case ',':
                  iftokener.nextClean() == ']' ){
                     fireArrayEndEventjsonConfig );
                     return jsonArray;
                  }
                  tokener.back();
                  break;
               case ']':
                  fireArrayEndEventjsonConfig );
                  return jsonArray;
               default:
                  throw tokener.syntaxError"Expected a ',' or ']'" );
            }
         }
      }catchJSONException jsone ){
         fireErrorEventjsone, jsonConfig );
         throw jsone;
      }
   }

   private static JSONArray _fromStringString string, JsonConfig jsonConfig ) {
      return _fromJSONTokenernew JSONTokenerstring ), jsonConfig );
   }

   private static void processArrayDimensionsJSONArray jsonArray, List dims, int index ) {
      ifdims.size() <= index ){
         dims.addnew IntegerjsonArray.size() ) );
      }else{
         int i = ((Integerdims.getindex )).intValue();
         ifjsonArray.size() > i ){
            dims.setindex, new IntegerjsonArray.size() ) );
         }
      }
      forIterator i = jsonArray.iterator(); i.hasNext()){
         Object item = i.next();
         ifitem instanceof JSONArray ){
            processArrayDimensions( (JSONArrayitem, dims, index + );
         }
      }
   }

   // ------------------------------------------------------

   /**
    * The List where the JSONArray's properties are kept.
    */
   private List elements;

   /**
    * A flag for XML processing.
    */
   private boolean expandElements;

   /**
    * Construct an empty JSONArray.
    */
   public JSONArray() {
      this.elements = new ArrayList();
   }

   public void addint index, Object value ) {
      addindex, value, new JsonConfig() );
   }

   public void addint index, Object value, JsonConfig jsonConfig ) {
      this.elements.addindex, processValuevalue, jsonConfig ) );
   }

   public boolean addObject value ) {
      return addvalue, new JsonConfig() );
   }

   public boolean addObject value, JsonConfig jsonConfig ) {
      elementvalue, jsonConfig );
      return true;
   }

   public boolean addAllCollection collection ) {
      return addAllcollection, new JsonConfig() );
   }

   public boolean addAllCollection collection, JsonConfig jsonConfig ) {
      ifcollection == null || collection.size() == ){
         return false;
      }
      forIterator i = collection.iterator(); i.hasNext()){
         elementi.next(), jsonConfig );
      }
      return true;
   }

   public boolean addAllint index, Collection collection ) {
      return addAllindex, collection, new JsonConfig() );
   }

   public boolean addAllint index, Collection collection, JsonConfig jsonConfig ) {
      ifcollection == null || collection.size() == ){
         return false;
      }
      int offset = 0;
      forIterator i = collection.iterator(); i.hasNext()){
         this.elements.addindex + (offset++), processValuei.next(), jsonConfig ) );
      }
      return true;
   }

   public void clear() {
      elements.clear();
   }

   public int compareToObject obj ) {
      ifobj != null && (obj instanceof JSONArray) ){
         JSONArray other = (JSONArrayobj;
         int size1 = size();
         int size2 = other.size();
         ifsize1 < size2 ){
            return -1;
         }else ifsize1 > size2 ){
            return 1;
         }else ifthis.equalsother ) ){
            return 0;
         }
      }
      return -1;
   }

   public boolean containsObject o ) {
      return containso, new JsonConfig() );
   }

   public boolean containsObject o, JsonConfig jsonConfig ) {
      return elements.containsprocessValueo, jsonConfig ) );
   }

   public boolean containsAllCollection collection ) {
      return containsAllcollection, new JsonConfig() );
   }

   public boolean containsAllCollection collection, JsonConfig jsonConfig ) {
      return elements.containsAllfromObjectcollection, jsonConfig ) );
   }

   /**
    * Remove an element, if present.
    *
    @param index the index of the element.
    @return this.
    */
   public JSONArray discardint index ) {
      elements.removeindex );
      return this;
   }

   /**
    * Remove an element, if present.
    *
    @param index the element.
    @return this.
    */
   public JSONArray discardObject o ) {
      elements.remove);
      return this;
   }

   /**
    * Append a boolean value. This increases the array's length by one.
    *
    @param value A boolean value.
    @return this.
    */
   public JSONArray elementboolean value ) {
      return elementvalue ? Boolean.TRUE : Boolean.FALSE );
   }

   /**
    * Append a value in the JSONArray, where the value will be a JSONArray which
    * is produced from a Collection.
    *
    @param value A Collection value.
    @return this.
    */
   public JSONArray elementCollection value ) {
      return elementvalue, new JsonConfig() );
   }

   /**
    * Append a value in the JSONArray, where the value will be a JSONArray which
    * is produced from a Collection.
    *
    @param value A Collection value.
    @return this.
    */
   public JSONArray elementCollection value, JsonConfig jsonConfig ) {
      ifvalue instanceof JSONArray ){
         elements.addvalue );
         return this;
      }else{
         return element_fromCollectionvalue, jsonConfig ) );
      }
   }

   /**
    * Append a double value. This increases the array's length by one.
    *
    @param value A double value.
    @throws JSONException if the value is not finite.
    @return this.
    */
   public JSONArray elementdouble value ) {
      Double d = new Doublevalue );
      JSONUtils.testValidity);
      return element);
   }

   /**
    * Append an int value. This increases the array's length by one.
    *
    @param value An int value.
    @return this.
    */
   public JSONArray elementint value ) {
      return elementnew Integervalue ) );
   }

   /**
    * Put or replace a boolean value in the JSONArray. If the index is greater
    * than the length of the JSONArray, then null elements will be added as
    * necessary to pad it out.
    *
    @param index The subscript.
    @param value A boolean value.
    @return this.
    @throws JSONException If the index is negative.
    */
   public JSONArray elementint index, boolean value ) {
      return elementindex, value ? Boolean.TRUE : Boolean.FALSE );
   }

   /**
    * Put a value in the JSONArray, where the value will be a JSONArray which is
    * produced from a Collection.
    *
    @param index The subscript.
    @param value A Collection value.
    @return this.
    @throws JSONException If the index is negative or if the value is not
    *         finite.
    */
   public JSONArray elementint index, Collection value ) {
      return elementindex, value, new JsonConfig() );
   }

   /**
    * Put a value in the JSONArray, where the value will be a JSONArray which is
    * produced from a Collection.
    *
    @param index The subscript.
    @param value A Collection value.
    @return this.
    @throws JSONException If the index is negative or if the value is not
    *         finite.
    */
   public JSONArray elementint index, Collection value, JsonConfig jsonConfig ) {
      ifvalue instanceof JSONArray ){
         ifindex < ){
            throw new JSONException"JSONArray[" + index + "] not found." );
         }
         ifindex < size() ){
            elements.setindex, value );
         }else{
            whileindex != size() ){
               elementJSONNull.getInstance() );
            }
            elementvalue, jsonConfig );
         }
         return this;
      }else{
         return elementindex, _fromCollectionvalue, jsonConfig ) );
      }
   }

   /**
    * Put or replace a double value. If the index is greater than the length of
    * the JSONArray, then null elements will be added as necessary to pad it
    * out.
    *
    @param index The subscript.
    @param value A double value.
    @return this.
    @throws JSONException If the index is negative or if the value is not
    *         finite.
    */
   public JSONArray elementint index, double value ) {
      return elementindex, new Doublevalue ) );
   }

   /**
    * Put or replace an int value. If the index is greater than the length of
    * the JSONArray, then null elements will be added as necessary to pad it
    * out.
    *
    @param index The subscript.
    @param value An int value.
    @return this.
    @throws JSONException If the index is negative.
    */
   public JSONArray elementint index, int value ) {
      return elementindex, new Integervalue ) );
   }

   /**
    * Put or replace a long value. If the index is greater than the length of
    * the JSONArray, then null elements will be added as necessary to pad it
    * out.
    *
    @param index The subscript.
    @param value A long value.
    @return this.
    @throws JSONException If the index is negative.
    */
   public JSONArray elementint index, long value ) {
      return elementindex, new Longvalue ) );
   }

   /**
    * Put a value in the JSONArray, where the value will be a JSONObject which
    * is produced from a Map.
    *
    @param index The subscript.
    @param value The Map value.
    @return this.
    @throws JSONException If the index is negative or if the the value is an
    *         invalid number.
    */
   public JSONArray elementint index, Map value ) {
      return elementindex, value, new JsonConfig() );
   }

   /**
    * Put a value in the JSONArray, where the value will be a JSONObject which
    * is produced from a Map.
    *
    @param index The subscript.
    @param value The Map value.
    @return this.
    @throws JSONException If the index is negative or if the the value is an
    *         invalid number.
    */
   public JSONArray elementint index, Map value, JsonConfig jsonConfig ) {
      ifvalue instanceof JSONObject ){
         ifindex < ){
            throw new JSONException"JSONArray[" + index + "] not found." );
         }
         ifindex < size() ){
            elements.setindex, value );
         }else{
            whileindex != size() ){
               elementJSONNull.getInstance() );
            }
            elementvalue, jsonConfig );
         }
         return this;
      }else{
         return elementindex, JSONObject.fromObjectvalue, jsonConfig ) );
      }
   }

   /**
    * Put or replace an object value in the JSONArray. If the index is greater
    * than the length of the JSONArray, then null elements will be added as
    * necessary to pad it out.
    *
    @param index The subscript.
    @param value An object value. The value should be a Boolean, Double,
    *        Integer, JSONArray, JSONObject, JSONFunction, Long, String,
    *        JSONString or the JSONNull object.
    @return this.
    @throws JSONException If the index is negative or if the the value is an
    *         invalid number.
    */
   public JSONArray elementint index, Object value ) {
      return elementindex, value, new JsonConfig() );
   }

   /**
    * Put or replace an object value in the JSONArray. If the index is greater
    * than the length of the JSONArray, then null elements will be added as
    * necessary to pad it out.
    *
    @param index The subscript.
    @param value An object value. The value should be a Boolean, Double,
    *        Integer, JSONArray, JSONObject, JSONFunction, Long, String,
    *        JSONString or the JSONNull object.
    @return this.
    @throws JSONException If the index is negative or if the the value is an
    *         invalid number.
    */
   public JSONArray elementint index, Object value, JsonConfig jsonConfig ) {
      JSONUtils.testValidityvalue );
      ifindex < ){
         throw new JSONException"JSONArray[" + index + "] not found." );
      }
      ifindex < size() ){
         this.elements.setindex, processValuevalue, jsonConfig ) );
      }else{
         whileindex != size() ){
            elementJSONNull.getInstance() );
         }
         elementvalue, jsonConfig );
      }
      return this;
   }

   /**
    * Put or replace a String value in the JSONArray. If the index is greater
    * than the length of the JSONArray, then null elements will be added as
    * necessary to pad it out.<br>
    * The string may be a valid JSON formatted string, in tha case, it will be
    * transformed to a JSONArray, JSONObject or JSONNull.
    *
    @param index The subscript.
    @param value A String value.
    @return this.
    @throws JSONException If the index is negative or if the the value is an
    *         invalid number.
    */
   public JSONArray elementint index, String value ) {
      return elementindex, value, new JsonConfig() );
   }

   /**
    * Put or replace a String value in the JSONArray. If the index is greater
    * than the length of the JSONArray, then null elements will be added as
    * necessary to pad it out.<br>
    * The string may be a valid JSON formatted string, in tha case, it will be
    * transformed to a JSONArray, JSONObject or JSONNull.
    *
    @param index The subscript.
    @param value A String value.
    @return this.
    @throws JSONException If the index is negative or if the the value is an
    *         invalid number.
    */
   public JSONArray elementint index, String value, JsonConfig jsonConfig ) {
      ifindex < ){
         throw new JSONException"JSONArray[" + index + "] not found." );
      }
      ifindex < size() ){
         ifvalue == null ){
            this.elements.setindex, "" );
         }else ifJSONUtils.mayBeJSONvalue ) ){
            try{
               this.elements.setindex, JSONSerializer.toJSONvalue, jsonConfig ) );
            }catchJSONException jsone ){
               this.elements.setindex, JSONUtils.stripQuotesvalue ) );
            }
         }else{
            this.elements.setindex, JSONUtils.stripQuotesvalue ) );
         }
      }else{
         whileindex != size() ){
            elementJSONNull.getInstance() );
         }
         elementvalue, jsonConfig );
      }
      return this;
   }

   /**
    * Append an JSON value. This increases the array's length by one.
    *
    @param value An JSON value.
    @return this.
    */
   public JSONArray elementJSONNull value ) {
      this.elements.addvalue );
      return this;
   }

   /**
    * Append an JSON value. This increases the array's length by one.
    *
    @param value An JSON value.
    @return this.
    */
   public JSONArray elementJSONObject value ) {
      this.elements.addvalue );
      return this;
   }

   /**
    * Append an long value. This increases the array's length by one.
    *
    @param value A long value.
    @return this.
    */
   public JSONArray elementlong value ) {
      return elementJSONUtils.transformNumbernew Longvalue ) ) );
   }

   /**
    * Put a value in the JSONArray, where the value will be a JSONObject which
    * is produced from a Map.
    *
    @param value A Map value.
    @return this.
    */
   public JSONArray elementMap value ) {
      return elementvalue, new JsonConfig() );
   }

   /**
    * Put a value in the JSONArray, where the value will be a JSONObject which
    * is produced from a Map.
    *
    @param value A Map value.
    @return this.
    */
   public JSONArray elementMap value, JsonConfig jsonConfig ) {
      ifvalue instanceof JSONObject ){
         elements.addvalue );
         return this;
      }else{
         return elementJSONObject.fromObjectvalue, jsonConfig ) );
      }
   }

   /**
    * Append an object value. This increases the array's length by one.
    *
    @param value An object value. The value should be a Boolean, Double,
    *        Integer, JSONArray, JSONObject, JSONFunction, Long, String,
    *        JSONString or the JSONNull object.
    @return this.
    */
   public JSONArray elementObject value ) {
      return elementvalue, new JsonConfig() );
   }

   /**
    * Append an object value. This increases the array's length by one.
    *
    @param value An object value. The value should be a Boolean, Double,
    *        Integer, JSONArray, JSONObject, JSONFunction, Long, String,
    *        JSONString or the JSONNull object.
    @return this.
    */
   public JSONArray elementObject value, JsonConfig jsonConfig ) {
      return addValuevalue, jsonConfig );
   }

   /**
    * Append a String value. This increases the array's length by one.<br>
    * The string may be a valid JSON formatted string, in tha case, it will be
    * transformed to a JSONArray, JSONObject or JSONNull.
    *
    @param value A String value.
    @return this.
    */
   public JSONArray elementString value ) {
      return elementvalue, new JsonConfig() );
   }

   /**
    * Append a String value. This increases the array's length by one.<br>
    * The string may be a valid JSON formatted string, in tha case, it will be
    * transformed to a JSONArray, JSONObject or JSONNull.
    *
    @param value A String value.
    @return this.
    */
   public JSONArray elementString value, JsonConfig jsonConfig ) {
      ifvalue == null ) {
         this.elements.add("");
      else ifJSONUtils.hasQuotesvalue )) {
         this.elements.add(value);
      else ifJSONNull.getInstance().equalsvalue )) {
         this.elements.addJSONNull.getInstance() );
      else ifJSONUtils.isJsonKeyword(value,jsonConfig)) {
         ifjsonConfig.isJavascriptCompliant() && "undefined".equalsvalue )){
            this.elements.addJSONNull.getInstance() );
         }else{
            this.elements.add(value);
         }
      else ifJSONUtils.mayBeJSONvalue ) ){
         try{
            this.elements.addJSONSerializer.toJSONvalue, jsonConfig ) );
         }catchJSONException jsone ){
            this.elements.addvalue );
         }
      else {
         this.elements.add(value);
      }
      return this;
   }

   public boolean equalsObject obj ) {
      ifobj == this ){
         return true;
      }
      ifobj == null ){
         return false;
      }

      if!(obj instanceof JSONArray) ){
         return false;
      }

      JSONArray other = (JSONArrayobj;

      ifother.size() != size() ){
         return false;
      }

      int max = size();
      forint i = 0; i < max; i++ ){
         Object o1 = get);
         Object o2 = other.get);

         // handle nulls
         ifJSONNull.getInstance()
               .equalso1 ) ){
            ifJSONNull.getInstance()
                  .equalso2 ) ){
               continue;
            }else{
               return false;
            }
         }else{
            ifJSONNull.getInstance()
                  .equalso2 ) ){
               return false;
            }
         }

         ifo1 instanceof JSONArray && o2 instanceof JSONArray ){
            JSONArray e = (JSONArrayo1;
            JSONArray a = (JSONArrayo2;
            if!a.equals) ){
               return false;
            }
         }else{
            ifo1 instanceof String && o2 instanceof JSONFunction ){
               if!o1.equalsString.valueOfo2 ) ) ){
                  return false;
               }
            }else ifo1 instanceof JSONFunction && o2 instanceof String ){
               if!o2.equalsString.valueOfo1 ) ) ){
                  return false;
               }
            }else ifo1 instanceof JSONObject && o2 instanceof JSONObject ){
               if!o1.equalso2 ) ){
                  return false;
               }
            }else ifo1 instanceof JSONArray && o2 instanceof JSONArray ){
               if!o1.equalso2 ) ){
                  return false;
               }
            }else ifo1 instanceof JSONFunction && o2 instanceof JSONFunction ){
               if!o1.equalso2 ) ){
                  return false;
               }
            }else{
               ifo1 instanceof String ){
                  if!o1.equalsString.valueOfo2 ) ) ){
                     return false;
                  }
               }else ifo2 instanceof String ){
                  if!o2.equalsString.valueOfo1 ) ) ){
                     return false;
                  }
               }else{
                  Morpher m1 = JSONUtils.getMorpherRegistry()
                        .getMorpherForo1.getClass() );
                  Morpher m2 = JSONUtils.getMorpherRegistry()
                        .getMorpherForo2.getClass() );
                  ifm1 != null && m1 != IdentityObjectMorpher.getInstance() ){
                     if!o1.equalsJSONUtils.getMorpherRegistry()
                           .morpho1.getClass(), o2 ) ) ){
                        return false;
                     }
                  }else ifm2 != null && m2 != IdentityObjectMorpher.getInstance() ){
                     if!JSONUtils.getMorpherRegistry()
                           .morpho1.getClass(), o1 )
                           .equalso2 ) ){
                        return false;
                     }
                  }else{
                     if!o1.equalso2 ) ){
                        return false;
                     }
                  }
               }
            }
         }
      }
      return true;
   }

   /**
    * Get the object value associated with an index.
    *
    @param index The index must be between 0 and size() - 1.
    @return An object value.
    */
   public Object getint index ) {
      /*
       * Object o = opt( index ); if( o == null ){ throw new JSONException(
       * "JSONArray[" + index + "] not found." ); } return o;
       */
      return this.elements.getindex );
   }

   /**
    * Get the boolean value associated with an index. The string values "true"
    * and "false" are converted to boolean.
    *
    @param index The index must be between 0 and size() - 1.
    @return The truth.
    @throws JSONException If there is no value for the index or if the value
    *         is not convertable to boolean.
    */
   public boolean getBooleanint index ) {
      Object o = getindex );
      ifo != null ){
         ifo.equalsBoolean.FALSE )
               || (instanceof String && ((Stringo).equalsIgnoreCase"false" )) ){
            return false;
         }else ifo.equalsBoolean.TRUE )
               || (instanceof String && ((Stringo).equalsIgnoreCase"true" )) ){
            return true;
         }
      }
      throw new JSONException"JSONArray[" + index + "] is not a Boolean." );
   }

   /**
    * Get the double value associated with an index.
    *
    @param index The index must be between 0 and size() - 1.
    @return The value.
    @throws JSONException If the key is not found or if the value cannot be
    *         converted to a number.
    */
   public double getDoubleint index ) {
      Object o = getindex );
      ifo != null ){
         try{
            return instanceof Number ? ((Numbero).doubleValue()
                  : Double.parseDouble( (String);
         }catchException e ){
            throw new JSONException"JSONArray[" + index + "] is not a number." );
         }
      }
      throw new JSONException"JSONArray[" + index + "] is not a number." );
   }

   /**
    * Get the int value associated with an index.
    *
    @param index The index must be between 0 and size() - 1.
    @return The value.
    @throws JSONException If the key is not found or if the value cannot be
    *         converted to a number. if the value cannot be converted to a
    *         number.
    */
   public int getIntint index ) {
      Object o = getindex );
      ifo != null ){
         return instanceof Number ? ((Numbero).intValue() (intgetDoubleindex );
      }
      throw new JSONException"JSONArray[" + index + "] is not a number." );
   }

   /**
    * Get the JSONArray associated with an index.
    *
    @param index The index must be between 0 and size() - 1.
    @return A JSONArray value.
    @throws JSONException If there is no value for the index. or if the value
    *         is not a JSONArray
    */
   public JSONArray getJSONArrayint index ) {
      Object o = getindex );
      ifo != null && o instanceof JSONArray ){
         return (JSONArrayo;
      }
      throw new JSONException"JSONArray[" + index + "] is not a JSONArray." );
   }

   /**
    * Get the JSONObject associated with an index.
    *
    @param index subscript
    @return A JSONObject value.
    @throws JSONException If there is no value for the index or if the value
    *         is not a JSONObject
    */
   public JSONObject getJSONObjectint index ) {
      Object o = getindex );
      ifJSONNull.getInstance()
            .equals) ){
         return new JSONObjecttrue );
      }else ifinstanceof JSONObject ){
         return (JSONObjecto;
      }
      throw new JSONException"JSONArray[" + index + "] is not a JSONObject." );
   }

   /**
    * Get the long value associated with an index.
    *
    @param index The index must be between 0 and size() - 1.
    @return The value.
    @throws JSONException If the key is not found or if the value cannot be
    *         converted to a number.
    */
   public long getLongint index ) {
      Object o = getindex );
      ifo != null ){
         return instanceof Number ? ((Numbero).longValue() (longgetDoubleindex );
      }
      throw new JSONException"JSONArray[" + index + "] is not a number." );
   }

   /**
    * Get the string associated with an index.
    *
    @param index The index must be between 0 and size() - 1.
    @return A string value.
    @throws JSONException If there is no value for the index.
    */
   public String getStringint index ) {
      Object o = getindex );
      ifo != null ){
         return o.toString();
      }
      throw new JSONException"JSONArray[" + index + "] not found." );
   }

   public int hashCode() {
      int hashcode = 29;

      forIterator e = elements.iterator(); e.hasNext()){
         Object element = e.next();
         hashcode += JSONUtils.hashCodeelement );
      }
      return hashcode;
   }

   public int indexOfObject o ) {
      return elements.indexOf);
   }

   public boolean isArray() {
      return true;
   }

   public boolean isEmpty() {
      return this.elements.isEmpty();
   }

   public boolean isExpandElements() {
      return expandElements;
   }

   /**
    * Returns an Iterator for this JSONArray
    */
   public Iterator iterator() {
      return new JSONArrayListIterator();
   }

   /**
    * Make a string from the contents of this JSONArray. The
    <code>separator</code> string is inserted between each element. Warning:
    * This method assumes that the data structure is acyclical.
    *
    @param separator A string that will be inserted between the elements.
    @return a string.
    @throws JSONException If the array contains an invalid number.
    */
   public String joinString separator ) {
      return joinseparator, false );
   }

   /**
    * Make a string from the contents of this JSONArray. The
    <code>separator</code> string is inserted between each element. Warning:
    * This method assumes that the data structure is acyclical.
    *
    @param separator A string that will be inserted between the elements.
    @return a string.
    @throws JSONException If the array contains an invalid number.
    */
   public String joinString separator, boolean stripQuotes ) {
      int len = size();
      StringBuffer sb = new StringBuffer();

      forint i = 0; i < len; i += ){
         ifi > ){
            sb.appendseparator );
         }
         String value = JSONUtils.valueToStringthis.elements.get) );
         sb.appendstripQuotes ? JSONUtils.stripQuotesvalue : value );
      }
      return sb.toString();
   }

   public int lastIndexOfObject o ) {
      return elements.lastIndexOf);
   }

   public ListIterator listIterator() {
      return listIterator);
   }

   public ListIterator listIteratorint index ) {
      ifindex < || index > size() )
         throw new IndexOutOfBoundsException"Index: " + index );

      return new JSONArrayListIteratorindex );
   }

   /**
    * Get the optional object value associated with an index.
    *
    @param index The index must be between 0 and size() - 1.
    @return An object value, or null if there is no object at that index.
    */
   public Object optint index ) {
      return (index < || index >= size()) null this.elements.getindex );
   }

   /**
    * Get the optional boolean value associated with an index. It returns false
    * if there is no value at that index, or if the value is not Boolean.TRUE or
    * the String "true".
    *
    @param index The index must be between 0 and size() - 1.
    @return The truth.
    */
   public boolean optBooleanint index ) {
      return optBooleanindex, false );
   }

   /**
    * Get the optional boolean value associated with an index. It returns the
    * defaultValue if there is no value at that index or if it is not a Boolean
    * or the String "true" or "false" (case insensitive).
    *
    @param index The index must be between 0 and size() - 1.
    @param defaultValue A boolean default.
    @return The truth.
    */
   public boolean optBooleanint index, boolean defaultValue ) {
      try{
         return getBooleanindex );
      }catchException e ){
         return defaultValue;
      }
   }

   /**
    * Get the optional double value associated with an index. NaN is returned if
    * there is no value for the index, or if the value is not a number and
    * cannot be converted to a number.
    *
    @param index The index must be between 0 and size() - 1.
    @return The value.
    */
   public double optDoubleint index ) {
      return optDoubleindex, Double.NaN );
   }

   /**
    * Get the optional double value associated with an index. The defaultValue
    * is returned if there is no value for the index, or if the value is not a
    * number and cannot be converted to a number.
    *
    @param index subscript
    @param defaultValue The default value.
    @return The value.
    */
   public double optDoubleint index, double defaultValue ) {
      try{
         return getDoubleindex );
      }catchException e ){
         return defaultValue;
      }
   }

   /**
    * Get the optional int value associated with an index. Zero is returned if
    * there is no value for the index, or if the value is not a number and
    * cannot be converted to a number.
    *
    @param index The index must be between 0 and size() - 1.
    @return The value.
    */
   public int optIntint index ) {
      return optIntindex, );
   }

   /**
    * Get the optional int value associated with an index. The defaultValue is
    * returned if there is no value for the index, or if the value is not a
    * number and cannot be converted to a number.
    *
    @param index The index must be between 0 and size() - 1.
    @param defaultValue The default value.
    @return The value.
    */
   public int optIntint index, int defaultValue ) {
      try{
         return getIntindex );
      }catchException e ){
         return defaultValue;
      }
   }

   /**
    * Get the optional JSONArray associated with an index.
    *
    @param index subscript
    @return A JSONArray value, or null if the index has no value, or if the
    *         value is not a JSONArray.
    */
   public JSONArray optJSONArrayint index ) {
      Object o = optindex );
      return instanceof JSONArray ? (JSONArrayo : null;
   }

   /**
    * Get the optional JSONObject associated with an index. Null is returned if
    * the key is not found, or null if the index has no value, or if the value
    * is not a JSONObject.
    *
    @param index The index must be between 0 and size() - 1.
    @return A JSONObject value.
    */
   public JSONObject optJSONObjectint index ) {
      Object o = optindex );
      return instanceof JSONObject ? (JSONObjecto : null;
   }

   /**
    * Get the optional long value associated with an index. Zero is returned if
    * there is no value for the index, or if the value is not a number and
    * cannot be converted to a number.
    *
    @param index The index must be between 0 and size() - 1.
    @return The value.
    */
   public long optLongint index ) {
      return optLongindex, );
   }

   /**
    * Get the optional long value associated with an index. The defaultValue is
    * returned if there is no value for the index, or if the value is not a
    * number and cannot be converted to a number.
    *
    @param index The index must be between 0 and size() - 1.
    @param defaultValue The default value.
    @return The value.
    */
   public long optLongint index, long defaultValue ) {
      try{
         return getLongindex );
      }catchException e ){
         return defaultValue;
      }
   }

   /**
    * Get the optional string value associated with an index. It returns an
    * empty string if there is no value at that index. If the value is not a
    * string and is not null, then it is coverted to a string.
    *
    @param index The index must be between 0 and size() - 1.
    @return A String value.
    */
   public String optStringint index ) {
      return optStringindex, "" );
   }

   /**
    * Get the optional string associated with an index. The defaultValue is
    * returned if the key is not found.
    *
    @param index The index must be between 0 and size() - 1.
    @param defaultValue The default value.
    @return A String value.
    */
   public String optStringint index, String defaultValue ) {
      Object o = optindex );
      return o != null ? o.toString() : defaultValue;
   }

   public Object removeint index ) {
      return elements.removeindex );
   }

   public boolean removeObject o ) {
      return elements.remove);
   }

   public boolean removeAllCollection collection ) {
      return removeAllcollection, new JsonConfig() );
   }

   public boolean removeAllCollection collection, JsonConfig jsonConfig ) {
      return elements.removeAllfromObjectcollection, jsonConfig ) );
   }

   public boolean retainAllCollection collection ) {
      return retainAllcollection, new JsonConfig() );
   }

   public boolean retainAllCollection collection, JsonConfig jsonConfig ) {
      return elements.retainAllfromObjectcollection, jsonConfig ) );
   }

   public Object setint index, Object value ) {
      return setindex, value, new JsonConfig() );
   }

   public Object setint index, Object value, JsonConfig jsonConfig ) {
      Object previous = getindex );
      elementindex, value, jsonConfig );
      return previous;
   }

   public void setExpandElementsboolean expandElements ) {
      this.expandElements = expandElements;
   }

   /**
    * Get the number of elements in the JSONArray, included nulls.
    *
    @return The length (or size).
    */
   public int size() {
      return this.elements.size();
   }

   public List subListint fromIndex, int toIndex ) {
      return elements.subListfromIndex, toIndex );
   }

   /**
    * Produce an Object[] with the contents of this JSONArray.
    */
   public Object[] toArray() {
      return this.elements.toArray();
   }

   public Object[] toArrayObject[] array ) {
      return elements.toArrayarray );
   }

   /**
    * Produce a JSONObject by combining a JSONArray of names with the values of
    * this JSONArray.
    *
    @param names A JSONArray containing a list of key strings. These will be
    *        paired with the values.
    @return A JSONObject, or null if there are no names or if this JSONArray
    *         has no values.
    @throws JSONException If any of the names are null.
    */
   public JSONObject toJSONObjectJSONArray names ) {
      ifnames == null || names.size() == || size() == ){
         return null;
      }
      JSONObject jo = new JSONObject();
      forint i = 0; i < names.size(); i++ ){
         jo.elementnames.getString)this.opt) );
      }
      return jo;
   }

   /**
    * Make a JSON text of this JSONArray. For compactness, no unnecessary
    * whitespace is added. If it is not possible to produce a syntactically
    * correct JSON text then null will be returned instead. This could occur if
    * the array contains an invalid number.
    <p>
    * Warning: This method assumes that the data structure is acyclical.
    *
    @return a printable, displayable, transmittable representation of the
    *         array.
    */
   public String toString() {
      try{
         return '[' + join"," ']';
      }catchException e ){
         return null;
      }
   }

   /**
    * Make a prettyprinted JSON text of this JSONArray. Warning: This method
    * assumes that the data structure is acyclical.
    *
    @param indentFactor The number of spaces to add to each level of
    *        indentation.
    @return a printable, displayable, transmittable representation of the
    *         object, beginning with <code>[</code>&nbsp;<small>(left
    *         bracket)</small> and ending with <code>]</code>&nbsp;<small>(right
    *         bracket)</small>.
    @throws JSONException
    */
   public String toStringint indentFactor ) {
      ifindentFactor == ){
         return this.toString();
      }
      return toStringindentFactor, );
   }

   /**
    * Make a prettyprinted JSON text of this JSONArray. Warning: This method
    * assumes that the data structure is acyclical.
    *
    @param indentFactor The number of spaces to add to each level of
    *        indentation.
    @param indent The indention of the top level.
    @return a printable, displayable, transmittable representation of the
    *         array.
    @throws JSONException
    */
   public String toStringint indentFactor, int indent ) {
      int len = size();
      iflen == ){
         return "[]";
      }
      ifindentFactor == ){
         return this.toString();
      }
      int i;
      StringBuffer sb = new StringBuffer"[" );
      iflen == ){
         sb.appendJSONUtils.valueToStringthis.elements.get), indentFactor, indent ) );
      }else{
         int newindent = indent + indentFactor;
         sb.append'\n' );
         fori = 0; i < len; i += ){
            ifi > ){
               sb.append",\n" );
            }
            forint j = 0; j < newindent; j += ){
               sb.append' ' );
            }
            sb.appendJSONUtils.valueToStringthis.elements.get), indentFactor, newindent ) );
         }
         sb.append'\n' );
         fori = 0; i < indent; i += ){
            sb.append' ' );
         }
         fori = 0; i < indent; i += ){
            sb.insert0' ' );
         }
      }
      sb.append']' );
      return sb.toString();
   }

   /**
    * Write the contents of the JSONArray as JSON text to a writer. For
    * compactness, no whitespace is added.
    <p>
    * Warning: This method assumes that the data structure is acyclical.
    *
    @return The writer.
    @throws JSONException
    */
   public Writer writeWriter writer ) {
      try{
         boolean b = false;
         int len = size();

         writer.write'[' );

         forint i = 0; i < len; i += ){
            if){
               writer.write',' );
            }
            Object v = this.elements.get);
            ifinstanceof JSONObject ){
               ((JSONObjectv).writewriter );
            }else ifinstanceof JSONArray ){
               ((JSONArrayv).writewriter );
            }else{
               writer.writeJSONUtils.valueToString) );
            }
            b = true;
         }
         writer.write']' );
         return writer;
      }catchIOException e ){
         throw new JSONException);
      }
   }

   /**
    * Adds a String without performing any conversion on it.
    */
   protected JSONArray addStringString str ) {
      ifstr != null ){
         elements.addstr );
      }
      return this;
   }

   /**
    * Append an object value. This increases the array's length by one.
    *
    @param value An object value. The value should be a Boolean, Double,
    *        Integer, JSONArray, JSONObject, JSONFunction, Long, String,
    *        JSONString or the JSONNull object.
    @return this.
    */
   private JSONArray _addValueObject value, JsonConfig jsonConfig ) {
      this.elements.add(value);
      return this;
   }

   protected Object _processValueObject value, JsonConfig jsonConfig ) {
      ifvalue instanceof JSONTokener ) {
         return _fromJSONTokener( (JSONTokenervalue, jsonConfig );
      }else ifvalue != null && Enum.class.isAssignableFromvalue.getClass() ) ){
         return ((Enumvalue).name();
      }else ifvalue instanceof Annotation || (value != null && value.getClass()
            .isAnnotation()) ){
         throw new JSONException"Unsupported type" );
      }
      return super._processValuevalue, jsonConfig );
   }

   /**
    * Append an object value. This increases the array's length by one.
    *
    @param value An object value. The value should be a Boolean, Double,
    *        Integer, JSONArray, JSONObject, JSONFunction, Long, String,
    *        JSONString or the JSONNull object.
    @return this.
    */
   private JSONArray addValueObject value, JsonConfig jsonConfig ) {
      return _addValueprocessValuevalue, jsonConfig ), jsonConfig );
   }

   private Object processValueObject value, JsonConfig jsonConfig ) {
      ifvalue != null ){
         JsonValueProcessor jsonValueProcessor = jsonConfig.findJsonValueProcessorvalue.getClass() );
         ifjsonValueProcessor != null ){
            value = jsonValueProcessor.processArrayValuevalue, jsonConfig );
            if!JsonVerifier.isValidJsonValuevalue ) ){
               throw new JSONException"Value is not a valid JSON value. " + value );
            }
         }
      }
      return _processValuevalue, jsonConfig );
   }

   private class JSONArrayListIterator implements ListIterator {
      int currentIndex = 0;
      int lastIndex = -1;

      JSONArrayListIterator() {

      }

      JSONArrayListIteratorint index ) {
         currentIndex = index;
      }

      public boolean hasNext() {
         return currentIndex != size();
      }

      public Object next() {
         try {
            Object next = getcurrentIndex );
            lastIndex = currentIndex++;
            return next;
         catchIndexOutOfBoundsException e ) {
            throw new NoSuchElementException();
         }
      }

      public void remove() {
         iflastIndex == -)
            throw new IllegalStateException();
         try {
            JSONArray.this.removelastIndex );
            iflastIndex < currentIndex ){
               currentIndex--;
            }
            lastIndex = -1;
         catchIndexOutOfBoundsException e ) {
            throw new ConcurrentModificationException();
         }
      }

      public boolean hasPrevious() {
         return currentIndex != 0;
      }

      public Object previous() {
         try {
            int index = currentIndex - 1;
            Object previous = getindex );
            lastIndex = currentIndex = index;
            return previous;
         catchIndexOutOfBoundsException e ) {
            throw new NoSuchElementException();
         }
      }

      public int nextIndex() {
         return currentIndex;
      }

      public int previousIndex() {
         return currentIndex - 1;
      }

      public void setObject obj ) {
         iflastIndex == -){
            throw new IllegalStateException();
         }

         try {
            JSONArray.this.setlastIndex, obj );
         catchIndexOutOfBoundsException ex ) {
            throw new ConcurrentModificationException();
         }
      }

      public void addObject obj ) {
         try {
            JSONArray.this.addcurrentIndex++, obj );
            lastIndex = -1;
         catchIndexOutOfBoundsException ex ) {
            throw new ConcurrentModificationException();
         }
      }
   }
}