/*
 *
 * 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.qpid.server.model;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;

import javax.xml.bind.DatatypeConverter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Defaults;

import org.apache.qpid.server.model.preferences.GenericPrincipal;
import org.apache.qpid.server.util.ServerScopedRuntimeException;
import org.apache.qpid.util.Strings;

abstract class AttributeValueConverter<T>
{
    static final AttributeValueConverter<String> STRING_CONVERTER = new AttributeValueConverter<String>()
    {
        @Override
        public String convert(final Object value, final ConfiguredObject object)
        {
            return value == null ? null : AbstractConfiguredObject.interpolate(object, value.toString());
        }
    };

    static final AttributeValueConverter<Object> OBJECT_CONVERTER = new AttributeValueConverter<Object>()
    {
        @Override
        public Object convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof String)
            {
                return AbstractConfiguredObject.interpolate(object, (String) value);
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                return value;
            }
        }
    };
    static final AttributeValueConverter<UUID> UUID_CONVERTER = new AttributeValueConverter<UUID>()
    {
        @Override
        public UUID convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof UUID)
            {
                return (UUID) value;
            }
            else if(value instanceof String)
            {
                return UUID.fromString(AbstractConfiguredObject.interpolate(object, (String) value));
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a UUID");
            }
        }
    };

    static final AttributeValueConverter<URI> URI_CONVERTER = new AttributeValueConverter<URI>()
    {
        @Override
        URI convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof URI)
            {
                return (URI) value;
            }
            else if(value instanceof String)
            {
                return URI.create(AbstractConfiguredObject.interpolate(object, (String) value));
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a URI");
            }
        }
    };

    static final AttributeValueConverter<byte[]> BINARY_CONVERTER = new AttributeValueConverter<byte[]>()
    {
        @Override
        byte[] convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof byte[])
            {
                return (byte[]) value;
            }
            else if(value == null)
            {
                return null;
            }
            else if(value instanceof String)
            {
                String interpolated = AbstractConfiguredObject.interpolate(object,
                                                                          (String) value);
                return Strings.decodeBase64(interpolated);

            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a byte[]");
            }
        }
    };

    public static final Pattern BASE64_PATTERN = Pattern.compile("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$");

    static final AttributeValueConverter<Certificate> CERTIFICATE_CONVERTER = new AttributeValueConverter<Certificate>()
    {
        private final CertificateFactory _certFactory;

        {
            try
            {
                _certFactory = CertificateFactory.getInstance("X.509");
            }
            catch (CertificateException e)
            {
                throw new ServerScopedRuntimeException(e);
            }
        }

        @Override
        public Certificate convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Certificate)
            {
                return (Certificate) value;
            }
            else if(value instanceof byte[])
            {
                try(ByteArrayInputStream is = new ByteArrayInputStream((byte[])value))
                {
                    return _certFactory.generateCertificate(is);
                }
                catch (IOException | CertificateException e)
                {
                    throw new IllegalArgumentException(e);
                }
            }
            else if(value instanceof String)
            {
                String strValue = AbstractConfiguredObject.interpolate(object, (String) value);
                if (BASE64_PATTERN.matcher(strValue).matches())
                {
                    byte[] certificateBytes = BINARY_CONVERTER.convert(strValue, object);
                    return convert(certificateBytes, object);
                }
                else
                {
                    return convert(strValue.getBytes(StandardCharsets.UTF_8), object);
                }
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Certificate");
            }
        }
    };

    static final AttributeValueConverter<Long> LONG_CONVERTER = new AttributeValueConverter<Long>()
    {

        @Override
        public Long convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Long)
            {
                return (Long) value;
            }
            else if(value instanceof Number)
            {
                return ((Number) value).longValue();
            }
            else if(value instanceof String)
            {
                String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
                try
                {
                    return Long.valueOf(interpolated);
                }
                catch(NumberFormatException e)
                {
                    throw new IllegalArgumentException("Cannot convert string '" + interpolated + "' to a long integer",e);
                }
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Long");
            }
        }
    };
    static final AttributeValueConverter<Integer> INT_CONVERTER = new AttributeValueConverter<Integer>()
    {

        @Override
        public Integer convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Integer)
            {
                return (Integer) value;
            }
            else if(value instanceof Number)
            {
                return ((Number) value).intValue();
            }
            else if(value instanceof String)
            {
                String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
                try
                {
                    return Integer.valueOf(interpolated);
                }
                catch(NumberFormatException e)
                {
                    throw new IllegalArgumentException("Cannot convert string '" + interpolated + "' to an integer",e);
                }
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to an Integer");
            }
        }
    };
    static final AttributeValueConverter<Short> SHORT_CONVERTER = new AttributeValueConverter<Short>()
    {

        @Override
        public Short convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Short)
            {
                return (Short) value;
            }
            else if(value instanceof Number)
            {
                return ((Number) value).shortValue();
            }
            else if(value instanceof String)
            {
                String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
                try
                {
                    return Short.valueOf(interpolated);
                }
                catch(NumberFormatException e)
                {
                    throw new IllegalArgumentException("Cannot convert string '" + interpolated + "' to a short integer",e);
                }
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Short");
            }
        }
    };

    static final AttributeValueConverter<Double> DOUBLE_CONVERTER = new AttributeValueConverter<Double>()
    {

        @Override
        public Double convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Double)
            {
                return (Double) value;
            }
            else if(value instanceof Number)
            {
                return ((Number) value).doubleValue();
            }
            else if(value instanceof String)
            {
                String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
                try
                {
                    return Double.valueOf(interpolated);
                }
                catch(NumberFormatException e)
                {
                    throw new IllegalArgumentException("Cannot convert string '" + interpolated + "' to a Double",e);
                }
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Double");
            }
        }
    };

    static final AttributeValueConverter<Boolean> BOOLEAN_CONVERTER = new AttributeValueConverter<Boolean>()
    {

        @Override
        public Boolean convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Boolean)
            {
                return (Boolean) value;
            }
            else if(value instanceof String)
            {
                return Boolean.valueOf(AbstractConfiguredObject.interpolate(object, (String) value));
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Boolean");
            }
        }
    };
    static final AttributeValueConverter<List> LIST_CONVERTER = new AttributeValueConverter<List>()
    {
        @Override
        public List convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof List)
            {
                return Collections.unmodifiableList((List) value);
            }
            else if(value instanceof Object[])
            {
                return convert(Arrays.asList((Object[]) value),object);
            }
            else if(value instanceof String)
            {
                return Collections.unmodifiableList(convertFromJson((String) value, object, List.class));
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a List");
            }
        }
    };

    static final AttributeValueConverter<Set> SET_CONVERTER = new AttributeValueConverter<Set>()
    {
        @Override
        public Set convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Set)
            {
                return Collections.unmodifiableSet((Set) value);
            }

            else if(value instanceof Object[])
            {
                return convert(new HashSet(Arrays.asList((Object[])value)),object);
            }
            else if(value instanceof String)
            {
                return Collections.unmodifiableSet(convertFromJson((String) value, object, Set.class));
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Set");
            }
        }
    };
    static final AttributeValueConverter<Collection>
            COLLECTION_CONVERTER = new AttributeValueConverter<Collection>()
    {
        @Override
        public Collection convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Collection)
            {
                return Collections.unmodifiableCollection((Collection) value);
            }
            else if(value instanceof Object[])
            {
                return convert(Arrays.asList((Object[]) value), object);
            }
            else if(value instanceof String)
            {
                return Collections.unmodifiableCollection(convertFromJson((String) value, object, Collection.class));
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Collection");
            }
        }
    };

    static final AttributeValueConverter<Map> MAP_CONVERTER = new AttributeValueConverter<Map>()
    {
        @Override
        public Map convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Map)
            {
                Map<Object,Object> originalMap = (Map) value;
                Map resolvedMap = new LinkedHashMap(originalMap.size());
                for(Map.Entry<Object,Object> entry : originalMap.entrySet())
                {
                    Object key = entry.getKey();
                    Object val = entry.getValue();
                    resolvedMap.put(key instanceof String ? AbstractConfiguredObject.interpolate(object, (String) key) : key,
                                    val instanceof String ? AbstractConfiguredObject.interpolate(object, (String) val) : val);
                }
                return Collections.unmodifiableMap(resolvedMap);
            }
            else if(value == null)
            {
                return null;
            }
            else if(value instanceof String)
            {
                return Collections.unmodifiableMap(convertFromJson((String) value, object, Map.class));
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Map");
            }
        }

    };

    static final AttributeValueConverter<Date> DATE_CONVERTER = new AttributeValueConverter<Date>()
    {

        @Override
        public Date convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Date)
            {
                return (Date) value;
            }
            else if(value instanceof Number)
            {
                return new Date(((Number) value).longValue());
            }
            else if(value instanceof String)
            {
                String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);

                try
                {
                    return new Date(Long.valueOf(interpolated));
                }
                catch(NumberFormatException e)
                {
                    try
                    {
                        return DatatypeConverter.parseDateTime(interpolated).getTime();
                    }
                    catch (IllegalArgumentException e1)
                    {
                        throw new IllegalArgumentException("Cannot convert string '" + interpolated + "' to a Date."
                                                           + " It is neither a ISO-8601 date or date time nor a string"
                                                           + " containing a numeric value.");
                    }
                }
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Date");
            }
        }
    };

    public static final AttributeValueConverter<Principal> PRINCIPAL_CONVERTER = new AttributeValueConverter<Principal>()
    {
        @Override
        public Principal convert(final Object value, final ConfiguredObject object)
        {
            if (value instanceof Principal)
            {
                return (Principal) value;
            }
            else if (value instanceof String)
            {
                String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
                return new GenericPrincipal(interpolated);
            }
            else if (value == null)
            {
                return null;
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Principal");
            }
        }
    };

    private static <T> T convertFromJson(final String value, final ConfiguredObject object, final Class<T> valueType)
    {
        String interpolated = AbstractConfiguredObject.interpolate(object, value);
        ObjectMapper objectMapper = new ObjectMapper();
        try
        {
            return objectMapper.readValue(interpolated, valueType);
        }
        catch (IOException e)
        {
            throw new IllegalArgumentException("Cannot convert String '"
                  + value + "'"
                  + (value.equals(interpolated)
                               ? "" : (" (interpolated to '" + interpolated + "')"))
                                       + " to a " + valueType.getSimpleName());
        }
    }

    static <X> AttributeValueConverter<X> getConverter(final Class<X> type, final Type returnType)
    {
        if(type == String.class)
        {
            return (AttributeValueConverter<X>) STRING_CONVERTER;
        }
        else if(type == Integer.class)
        {
            return (AttributeValueConverter<X>) INT_CONVERTER;
        }
        else if(type == Short.class)
        {
            return (AttributeValueConverter<X>) SHORT_CONVERTER;
        }
        else if(type == Long.class)
        {
            return (AttributeValueConverter<X>) LONG_CONVERTER;
        }
        else if(type == Double.class)
        {
            return (AttributeValueConverter<X>) DOUBLE_CONVERTER;
        }
        else if(type == Boolean.class)
        {
            return (AttributeValueConverter<X>) BOOLEAN_CONVERTER;
        }
        else if(type == Date.class)
        {
            return (AttributeValueConverter<X>) DATE_CONVERTER;
        }
        else if(type == UUID.class)
        {
            return (AttributeValueConverter<X>) UUID_CONVERTER;
        }
        else if(type == URI.class)
        {
            return (AttributeValueConverter<X>) URI_CONVERTER;
        }
        else if(type == byte[].class)
        {
            return (AttributeValueConverter<X>) BINARY_CONVERTER;
        }
        else if(Certificate.class.isAssignableFrom(type))
        {
            return (AttributeValueConverter<X>) CERTIFICATE_CONVERTER;
        }
        else if(Enum.class.isAssignableFrom(type))
        {
            return (AttributeValueConverter<X>) new EnumConverter((Class<? extends Enum>)type);
        }
        else if(List.class.isAssignableFrom(type))
        {
            if (returnType instanceof ParameterizedType)
            {
                Type parameterizedType = ((ParameterizedType) returnType).getActualTypeArguments()[0];
                return (AttributeValueConverter<X>) new GenericListConverter(parameterizedType);
            }
            else
            {
                return (AttributeValueConverter<X>) LIST_CONVERTER;
            }
        }
        else if(Set.class.isAssignableFrom(type))
        {
            if (returnType instanceof ParameterizedType)
            {
                Type parameterizedType = ((ParameterizedType) returnType).getActualTypeArguments()[0];
                return (AttributeValueConverter<X>) new GenericSetConverter(parameterizedType);
            }
            else
            {
                return (AttributeValueConverter<X>) SET_CONVERTER;
            }
        }
        else if(Map.class.isAssignableFrom(type))
        {
            if(returnType instanceof ParameterizedType)
            {
                Type keyType = ((ParameterizedType) returnType).getActualTypeArguments()[0];
                Type valueType = ((ParameterizedType) returnType).getActualTypeArguments()[1];

                return (AttributeValueConverter<X>) new GenericMapConverter(keyType,valueType);
            }
            else
            {
                return (AttributeValueConverter<X>) MAP_CONVERTER;
            }
        }
        else if(Collection.class.isAssignableFrom(type))
        {
            if (returnType instanceof ParameterizedType)
            {
                Type parameterizedType = ((ParameterizedType) returnType).getActualTypeArguments()[0];
                return (AttributeValueConverter<X>) new GenericCollectionConverter(parameterizedType);
            }
            else
            {
                return (AttributeValueConverter<X>) COLLECTION_CONVERTER;
            }
        }
        else if(Principal.class.isAssignableFrom(type))
        {
            return (AttributeValueConverter<X>) PRINCIPAL_CONVERTER;
        }
        else if(ConfiguredObject.class.isAssignableFrom(type))
        {
            return (AttributeValueConverter<X>) new ConfiguredObjectConverter(type);
        }
        else if(ManagedAttributeValue.class.isAssignableFrom(type))
        {
            return (AttributeValueConverter<X>) new ManageableAttributeTypeConverter(type);
        }
        else if(Object.class == type)
        {
            return (AttributeValueConverter<X>) OBJECT_CONVERTER;
        }
        throw new IllegalArgumentException("Cannot create attribute converter of type " + type.getName());
    }

    static Class<?> getTypeFromMethod(final Method m)
    {
        return convertPrimitiveToBoxed(m.getReturnType());
    }

    static Class<?> convertPrimitiveToBoxed(Class<?> type)
    {
        if(type.isPrimitive())
        {
            if(type == Boolean.TYPE)
            {
                type = Boolean.class;
            }
            else if(type == Byte.TYPE)
            {
                type = Byte.class;
            }
            else if(type == Short.TYPE)
            {
                type = Short.class;
            }
            else if(type == Integer.TYPE)
            {
                type = Integer.class;
            }
            else if(type == Long.TYPE)
            {
                type = Long.class;
            }
            else if(type == Float.TYPE)
            {
                type = Float.class;
            }
            else if(type == Double.TYPE)
            {
                type = Double.class;
            }
            else if(type == Character.TYPE)
            {
                type = Character.class;
            }
        }
        return type;
    }

    static String getNameFromMethod(final Method m, final Class<?> type)
    {
        String methodName = m.getName();
        String baseName;

        if(type == Boolean.class )
        {
            if((methodName.startsWith("get") || methodName.startsWith("has")) && methodName.length() >= 4)
            {
                baseName = methodName.substring(3);
            }
            else if(methodName.startsWith("is") && methodName.length() >= 3)
            {
                baseName = methodName.substring(2);
            }
            else
            {
                throw new IllegalArgumentException("Method name " + methodName + " does not conform to the required pattern for ManagedAttributes");
            }
        }
        else
        {
            if(methodName.startsWith("get") && methodName.length() >= 4)
            {
                baseName = methodName.substring(3);
            }
            else
            {
                throw new IllegalArgumentException("Method name " + methodName + " does not conform to the required pattern for ManagedAttributes");
            }
        }

        String name = baseName.length() == 1 ? baseName.toLowerCase() : baseName.substring(0,1).toLowerCase() + baseName.substring(1);
        name = name.replace('_','.');
        return name;
    }

    abstract T convert(Object value, final ConfiguredObject object);

    public static class GenericListConverter extends AttributeValueConverter<List>
    {

        private final AttributeValueConverter<?> _memberConverter;

        public GenericListConverter(final Type genericType)
        {
            _memberConverter = getConverter(getRawType(genericType), genericType);
        }

        @Override
        public List convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Collection)
            {
                Collection original = (Collection)value;
                List converted = new ArrayList(original.size());
                for(Object member : original)
                {
                    converted.add(_memberConverter.convert(member, object));
                }
                return Collections.unmodifiableList(converted);
            }
            else if(value instanceof Object[])
            {
                return convert(Arrays.asList((Object[])value),object);
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                if(value instanceof String)
                {
                    String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
                    ObjectMapper objectMapper = new ObjectMapper();
                    try
                    {
                        return convert(objectMapper.readValue(interpolated, List.class), object);
                    }
                    catch (IOException e)
                    {
                        // fall through to the non-JSON single object case
                    }
                }
                return "".equals(value) ? Collections.emptyList() : Collections.unmodifiableList(Collections.singletonList(_memberConverter.convert(value, object)));
            }
        }
    }

    public static class GenericSetConverter extends AttributeValueConverter<Set>
    {

        private final AttributeValueConverter<?> _memberConverter;

        public GenericSetConverter(final Type genericType)
        {
            _memberConverter = getConverter(getRawType(genericType), genericType);
        }

        @Override
        public Set convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Collection)
            {
                Collection original = (Collection)value;
                Set converted = new HashSet(original.size());
                for(Object member : original)
                {
                    converted.add(_memberConverter.convert(member, object));
                }
                return Collections.unmodifiableSet(converted);
            }
            else if(value instanceof Object[])
            {
                return convert(new HashSet(Arrays.asList((Object[])value)),object);
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                if(value instanceof String)
                {
                    String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
                    ObjectMapper objectMapper = new ObjectMapper();
                    try
                    {
                        return convert(objectMapper.readValue(interpolated, Set.class), object);
                    }
                    catch (IOException e)
                    {
                        // fall through to the non-JSON single object case
                    }
                }
                return Collections.unmodifiableSet(Collections.singleton(_memberConverter.convert(value, object)));
            }
        }
    }

    public static class GenericCollectionConverter extends AttributeValueConverter<Collection>
    {

        private final AttributeValueConverter<?> _memberConverter;

        public GenericCollectionConverter(final Type genericType)
        {
            _memberConverter = getConverter(getRawType(genericType), genericType);
        }


        @Override
        public Collection convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Collection)
            {
                Collection original = (Collection)value;
                Collection converted = new ArrayList(original.size());
                for(Object member : original)
                {
                    converted.add(_memberConverter.convert(member, object));
                }
                return Collections.unmodifiableCollection(converted);
            }
            else if(value instanceof Object[])
            {
                return convert(Arrays.asList((Object[])value),object);
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                if(value instanceof String)
                {
                    String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
                    ObjectMapper objectMapper = new ObjectMapper();
                    try
                    {
                        return convert(objectMapper.readValue(interpolated, List.class), object);
                    }
                    catch (IOException e)
                    {
                        // fall through to the non-JSON single object case
                    }
                }
                return Collections.unmodifiableCollection(Collections.singletonList(_memberConverter.convert(value, object)));
            }
        }
    }

    public static class GenericMapConverter extends AttributeValueConverter<Map>
    {

        private final AttributeValueConverter<?> _keyConverter;
        private final AttributeValueConverter<?> _valueConverter;


        public GenericMapConverter(final Type keyType, final Type valueType)
        {
            _keyConverter = getConverter(getRawType(keyType), keyType);

            _valueConverter = getConverter(getRawType(valueType), valueType);
        }


        @Override
        public Map convert(final Object value, final ConfiguredObject object)
        {
            if(value instanceof Map)
            {
                Map<?,?> original = (Map<?,?>)value;
                Map converted = new LinkedHashMap(original.size());
                for(Map.Entry<?,?> entry : original.entrySet())
                {
                    converted.put(_keyConverter.convert(entry.getKey(),object),
                                  _valueConverter.convert(entry.getValue(), object));
                }
                return Collections.unmodifiableMap(converted);
            }
            else if(value == null)
            {
                return null;
            }
            else
            {
                if(value instanceof String)
                {
                    String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
                    ObjectMapper objectMapper = new ObjectMapper();
                    try
                    {
                        return convert(objectMapper.readValue(interpolated, Map.class), object);
                    }
                    catch (IOException e)
                    {
                        // fall through to the non-JSON single object case
                    }
                }

                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Map");
            }

        }
    }


    static final class EnumConverter<X extends Enum<X>> extends AttributeValueConverter<X>
    {
        private final Class<X> _klazz;

        private EnumConverter(final Class<X> klazz)
        {
            _klazz = klazz;
        }

        @Override
        public X convert(final Object value, final ConfiguredObject object)
        {
            if(value == null)
            {
                return null;
            }
            else if(_klazz.isInstance(value))
            {
                return (X) value;
            }
            else if(value instanceof String)
            {
                return Enum.valueOf(_klazz, AbstractConfiguredObject.interpolate(object, (String) value));
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a " + _klazz.getName());
            }
        }
    }

    static final class ConfiguredObjectConverter<X extends ConfiguredObject<X>> extends AttributeValueConverter<X>
    {
        private final Class<X> _klazz;

        private ConfiguredObjectConverter(final Class<X> klazz)
        {
            _klazz = klazz;
        }

        @Override
        public X convert(final Object value, final ConfiguredObject object)
        {
            if(value == null)
            {
                return null;
            }
            else if(_klazz.isInstance(value))
            {
                return (X) value;
            }
            else if(value instanceof UUID)
            {
                Collection<X> reachable = object.getModel().getReachableObjects(object, _klazz);
                for(X candidate : reachable)
                {
                    if(candidate.getId().equals(value))
                    {
                        return candidate;
                    }
                }
                throw new UnknownConfiguredObjectException(_klazz, (UUID)value);
            }
            else if(value instanceof String)
            {
                String valueStr = AbstractConfiguredObject.interpolate(object, (String) value);
                Collection<X> reachable = object.getModel().getReachableObjects(object, _klazz);
                for(X candidate : reachable)
                {
                    if(candidate.getName().equals(valueStr))
                    {
                        return candidate;
                    }
                }
                try
                {
                    UUID id = UUID.fromString(valueStr);
                    return convert(id, object);
                }
                catch (IllegalArgumentException e)
                {
                    throw new UnknownConfiguredObjectException(_klazz, valueStr);
                }
            }
            else
            {
                throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a " + _klazz.getName());
            }
        }
    }

    private static Class getRawType(Type t)
    {
        if(t instanceof Class)
        {
            return (Class)t;
        }
        else if(t instanceof ParameterizedType)
        {
            return (Class)((ParameterizedType)t).getRawType();
        }
        else if(t instanceof TypeVariable)
        {
            Type[] bounds = ((TypeVariable)t).getBounds();
            if(bounds.length == 1)
            {
                return getRawType(bounds[0]);
            }
        }
        throw new ServerScopedRuntimeException("Unable to process type when constructing configuration model: " + t);
    }

    private interface ValueMethod<X extends ManagedAttributeValue>
    {
        Object getValue(X object);
    }


    private static class ConstantValueMethod<X extends ManagedAttributeValue> implements ValueMethod<X>
    {

        private final String _value;

        public ConstantValueMethod(final String derivedMethodValue)
        {
            _value = derivedMethodValue;
        }

        @Override
        public Object getValue(final X object)
        {
            return _value;
        }
    }


    private static class ObjectMethodValueMethod<X extends ManagedAttributeValue> implements ValueMethod<X>
    {
        private final Method _sourceMethod;

        public ObjectMethodValueMethod(final Method sourceMethod)
        {
            _sourceMethod = sourceMethod;
        }

        @Override
        public Object getValue(final X object)
        {
            try
            {
                return _sourceMethod.invoke(object);
            }
            catch (IllegalAccessException | InvocationTargetException e)
            {
                throw new IllegalArgumentException(e);
            }
        }
    }


    private static class StaticMethodValueMethod<X extends ManagedAttributeValue> implements ValueMethod<X>
    {
        private final Method _sourceMethod;

        public StaticMethodValueMethod(final Method sourceMethod)
        {
            _sourceMethod = sourceMethod;
        }

        @Override
        public Object getValue(final X object)
        {
            try
            {
                return _sourceMethod.invoke(null, object);
            }
            catch (IllegalAccessException | InvocationTargetException e)
            {
                throw new IllegalArgumentException(e);
            }
        }
    }

    static final class ManageableAttributeTypeConverter<X extends ManagedAttributeValue> extends AttributeValueConverter<X>
    {
        private static final Pattern STATIC_METHOD_PATTERN = Pattern.compile("([\\w][\\w\\d_]+\\.)+[\\w][\\w\\d_\\$]*#[\\w\\d_]+\\s*\\(\\s*\\)");
        private static final Pattern OBJECT_METHOD_PATTERN = Pattern.compile("#[\\w\\d_]+\\s*\\(\\s*\\)");

        private final Class<X> _klazz;
        private final Map<Method, AttributeValueConverter<?>> _propertyConverters = new HashMap<>();
        private final Map<Method, ValueMethod<X>> _derivedValueMethod = new HashMap<>();

        private ManageableAttributeTypeConverter(final Class<X> klazz)
        {
            _klazz = klazz;
            for(Method method : klazz.getMethods())
            {
                final String methodName = method.getName();
                if(method.getParameterTypes().length == 0
                   && !Arrays.asList(Object.class.getMethods()).contains(method)
                   && (methodName.startsWith("get") || methodName.startsWith("is") || methodName.startsWith("has")))
                {
                    _propertyConverters.put(method, AttributeValueConverter.getConverter(getTypeFromMethod(method), method.getGenericReturnType()));
                }

                final ManagedAttributeValueTypeDerivedMethod derivedMethodAnnotation =
                        method.getAnnotation(ManagedAttributeValueTypeDerivedMethod.class);
                if (derivedMethodAnnotation != null)
                {
                    String derivedMethodValue = derivedMethodAnnotation.value();
                    if (STATIC_METHOD_PATTERN.matcher(derivedMethodValue).matches())
                    {
                        try
                        {
                            String className = derivedMethodValue.split("#")[0].trim();
                            String sourceMethodName = derivedMethodValue.split("#")[1].split("\\(")[0].trim();
                            Class<?> sourceMethodClass = Class.forName(className);
                            Method sourceMethod = sourceMethodClass.getMethod(sourceMethodName, klazz);
                            _derivedValueMethod.put(method, new StaticMethodValueMethod<X>(sourceMethod));

                        }
                        catch (ClassNotFoundException | NoSuchMethodException e)
                        {
                            throw new IllegalArgumentException(e);
                        }
                    }
                    else if (OBJECT_METHOD_PATTERN.matcher(derivedMethodValue).matches())
                    {
                        try
                        {
                            final Method sourceMethod =
                                    klazz.getMethod(derivedMethodValue.substring(1, derivedMethodValue.indexOf((int) '(')));
                            _derivedValueMethod.put(method, new ObjectMethodValueMethod<X>(sourceMethod));
                        }
                        catch (NoSuchMethodException e)
                        {
                            throw new IllegalArgumentException(e);
                        }
                    }
                    else
                    {
                        _derivedValueMethod.put(method, new ConstantValueMethod<X>(derivedMethodValue));
                    }
                }
            }

        }

        @Override
        X convert(final Object value, final ConfiguredObject object)
        {
            if(value == null)
            {
                return null;
            }
            else if(_klazz.isInstance(value))
            {
                return (X) value;
            }
            else if(value instanceof Map)
            {
                @SuppressWarnings("unchecked")
                final X proxyObject =
                        (X) Proxy.newProxyInstance(_klazz.getClassLoader(), new Class[]{_klazz}, new InvocationHandler()
                        {
                            @Override
                            public Object invoke(final Object proxy, final Method method, final Object[] args)
                                    throws Throwable
                            {
                                AttributeValueConverter<?> converter = _propertyConverters.get(method);
                                Map map = (Map) value;
                                if (converter != null)
                                {
                                    return convertValue(map, converter, method, proxy);
                                }
                                else if ("toString".equals(method.getName()) && method.getParameterTypes().length == 0)
                                {
                                    return _klazz.getSimpleName() + " : " + map.toString();
                                }
                                else if ("hashCode".equals(method.getName()) && method.getParameterTypes().length == 0)
                                {
                                    return map.hashCode();
                                }
                                else if ("equals".equals(method.getName())
                                         && method.getParameterTypes().length == 1
                                         && method.getParameterTypes()[0] == Object.class)
                                {
                                    if (_klazz.isInstance(args[0]))
                                    {
                                        for (Map.Entry<Method, AttributeValueConverter<?>> entry : _propertyConverters.entrySet())
                                        {
                                            AttributeValueConverter<?> conv = entry.getValue();
                                            Method meth = entry.getKey();

                                            Object lvalue = convertValue(map, conv, meth, proxy);
                                            Object rvalue = meth.invoke(args[0]);
                                            if ((lvalue == null && rvalue != null) || (lvalue != null && !lvalue.equals(
                                                    rvalue)))
                                            {
                                                return false;
                                            }
                                        }
                                        return true;
                                    }
                                    else
                                    {
                                        return false;
                                    }
                                }
                                throw new UnsupportedOperationException(
                                        "The proxy class implements only attribute getters and toString(), hashCode() and equals()");
                            }

                            private Object convertValue(final Map map,
                                                        final AttributeValueConverter<?> converter,
                                                        final Method method, final Object proxy)
                            {
                                String attributeName = getNameFromMethod(method, getTypeFromMethod(method));
                                if (_derivedValueMethod.containsKey(method))
                                {
                                    return converter.convert(_derivedValueMethod.get(method).getValue((X) proxy),
                                                             object);
                                }
                                else if (map.containsKey(attributeName))
                                {
                                    return converter.convert(map.get(attributeName), object);
                                }
                                else
                                {
                                    return Defaults.defaultValue(method.getReturnType());
                                }
                            }
                        });
                return proxyObject;
            }
            else if(value instanceof String)
            {
                String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
                ObjectMapper objectMapper = new ObjectMapper();
                try
                {
                    return convert(objectMapper.readValue(interpolated, Map.class), object);
                }
                catch (IOException e)
                {

                }

            }
            throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a " + _klazz.getName());
        }

    }

}
