/* 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, either version 3 of
the License, or (at your option) any later version.
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package org.opentripplanner.routing.spt;
import java.util.ArrayList;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.opentripplanner.common.MavenVersion;
import org.opentripplanner.routing.core.State;
import org.opentripplanner.routing.core.RoutingRequest;
import org.opentripplanner.routing.graph.AbstractVertex;
import org.opentripplanner.routing.graph.Vertex;
public class ArrayMultiShortestPathTree extends AbstractShortestPathTree {
private static final long serialVersionUID = MavenVersion.VERSION.getUID();
public static final ShortestPathTreeFactory FACTORY = new FactoryImpl();
private Map<Vertex, List<State>> stateSets;
private List<State>[] stateSetArray;
private int maxIndex;
@SuppressWarnings("unchecked")
public ArrayMultiShortestPathTree(RoutingRequest options) {
super(options);
stateSets = new IdentityHashMap<Vertex, List<State>>();
maxIndex = AbstractVertex.getMaxIndex();
stateSetArray = new List[maxIndex];
}
public Set<Vertex> getVertices() {
throw new UnsupportedOperationException();
}
/****
* {@link ShortestPathTree} Interface
****/
@Override
public boolean add(State newState) {
Vertex vertex = newState.getVertex();
int index = vertex.getIndex();
List<State> states;
if (index < maxIndex) {
states = stateSetArray[index];
if (states == null) {
states = new ArrayList<State>();
stateSetArray[index] = states;
states.add(newState);
return true;
}
} else {
states = stateSets.get(vertex);
if (states == null) {
states = new ArrayList<State>();
stateSets.put(vertex, states);
states.add(newState);
return true;
}
}
Iterator<State> it = states.iterator();
while (it.hasNext()) {
State oldState = it.next();
// order is important, because in the case of a tie
// we want to reject the new state
if (oldState.dominates(newState))
return false;
if (newState.dominates(oldState))
it.remove();
}
states.add(newState);
return true;
}
@Override
public State getState(Vertex dest) {
List<State> states = getStates(dest);
if (states == null)
return null;
State ret = null;
for (State s : states) {
if ((ret == null || s.betterThan(ret)) && s.isFinal() && s.allPathParsersAccept()) {
ret = s;
}
}
return ret;
}
@Override
public List<State> getStates(Vertex dest) {
int index = dest.getIndex();
if (index < maxIndex) {
return stateSetArray[index];
} else {
return stateSets.get(dest);
}
}
@Override
public int getVertexCount() {
throw new UnsupportedOperationException();
}
@Override
public boolean visit(State state) {
boolean ret = false;
for (State s : getStates(state.getVertex())) {
if (s == state) {
ret = true;
break;
}
}
return ret;
}
public String toString() {
return "MultiSPT(" + this.stateSets.size() + " vertices)";
}
private static final class FactoryImpl implements ShortestPathTreeFactory {
@Override
public ShortestPathTree create(RoutingRequest options) {
return new ArrayMultiShortestPathTree(options);
}
}
@Override
public Collection<State> getAllStates() {
ArrayList<State> allStates = new ArrayList<State>();
for (List<State> stateSet : stateSets.values()) {
allStates.addAll(stateSet);
}
for (List<State> stateSet : stateSetArray) {
if (stateSet == null) continue;
allStates.addAll(stateSet);
}
return allStates;
}
}