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