// License: GPL. For details, see LICENSE file. package public_transport; import static org.openstreetmap.josm.tools.I18n.tr; import java.util.Iterator; import java.util.Vector; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.DefaultTableModel; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.DataSource; import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.data.osm.DataSet; import org.openstreetmap.josm.data.osm.Node; public class GTFSStopTableModel extends DefaultTableModel implements TableModelListener { private GTFSImporterAction controller = null; public Vector<Node> nodes = new Vector<>(); public Vector<LatLon> coors = new Vector<>(); private int idCol = -1; private int nameCol = -1; private int latCol = -1; private int lonCol = -1; private char separator = ','; public GTFSStopTableModel(GTFSImporterAction controller, String columnConfig) { int pos = columnConfig.indexOf(separator); if (pos == -1) { separator = ';'; pos = columnConfig.indexOf(separator); } if (pos == -1) { separator = '\t'; pos = columnConfig.indexOf(separator); } int oldPos = 0; int i = 0; while (pos > -1) { String title = stripQuot(columnConfig.substring(oldPos, pos)); if ("stop_id".equals(title)) idCol = i; else if ("stop_name".equals(title)) nameCol = i; else if ("stop_lat".equals(title)) latCol = i; else if ("stop_lon".equals(title)) lonCol = i; ++i; oldPos = pos + 1; pos = columnConfig.indexOf(separator, oldPos); } String title = columnConfig.substring(oldPos); if ("stop_id".equals(title)) idCol = i; else if ("stop_name".equals(title)) nameCol = i; else if ("stop_lat".equals(title)) latCol = i; else if ("stop_lon".equals(title)) lonCol = i; this.controller = controller; addColumn(tr("Id")); addColumn(tr("Name")); addColumn(tr("State")); addTableModelListener(this); } @Override public boolean isCellEditable(int row, int column) { return false; } @Override public void addRow(Object[] obj) { throw new UnsupportedOperationException(); } @Override public void insertRow(int insPos, Object[] obj) { throw new UnsupportedOperationException(); } public void addRow(String s) { insertRow(-1, s, new Vector<Node>()); } public void addRow(String s, Vector<Node> existingStops) { insertRow(-1, s, existingStops); } /** * tokenizes a line as follows: any comma outside a pair of double quotation marks is taken as field separator. * In particular, neither \" nor \, have a special meaning. Returns the position of the next field separator, if any. * Otherwise it returns -1. s - the string to tokenize. startPos * - the position of the last field separator plus 1 or the value 0. */ private int tokenize(String s, int startPos) { int pos = startPos; boolean insideDoubleQuoted = false; while (pos < s.length()) { if ('"' == s.charAt(pos)) insideDoubleQuoted = !insideDoubleQuoted; else if ((separator == s.charAt(pos)) && (!insideDoubleQuoted)) break; ++pos; } if (pos < s.length()) return pos; else return -1; } private String stripQuot(String s) { int pos = s.indexOf('"'); while (pos > -1) { s = s.substring(0, pos) + s.substring(pos + 1); pos = s.indexOf('"'); } return s; } public void insertRow(int insPos, String s, Vector<Node> existingStops) { String[] buf = {"", "", tr("pending")}; int pos = tokenize(s, 0); int oldPos = 0; int i = 0; double lat = 0; double lon = 0; while (pos > -1) { if (i == idCol) buf[0] = stripQuot(s.substring(oldPos, pos)); else if (i == nameCol) buf[1] = stripQuot(s.substring(oldPos, pos)); else if (i == latCol) lat = Double.parseDouble(stripQuot(s.substring(oldPos, pos))); else if (i == lonCol) lon = Double.parseDouble(stripQuot(s.substring(oldPos, pos))); ++i; oldPos = pos + 1; pos = tokenize(s, oldPos); } if (i == idCol) buf[0] = stripQuot(s.substring(oldPos)); else if (i == nameCol) buf[1] = stripQuot(s.substring(oldPos)); else if (i == latCol) lat = Double.parseDouble(stripQuot(s.substring(oldPos))); else if (i == lonCol) lon = Double.parseDouble(stripQuot(s.substring(oldPos))); LatLon coor = new LatLon(lat, lon); DataSet ds = Main.getLayerManager().getEditDataSet(); if (ds != null) { boolean inside = false; Iterator<DataSource> iter = ds.getDataSources().iterator(); while (iter.hasNext()) { if (iter.next().bounds.contains(coor)) { inside = true; break; } } if (!inside) buf[2] = tr("outside"); } boolean nearBusStop = false; Iterator<Node> iter = existingStops.iterator(); while (iter.hasNext()) { Node node = iter.next(); if (coor.greatCircleDistance(node.getCoor()) < 1000) { nearBusStop = true; break; } } if (insPos == -1) { if ((nearBusStop) || !(tr("pending").equals(buf[2]))) nodes.addElement(null); else { Node node = GTFSImporterAction.createNode(coor, buf[0], buf[1]); nodes.addElement(node); buf[2] = tr("added"); } coors.addElement(coor); super.addRow(buf); } else { if ((nearBusStop) || !(tr("pending").equals(buf[2]))) nodes.insertElementAt(null, insPos); else { Node node = GTFSImporterAction.createNode(coor, buf[0], buf[1]); nodes.insertElementAt(node, insPos); buf[2] = tr("added"); } coors.insertElementAt(coor, insPos); super.insertRow(insPos, buf); } } public void clear() { nodes.clear(); super.setRowCount(0); } @Override public void tableChanged(TableModelEvent e) { } }