/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.management.internal;

import static javax.management.openmbean.SimpleType.BIGDECIMAL;
import static javax.management.openmbean.SimpleType.BIGINTEGER;
import static javax.management.openmbean.SimpleType.BOOLEAN;
import static javax.management.openmbean.SimpleType.BYTE;
import static javax.management.openmbean.SimpleType.CHARACTER;
import static javax.management.openmbean.SimpleType.DATE;
import static javax.management.openmbean.SimpleType.DOUBLE;
import static javax.management.openmbean.SimpleType.FLOAT;
import static javax.management.openmbean.SimpleType.INTEGER;
import static javax.management.openmbean.SimpleType.LONG;
import static javax.management.openmbean.SimpleType.OBJECTNAME;
import static javax.management.openmbean.SimpleType.SHORT;
import static javax.management.openmbean.SimpleType.STRING;
import static javax.management.openmbean.SimpleType.VOID;

import java.beans.ConstructorProperties;
import java.io.InvalidObjectException;
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.Arrays;
import java.util.BitSet;
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.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.TabularType;

import org.apache.geode.annotations.Immutable;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.management.ManagementException;

/**
 * It takes care of converting a Java type to an open types
 *
 * A Java type is an instance of java.lang.reflect.Type representing all types in Java.
 *
 * Each Type is associated with an OpenTypeConverter. The OpenTypeConverter defines an OpenType
 * corresponding to the Type, plus a Java class corresponding to the OpenType. For example:
 *
 *
 * Java Type : Integer Open Class :Integer Open Type :SimpleType.INTEGER
 *
 * Apart from simple types, arrays, and collections, Java types are converted through introspection
 * into CompositeType
 */
public abstract class OpenTypeConverter {

  private final Type targetType;

  /**
   * 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.
   */
  private final OpenType openType;

  private final Class openClass;

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

  @MakeNotStatic
  private static final ConverterMap converterMap = new ConverterMap();

  @MakeNotStatic
  private static final Map<Type, Type> inProgress = OpenTypeUtil.newIdentityHashMap();

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

  protected OpenTypeConverter(Type targetType, OpenType openType, Class openClass) {
    this.targetType = targetType;
    this.openType = openType;
    this.openClass = openClass;
  }

  /**
   * Convert an instance of openClass into an instance of targetType.
   *
   * @return the java type object
   */
  public Object fromOpenValue(Object value) throws InvalidObjectException {
    if (value == null)
      return null;
    else
      return fromNonNullOpenValue(value);
  }

  abstract Object fromNonNullOpenValue(Object value) throws InvalidObjectException;

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

  /**
   * Convert an instance of targetType into an instance of openClass.
   *
   * @return open class object
   */
  Object toOpenValue(Object value) throws OpenDataException {
    if (value == null)
      return null;
    else
      return toNonNullOpenValue(value);
  }

  abstract Object toNonNullOpenValue(Object value) throws OpenDataException;

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

  Type getTargetType() {
    return targetType;
  }

  OpenType getOpenType() {
    return openType;
  }

  Class getOpenClass() {
    return openClass;
  }

  /**
   * @return a converter corresponding to a type
   */
  private static synchronized OpenTypeConverter getConverter(Type type) {

    if (type instanceof GenericArrayType) {
      Type component = ((GenericArrayType) type).getGenericComponentType();
      if (component instanceof Class)
        type = Array.newInstance((Class<?>) component, 0).getClass();
    }

    WeakReference<OpenTypeConverter> wr = converterMap.get(type);
    return (wr == null) ? null : wr.get();
  }

  /**
   * Put the converter in the map to avoid future creation
   */
  private static synchronized void putConverter(Type type, OpenTypeConverter conv) {
    WeakReference<OpenTypeConverter> wr = new WeakReference<OpenTypeConverter>(conv);
    converterMap.put(type, wr);
  }

  private static synchronized void putPreDefinedConverter(Type type, OpenTypeConverter conv) {
    putConverter(type, conv);
    preDefinedConverters.add(conv);
  }

  /*
   * Static block to initialize pre defined convertor
   */
  static {

    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) {
        throw new Error(e);
      }
      final OpenTypeConverter conv = new IdentityConverter(c, t, c);
      putPreDefinedConverter(c, conv);

