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

com.github.nill14.parsers.dependency.impl.DependencyGraph Maven / Gradle / Ivy

Go to download

Implementation of directed acyclic graph along with some graph algorithms and dependency management.

The newest version!
package com.github.nill14.parsers.dependency.impl;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;

import com.github.nill14.parsers.dependency.IConsumer;
import com.github.nill14.parsers.dependency.IDependencyGraph;
import com.github.nill14.parsers.graph.CyclicGraphException;
import com.github.nill14.parsers.graph.DirectedGraph;
import com.github.nill14.parsers.graph.GraphEdge;
import com.github.nill14.parsers.graph.GraphWalker;
import com.github.nill14.parsers.graph.utils.GraphWalker3;
import com.github.nill14.parsers.graph.utils.LongestPathTopoSorter;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;

class DependencyGraph implements IDependencyGraph {
	
	private final Set modules;
	private final DirectedGraph> graph;
	private final LinkedHashMap moduleRankings;
	
	private final ImmutableList topologicalOrdering;
	private final Map> dependencySets = new ConcurrentHashMap<>();
	
	public DependencyGraph(DirectedGraph> graph) throws CyclicGraphException {
		this.graph = graph;
		this.modules = graph.nodes();
		moduleRankings = new LongestPathTopoSorter<>(graph).getLongestPathMap();
		topologicalOrdering = ImmutableList.copyOf(moduleRankings.keySet());
	}
	
	public DependencyGraph(DirectedGraph> graph, Function priorityFunction) throws CyclicGraphException {
		this.graph = graph;
		this.modules = graph.nodes();
		moduleRankings = new LongestPathTopoSorter<>(graph).getLongestPathMap(priorityFunction);
		topologicalOrdering = ImmutableList.copyOf(moduleRankings.keySet());
		
	}

	
	@Override
	public DirectedGraph> getGraph() {
		return graph;
	}
	
	@Override
	public Set getModules() {
		return modules;
	}
	
	@Override
	public Set getDirectDependencies(M module) {
		return graph.predecessors(module);
	}
	
	@Override
	public Set getAllDependencies(M module) {
		if (module == null) {
			throw new NullPointerException();
		}
		
		DependencySet dependencySet = dependencySets.get(module);
		if (dependencySet == null) {
			/*
			 * I don't like sync over exposed object
			 * but this is the fastest alternative.
			 */			
			synchronized (module) {
				dependencySet = dependencySets.get(module);
				if (dependencySet == null) {
					dependencySet = new DependencySet(this, module);
					dependencySets.put(module, dependencySet);
				}
			}
		}
		return dependencySet;
	}
	
	@Override
	public List getTopologicalOrder() {
		return topologicalOrdering;
	}
	
	@Override
	public Map getModuleRankings() {
		return Maps.newLinkedHashMap(moduleRankings);
	}
	
	@Override
	public void walkGraph(final ExecutorService executor,
			final IConsumer moduleConsumer)
			throws ExecutionException {
		
		int parallelism = Runtime.getRuntime().availableProcessors();
		if (executor instanceof ThreadPoolExecutor) {
			int coreSize = ((ThreadPoolExecutor) executor).getCorePoolSize();
			int maxSize = ((ThreadPoolExecutor) executor).getMaximumPoolSize();
			
			parallelism = Math.max(parallelism, coreSize);
			parallelism = Math.min(parallelism, maxSize);
		}
		walkGraph(executor, moduleConsumer, parallelism);
	}
	
	@Override
	public void iterateTopoOrder(IConsumer moduleConsumer) throws ExecutionException {
		
		for (M module : topologicalOrdering) {
			try {
				moduleConsumer.process(module);
			} catch (Exception e) {
				throw new ExecutionException(e);
			}
		}
	}

	
	public void walkGraph(final ExecutorService executor,
			final IConsumer moduleConsumer, int parallelism)
			throws ExecutionException {
		
		final GraphWalker graphWalker = new GraphWalker3<>(graph, topologicalOrdering, parallelism);
		
		for (int i = 0; i < graphWalker.size(); i++) {
			final M module = graphWalker.releaseNext();
			executor.execute(new Runnable() {
				@Override
				public void run() {
					try {
						moduleConsumer.process(module);
						graphWalker.onComplete(module);
					} catch (Exception e) {
						graphWalker.onFailure(module, e);
					}
				}
			});
		}
		graphWalker.awaitCompletion();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy