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

com.maxifier.mxcache.impl.DefaultStorageFactory 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.hashing.HashingStrategyFactory;
import com.maxifier.mxcache.provider.CacheDescriptor;
import com.maxifier.mxcache.provider.Signature;
import com.maxifier.mxcache.provider.StorageFactory;
import com.maxifier.mxcache.storage.Storage;
import com.maxifier.mxcache.transform.Ignore;
import com.maxifier.mxcache.transform.SoftKey;
import com.maxifier.mxcache.transform.WeakKey;
import gnu.trove.list.array.TIntArrayList;

import javax.annotation.Nonnull;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @author Alexander Kochurov ([email protected])
*/
public class DefaultStorageFactory implements StorageFactory {
    private static final String CACHES_PACKAGE = "com.maxifier.mxcache.impl.caches.def.";

    private final Class implementation;
    private final Object hashingStrategy;

    private final Constructor storageConstructor;
    private final int[] tupleIndices;

    DefaultStorageFactory(CacheContext context, HashingStrategyFactory hashingStrategyFactory, CacheDescriptor descriptor) {
        Signature transformedSignature = descriptor.getTransformedSignature();
        if (!transformedSignature.hasKeys()) {
            implementation = transformedSignature.getImplementationClass(CACHES_PACKAGE, "StorageImpl");
            tupleIndices = null;
        } else {
            TIntArrayList p = getReferenceKeys(descriptor);
            if (p.isEmpty()) {
                implementation = transformedSignature.getImplementationClass(CACHES_PACKAGE, "TroveStorage");
                tupleIndices = null;
            } else if (transformedSignature.getKeyCount() == 1) {
                implementation = transformedSignature.getImplementationClass(CACHES_PACKAGE, "WeakTroveStorage");
                tupleIndices = null;
            } else {
                implementation = findClass(CACHES_PACKAGE + "Tuple" + Signature.toString(descriptor.getValueType()) + "WeakTroveStorage");
                tupleIndices = p.toArray();
            }
        }
        hashingStrategy = hashingStrategyFactory.createHashingStrategy(context, descriptor.getMethod());

        storageConstructor = getStorageConstructor();
    }

    private Class findClass(String name) {
        try {
            return Class.forName(name);
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException(e);
        }
    }

    @SuppressWarnings({ "unchecked" })
    private Constructor getStorageConstructor() {
        int desiredCount = hashingStrategy == null ? 0 : 1;
        if (tupleIndices != null) {
            desiredCount++;
        }
        for (Constructor constructor : implementation.getConstructors()) {
            if (constructor.getParameterTypes().length == desiredCount) {
                return (Constructor) constructor;
            }
        }
        throw new IllegalStateException("No corresponding constructor at " + implementation);
    }

    @Nonnull
    @Override
    public Storage createStorage(T owner) throws InvocationTargetException, IllegalAccessException, InstantiationException {
        if (tupleIndices == null) {
            if (hashingStrategy != null) {
                return storageConstructor.newInstance(hashingStrategy);
            } else {
                return storageConstructor.newInstance();
            }
        } else {
            if (hashingStrategy != null) {
                return storageConstructor.newInstance(hashingStrategy, tupleIndices);
            } else {
                return storageConstructor.newInstance((Object) tupleIndices);
            }
        }
    }

    private TIntArrayList getReferenceKeys(CacheDescriptor descriptor) {
        Annotation[][] ann = descriptor.getMethod().getParameterAnnotations();
        TIntArrayList p = new TIntArrayList(ann.length);
        int pos = 0;
        for (Annotation[] annotations : ann) {
            boolean ref = false;
            boolean ignored = false;
            for (Annotation a : annotations) {
                if ((a instanceof WeakKey) || (a instanceof SoftKey)) {
                    ref = true;
                }
                if (a instanceof Ignore) {
                    ignored = true;
                }
            }
            if (!ignored) {
                if (ref) {
                    p.add(pos);
                }
                pos++;
            }
        }
        return p;
    }

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy