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.util.ArrayList;
008import java.util.Arrays;
009import java.util.List;
010
011import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
012import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
013import org.openstreetmap.josm.data.osm.PrimitiveData;
014import org.openstreetmap.josm.gui.datatransfer.data.OsmLayerTransferData;
015import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTagTransferData;
016import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData;
017import org.openstreetmap.josm.gui.datatransfer.data.TagTransferData;
018import org.openstreetmap.josm.gui.layer.OsmDataLayer;
019
020/**
021 * Transferable objects for {@link PrimitiveTransferData} objects
022 * @since 9369
023 * @since 10604 Complete rework
024 */
025public class PrimitiveTransferable implements Transferable {
026
027    /**
028     * The flavors that are available for normal primitives.
029     */
030    private static final List<DataFlavor> PRIMITIVE_FLAVORS = Arrays.asList(PrimitiveTransferData.DATA_FLAVOR,
031            TagTransferData.FLAVOR, DataFlavor.stringFlavor);
032    private final PrimitiveTransferData primitives;
033    private final OsmDataLayer sourceLayer;
034
035    /**
036     * Constructs a new {@code PrimitiveTransferable}.
037     * @param primitives collection of OSM primitives
038     */
039    public PrimitiveTransferable(PrimitiveTransferData primitives) {
040        this(primitives, null);
041    }
042
043    /**
044     * Constructs a new {@code PrimitiveTransferable}.
045     * @param primitives collection of OSM primitives
046     * @param sourceLayer The layer the primitives are copied from
047     */
048    public PrimitiveTransferable(PrimitiveTransferData primitives, OsmDataLayer sourceLayer) {
049        this.primitives = primitives;
050        this.sourceLayer = sourceLayer;
051    }
052
053    @Override
054    public DataFlavor[] getTransferDataFlavors() {
055        ArrayList<DataFlavor> flavors = new ArrayList<>(PRIMITIVE_FLAVORS);
056        if (sourceLayer != null) {
057            flavors.addAll(OsmLayerTransferData.FLAVORS);
058        }
059        return flavors.toArray(new DataFlavor[0]);
060    }
061
062    @Override
063    public boolean isDataFlavorSupported(DataFlavor flavor) {
064        DataFlavor[] flavors = getTransferDataFlavors();
065        return Arrays.stream(flavors)
066                .anyMatch(flavor::equals);
067    }
068
069    @Override
070    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
071        if (DataFlavor.stringFlavor.equals(flavor)) {
072            return getStringData();
073        } else if (PrimitiveTransferData.DATA_FLAVOR.equals(flavor)) {
074            return primitives;
075        } else if (PrimitiveTagTransferData.FLAVOR.equals(flavor)) {
076            return new PrimitiveTagTransferData(primitives);
077        } else if (TagTransferData.FLAVOR.equals(flavor)) {
078            return new TagTransferData(primitives.getDirectlyAdded());
079        } else if (sourceLayer != null && OsmLayerTransferData.FLAVORS.contains(flavor)) {
080            return new OsmLayerTransferData(null, sourceLayer);
081        } else {
082            throw new UnsupportedFlavorException(flavor);
083        }
084    }
085
086    protected String getStringData() {
087        final StringBuilder sb = new StringBuilder();
088        for (PrimitiveData primitive : primitives.getDirectlyAdded()) {
089            if (sb.length() > 0) {
090                sb.append('\n');
091            }
092            sb.append(OsmPrimitiveType.from(primitive).getAPIName()).append(' ').append(primitive.getId());
093        }
094        return DefaultNameFormatter.removeBiDiCharacters(sb.toString());
095    }
096}