/*
 * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.jmx.mbeanserver;

import static com.sun.jmx.mbeanserver.Util.*;

import static javax.management.openmbean.SimpleType.*;

import com.sun.jmx.remote.util.EnvHelp;

import java.beans.ConstructorProperties;
import java.io.InvalidObjectException;
import java.lang.annotation.ElementType;
import java.lang.ref.WeakReference;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.WeakHashMap;

import javax.management.JMX;
import javax.management.ObjectName;
import javax.management.openmbean.ArrayType;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataInvocationHandler;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeDataView;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;

/**
   <p>A converter between Java types and the limited set of classes
   defined by Open MBeans.</p>

   <p>A Java type is an instance of java.lang.reflect.Type.  For our
   purposes, it is either a Class, such as String.class or int.class;
   or a ParameterizedType, such as List<String> or Map<Integer,
   String[]>.  On J2SE 1.4 and earlier, it can only be a Class.</p>

   <p>Each Type is associated with an OpenConverter.  The
   OpenConverter defines an OpenType corresponding to the Type, plus a
   Java class corresponding to the OpenType.  For example:</p>

   <pre>
   Type                     Open class     OpenType
   ----                     ----------     --------
   Integer                  Integer        SimpleType.INTEGER
   int                      int            SimpleType.INTEGER
   Integer[]                Integer[]      ArrayType(1, SimpleType.INTEGER)
   int[]                    Integer[]      ArrayType(SimpleType.INTEGER, true)
   String[][]               String[][]     ArrayType(2, SimpleType.STRING)
   List<String>             String[]       ArrayType(1, SimpleType.STRING)
   ThreadState (an Enum)    String         SimpleType.STRING
   Map<Integer, String[]>   TabularData    TabularType(
                                             CompositeType(
                                               {"key", SimpleType.INTEGER},
                                               {"value",
                                                 ArrayType(1,
                                                  SimpleType.STRING)}),
                                             indexNames={"key"})
   </pre>

   <p>Apart from simple types, arrays, and collections, Java types are
   converted through introspection into CompositeType.  The Java type
   must have at least one getter (method such as "int getSize()" or
   "boolean isBig()"), and we must be able to deduce how to
   reconstruct an instance of the Java class from the values of the
   getters using one of various heuristics.</p>

   @since 1.6
 */
public abstract class OpenConverter {
    private OpenConverter(Type targetType, OpenType openType,
                          Class openClass) {
        this.targetType = targetType;
        this.openType = openType;
        this.openClass = openClass;
    }

    /** <p>Convert an instance of openClass into an instance of targetType. */
    public final Object fromOpenValue(MXBeanLookup lookup, Object value)
            throws InvalidObjectException {
        if (value == null)
            return null;
        else
            return fromNonNullOpenValue(lookup, value);
    }

    abstract Object fromNonNullOpenValue(MXBeanLookup lookup, Object value)
            throws InvalidObjectException;

    /** <p>Throw an appropriate InvalidObjectException if we will not be able
        to convert back from the open data to the original Java object.</p> */
    void checkReconstructible() throws InvalidObjectException {
        // subclasses override if action necessary
    }

    /** <p>Convert an instance of targetType into an instance of openClass. */
    final Object toOpenValue(MXBeanLookup lookup, Object value)
            throws OpenDataException {
        if (value == null)
            return null;
        else
            return toNonNullOpenValue(lookup, value);
    }

    abstract Object toNonNullOpenValue(MXBeanLookup lookup, Object value)
            throws OpenDataException;

    /** <p>True if and only if this OpenConverter's toOpenValue and fromOpenValue
        methods are the identity function.</p> */
    boolean isIdentity() {
        return false;
    }

    /** <p>True if and only if isIdentity() and even an array of the underlying type
       is transformed as the identity.  This is true for Integer and
       ObjectName, for instance, but not for int.</p> */
    final Type getTargetType() {
        return targetType;
    }

    final OpenType getOpenType() {
        return openType;
    }

    /* The Java class corresponding to getOpenType().  This is the class
       named by getOpenType().getClassName(), except that it may be a
       primitive type or an array of primitive type.  */
    final Class getOpenClass() {
        return openClass;
    }

    private final Type targetType;
    private final OpenType openType;
    private final Class openClass;

    private static final class ConverterMap
        extends WeakHashMap<Type, WeakReference<OpenConverter>> {}

    private static final ConverterMap converterMap = new ConverterMap();

    /** Following List simply serves to keep a reference to predefined
        OpenConverters so they don't get garbage collected. */
    private static final List<OpenConverter> permanentConverters = newList();

    private static synchronized OpenConverter getConverter(Type type) {
        WeakReference<OpenConverter> wr = converterMap.get(type);
        return (wr == null) ? null : wr.get();
    }

    private static synchronized void putConverter(Type type,
                                                  OpenConverter conv) {
        WeakReference<OpenConverter> wr =
            new WeakReference<OpenConverter>(conv);
        converterMap.put(type, wr);
    }

    private static synchronized void putPermanentConverter(Type type,
                                                           OpenConverter conv) {
        putConverter(type, conv);
        permanentConverters.add(conv);
    }

