001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions.upload; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.util.Collection; 007import java.util.Collections; 008 009import javax.swing.JOptionPane; 010 011import org.openstreetmap.josm.Main; 012import org.openstreetmap.josm.data.APIDataSet; 013import org.openstreetmap.josm.data.osm.OsmPrimitive; 014import org.openstreetmap.josm.data.osm.Way; 015import org.openstreetmap.josm.gui.ExceptionDialogUtil; 016import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 017import org.openstreetmap.josm.io.OnlineResource; 018import org.openstreetmap.josm.io.OsmApi; 019import org.openstreetmap.josm.io.OsmApiInitializationException; 020import org.openstreetmap.josm.io.OsmTransferCanceledException; 021 022public class ApiPreconditionCheckerHook implements UploadHook { 023 024 @Override 025 public boolean checkUpload(APIDataSet apiData) { 026 OsmApi api = OsmApi.getOsmApi(); 027 try { 028 if (Main.isOffline(OnlineResource.OSM_API)) { 029 return false; 030 } 031 // FIXME: this should run asynchronously and a progress monitor 032 // should be displayed. 033 api.initialize(NullProgressMonitor.INSTANCE); 034 long maxNodes = api.getCapabilities().getMaxWayNodes(); 035 if (maxNodes > 0) { 036 if (!checkMaxNodes(apiData.getPrimitivesToAdd(), maxNodes)) 037 return false; 038 if (!checkMaxNodes(apiData.getPrimitivesToUpdate(), maxNodes)) 039 return false; 040 if (!checkMaxNodes(apiData.getPrimitivesToDelete(), maxNodes)) 041 return false; 042 } 043 } catch (OsmTransferCanceledException e) { 044 Main.trace(e); 045 return false; 046 } catch (OsmApiInitializationException e) { 047 ExceptionDialogUtil.explainOsmTransferException(e); 048 return false; 049 } 050 return true; 051 } 052 053 private static boolean checkMaxNodes(Collection<OsmPrimitive> primitives, long maxNodes) { 054 for (OsmPrimitive osmPrimitive : primitives) { 055 for (String key: osmPrimitive.keySet()) { 056 String value = osmPrimitive.get(key); 057 if (key.length() > 255) { 058 if (osmPrimitive.isDeleted()) { 059 // if OsmPrimitive is going to be deleted we automatically shorten the value 060 Main.warn( 061 tr("Automatically truncating value of tag ''{0}'' on deleted object {1}", 062 key, 063 Long.toString(osmPrimitive.getId()) 064 ) 065 ); 066 osmPrimitive.put(key, value.substring(0, 255)); 067 continue; 068 } 069 JOptionPane.showMessageDialog(Main.parent, 070 tr("Length of value for tag ''{0}'' on object {1} exceeds the max. allowed length {2}. Values length is {3}.", 071 key, Long.toString(osmPrimitive.getId()), 255, value.length() 072 ), 073 tr("Precondition Violation"), 074 JOptionPane.ERROR_MESSAGE 075 ); 076 Main.getLayerManager().getEditDataSet().setSelected(Collections.singleton(osmPrimitive)); 077 return false; 078 } 079 } 080 081 if (osmPrimitive instanceof Way && 082 ((Way) osmPrimitive).getNodesCount() > maxNodes) { 083 JOptionPane.showMessageDialog( 084 Main.parent, 085 tr("{0} nodes in way {1} exceed the max. allowed number of nodes {2}", 086 ((Way) osmPrimitive).getNodesCount(), 087 Long.toString(osmPrimitive.getId()), 088 maxNodes 089 ), 090 tr("API Capabilities Violation"), 091 JOptionPane.ERROR_MESSAGE 092 ); 093 Main.getLayerManager().getEditDataSet().setSelected(Collections.singleton(osmPrimitive)); 094 return false; 095 } 096 } 097 return true; 098 } 099}