All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.maxifier.mxcache.impl.CustomStorageFactory Maven / Gradle / Ivy

/*
 * Copyright (c) 2008-2014 Maxifier Ltd. All Rights Reserved.
 */
package com.maxifier.mxcache.impl;

import com.maxifier.mxcache.context.CacheContext;
import com.maxifier.mxcache.provider.CacheDescriptor;
import com.maxifier.mxcache.provider.StorageFactory;
import com.maxifier.mxcache.storage.Storage;

import javax.annotation.Nonnull;

import javax.annotation.Nullable;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @author Alexander Kochurov ([email protected])
*/
public class CustomStorageFactory implements StorageFactory {
    private static final Object[] EMPTY_ARRAY = {};

    private final Constructor constructor;

    private final Object[] arguments;

    public CustomStorageFactory(CacheContext context, CacheDescriptor descriptor, Class storageClass) {
        if (!Storage.class.isAssignableFrom(storageClass)) {
            throw new IllegalStateException("Storage implementation should extend Storage interface " + storageClass);
        }
        this.constructor = getCustomConstructor(storageClass);
        if (constructor == null) {
            throw new IllegalStateException("Storage should have constructor taking CacheDescriptor, CacheContext or both: " + storageClass);
        }
        this.arguments = createArguments(constructor, context, descriptor);
    }

    private static boolean isAllowedConstructorArgumentType(Class type) {
        return type == CacheDescriptor.class || type == CacheContext.class;
    }

    private static boolean isAllowedConstructorArgumentTypes(Class[] types) {
        for (Class type : types) {
            if (!isAllowedConstructorArgumentType(type)) {
                return false;
            }
        }
        return true;
    }

    @Nonnull
    @Override
    public Storage createStorage(Object owner) throws InvocationTargetException, IllegalAccessException, InstantiationException {
        return constructor.newInstance(arguments);
    }

    @Override
    public String getImplementationDetails() {
        return constructor.getDeclaringClass().getCanonicalName();
    }

    @Nullable
    static  Constructor getCustomConstructor(Class cls) {
        Constructor[] constructors = cls.getDeclaredConstructors();

        Constructor res = null;
        int n = 0;
        for (Constructor constructor : constructors) {
            Class[] types = constructor.getParameterTypes();
            if (isAllowedConstructorArgumentTypes(types) && (res == null || n < types.length)) {
                //noinspection unchecked
                res = constructor;
                n = types.length;
            }
        }
        return res;
    }

    static  Object[] createArguments(Constructor constructor, CacheContext context, CacheDescriptor descriptor) {
        Class[] types = constructor.getParameterTypes();
        if (types.length == 0) {
            return EMPTY_ARRAY;
        }
        Object[] res = new Object[types.length];
        for (int i = 0; i < types.length; i++) {
            assert isAllowedConstructorArgumentType(types[i]);
            res[i] = types[i] == CacheDescriptor.class ? descriptor : context;
        }
        return res;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy