ru.runa.wfe.ss.cache.AltSubstitutionCacheImpl.java Source code

Java tutorial

Introduction

Here is the source code for ru.runa.wfe.ss.cache.AltSubstitutionCacheImpl.java

Source

/*
 * This file is part of the RUNA WFE project.
 * 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU Lesser General Public License 
 * as published by the Free Software Foundation; version 2.1 
 * of the License. 
 * 
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU Lesser General Public License for more details. 
 * 
 * You should have received a copy of the GNU Lesser General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 */
package ru.runa.wfe.ss.cache;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import ru.runa.wfe.commons.ApplicationContextFactory;
import ru.runa.wfe.commons.cache.BaseCacheImpl;
import ru.runa.wfe.commons.cache.Cache;
import ru.runa.wfe.commons.cache.CacheImplementation;
import ru.runa.wfe.commons.cache.Change;
import ru.runa.wfe.commons.cache.ChangedObjectParameter;
import ru.runa.wfe.execution.logic.SwimlaneInitializerHelper;
import ru.runa.wfe.presentation.BatchPresentationFactory;
import ru.runa.wfe.ss.Substitution;
import ru.runa.wfe.ss.TerminatorSubstitution;
import ru.runa.wfe.ss.dao.SubstitutionDao;
import ru.runa.wfe.user.Actor;
import ru.runa.wfe.user.Executor;
import ru.runa.wfe.user.Group;
import ru.runa.wfe.user.dao.ExecutorDao;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

class AltSubstitutionCacheImpl extends BaseCacheImpl implements SubstitutionCache {
    public static final String substitutorsName = "ru.runa.wfe.ss.cache.substitutors";
    public static final String substitutedName = "ru.runa.wfe.ss.cache.substituted";
    private final Cache<Long, TreeMap<Substitution, HashSet<Long>>> actorToSubstitutorsCache;
    private final Cache<Long, HashSet<Long>> actorToSubstitutedCache;
    private final ExecutorDao executorDao = ApplicationContextFactory.getExecutorDAO();
    private final SubstitutionDao substitutionDao = ApplicationContextFactory.getSubstitutionDAO();

    public AltSubstitutionCacheImpl() {
        actorToSubstitutorsCache = createCache(substitutorsName, true);
        actorToSubstitutedCache = createCache(substitutedName, true);
        for (Actor actor : executorDao.getAllActors(BatchPresentationFactory.ACTORS.createNonPaged())) {
            if (!actor.isActive()) {
                loadCacheFor(actor.getId());
            }
        }
    }

    private HashSet<Long> loadCacheFor(Long actorId, Substitution substitution) {
        HashSet<Long> substitutors = Sets.newHashSet();
        if (!substitution.isEnabled()) {
            return substitutors;
        }
        if (substitution instanceof TerminatorSubstitution) {
            return substitutors;
        }
        try {
            List<? extends Executor> executors = SwimlaneInitializerHelper.evaluate(substitution.getOrgFunction(),
                    null);
            for (Executor executor : executors) {
                if (executor instanceof Actor) {
                    substitutors.add(executor.getId());
                } else {
                    for (Actor groupActor : executorDao.getGroupActors((Group) executor)) {
                        substitutors.add(groupActor.getId());
                    }
                }
            }
            for (Long substitutor : substitutors) {
                HashSet<Long> substituted = actorToSubstitutedCache.get(substitutor);
                if (substituted == null) {
                    substituted = Sets.newHashSet();
                    actorToSubstitutedCache.put(substitutor, substituted);
                }
                substituted.add(actorId);
            }
        } catch (Exception e) {
            log.error("Error in " + substitution, e);
        }
        return substitutors;
    }

    private void loadCacheFor(Long actorId) {
        TreeMap<Substitution, HashSet<Long>> result = Maps.newTreeMap();
        for (Substitution substitution : substitutionDao.getByActorId(actorId, true)) {
            HashSet<Long> substitutors = loadCacheFor(actorId, substitution);
            result.put(substitution, substitutors);
        }
        actorToSubstitutorsCache.put(actorId, result);
    }

    @Override
    public TreeMap<Substitution, Set<Long>> getSubstitutors(Actor actor, boolean loadIfRequired) {
        TreeMap<Substitution, HashSet<Long>> result = actorToSubstitutorsCache.get(actor.getId());
        return result != null ? new TreeMap<Substitution, Set<Long>>(result)
                : new TreeMap<Substitution, Set<Long>>();
    }

    @Override
    public TreeMap<Substitution, Set<Long>> tryToGetSubstitutors(Actor actor) {
        return null;
    }

    @Override
    public HashSet<Long> getSubstituted(Actor actor) {
        HashSet<Long> result = actorToSubstitutedCache.get(actor.getId());
        return result != null ? result : new HashSet<Long>();
    }

    public void onSubstitutionChange(Actor actor, Substitution substitution, Change change) {
        if (actor != null && !actor.isActive()) {
            if (change == Change.CREATE) {
                loadCacheFor(actor.getId(), substitution);
            }
            if (change == Change.UPDATE) {
                // TODO implement additional logic
            }
            if (change == Change.DELETE) {
                // TODO implement additional logic
            }
        }
    }

    public void onActorNameChange(Actor actor, Change change) {
    }

    public void onActorStatusChange(Actor actor, Change change) {
        TreeMap<Substitution, HashSet<Long>> substitutors = actorToSubstitutorsCache.get(actor.getId());
        if (substitutors == null) {
            // status change: active -> inactive OR new actor has been created
            if (!actor.isActive()) {
                loadCacheFor(actor.getId());
            }
        } else {
            // status change: inactive -> active OR actor deletion
            if (actor.isActive() || change == Change.DELETE) {
                for (Map.Entry<Substitution, HashSet<Long>> entry : substitutors.entrySet()) {
                    if (entry.getKey() instanceof TerminatorSubstitution) {
                        continue;
                    }
                    for (Long substitutor : entry.getValue()) {
                        HashSet<Long> substituted = actorToSubstitutedCache.get(substitutor);
                        substituted.remove(actor.getId());
                    }
                }
                actorToSubstitutorsCache.remove(actor.getId());
            }
        }
    }

    @Override
    public CacheImplementation unlock() {
        return null;
    }

    @Override
    public boolean onChange(ChangedObjectParameter changedObject) {
        return false;
    }
}