/* Copyright (c) 2014 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Justin Deoliveira (Boundless) - initial implementation
*/
package org.locationtech.geogig.storage.sqlite;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.PriorityQueue;
import org.locationtech.geogig.api.ObjectId;
import com.google.common.collect.Maps;
/**
* Walks a shortest path between two nodes applying Dijkstra's algorithm.
*
* @author Justin Deoliveira, Boundless
*
* @param <C> Connection type.
*/
public class ShortestPathWalker<T> implements Iterator<ObjectId> {
final ObjectId start;
final ObjectId end;
final SQLiteGraphDatabase<T> graph;
final T cx;
final Map<String, Node> nodes;
final PriorityQueue<Node> q;
ShortestPathWalker(ObjectId start, ObjectId end, SQLiteGraphDatabase<T> graph, T cx) {
this.start = start;
this.end = end;
this.graph = graph;
this.cx = cx;
nodes = Maps.newHashMap();
q = new PriorityQueue<Node>(100, new Comparator<Node>() {
@Override
public int compare(Node o1, Node o2) {
return o1.cost.compareTo(o2.cost);
}
});
q.offer(newNode(start.toString(), 0d));
}
Node newNode(String id, Double cost) {
Node n = new Node(id, cost);
nodes.put(id, n);
return n;
}
@Override
public boolean hasNext() {
return !q.isEmpty();
}
@Override
public ObjectId next() {
// grab next node
Node n = q.poll();
// update the adjacent nodes
for (String adj : graph.outgoing(n.id, cx)) {
Node m = nodes.get(adj);
Double cost = n.cost + 1;
if (m == null) {
m = newNode(adj, cost);
q.offer(m);
} else {
if (cost < m.cost) {
// update the node
m.cost = cost;
q.remove(m);
q.offer(m);
}
}
}
return ObjectId.valueOf(n.id);
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
static class Node {
String id;
Double cost = Double.MAX_VALUE;
Node(String id, Double cost) {
this.id = id;
this.cost = cost;
}
}
}