package org.dcache.pool.migration;
import com.google.common.collect.ImmutableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
import diskCacheV111.vehicles.PoolManagerPoolInformation;
import org.dcache.util.expression.Expression;
/**
* RefreshablePoolList decorator that can filter the list of pools.
*/
public class PoolListFilter implements RefreshablePoolList
{
private static final Logger _log =
LoggerFactory.getLogger(PoolListFilter.class);
private final Collection<Pattern> _exclude;
private final Expression _excludeWhen;
private final Collection<Pattern> _include;
private final Expression _includeWhen;
private final RefreshablePoolList _sourceList;
private final RefreshablePoolList _poolList;
private ImmutableList<PoolManagerPoolInformation> _cachedList;
private ImmutableList<PoolManagerPoolInformation> _filteredList;
private ImmutableList<String> _cachedOfflinePools;
private ImmutableList<String> _filteredOfflinePools;
public PoolListFilter(RefreshablePoolList poolList,
Collection<Pattern> exclude,
Expression excludeWhen,
Collection<Pattern> include,
Expression includeWhen,
RefreshablePoolList sourceList)
{
_poolList = poolList;
_exclude = exclude;
_excludeWhen = excludeWhen;
_include = include;
_includeWhen = includeWhen;
_sourceList = sourceList;
}
@Override
public boolean isValid()
{
return _sourceList.isValid() && !_sourceList.getPools().isEmpty() && _poolList.isValid();
}
@Override
public void refresh()
{
_poolList.refresh();
}
@Override
public ImmutableList<String> getOfflinePools()
{
if (!isValid()) {
return ImmutableList.of();
}
PoolManagerPoolInformation source = getSource();
if (source == null) {
return ImmutableList.of();
}
ImmutableList<String> pools = _poolList.getOfflinePools();
if (!pools.equals(_cachedOfflinePools)) {
ImmutableList.Builder<String> filteredOfflinePools =
ImmutableList.builder();
for (String pool: pools) {
if (!isExcluded(source, pool) && isIncluded(source, pool)) {
filteredOfflinePools.add(pool);
}
}
_filteredOfflinePools = filteredOfflinePools.build();
}
_cachedOfflinePools = pools;
return _filteredOfflinePools;
}
@Override
public synchronized
ImmutableList<PoolManagerPoolInformation> getPools()
{
if (!isValid()) {
return ImmutableList.of();
}
PoolManagerPoolInformation source = getSource();
if (source == null) {
return ImmutableList.of();
}
ImmutableList<PoolManagerPoolInformation> list = _poolList.getPools();
if (!list.equals(_cachedList)) {
ImmutableList.Builder<PoolManagerPoolInformation> filteredList =
ImmutableList.builder();
for (PoolManagerPoolInformation pool: list) {
if (!isExcluded(source, pool) && isIncluded(source, pool)) {
filteredList.add(pool);
}
}
_filteredList = filteredList.build();
}
_cachedList = list;
return _filteredList;
}
private boolean matchesAny(Collection<Pattern> patterns, String s)
{
for (Pattern pattern: patterns) {
if (pattern.matcher(s).matches()) {
return true;
}
}
return false;
}
private boolean isExcluded(PoolManagerPoolInformation source, String pool)
{
return matchesAny(_exclude, pool);
}
private boolean isIncluded(PoolManagerPoolInformation source, String pool)
{
return _include.isEmpty() || matchesAny(_include, pool);
}
private boolean isExcluded(PoolManagerPoolInformation source, PoolManagerPoolInformation pool)
{
if (matchesAny(_exclude, pool.getName())) {
return true;
}
return evaluate(_excludeWhen, source, pool);
}
private boolean isIncluded(PoolManagerPoolInformation source, PoolManagerPoolInformation pool)
{
if (!_include.isEmpty()) {
return matchesAny(_include, pool.getName());
}
return evaluate(_includeWhen, source, pool);
}
private PoolManagerPoolInformation getSource()
{
List<PoolManagerPoolInformation> list = _sourceList.getPools();
if (list.isEmpty()) {
return null;
}
if (list.size() > 1) {
throw new IllegalStateException("Unexpected source pool list: Exactly one item was expected, but it contained " + list.size());
}
return list.get(0);
}
private boolean evaluate(Expression expression,
PoolManagerPoolInformation source,
PoolManagerPoolInformation pool)
{
SymbolTable symbols = new SymbolTable();
symbols.put(MigrationModule.CONSTANT_TARGET, pool);
symbols.put(MigrationModule.CONSTANT_SOURCE, source);
return expression.evaluateBoolean(symbols);
}
@Override
public String toString()
{
List<PoolManagerPoolInformation> pools = getPools();
if (pools.isEmpty()) {
return "";
}
StringBuilder s = new StringBuilder();
s.append(pools.get(0).getName());
for (int i = 1; i < pools.size(); i++) {
s.append(',').append(pools.get(i).getName());
}
return s.toString();
}
}