/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onebusaway.transit_data_federation.bundle.tasks.transfer_pattern;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.onebusaway.collections.tuple.Pair;
import org.onebusaway.csv_entities.CSVLibrary;
import org.onebusaway.transit_data_federation.services.AgencyAndIdLibrary;
import org.onebusaway.transit_data_federation.services.transit_graph.StopEntry;
import org.onebusaway.transit_data_federation.services.tripplanner.TransferParent;
import org.onebusaway.transit_data_federation.services.tripplanner.TransferPattern;
public class MutableTransferPattern implements TransferPattern {
private final Map<StopEntry, Set<Entry>> _stops = new HashMap<StopEntry, Set<Entry>>();
private final Entry _root;
public MutableTransferPattern(StopEntry origin) {
_root = new Entry(origin, true, null, 0);
}
public void addPath(List<Pair<StopEntry>> path) {
if (path.isEmpty())
return;
Entry node = _root;
for (Pair<StopEntry> segment : path) {
StopEntry from = segment.getFirst();
StopEntry to = segment.getSecond();
if (node == _root) {
if (from != _root.stop)
throw new IllegalStateException();
} else {
node = node.extend(from);
}
node = node.extend(to);
}
StopEntry stop = node.stop;
Set<Entry> nodes = _stops.get(stop);
if (nodes == null) {
nodes = new HashSet<Entry>();
_stops.put(stop, nodes);
}
nodes.add(node);
}
public long writeTransferPatternsToPrintWriter(PrintWriter out, long index) {
return writeEntryToPrintWriter(_root, out, index, -1);
}
/****
* {@link TransferPattern} Interface
****/
@Override
public StopEntry getOriginStop() {
return _root.stop;
}
@Override
public Collection<TransferParent> getTransfersForStops(TransferParent root,
List<StopEntry> stops) {
List<TransferParent> paths = new ArrayList<TransferParent>();
for (StopEntry stop : stops) {
Set<Entry> entries = _stops.get(stop);
if (entries != null) {
for (Entry entry : entries)
paths.add(getTransferForEntry(entry, true, root));
}
}
return paths;
}
@Override
public Collection<TransferParent> getTransfersForAllStops(TransferParent root) {
List<TransferParent> paths = new ArrayList<TransferParent>();
for (Set<Entry> entries : _stops.values()) {
for (Entry entry : entries)
paths.add(getTransferForEntry(entry, true, root));
}
return paths;
}
@Override
public Map<StopEntry, List<TransferParent>> getTransfersForHubStops(
TransferParent root) {
return Collections.emptyMap();
}
/****
* Private Methods
*****/
private TransferParent getTransferForEntry(Entry node, boolean exitAllowed,
TransferParent root) {
if (node == null)
return root;
Entry b = node;
Entry a = node.parent;
if (a == null)
throw new IllegalStateException();
node = a.parent;
TransferParent parent = getTransferForEntry(node, false, root);
return parent.extendTree(a.stop, b.stop, exitAllowed);
}
private long writeEntryToPrintWriter(Entry entry, PrintWriter out,
long index, long parentIndex) {
String line = null;
String stopId = AgencyAndIdLibrary.convertToString(entry.stop.getId());
Set<Entry> endpoints = _stops.get(entry.stop);
String endpoint = (endpoints != null && endpoints.contains(entry)) ? "1"
: "0";
if (entry.parent != null)
line = CSVLibrary.getAsCSV(index, stopId, endpoint, parentIndex);
else
line = CSVLibrary.getAsCSV(index, stopId, endpoint);
out.println(line);
parentIndex = index;
index++;
for (Entry child : entry._children.values())
index = writeEntryToPrintWriter(child, out, index, parentIndex);
return index;
}
private static class Entry {
private final StopEntry stop;
private final boolean transfer;
private final Map<StopEntry, Entry> _children = new HashMap<StopEntry, MutableTransferPattern.Entry>();
private final Entry parent;
private final int depth;
public Entry(StopEntry stop, boolean transfer, Entry parent, int depth) {
if (stop == null)
throw new IllegalArgumentException();
this.stop = stop;
this.transfer = transfer;
this.parent = parent;
this.depth = depth;
}
public Entry extend(StopEntry from) {
Entry node = _children.get(from);
if (node == null) {
node = new Entry(from, !this.transfer, this, depth + 1);
_children.put(from, node);
}
return node;
}
@Override
public String toString() {
return stop.getId() + " " + transfer;
}
}
}