    static {
        /* Set up the mappings for Java types that map to SimpleType.  */

        final OpenType[] simpleTypes = {
            BIGDECIMAL, BIGINTEGER, BOOLEAN, BYTE, CHARACTER, DATE,
            DOUBLE, FLOAT, INTEGER, LONG, OBJECTNAME, SHORT, STRING,
            VOID,
        };

        for (int i = 0; i < simpleTypes.length; i++) {
            final OpenType t = simpleTypes[i];
            Class c;
            try {
                c = Class.forName(t.getClassName(), false,
                                  ObjectName.class.getClassLoader());
            } catch (ClassNotFoundException e) {
                // the classes that these predefined types declare must exist!
                throw new Error(e);
            }
            final OpenConverter conv = new IdentityConverter(c, t, c);
            putPermanentConverter(c, conv);

            if (c.getName().startsWith("java.lang.")) {
                try {
                    final Field typeField = c.getField("TYPE");
                    final Class primitiveType = (Class) typeField.get(null);
                    final OpenConverter primitiveConv =
                        new IdentityConverter(primitiveType, t, primitiveType);
                    putPermanentConverter(primitiveType,
                                          primitiveConv);
                    if (primitiveType != void.class) {
                        final Class<?> primitiveArrayType =
                            Array.newInstance(primitiveType, 0).getClass();
                        final OpenType primitiveArrayOpenType =
                            ArrayType.getPrimitiveArrayType(primitiveArrayType);
                        final OpenConverter primitiveArrayConv =
                            new IdentityConverter(primitiveArrayType,
                                                  primitiveArrayOpenType,
                                                  primitiveArrayType);
                        putPermanentConverter(primitiveArrayType,
                                              primitiveArrayConv);
                    }
                } catch (NoSuchFieldException e) {
                    // OK: must not be a primitive wrapper
                } catch (IllegalAccessException e) {
                    // Should not reach here
                    assert(false);
                }
            }
        }
    }

    /** Get the converter for the given Java type, creating it if necessary. */
    public static synchronized OpenConverter toConverter(Type objType)
            throws OpenDataException {

        if (inProgress.containsKey(objType))
            throw new OpenDataException("Recursive data structure");

        OpenConverter conv;

        conv = getConverter(objType);
        if (conv != null)
            return conv;

        inProgress.put(objType, objType);
        try {
            conv = makeConverter(objType);
        } finally {
            inProgress.remove(objType);
        }

        putConverter(objType, conv);
        return conv;
    }

    private static OpenConverter makeConverter(Type objType)
            throws OpenDataException {

        /* It's not yet worth formalizing these tests by having for example
           an array of factory classes, each of which says whether it
           recognizes the Type (Chain of Responsibility pattern).  */
        if (objType instanceof GenericArrayType) {
            Type componentType =
                ((GenericArrayType) objType).getGenericComponentType();
            return makeArrayOrCollectionConverter(objType, componentType);
        } else if (objType instanceof Class) {
            Class<?> objClass = (Class<?>) objType;
            if (objClass.isEnum()) {
                // Huge hack to avoid compiler warnings here.  The ElementType
                // parameter is ignored but allows us to obtain a type variable
                // T that matches <T extends Enum<T>>.
                return makeEnumConverter(objClass, ElementType.class);
            } else if (objClass.isArray()) {
                Type componentType = objClass.getComponentType();
                return makeArrayOrCollectionConverter(objClass, componentType);
            } else if (JMX.isMXBeanInterface(objClass)) {
                return makeMXBeanConverter(objClass);
            } else {
                return makeCompositeConverter(objClass);
            }
        } else if (objType instanceof ParameterizedType) {
            return makeParameterizedConverter((ParameterizedType) objType);
        } else
            throw new OpenDataException("Cannot map type: " + objType);
    }

    private static <T extends Enum<T>> OpenConverter
            makeEnumConverter(Class<?> enumClass, Class<T> fake) {
        Class<T> enumClassT = Util.cast(enumClass);
        return new EnumConverter<T>(enumClassT);
    }

    /* Make the converter for an array type, or a collection such as
     * List<String> or Set<Integer>.  We never see one-dimensional
     * primitive arrays (e.g. int[]) here because they use the identity
     * converter and are registered as such in the static initializer.
     */
    private static OpenConverter
        makeArrayOrCollectionConverter(Type collectionType, Type elementType)
            throws OpenDataException {

        final OpenConverter elementConverter = toConverter(elementType);
        final OpenType<?> elementOpenType = elementConverter.getOpenType();
        final ArrayType<?> openType = ArrayType.getArrayType(elementOpenType);
        final Class<?> elementOpenClass = elementConverter.getOpenClass();

        final Class<?> openArrayClass;
        final String openArrayClassName;
        if (elementOpenClass.isArray())
            openArrayClassName = "[" + elementOpenClass.getName();
        else
            openArrayClassName = "[L" + elementOpenClass.getName() + ";";
        try {
            openArrayClass = Class.forName(openArrayClassName);
        } catch (ClassNotFoundException e) {
            throw openDataException("Cannot obtain array class", e);
        }

        if (collectionType instanceof ParameterizedType) {
            return new CollectionConverter(collectionType,
                                           openType, openArrayClass,
                                           elementConverter);
        } else {
            if (elementConverter.isIdentity()) {
                return new IdentityConverter(collectionType,
                                             openType,
                                             openArrayClass);
            } else {
                return new ArrayConverter(collectionType,
                                          openType,
                                          openArrayClass,
                                          elementConverter);
            }
        }
    }

    private static final String[] keyArray = {"key"};
    private static final String[] keyValueArray = {"key", "value"};

    private static OpenConverter
        makeTabularConverter(Type objType, boolean sortedMap,
                             Type keyType, Type valueType)
            throws OpenDataException {

        final String objTypeName = objType.toString();
        final OpenConverter keyConverter = toConverter(keyType);
        final OpenConverter valueConverter = toConverter(valueType);
        final OpenType keyOpenType = keyConverter.getOpenType();
        final OpenType valueOpenType = valueConverter.getOpenType();
        final CompositeType rowType =
            new CompositeType(objTypeName,
                              objTypeName,
                              keyValueArray,
                              keyValueArray,
                              new OpenType[] {keyOpenType, valueOpenType});
        final TabularType tabularType =
            new TabularType(objTypeName, objTypeName, rowType, keyArray);
        return new TabularConverter(objType, sortedMap, tabularType,
                                    keyConverter, valueConverter);
    }

