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}