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