// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.actions.upload;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Iterator;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.APIDataSet;
import org.openstreetmap.josm.data.osm.Relation;
import org.openstreetmap.josm.gui.ExtendedDialog;
import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
import org.openstreetmap.josm.tools.WindowGeometry;
/**
* This upload hook reorders the list of new relations to upload such that child
* relations are uploaded before parent relations. It also checks for cyclic
* dependencies in the list of new relations.
*
*
*/
public class RelationUploadOrderHook implements UploadHook {
/**
* builds the panel which warns users about a cyclic dependency
*
* @param dep the list of relations with a cyclic dependency
* @return the panel
*/
protected JPanel buildWarningPanel(List<Relation> dep) {
JPanel pnl = new JPanel();
pnl.setLayout(new BorderLayout());
String msg = tr("<html>{0} relations build a cycle because they refer to each other.<br>"
+ "JOSM cannot upload them. Please edit the relations and remove the "
+ "cyclic dependency.</html>", dep.size()-1);
pnl.add(new JLabel(msg), BorderLayout.NORTH);
DefaultTableModel model = new DefaultTableModel();
model.addColumn(tr("Relation ..."));
model.addColumn(tr("... refers to relation"));
for (int i=0; i<dep.size()-1;i++) {
Relation r1 = dep.get(i);
Relation r2 = dep.get(i+1);
model.addRow(new Relation[] {r1,r2});
}
JTable tbl = new JTable(model);
OsmPrimitivRenderer renderer = new OsmPrimitivRenderer();
tbl.getColumnModel().getColumn(0).setCellRenderer(renderer);
tbl.getColumnModel().getColumn(1).setCellRenderer(renderer);
pnl.add(new JScrollPane(tbl), BorderLayout.CENTER);
return pnl;
}
/**
* Warns the user if a cyclic dependency is detected
*
* @param e the cyclic dependency exception
*/
protected void warnCyclicUploadDependency(CyclicUploadDependencyException e) {
List<Relation> dep = e.getCyclicUploadDependency();
Relation last = dep.get(dep.size() -1);
Iterator<Relation> it = dep.iterator();
while(it.hasNext()) {
if (it.next() != last) {
it.remove();
} else {
break;
}
}
JPanel pnl = buildWarningPanel(dep);
ExtendedDialog dialog = new ExtendedDialog(
Main.parent,
tr("Cycling dependencies"),
new String[] {tr("OK")}
);
dialog.setContent(pnl, false /* don't embed in scroll pane */);
dialog.setButtonIcons(new String[] {"ok"});
dialog.setRememberWindowGeometry(
getClass().getName() + ".geometry",
WindowGeometry.centerInWindow(Main.parent, new Dimension(300, 300))
);
dialog.showDialog();
}
@Override
public boolean checkUpload(APIDataSet apiDataSet) {
try {
apiDataSet.adjustRelationUploadOrder();
return true;
} catch(CyclicUploadDependencyException e) {
warnCyclicUploadDependency(e);
return false;
}
}
}