      if (c.getName().startsWith("java.lang.")) {
        try {
          final Field typeField = c.getField("TYPE");
          final Class primitiveType = (Class) typeField.get(null);
          final OpenTypeConverter primitiveConv =
              new IdentityConverter(primitiveType, t, primitiveType);
          putPreDefinedConverter(primitiveType, primitiveConv);
          if (primitiveType != void.class) {
            final Class primitiveArrayType = Array.newInstance(primitiveType, 0).getClass();
            final OpenType primitiveArrayOpenType =
                ArrayType.getPrimitiveArrayType(primitiveArrayType);
            final OpenTypeConverter primitiveArrayConv = new IdentityConverter(primitiveArrayType,
                primitiveArrayOpenType, primitiveArrayType);
            putPreDefinedConverter(primitiveArrayType, primitiveArrayConv);
          }
        } catch (NoSuchFieldException e) {

        } catch (IllegalAccessException e) {
          assert (false);
        }
      }
    }
  }

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

    if (inProgress.containsKey(objType)) {
      throw new OpenDataException("Recursive data structure, including " + typeName(objType));
    }

    OpenTypeConverter conv;

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

    inProgress.put(objType, objType);
    try {
      conv = makeConverter(objType);
    } catch (OpenDataException e) {
      throw openDataException("Cannot convert type: " + objType, e);
    } finally {
      inProgress.remove(objType);
    }

    putConverter(objType, conv);
    return conv;
  }

  /**
   * @return the open type converter for a given type
   */
  private static OpenTypeConverter makeConverter(Type objType) throws OpenDataException {

    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()) {
        return makeEnumConverter(objClass);
      } else if (objClass.isArray()) {
        Type componentType = objClass.getComponentType();
        return makeArrayOrCollectionConverter(objClass, componentType);
      } else if (JMX.isMXBeanInterface(objClass)) {
        throw openDataException("Cannot obtain array class",
            new ManagementException(" MXBean as an Return Type is not supported"));
      } 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>> OpenTypeConverter makeEnumConverter(Class<T> enumClass) {
    return new EnumConverter<T>(enumClass);
  }

  private static OpenTypeConverter makeArrayOrCollectionConverter(Type collectionType,
      Type elementType) throws OpenDataException {

    final OpenTypeConverter elementConverter = toConverter(elementType);
    final OpenType elementOpenType = elementConverter.getOpenType();
    final ArrayType openType = new ArrayType(1, 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);
      }
    }
  }

  @Immutable
  protected static final String[] keyArray = {"key"};

  @Immutable
  protected static final String[] keyValueArray = {"key", "value"};

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

    final String objTypeName = objType.toString();
    final OpenTypeConverter keyConverter = toConverter(keyType);
    final OpenTypeConverter 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 TableConverter(objType, sortedMap, tabularType, keyConverter, valueConverter);
  }

  /**
   * Supported types are List<E>, Set<E>, SortedSet<E>, Map<K,V>, SortedMap<K,V>.
   *
   * Subclasses of the above types wont be supported as deserialize info wont be there.
   *
   * Queue<E> won't be supported as Queue is more of a functional data structure rather than a data
   * holder
   *
   * @return the open type converter for a given type
   */
  private static OpenTypeConverter 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 = ((ParameterizedType) 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 = ((ParameterizedType) 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);
  }

  /**
   * @return the open type converrter for a given type
   */
  private static OpenTypeConverter makeCompositeConverter(Class c) throws OpenDataException {

    final List<Method> methods = Arrays.asList(c.getMethods());
    final SortedMap<String, Method> getterMap = OpenTypeUtil.newSortedMap();

    for (Method method : methods) {
      final String propertyName = propertyName(method);

      if (propertyName == null)
        continue;

      Method old = getterMap.put(OpenTypeUtil.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);
  }

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

    Class getTargetClass() {
      return targetClass;
    }

    String[] getItemNames() {
      return itemNames;
    }

    /**
     * If the subclass should be appropriate but there is a problem, then the method throws
     * InvalidObjectException.
     *
     * @return 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.
     */
    abstract String applicable(Method[] getters) throws InvalidObjectException;

    /**
     *
     * @return possible cause if target class is not applicable
     */
    Throwable possibleCause() {
      return null;
    }

    /**
     * @return Actual java types from the composite type
     */
    abstract Object fromCompositeData(CompositeData cd, String[] itemNames,
        OpenTypeConverter[] converters) throws InvalidObjectException;

    private final Class targetClass;
    private final String[] itemNames;
  }

  /**
   * Builder if the target class has a method "public static from(CompositeData)"
   */
  protected static class CompositeBuilderViaFrom extends CompositeBuilder {

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

    @Override
    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 "
              + typeName(fromMethod.getReturnType()) + " not " + typeName(targetClass);
          throw new InvalidObjectException(msg);
        }

        this.fromMethod = fromMethod;
        return null;
      } catch (InvalidObjectException e) {
        throw e;
      } catch (Exception e) {
        return "no method from(CompositeData)";
      }
    }

    @Override
    Object fromCompositeData(CompositeData cd, String[] itemNames, OpenTypeConverter[] 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.
   */
  protected static class CompositeBuilderCheckGetters extends CompositeBuilder {
    CompositeBuilderCheckGetters(Class targetClass, String[] itemNames,
        OpenTypeConverter[] getterConverters) {
      super(targetClass, itemNames);
      this.getterConverters = getterConverters;
    }

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

    @Override
    Throwable possibleCause() {
      return possibleCause;
    }

    @Override
    Object fromCompositeData(CompositeData cd, String[] itemNames, OpenTypeConverter[] converters) {
      throw new Error();
    }

    private final OpenTypeConverter[] getterConverters;
    private Throwable possibleCause;
  }

  /**
   * Builder if the target class has a setter for every getter
   */
  protected static class CompositeBuilderViaSetters extends CompositeBuilder {

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

    @Override
    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;
    }

    @Override
    Object fromCompositeData(CompositeData cd, String[] itemNames, OpenTypeConverter[] 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(openItem);
            setters[i].invoke(o, javaItem);
          }
        }
      } catch (Exception e) {
        throw invalidObjectException(e);
      }
      return o;
    }

    private Method[] setters;
  }

  /**
   * Builder if the target class has a constructor that is annotated with @ConstructorProperties so
   * we can derive the corresponding getters.
   */
  protected static class CompositeBuilderViaConstructor extends CompositeBuilder {

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

    @Override
    String applicable(Method[] getters) throws InvalidObjectException {

      final Class<ConstructorProperties> propertyNamesClass = ConstructorProperties.class;

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

      List<Constructor> annotatedConstrList = OpenTypeUtil.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 = OpenTypeUtil.newList();

      Map<String, Integer> getterMap = OpenTypeUtil.newMap();
      String[] itemNames = getItemNames();
      for (int i = 0; i < itemNames.length; i++)
        getterMap.put(itemNames[i], i);

      Set<BitSet> getterIndexSets = OpenTypeUtil.newSet();
      for (Constructor constr : annotatedConstrList) {
        String[] propertyNames =
            ((ConstructorProperties) 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);
        }

        for (int i = 0; i < paramTypes.length; i++)
          paramTypes[i] = fixType(paramTypes[i]);

        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)) {
            String msg = "@ConstructorProperties includes name " + propertyName
                + " which does not correspond to a property";
            for (String getterName : getterMap.keySet()) {
              if (getterName.equalsIgnoreCase(propertyName)) {
                msg += " (differs only in case from property " + getterName + ")";
              }
            }
            msg += ": " + 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);
      }

      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;
    }

    @Override
    Object fromCompositeData(CompositeData cd, String[] itemNames, OpenTypeConverter[] converters)
        throws InvalidObjectException {

      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(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 if 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
   */
  protected static class CompositeBuilderViaProxy extends CompositeBuilder {

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

    @Override
    String applicable(Method[] getters) {
      Class targetClass = getTargetClass();
      if (!targetClass.isInterface())
        return "not an interface";
      Set<Method> methods = OpenTypeUtil.newSet(Arrays.asList(targetClass.getMethods()));
      methods.removeAll(Arrays.asList(getters));

      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;
        }

      }
      if (bad != null)
        return "contains methods other than getters (" + bad + ")";
      return null;
    }

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

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

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

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

  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);
    }
  }

  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;
  }

  protected static String typeName(Type t) {
    if (t instanceof Class<?>) {
      Class<?> c = (Class<?>) t;
      if (c.isArray())
        return typeName(c.getComponentType()) + "[]";
      else
        return c.getName();
    }
    return t.toString();
  }

  private static Type fixType(Type t) {
    if (!(t instanceof GenericArrayType))
      return t;
    GenericArrayType gat = (GenericArrayType) t;
    Type ultimate = ultimateComponentType(gat);
    if (!(ultimate instanceof Class<?>))
      return t;
    Class<?> component = (Class<?>) fixType(gat.getGenericComponentType());
    return Array.newInstance(component, 0).getClass();
  }

  private static Type ultimateComponentType(GenericArrayType gat) {
    Type component = gat.getGenericComponentType();
    if (component instanceof GenericArrayType)
      return ultimateComponentType((GenericArrayType) component);
    else
      return component;
  }

}
