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 = 0; 035 if (api.getCapabilities().isDefined("waynodes", "maximum")) { 036 maxNodes = api.getCapabilities().getLong("waynodes","maximum"); 037 } 038 if (maxNodes > 0) { 039 if( !checkMaxNodes(apiData.getPrimitivesToAdd(), maxNodes)) 040 return false; 041 if( !checkMaxNodes(apiData.getPrimitivesToUpdate(), maxNodes)) 042 return false; 043 if( !checkMaxNodes(apiData.getPrimitivesToDelete(), maxNodes)) 044 return false; 045 } 046 } catch (OsmTransferCanceledException e) { 047 return false; 048 } catch (OsmApiInitializationException e) { 049 ExceptionDialogUtil.explainOsmTransferException(e); 050 return false; 051 } 052 return true; 053 } 054 055 private boolean checkMaxNodes(Collection<OsmPrimitive> primitives, long maxNodes) { 056 for (OsmPrimitive osmPrimitive : primitives) { 057 for (String key: osmPrimitive.keySet()) { 058 String value = osmPrimitive.get(key); 059 if (key.length() > 255) { 060 if (osmPrimitive.isDeleted()) { 061 // if OsmPrimitive is going to be deleted we automatically shorten the value 062 Main.warn( 063 tr("Automatically truncating value of tag ''{0}'' on deleted object {1}", 064 key, 065 Long.toString(osmPrimitive.getId()) 066 ) 067 ); 068 osmPrimitive.put(key, value.substring(0, 255)); 069 continue; 070 } 071 JOptionPane.showMessageDialog(Main.parent, 072 tr("Length of value for tag ''{0}'' on object {1} exceeds the max. allowed length {2}. Values length is {3}.", 073 key, Long.toString(osmPrimitive.getId()), 255, value.length() 074 ), 075 tr("Precondition Violation"), 076 JOptionPane.ERROR_MESSAGE 077 ); 078 Main.main.getCurrentDataSet().setSelected(Collections.singleton(osmPrimitive)); 079 return false; 080 } 081 } 082 083 if (osmPrimitive instanceof Way && 084 ((Way)osmPrimitive).getNodesCount() > maxNodes) { 085 JOptionPane.showMessageDialog( 086 Main.parent, 087 tr("{0} nodes in way {1} exceed the max. allowed number of nodes {2}", 088 ((Way)osmPrimitive).getNodesCount(), 089 Long.toString(osmPrimitive.getId()), 090 maxNodes 091 ), 092 tr("API Capabilities Violation"), 093 JOptionPane.ERROR_MESSAGE 094 ); 095 Main.main.getCurrentDataSet().setSelected(Collections.singleton(osmPrimitive)); 096 return false; 097 } 098 } 099 return true; 100 } 101}