    /* We know how to translate List<E>, Set<E>, SortedSet<E>,
       Map<K,V>, SortedMap<K,V>, and that's it.  We don't accept
       subtypes of those because we wouldn't know how to deserialize
       them.  We don't accept Queue<E> because it is unlikely people
       would use that as a parameter or return type in an MBean.  */
    private static OpenConverter
        makeParameterizedConverter(ParameterizedType objType) throws OpenDataException {

        final Type rawType = objType.getRawType();

        if (rawType instanceof Class) {
            Class c = (Class<?>) rawType;
            if (c == List.class || c == Set.class || c == SortedSet.class) {
                Type[] actuals = objType.getActualTypeArguments();
                assert(actuals.length == 1);
                if (c == SortedSet.class)
                    mustBeComparable(c, actuals[0]);
                return makeArrayOrCollectionConverter(objType, actuals[0]);
            } else {
                boolean sortedMap = (c == SortedMap.class);
                if (c == Map.class || sortedMap) {
                    Type[] actuals = objType.getActualTypeArguments();
                    assert(actuals.length == 2);
                    if (sortedMap)
                        mustBeComparable(c, actuals[0]);
                    return makeTabularConverter(objType, sortedMap,
                            actuals[0], actuals[1]);
                }
            }
        }
        throw new OpenDataException("Cannot convert type: " + objType);
    }

    private static OpenConverter makeMXBeanConverter(Type t)
            throws OpenDataException {
        return new MXBeanConverter(t);
    }

    private static OpenConverter makeCompositeConverter(Class c)
            throws OpenDataException {

        // For historical reasons GcInfo implements CompositeData but we
        // shouldn't count its CompositeData.getCompositeType() field as
        // an item in the computed CompositeType.
        final boolean gcInfoHack =
            (c.getName().equals("com.sun.management.GcInfo") &&
                c.getClassLoader() == null);

        final List<Method> methods =
                MBeanAnalyzer.eliminateCovariantMethods(c.getMethods());
        final SortedMap<String,Method> getterMap = newSortedMap();

        /* Select public methods that look like "T getX()" or "boolean
           isX()", where T is not void and X is not the empty
           string.  Exclude "Class getClass()" inherited from Object.  */
        for (Method method : methods) {
            final String propertyName = propertyName(method);

            if (propertyName == null)
                continue;
            if (gcInfoHack && propertyName.equals("CompositeType"))
                continue;

            Method old =
                getterMap.put(decapitalize(propertyName),
                            method);
            if (old != null) {
                final String msg =
                    "Class " + c.getName() + " has method name clash: " +
                    old.getName() + ", " + method.getName();
                throw new OpenDataException(msg);
            }
        }

        final int nitems = getterMap.size();

        if (nitems == 0) {
            throw new OpenDataException("Can't map " + c.getName() +
                                        " to an open data type");
        }

        final Method[] getters = new Method[nitems];
        final String[] itemNames = new String[nitems];
        final OpenType[] openTypes = new OpenType[nitems];
        int i = 0;
        for (Map.Entry<String,Method> entry : getterMap.entrySet()) {
            itemNames[i] = entry.getKey();
            final Method getter = entry.getValue();
            getters[i] = getter;
            final Type retType = getter.getGenericReturnType();
            openTypes[i] = toConverter(retType).getOpenType();
            i++;
        }

        CompositeType compositeType =
            new CompositeType(c.getName(),
                              c.getName(),
                              itemNames, // field names
                              itemNames, // field descriptions
                              openTypes);

        return new CompositeConverter(c,
                                      compositeType,
                                      itemNames,
                                      getters);
    }

    /* Converter for classes where the open data is identical to the
       original data.  This is true for any of the SimpleType types,
       and for an any-dimension array of those.  It is also true for
       primitive types as of JMX 1.3, since an int[] needs to
       can be directly represented by an ArrayType, and an int needs no mapping
       because reflection takes care of it.  */
    private static final class IdentityConverter extends OpenConverter {
        IdentityConverter(Type targetType, OpenType openType,
                          Class openClass) {
            super(targetType, openType, openClass);
        }

        boolean isIdentity() {
            return true;
        }

        final Object toNonNullOpenValue(MXBeanLookup lookup, Object value) {
            return value;
        }

        public final Object fromNonNullOpenValue(MXBeanLookup lookup, Object value) {
            return value;
        }
    }

    private static final class EnumConverter<T extends Enum<T>>
            extends OpenConverter {

        EnumConverter(Class<T> enumClass) {
            super(enumClass, SimpleType.STRING, String.class);
            this.enumClass = enumClass;
        }

        final Object toNonNullOpenValue(MXBeanLookup lookup, Object value) {
            return ((Enum) value).name();
        }

        // return type could be T, but after erasure that would be
        // java.lang.Enum, which doesn't exist on J2SE 1.4
        public final Object fromNonNullOpenValue(MXBeanLookup lookup, Object value)
                throws InvalidObjectException {
            try {
                return Enum.valueOf(enumClass, (String) value);
            } catch (Exception e) {
                throw invalidObjectException("Cannot convert to enum: " +
                                             value, e);
            }
        }

        private final Class<T> enumClass;
    }

    private static final class ArrayConverter extends OpenConverter {
        ArrayConverter(Type targetType,
                       ArrayType openArrayType, Class openArrayClass,
                       OpenConverter elementConverter) {
            super(targetType, openArrayType, openArrayClass);
            this.elementConverter = elementConverter;
        }

        final Object toNonNullOpenValue(MXBeanLookup lookup, Object value)
                throws OpenDataException {
            Object[] valueArray = (Object[]) value;
            final int len = valueArray.length;
            final Object[] openArray = (Object[])
                Array.newInstance(getOpenClass().getComponentType(), len);
            for (int i = 0; i < len; i++) {
                openArray[i] =
                    elementConverter.toOpenValue(lookup, valueArray[i]);
            }
            return openArray;
        }

