001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.datatransfer;
003
004import java.awt.datatransfer.DataFlavor;
005import java.awt.datatransfer.Transferable;
006import java.awt.datatransfer.UnsupportedFlavorException;
007import java.io.IOException;
008import java.util.Arrays;
009import java.util.Collection;
010import java.util.Collections;
011
012import org.openstreetmap.josm.data.coor.EastNorth;
013import org.openstreetmap.josm.data.osm.OsmPrimitive;
014import org.openstreetmap.josm.gui.MainApplication;
015import org.openstreetmap.josm.gui.datatransfer.importers.AbstractOsmDataPaster;
016import org.openstreetmap.josm.gui.datatransfer.importers.FilePaster;
017import org.openstreetmap.josm.gui.datatransfer.importers.OsmLinkPaster;
018import org.openstreetmap.josm.gui.datatransfer.importers.PrimitiveDataPaster;
019import org.openstreetmap.josm.gui.datatransfer.importers.PrimitiveTagTransferPaster;
020import org.openstreetmap.josm.gui.datatransfer.importers.TagTransferPaster;
021import org.openstreetmap.josm.gui.datatransfer.importers.TextTagPaster;
022import org.openstreetmap.josm.gui.layer.OsmDataLayer;
023import org.openstreetmap.josm.tools.Logging;
024
025/**
026 * This transfer handler provides the ability to transfer OSM data. It allows you to receive files, primitives or tags.
027 * @author Michael Zangl
028 * @since 10604
029 */
030public class OsmTransferHandler extends AbstractStackTransferHandler {
031
032    private static final Collection<AbstractOsmDataPaster> SUPPORTED = Arrays.asList(
033            new FilePaster(), new PrimitiveDataPaster(),
034            new PrimitiveTagTransferPaster(),
035            new TagTransferPaster(), new OsmLinkPaster(), new TextTagPaster());
036
037    @Override
038    protected Collection<AbstractOsmDataPaster> getSupportedPasters() {
039        return Collections.unmodifiableCollection(SUPPORTED);
040    }
041
042    private boolean importTags(TransferSupport support, Collection<? extends OsmPrimitive> primitives) {
043        for (AbstractOsmDataPaster df : SUPPORTED) {
044            if (df.supports(support)) {
045                try {
046                    if (df.importTagsOn(support, primitives)) {
047                        return true;
048                    }
049                } catch (UnsupportedFlavorException | IOException e) {
050                    Logging.warn(e);
051                }
052            }
053        }
054        return super.importData(support);
055    }
056
057    /**
058     * Paste the current clipboard current at the given position
059     * @param editLayer The layer to paste on.
060     * @param mPosition The position to paste at. If it is <code>null</code>, the original position will be used.
061     */
062    public void pasteOn(OsmDataLayer editLayer, EastNorth mPosition) {
063        Transferable transferable = ClipboardUtils.getClipboardContent();
064        pasteOn(editLayer, mPosition, transferable);
065    }
066
067    /**
068     * Paste the given clipboard current at the given position
069     * @param editLayer The layer to paste on.
070     * @param mPosition The position to paste at. If it is <code>null</code>, the original position will be used.
071     * @param transferable The transferable to use.
072     */
073    public void pasteOn(OsmDataLayer editLayer, EastNorth mPosition, Transferable transferable) {
074        importData(new TransferSupport(MainApplication.getMainPanel(), transferable), editLayer, mPosition);
075    }
076
077    /**
078     * Paste the given tags on the primitives.
079     * @param primitives The primitives to paste on.
080     */
081    public void pasteTags(Collection<? extends OsmPrimitive> primitives) {
082        Transferable transferable = ClipboardUtils.getClipboardContent();
083        importTags(new TransferSupport(MainApplication.getMainPanel(), transferable), primitives);
084    }
085
086    /**
087     * Check if any primitive data or any other supported data is available in the clipboard.
088     * @return <code>true</code> if any flavor is supported.
089     */
090    public boolean isDataAvailable() {
091        try {
092            Collection<DataFlavor> available = Arrays.asList(ClipboardUtils.getClipboard().getAvailableDataFlavors());
093            for (AbstractOsmDataPaster s : SUPPORTED) {
094                if (s.supports(available)) {
095                    return true;
096                }
097            }
098        } catch (IllegalStateException e) {
099            Logging.debug(e);
100        } catch (NullPointerException e) { // NOPMD
101            // JDK-6322854: On Linux/X11, NPE can happen for unknown reasons, on all versions of Java
102            Logging.error(e);
103        }
104        return false;
105    }
106}