package org.jbehave.eclipse.cache.container;
import static org.jbehave.eclipse.cache.container.Containers.wrapMonitorForRecursive;
import java.util.ArrayList;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.jbehave.eclipse.cache.container.Containers.Factory;
import org.jbehave.eclipse.util.New;
import org.jbehave.eclipse.util.Visitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HierarchicalContainer<E> extends Container<E> {
private Logger log = LoggerFactory.getLogger(HierarchicalContainer.class);
private final ConcurrentMap<String, Container<E>> children = New.concurrentHashMap();
public HierarchicalContainer(String containerName) {
super(containerName);
}
@Override
public void clear() {
children.clear();
}
@Override
public void add(E element) {
throw new IllegalStateException();
}
@Override
public void recursivelyRemoveBuildOlderThan(int buildTick, IProgressMonitor monitor) {
ArrayList<Entry<String, Container<E>>> elems = New.arrayList(children.entrySet());
monitor.beginTask("", elems.size());
int removed = 0;
int remaining = 0;
for (Entry<String, Container<E>> e : elems) {
Container<E> child = e.getValue();
if (child.getLastBuildTick() < buildTick) {
removed++;
children.remove(e.getKey());
} else {
remaining++;
child.recursivelyRemoveBuildOlderThan(buildTick, wrapMonitorForRecursive(monitor));
}
monitor.worked(1);
}
monitor.done();
log.debug("Unsed #" + removed + " removed (#"+remaining+" remaining) in " + containerName);
}
@Override
public void traverse(Visitor<E, ?> visitor) {
for (Container<E> child : children.values()) {
child.traverse(visitor);
if (visitor.isDone())
return;
}
}
@Override
public Container<E> specializeFor(IPackageFragmentRoot pkgFragmentRoot) {
int kind;
try {
kind = pkgFragmentRoot.getKind();
} catch (JavaModelException e) {
log.error("Failed to retrieve kind of " + Containers.pathOf(pkgFragmentRoot), e);
kind = IPackageFragmentRoot.K_BINARY;
}
Factory<E> factory;
if (kind == IPackageFragmentRoot.K_SOURCE) {
factory = Containers.hierarchicalFactory();
} else {
factory = Containers.flatFactory();
}
return specializeFor(pkgFragmentRoot, factory);
}
@Override
public Container<E> specializeFor(IPackageFragment pkgFragment) {
Factory<E> factory = Containers.hierarchicalFactory();
return specializeFor(pkgFragment, factory);
}
@Override
public Container<E> specializeFor(ICompilationUnit cunit) {
Factory<E> factory = Containers.flatFactory();
return specializeFor(cunit, factory);
}
protected Container<E> specializeFor(IJavaElement javaElement, Factory<E> factory) {
String path = javaElement.getPath().toString();
Container<E> container = children.get(path);
if (container == null) {
Container<E> newContainer = factory.create(path);
container = children.putIfAbsent(path, newContainer);
if (container == null)
container = newContainer;
}
return container;
}
}