        public final Object fromNonNullOpenValue(MXBeanLookup lookup, Object openValue)
                throws InvalidObjectException {
            final Object[] openArray = (Object[]) openValue;
            final Type targetType = getTargetType();
            final Object[] valueArray;
            final Type componentType;
            if (targetType instanceof GenericArrayType) {
                componentType =
                    ((GenericArrayType) targetType).getGenericComponentType();
            } else if (targetType instanceof Class &&
                       ((Class<?>) targetType).isArray()) {
                componentType = ((Class<?>) targetType).getComponentType();
            } else {
                throw new IllegalArgumentException("Not an array: " +
                                                   targetType);
            }
            valueArray = (Object[]) Array.newInstance((Class<?>) componentType,
                                                      openArray.length);
            for (int i = 0; i < openArray.length; i++) {
                valueArray[i] =
                    elementConverter.fromOpenValue(lookup, openArray[i]);
            }
            return valueArray;
        }

        void checkReconstructible() throws InvalidObjectException {
            elementConverter.checkReconstructible();
        }

        /** OpenConverter for the elements of this array.  If this is an
            array of arrays, the converter converts the second-level arrays,
            not the deepest elements.  */
        private final OpenConverter elementConverter;
    }

    private static final class CollectionConverter extends OpenConverter {
        CollectionConverter(Type targetType,
                            ArrayType openArrayType,
                            Class openArrayClass,
                            OpenConverter elementConverter) {
            super(targetType, openArrayType, openArrayClass);
            this.elementConverter = elementConverter;

            /* Determine the concrete class to be used when converting
               back to this Java type.  We convert all Lists to ArrayList
               and all Sets to TreeSet.  (TreeSet because it is a SortedSet,
               so works for both Set and SortedSet.)  */
            Type raw = ((ParameterizedType) targetType).getRawType();
            Class c = (Class<?>) raw;
            if (c == List.class)
                collectionClass = ArrayList.class;
            else if (c == Set.class)
                collectionClass = HashSet.class;
            else if (c == SortedSet.class)
                collectionClass = TreeSet.class;
            else { // can't happen
                assert(false);
                collectionClass = null;
            }
        }

        final Object toNonNullOpenValue(MXBeanLookup lookup, Object value)
                throws OpenDataException {
            final Collection valueCollection = (Collection) value;
            if (valueCollection instanceof SortedSet) {
                Comparator comparator =
                    ((SortedSet) valueCollection).comparator();
                if (comparator != null) {
                    final String msg =
                        "Cannot convert SortedSet with non-null comparator: " +
                        comparator;
                    throw new OpenDataException(msg);
                }
            }
            final Object[] openArray = (Object[])
                Array.newInstance(getOpenClass().getComponentType(),
                                  valueCollection.size());
            int i = 0;
            for (Object o : valueCollection)
                openArray[i++] = elementConverter.toOpenValue(lookup, o);
            return openArray;
        }

        public final Object fromNonNullOpenValue(MXBeanLookup lookup, Object openValue)
                throws InvalidObjectException {
            final Object[] openArray = (Object[]) openValue;
            final Collection<Object> valueCollection;
            try {
                valueCollection = Util.cast(collectionClass.newInstance());
            } catch (Exception e) {
                throw invalidObjectException("Cannot create collection", e);
            }
            for (Object o : openArray) {
                Object value = elementConverter.fromOpenValue(lookup, o);
                if (!valueCollection.add(value)) {
                    final String msg =
                        "Could not add " + o + " to " +
                        collectionClass.getName() +
                        " (duplicate set element?)";
                    throw new InvalidObjectException(msg);
                }
            }
            return valueCollection;
        }

        void checkReconstructible() throws InvalidObjectException {
            elementConverter.checkReconstructible();
        }

        private final Class<? extends Collection> collectionClass;
        private final OpenConverter elementConverter;
    }

    private static final class MXBeanConverter extends OpenConverter {
        MXBeanConverter(Type intf) {
            super(intf, SimpleType.OBJECTNAME, ObjectName.class);
        }

        final Object toNonNullOpenValue(MXBeanLookup lookup, Object value)
                throws OpenDataException {
            lookupNotNull(lookup, OpenDataException.class);
            ObjectName name = lookup.mxbeanToObjectName(value);
            if (name == null)
                throw new OpenDataException("No name for object: " + value);
            return name;
        }

        public final Object fromNonNullOpenValue(MXBeanLookup lookup, Object value)
                throws InvalidObjectException {
            lookupNotNull(lookup, InvalidObjectException.class);
            ObjectName name = (ObjectName) value;
            Object mxbean =
                lookup.objectNameToMXBean(name, (Class<?>) getTargetType());
            if (mxbean == null) {
                final String msg =
                    "No MXBean for name: " + name;
                throw new InvalidObjectException(msg);
            }
            return mxbean;
        }

        private <T extends Exception> void
            lookupNotNull(MXBeanLookup lookup, Class<T> excClass)
                throws T {
            if (lookup == null) {
                final String msg =
                    "Cannot convert MXBean interface in this context";
                T exc;
                try {
                    Constructor<T> con = excClass.getConstructor(String.class);
                    exc = con.newInstance(msg);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                throw exc;
            }
        }
    }

    private static final class TabularConverter extends OpenConverter {
        TabularConverter(Type targetType,
                         boolean sortedMap,
                         TabularType tabularType,
                         OpenConverter keyConverter,
                         OpenConverter valueConverter) {
            super(targetType, tabularType, TabularData.class);
            this.sortedMap = sortedMap;
            this.keyConverter = keyConverter;
            this.valueConverter = valueConverter;
        }

