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

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

Go to download

Constains all classes necessary for launching a MxCache-instrumentated application

There is a newer version: 2.6.9
Show newest version
/*
 * Copyright (c) 2008-2014 Maxifier Ltd. All Rights Reserved.
 */
package com.maxifier.mxcache.impl;

import com.maxifier.mxcache.*;
import com.maxifier.mxcache.context.CacheContext;
import com.maxifier.mxcache.impl.wrapping.Wrapping;
import com.maxifier.mxcache.impl.resource.MxResourceFactory;
import com.maxifier.mxcache.provider.CacheManager;
import com.maxifier.mxcache.provider.CacheDescriptor;
import com.maxifier.mxcache.impl.resource.DependencyNode;
import com.maxifier.mxcache.impl.resource.DependencyTracker;
import com.maxifier.mxcache.caches.Cache;
import com.maxifier.mxcache.resource.MxResource;
import javax.annotation.Nullable;

import javax.annotation.Nonnull;

import java.util.Set;

/**
 * @author Alexander Kochurov ([email protected])
 */
public abstract class AbstractCacheManager implements CacheManager {
    private static final DependencyTracking DEFAULT_DEPENDENCY_TRACKING_VALUE = DependencyTracking.INSTANCE;
    private static final StatisticsModeEnum DEFAULT_STATISTICS_MODE = StatisticsModeEnum.STATIC_OR_STORAGE;

    private final CacheDescriptor descriptor;

    private final DependencyNode staticNode;

    private final DependencyTracking trackDependency;
    private final MxResource[] resourceDependencies;

    private final CacheContext context;

    private final StatisticsModeEnum statisticsMode;

    private final MutableStatistics staticStatistics;

    public AbstractCacheManager(CacheContext context, CacheDescriptor descriptor) {
        this.descriptor = descriptor;
        this.context = context;

        statisticsMode = descriptor.getStatisticsMode() == null ? DEFAULT_STATISTICS_MODE : descriptor.getStatisticsMode();

        switch (statisticsMode) {
            case STATIC:
            case STATIC_OR_STORAGE:
                staticStatistics = new MutableStatisticsImpl();
                break;
            case INSTANCE:
            case STORAGE:
                staticStatistics = null;
                break;
            default:
                throw new UnsupportedOperationException("Unknown statistics mode: " + statisticsMode);
        }

        trackDependency = convertStatic(convertDefault(descriptor.getTrackDependency()));
        resourceDependencies = getResources(descriptor.getResourceDependencies());

        switch (trackDependency) {
            case NONE:
                if (resourceDependencies == null) {
                    staticNode = null;
                } else {
                    staticNode = createStaticNode();
                }
                break;
            case STATIC:
                staticNode = createStaticNode();
                break;
            case INSTANCE:
                staticNode = null;
                break;
            default:
                throw new UnsupportedOperationException("Unknown value: " + trackDependency);
        }
    }

    private MxResource[] getResources(Set resourceNames) {
        if (resourceNames == null || resourceNames.isEmpty()) {
            return null;
        }
        MxResource[] res = new MxResource[resourceNames.size()];
        int i = 0;
        for (String resourceName : resourceNames) {
            res[i++] = MxResourceFactory.getResource(resourceName);
        }
        return res;
    }

    protected StatisticsModeEnum getStatisticsMode() {
        return statisticsMode;
    }

    /**
     * Creates static dependency node and registers it's resource dependencies with registerExplicitDependencies.
     *
     * @return created dependency node
     */
    protected DependencyNode createStaticNode() {
        DependencyNode node;
        if (descriptor.isStatic()) {
            node = Wrapping.getSingletonNode(descriptor);
        } else {
            node = Wrapping.getMultipleNode(descriptor);
        }
        registerExplicitDependencies(node);
        return node;
    }

    /**
     * Creates instance dependency node. Must register explicit resource dependencies with registerExplicitDependencies.
     *
     * @return created dependency node
     */
    protected DependencyNode createInstanceNode() {
        DependencyNode node = Wrapping.getSingletonNode(descriptor);
        registerExplicitDependencies(node);
        return node;
    }

    private DependencyTracking convertStatic(DependencyTracking tracking) {
        if (descriptor.isStatic() && tracking == DependencyTracking.INSTANCE) {
            return DependencyTracking.STATIC;
        }
        return tracking;
    }

    private static DependencyTracking convertDefault(DependencyTracking tracking) {
        return tracking == DependencyTracking.DEFAULT ? DEFAULT_DEPENDENCY_TRACKING_VALUE : tracking;
    }

    /**
     * Adds explicit resource dependencies to given node.
     *
     * @param node dependency node
     */
    protected void registerExplicitDependencies(DependencyNode node) {
        if (resourceDependencies != null) {
            for (MxResource resourceId : resourceDependencies) {
                DependencyTracker.addExplicitDependency(node, resourceId);
            }
        }
    }

    @Override
    public Cache createCache(@Nullable T owner) {
        if (descriptor.isStatic()) {
            if (owner != null) {
                throw new IllegalArgumentException("Static cache " + this + " requires no instance");
            }
        } else if (owner == null) {
            throw new IllegalArgumentException("Non-static cache " + this + " requires instance");
        }
        try {
            DependencyNode dependencyNode = getDependencyNode();
            Cache instance = createCache(owner, trackDependency == DependencyTracking.NONE ? DependencyTracker.DUMMY_NODE : dependencyNode, createStatistics());
            if (dependencyNode != null) {
                dependencyNode.addNode(instance);
            }
            return ProxyingCacheGenerator.wrapCacheWithProxy(descriptor, context, instance);
        } catch (Exception e) {
            throw new IllegalStateException("Cannot create cache", e);
        }
    }

    private MutableStatistics createStatistics() {
        switch (statisticsMode) {
            case STATIC:
            case STATIC_OR_STORAGE:
                return staticStatistics;
            case INSTANCE:
                return new MutableStatisticsImpl();
            case STORAGE:
                return null;
            default:
                throw new UnsupportedOperationException("Unsupported statistics mode: " + statisticsMode);
        }
    }

    private DependencyNode getDependencyNode() {
        switch (trackDependency) {
            case NONE:
            case STATIC:
                return staticNode;
            case INSTANCE:
                return createInstanceNode();
            default:
                throw new UnsupportedOperationException("Unknown value: " + trackDependency);
        }
    }

    @Nonnull
    protected abstract Cache createCache(T owner, DependencyNode dependencyNode, MutableStatistics statistics) throws Exception;

    @Override
    public CacheDescriptor getDescriptor() {
        return descriptor;
    }

    @Override
    public String toString() {
        return descriptor.toString();
    }

    @Override
    public CacheContext getContext() {
        return context;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy