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; 008import java.util.Map; 009 010import javax.swing.JOptionPane; 011 012import org.openstreetmap.josm.data.APIDataSet; 013import org.openstreetmap.josm.data.osm.OsmPrimitive; 014import org.openstreetmap.josm.data.osm.Tagged; 015import org.openstreetmap.josm.data.osm.Way; 016import org.openstreetmap.josm.gui.ExceptionDialogUtil; 017import org.openstreetmap.josm.gui.MainApplication; 018import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 019import org.openstreetmap.josm.io.NetworkManager; 020import org.openstreetmap.josm.io.OnlineResource; 021import org.openstreetmap.josm.io.OsmApi; 022import org.openstreetmap.josm.io.OsmApiInitializationException; 023import org.openstreetmap.josm.io.OsmTransferCanceledException; 024import org.openstreetmap.josm.tools.Logging; 025 026/** 027 * Checks certain basic conditions, that are listed in the OSM API 028 * {@link org.openstreetmap.josm.io.Capabilities}. 029 */ 030public class ApiPreconditionCheckerHook implements UploadHook { 031 032 @Override 033 public boolean checkUpload(APIDataSet apiData) { 034 OsmApi api = OsmApi.getOsmApi(); 035 try { 036 if (NetworkManager.isOffline(OnlineResource.OSM_API)) { 037 return false; 038 } 039 // FIXME: this should run asynchronously and a progress monitor 040 // should be displayed. 041 api.initialize(NullProgressMonitor.INSTANCE); 042 long maxNodes = api.getCapabilities().getMaxWayNodes(); 043 if (maxNodes > 0) { 044 if (!checkMaxNodes(apiData.getPrimitivesToAdd(), maxNodes)) 045 return false; 046 if (!checkMaxNodes(apiData.getPrimitivesToUpdate(), maxNodes)) 047 return false; 048 if (!checkMaxNodes(apiData.getPrimitivesToDelete(), maxNodes)) 049 return false; 050 } 051 } catch (OsmTransferCanceledException e) { 052 Logging.trace(e); 053 return false; 054 } catch (OsmApiInitializationException e) { 055 ExceptionDialogUtil.explainOsmTransferException(e); 056 return false; 057 } 058 return true; 059 } 060 061 private static boolean checkMaxNodes(Collection<OsmPrimitive> primitives, long maxNodes) { 062 for (OsmPrimitive osmPrimitive : primitives) { 063 for (Map.Entry<String, String> entry: osmPrimitive.getKeys().entrySet()) { 064 String key = entry.getKey(); 065 String value = entry.getValue(); 066 if (key.length() > Tagged.MAX_TAG_LENGTH) { 067 if (osmPrimitive.isDeleted()) { 068 // if OsmPrimitive is going to be deleted we automatically shorten the value 069 Logging.warn( 070 tr("Automatically truncating value of tag ''{0}'' on deleted object {1}", 071 key, 072 Long.toString(osmPrimitive.getId()) 073 ) 074 ); 075 osmPrimitive.put(key, value.substring(0, Tagged.MAX_TAG_LENGTH)); 076 continue; 077 } 078 JOptionPane.showMessageDialog(MainApplication.getMainFrame(), 079 tr("Length of value for tag ''{0}'' on object {1} exceeds the max. allowed length {2}. Values length is {3}.", 080 key, Long.toString(osmPrimitive.getId()), Tagged.MAX_TAG_LENGTH, value.length() 081 ), 082 tr("Precondition violation"), 083 JOptionPane.ERROR_MESSAGE 084 ); 085 MainApplication.getLayerManager().getEditDataSet().setSelected(Collections.singleton(osmPrimitive)); 086 return false; 087 } 088 } 089 090 if (osmPrimitive instanceof Way && 091 ((Way) osmPrimitive).getNodesCount() > maxNodes) { 092 JOptionPane.showMessageDialog( 093 MainApplication.getMainFrame(), 094 tr("{0} nodes in way {1} exceed the max. allowed number of nodes {2}", 095 ((Way) osmPrimitive).getNodesCount(), 096 Long.toString(osmPrimitive.getId()), 097 maxNodes 098 ), 099 tr("API Capabilities Violation"), 100 JOptionPane.ERROR_MESSAGE 101 ); 102 MainApplication.getLayerManager().getEditDataSet().setSelected(Collections.singleton(osmPrimitive)); 103 return false; 104 } 105 } 106 return true; 107 } 108}