        final Object toNonNullOpenValue(MXBeanLookup lookup, Object value)
                throws OpenDataException {
            final Map<Object, Object> valueMap = Util.cast(value);
            if (valueMap instanceof SortedMap) {
                Comparator comparator = ((SortedMap) valueMap).comparator();
                if (comparator != null) {
                    final String msg =
                        "Cannot convert SortedMap with non-null comparator: " +
                        comparator;
                    throw new OpenDataException(msg);
                }
            }
            final TabularType tabularType = (TabularType) getOpenType();
            final TabularData table = new TabularDataSupport(tabularType);
            final CompositeType rowType = tabularType.getRowType();
            for (Map.Entry entry : valueMap.entrySet()) {
                final Object openKey =
                    keyConverter.toOpenValue(lookup, entry.getKey());
                final Object openValue =
                    valueConverter.toOpenValue(lookup, entry.getValue());
                final CompositeData row;
                row =
                    new CompositeDataSupport(rowType, keyValueArray,
                                             new Object[] {openKey,
                                                           openValue});
                table.put(row);
            }
            return table;
        }

        public final Object fromNonNullOpenValue(MXBeanLookup lookup, Object openValue)
                throws InvalidObjectException {
            final TabularData table = (TabularData) openValue;
            final Collection<CompositeData> rows = Util.cast(table.values());
            final Map<Object, Object> valueMap =
                sortedMap ? newSortedMap() : newMap();
            for (CompositeData row : rows) {
                final Object key =
                    keyConverter.fromOpenValue(lookup, row.get("key"));
                final Object value =
                    valueConverter.fromOpenValue(lookup, row.get("value"));
                if (valueMap.put(key, value) != null) {
                    final String msg =
                        "Duplicate entry in TabularData: key=" + key;
                    throw new InvalidObjectException(msg);
                }
            }
            return valueMap;
        }

        void checkReconstructible() throws InvalidObjectException {
            keyConverter.checkReconstructible();
            valueConverter.checkReconstructible();
        }

        private final boolean sortedMap;
        private final OpenConverter keyConverter;
        private final OpenConverter valueConverter;
    }

    private static final class CompositeConverter extends OpenConverter {
        CompositeConverter(Class targetClass,
                           CompositeType compositeType,
                           String[] itemNames,
                           Method[] getters) throws OpenDataException {
            super(targetClass, compositeType, CompositeData.class);

            assert(itemNames.length == getters.length);

            this.itemNames = itemNames;
            this.getters = getters;
            this.getterConverters = new OpenConverter[getters.length];
            for (int i = 0; i < getters.length; i++) {
                Type retType = getters[i].getGenericReturnType();
                getterConverters[i] = OpenConverter.toConverter(retType);
            }
        }

        final Object toNonNullOpenValue(MXBeanLookup lookup, Object value)
                throws OpenDataException {
            CompositeType ct = (CompositeType) getOpenType();
            if (value instanceof CompositeDataView)
                return ((CompositeDataView) value).toCompositeData(ct);
            if (value == null)
                return null;

            Object[] values = new Object[getters.length];
            for (int i = 0; i < getters.length; i++) {
                try {
                    Object got = getters[i].invoke(value, (Object[]) null);
                    values[i] = getterConverters[i].toOpenValue(lookup, got);
                } catch (Exception e) {
                    throw openDataException("Error calling getter for " +
                                            itemNames[i] + ": " + e, e);
                }
            }
            return new CompositeDataSupport(ct, itemNames, values);
        }

        /** Determine how to convert back from the CompositeData into
            the original Java type.  For a type that is not reconstructible,
            this method will fail every time, and will throw the right
            exception. */
        private synchronized void makeCompositeBuilder()
                throws InvalidObjectException {
            if (compositeBuilder != null)
                return;

            Class targetClass = (Class<?>) getTargetType();
            /* In this 2D array, each subarray is a set of builders where
               there is no point in consulting the ones after the first if
               the first refuses.  */
            CompositeBuilder[][] builders = {
                {
                    new CompositeBuilderViaFrom(targetClass, itemNames),
                },
                {
                    new CompositeBuilderViaConstructor(targetClass, itemNames),
                },
                {
                    new CompositeBuilderCheckGetters(targetClass, itemNames,
                                                     getterConverters),
                    new CompositeBuilderViaSetters(targetClass, itemNames),
                    new CompositeBuilderViaProxy(targetClass, itemNames),
                },
            };
            CompositeBuilder foundBuilder = null;
            /* We try to make a meaningful exception message by
               concatenating each Builder's explanation of why it
               isn't applicable.  */
            final StringBuilder whyNots = new StringBuilder();
        find:
            for (CompositeBuilder[] relatedBuilders : builders) {
                for (int i = 0; i < relatedBuilders.length; i++) {
                    CompositeBuilder builder = relatedBuilders[i];
                    String whyNot = builder.applicable(getters);
                    if (whyNot == null) {
                        foundBuilder = builder;
                        break find;
                    }
                    if (whyNot.length() > 0) {
                        if (whyNots.length() > 0)
                            whyNots.append("; ");
                        whyNots.append(whyNot);
                        if (i == 0)
                           break; // skip other builders in this group
                    }
                }
            }
            if (foundBuilder == null) {
                final String msg =
                    "Do not know how to make a " + targetClass.getName() +
                    " from a CompositeData: " + whyNots;
                throw new InvalidObjectException(msg);
            }
            compositeBuilder = foundBuilder;
        }

        void checkReconstructible() throws InvalidObjectException {
            makeCompositeBuilder();
        }

        public final Object fromNonNullOpenValue(MXBeanLookup lookup, Object value)
                throws InvalidObjectException {
            makeCompositeBuilder();
            return compositeBuilder.fromCompositeData(lookup,
                                                      (CompositeData) value,
                                                      itemNames,
                                                      getterConverters);
        }

        private final String[] itemNames;
        private final Method[] getters;
        private final OpenConverter[] getterConverters;
        private CompositeBuilder compositeBuilder;
    }

    /** Converts from a CompositeData to an instance of the targetClass.  */
    private static abstract class CompositeBuilder {
        CompositeBuilder(Class targetClass, String[] itemNames) {
            this.targetClass = targetClass;
            this.itemNames = itemNames;
        }

        Class<?> getTargetClass() {
            return targetClass;
        }

        String[] getItemNames() {
            return itemNames;
        }

        /** If the subclass is appropriate for targetClass, then the
            method returns null.  If the subclass is not appropriate,
            then the method returns an explanation of why not.  If the
            subclass should be appropriate but there is a problem,
            then the method throws InvalidObjectException.  */
        abstract String applicable(Method[] getters)
                throws InvalidObjectException;

        abstract Object fromCompositeData(MXBeanLookup lookup, CompositeData cd,
                                          String[] itemNames,
                                          OpenConverter[] converters)
                throws InvalidObjectException;

        private final Class<?> targetClass;
        private final String[] itemNames;
    }

    /** Builder for when the target class has a method "public static
        from(CompositeData)".  */
    private static final class CompositeBuilderViaFrom
            extends CompositeBuilder {

        CompositeBuilderViaFrom(Class targetClass, String[] itemNames) {
            super(targetClass, itemNames);
        }

        String applicable(Method[] getters) throws InvalidObjectException {
            // See if it has a method "T from(CompositeData)"
            // as is conventional for a CompositeDataView
            Class<?> targetClass = getTargetClass();
            try {
                Method fromMethod =
                    targetClass.getMethod("from",
                                          new Class[] {CompositeData.class});

                if (!Modifier.isStatic(fromMethod.getModifiers())) {
                    final String msg =
                        "Method from(CompositeData) is not static";
                    throw new InvalidObjectException(msg);
                }

                if (fromMethod.getReturnType() != getTargetClass()) {
                    final String msg =
                        "Method from(CompositeData) returns " +
                        fromMethod.getReturnType().getName() +
                        " not " + targetClass.getName();
                    throw new InvalidObjectException(msg);
                }

                this.fromMethod = fromMethod;
                return null; // success!
            } catch (InvalidObjectException e) {
                throw e;
            } catch (Exception e) {
                // OK: it doesn't have the method
                return "no method from(CompositeData)";
            }
        }

        final Object fromCompositeData(MXBeanLookup lookup, CompositeData cd,
                                 String[] itemNames,
                                 OpenConverter[] converters)
                throws InvalidObjectException {
            try {
                return fromMethod.invoke(null, cd);
            } catch (Exception e) {
                final String msg = "Failed to invoke from(CompositeData)";
                throw invalidObjectException(msg, e);
            }
        }

        private Method fromMethod;
    }

    /** This builder never actually returns success.  It simply serves
        to check whether the other builders in the same group have any
        chance of success.  If any getter in the targetClass returns
        a type that we don't know how to reconstruct, then we will
        not be able to make a builder, and there is no point in repeating
        the error about the problematic getter as many times as there are
        candidate builders.  Instead, the "applicable" method will return
        an explanatory string, and the other builders will be skipped.
        If all the getters are OK, then the "applicable" method will return
        an empty string and the other builders will be tried.  */
    private static class CompositeBuilderCheckGetters extends CompositeBuilder {
        CompositeBuilderCheckGetters(Class targetClass, String[] itemNames,
                                     OpenConverter[] getterConverters) {
            super(targetClass, itemNames);
            this.getterConverters = getterConverters;
        }

        String applicable(Method[] getters) {
            for (int i = 0; i < getters.length; i++) {
                try {
                    getterConverters[i].checkReconstructible();
                } catch (InvalidObjectException e) {
                    return "method " + getters[i].getName() + " returns type " +
                        "that cannot be mapped back from OpenData";
                }
            }
            return "";
        }

        final Object fromCompositeData(MXBeanLookup lookup, CompositeData cd,
                                       String[] itemNames,
                                       OpenConverter[] converters) {
            throw new Error();
        }

        private final OpenConverter[] getterConverters;
    }

    /** Builder for when the target class has a setter for every getter. */
    private static class CompositeBuilderViaSetters extends CompositeBuilder {

        CompositeBuilderViaSetters(Class targetClass, String[] itemNames) {
            super(targetClass, itemNames);
        }

        String applicable(Method[] getters) {
            try {
                Constructor<?> c = getTargetClass().getConstructor((Class[]) null);
            } catch (Exception e) {
                return "does not have a public no-arg constructor";
            }

            Method[] setters = new Method[getters.length];
            for (int i = 0; i < getters.length; i++) {
                Method getter = getters[i];
                Class returnType = getter.getReturnType();
                String name = propertyName(getter);
                String setterName = "set" + name;
                Method setter;
                try {
                    setter = getTargetClass().getMethod(setterName, returnType);
                    if (setter.getReturnType() != void.class)
                        throw new Exception();
                } catch (Exception e) {
                    return "not all getters have corresponding setters " +
                           "(" + getter + ")";
                }
                setters[i] = setter;
            }
            this.setters = setters;
            return null;
        }

        Object fromCompositeData(MXBeanLookup lookup, CompositeData cd,
                                 String[] itemNames,
                                 OpenConverter[] converters)
                throws InvalidObjectException {
            Object o;
            try {
                o = getTargetClass().newInstance();
                for (int i = 0; i < itemNames.length; i++) {
                    if (cd.containsKey(itemNames[i])) {
                        Object openItem = cd.get(itemNames[i]);
                        Object javaItem =
                            converters[i].fromOpenValue(lookup, openItem);
                        setters[i].invoke(o, javaItem);
                    }
                }
            } catch (Exception e) {
                throw invalidObjectException(e);
            }
            return o;
        }

        private Method[] setters;
    }

    /** Builder for when the target class has a constructor that is
        annotated with @ConstructorProperties so we can see the correspondence
        to getters.  */
    private static final class CompositeBuilderViaConstructor
            extends CompositeBuilder {

        CompositeBuilderViaConstructor(Class targetClass, String[] itemNames) {
            super(targetClass, itemNames);
        }

        String applicable(Method[] getters) throws InvalidObjectException {

            final Class<ConstructorProperties> propertyNamesClass = ConstructorProperties.class;

            Class targetClass = getTargetClass();
            Constructor[] constrs = targetClass.getConstructors();

            // Applicable if and only if there are any annotated constructors
            List<Constructor> annotatedConstrList = newList();
            for (Constructor constr : constrs) {
                if (Modifier.isPublic(constr.getModifiers())
                        && constr.getAnnotation(propertyNamesClass) != null)
                    annotatedConstrList.add(constr);
            }

            if (annotatedConstrList.isEmpty())
                return "no constructor has @ConstructorProperties annotation";

            annotatedConstructors = newList();

            // Now check that all the annotated constructors are valid
            // and throw an exception if not.

            // First link the itemNames to their getter indexes.
            Map<String, Integer> getterMap = newMap();
            String[] itemNames = getItemNames();
            for (int i = 0; i < itemNames.length; i++)
                getterMap.put(itemNames[i], i);

            // Run through the constructors making the checks in the spec.
            // For each constructor, remember the correspondence between its
            // parameters and the items.  The int[] for a constructor says
            // what parameter index should get what item.  For example,
            // if element 0 is 2 then that means that item 0 in the
            // CompositeData goes to parameter 2 of the constructor.  If an
            // element is -1, that item isn't given to the constructor.
            // Also remember the set of properties in that constructor
            // so we can test unambiguity.
            Set<BitSet> getterIndexSets = newSet();
            for (Constructor constr : annotatedConstrList) {
                String[] propertyNames =
                    constr.getAnnotation(propertyNamesClass).value();

                Type[] paramTypes = constr.getGenericParameterTypes();
                if (paramTypes.length != propertyNames.length) {
                    final String msg =
                        "Number of constructor params does not match " +
                        "@ConstructorProperties annotation: " + constr;
                    throw new InvalidObjectException(msg);
                }

                int[] paramIndexes = new int[getters.length];
                for (int i = 0; i < getters.length; i++)
                    paramIndexes[i] = -1;
                BitSet present = new BitSet();

                for (int i = 0; i < propertyNames.length; i++) {
                    String propertyName = propertyNames[i];
                    if (!getterMap.containsKey(propertyName)) {
                        final String msg =
                            "@ConstructorProperties includes name " + propertyName +
                            " which does not correspond to a property: " +
                            constr;
                        throw new InvalidObjectException(msg);
                    }
                    int getterIndex = getterMap.get(propertyName);
                    paramIndexes[getterIndex] = i;
                    if (present.get(getterIndex)) {
                        final String msg =
                            "@ConstructorProperties contains property " +
                            propertyName + " more than once: " + constr;
                        throw new InvalidObjectException(msg);
                    }
                    present.set(getterIndex);
                    Method getter = getters[getterIndex];
                    Type propertyType = getter.getGenericReturnType();
                    if (!propertyType.equals(paramTypes[i])) {
                        final String msg =
                            "@ConstructorProperties gives property " + propertyName +
                            " of type " + propertyType + " for parameter " +
                            " of type " + paramTypes[i] + ": " + constr;
                        throw new InvalidObjectException(msg);
                    }
                }

                if (!getterIndexSets.add(present)) {
                    final String msg =
                        "More than one constructor has a @ConstructorProperties " +
                        "annotation with this set of names: " +
                        Arrays.toString(propertyNames);
                    throw new InvalidObjectException(msg);
                }

                Constr c = new Constr(constr, paramIndexes, present);
                annotatedConstructors.add(c);
            }

            /* Check that no possible set of items could lead to an ambiguous
             * choice of constructor (spec requires this check).  For any
             * pair of constructors, their union would be the minimal
             * ambiguous set.  If this set itself corresponds to a constructor,
             * there is no ambiguity for that pair.  In the usual case, one
             * of the constructors is a superset of the other so the union is
             * just the bigger constuctor.
             *
             * The algorithm here is quadratic in the number of constructors
             * with a @ConstructorProperties annotation.  Typically this corresponds
             * to the number of versions of the class there have been.  Ten
             * would already be a large number, so although it's probably
             * possible to have an O(n lg n) algorithm it wouldn't be
             * worth the complexity.
             */
            for (BitSet a : getterIndexSets) {
                boolean seen = false;
                for (BitSet b : getterIndexSets) {
                    if (a == b)
                        seen = true;
                    else if (seen) {
                        BitSet u = new BitSet();
                        u.or(a); u.or(b);
                        if (!getterIndexSets.contains(u)) {
                            Set<String> names = new TreeSet<String>();
                            for (int i = u.nextSetBit(0); i >= 0;
                                 i = u.nextSetBit(i+1))
                                names.add(itemNames[i]);
                            final String msg =
                                "Constructors with @ConstructorProperties annotation " +
                                " would be ambiguous for these items: " +
                                names;
                            throw new InvalidObjectException(msg);
                        }
                    }
                }
            }

            return null; // success!
        }

        Object fromCompositeData(MXBeanLookup lookup, CompositeData cd,
                                 String[] itemNames,
                                 OpenConverter[] converters)
                throws InvalidObjectException {
            // The CompositeData might come from an earlier version where
            // not all the items were present.  We look for a constructor
            // that accepts just the items that are present.  Because of
            // the ambiguity check in applicable(), we know there must be
            // at most one maximally applicable constructor.
            CompositeType ct = cd.getCompositeType();
            BitSet present = new BitSet();
            for (int i = 0; i < itemNames.length; i++) {
                if (ct.getType(itemNames[i]) != null)
                    present.set(i);
            }

            Constr max = null;
            for (Constr constr : annotatedConstructors) {
                if (subset(constr.presentParams, present) &&
                        (max == null ||
                         subset(max.presentParams, constr.presentParams)))
                    max = constr;
            }

            if (max == null) {
                final String msg =
                    "No constructor has a @ConstructorProperties for this set of " +
                    "items: " + ct.keySet();
                throw new InvalidObjectException(msg);
            }

            Object[] params = new Object[max.presentParams.cardinality()];
            for (int i = 0; i < itemNames.length; i++) {
                if (!max.presentParams.get(i))
                    continue;
                Object openItem = cd.get(itemNames[i]);
                Object javaItem = converters[i].fromOpenValue(lookup, openItem);
                int index = max.paramIndexes[i];
                if (index >= 0)
                    params[index] = javaItem;
            }

            try {
                return max.constructor.newInstance(params);
            } catch (Exception e) {
                final String msg =
                    "Exception constructing " + getTargetClass().getName();
                throw invalidObjectException(msg, e);
            }
        }

        private static boolean subset(BitSet sub, BitSet sup) {
            BitSet subcopy = (BitSet) sub.clone();
            subcopy.andNot(sup);
            return subcopy.isEmpty();
        }

        private static class Constr {
            final Constructor constructor;
            final int[] paramIndexes;
            final BitSet presentParams;
            Constr(Constructor constructor, int[] paramIndexes,
                   BitSet presentParams) {
                this.constructor = constructor;
                this.paramIndexes = paramIndexes;
                this.presentParams = presentParams;
            }
        }

        private List<Constr> annotatedConstructors;
    }

    /** Builder for when the target class is an interface and contains
        no methods other than getters.  Then we can make an instance
        using a dynamic proxy that forwards the getters to the source
        CompositeData.  */
    private static final class CompositeBuilderViaProxy
            extends CompositeBuilder {

        CompositeBuilderViaProxy(Class targetClass, String[] itemNames) {
            super(targetClass, itemNames);
        }

        String applicable(Method[] getters) {
            Class targetClass = getTargetClass();
            if (!targetClass.isInterface())
                return "not an interface";
            Set<Method> methods =
                newSet(Arrays.asList(targetClass.getMethods()));
            methods.removeAll(Arrays.asList(getters));
            /* If the interface has any methods left over, they better be
             * public methods that are already present in java.lang.Object.
             */
            String bad = null;
            for (Method m : methods) {
                String mname = m.getName();
                Class[] mparams = m.getParameterTypes();
                try {
                    Method om = Object.class.getMethod(mname, mparams);
                    if (!Modifier.isPublic(om.getModifiers()))
                        bad = mname;
                } catch (NoSuchMethodException e) {
                    bad = mname;
                }
                /* We don't catch SecurityException since it shouldn't
                 * happen for a method in Object and if it does we would
                 * like to know about it rather than mysteriously complaining.
                 */
            }
            if (bad != null)
                return "contains methods other than getters (" + bad + ")";
            return null; // success!
        }

        final Object fromCompositeData(MXBeanLookup lookup, CompositeData cd,
                                 String[] itemNames,
                                 OpenConverter[] converters) {
            final Class targetClass = getTargetClass();
            return
                Proxy.newProxyInstance(targetClass.getClassLoader(),
                                       new Class[] {targetClass},
                                       new CompositeDataInvocationHandler(cd));
        }
    }

    static InvalidObjectException invalidObjectException(String msg,
                                                         Throwable cause) {
        return EnvHelp.initCause(new InvalidObjectException(msg), cause);
    }

    static InvalidObjectException invalidObjectException(Throwable cause) {
        return invalidObjectException(cause.getMessage(), cause);
    }

    static OpenDataException openDataException(String msg, Throwable cause) {
        return EnvHelp.initCause(new OpenDataException(msg), cause);
    }

    static OpenDataException openDataException(Throwable cause) {
        return openDataException(cause.getMessage(), cause);
    }

    static void mustBeComparable(Class collection, Type element)
            throws OpenDataException {
        if (!(element instanceof Class)
            || !Comparable.class.isAssignableFrom((Class<?>) element)) {
            final String msg =
                "Parameter class " + element + " of " +
                collection.getName() + " does not implement " +
                Comparable.class.getName();
            throw new OpenDataException(msg);
        }
    }

    /**
     * Utility method to take a string and convert it to normal Java variable
     * name capitalization.  This normally means converting the first
     * character from upper case to lower case, but in the (unusual) special
     * case when there is more than one character and both the first and
     * second characters are upper case, we leave it alone.
     * <p>
     * Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays
     * as "URL".
     *
     * @param  name The string to be decapitalized.
     * @return  The decapitalized version of the string.
     */
    public static String decapitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        }
        int offset1 = Character.offsetByCodePoints(name, 0, 1);
        // Should be name.offsetByCodePoints but 6242664 makes this fail
        if (offset1 < name.length() &&
                Character.isUpperCase(name.codePointAt(offset1)))
            return name;
        return name.substring(0, offset1).toLowerCase() +
               name.substring(offset1);
    }

    /**
     * Reverse operation for java.beans.Introspector.decapitalize.  For any s,
     * capitalize(decapitalize(s)).equals(s).  The reverse is not true:
     * e.g. capitalize("uRL") produces "URL" which is unchanged by
     * decapitalize.
     */
    static String capitalize(String name) {
        if (name == null || name.length() == 0)
            return name;
        int offset1 = name.offsetByCodePoints(0, 1);
        return name.substring(0, offset1).toUpperCase() +
               name.substring(offset1);
    }

    public static String propertyName(Method m) {
        String rest = null;
        String name = m.getName();
        if (name.startsWith("get"))
            rest = name.substring(3);
        else if (name.startsWith("is") && m.getReturnType() == boolean.class)
            rest = name.substring(2);
        if (rest == null || rest.length() == 0
            || m.getParameterTypes().length > 0
            || m.getReturnType() == void.class
            || name.equals("getClass"))
            return null;
        return rest;
    }

    private final static Map<Type, Type> inProgress = newIdentityHashMap();
    // really an IdentityHashSet but that doesn't exist
}
