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.Serializable;
008import java.util.ArrayList;
009import java.util.Arrays;
010import java.util.Collection;
011import java.util.Collections;
012import java.util.HashSet;
013import java.util.stream.Collectors;
014
015import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
016import org.openstreetmap.josm.data.osm.OsmPrimitive;
017import org.openstreetmap.josm.data.osm.RelationMember;
018import org.openstreetmap.josm.data.osm.RelationMemberData;
019import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData;
020import org.openstreetmap.josm.tools.CheckParameterUtil;
021
022/**
023 * Transferable objects for {@link RelationMemberData}.
024 * @since 9368
025 */
026public class RelationMemberTransferable implements Transferable {
027
028    /**
029     * A wrapper for a collection of {@link RelationMemberData}.
030     */
031    public static final class Data implements Serializable {
032        private static final long serialVersionUID = -8432393711635811029L;
033        private final Collection<RelationMemberData> relationMemberDatas;
034
035        private Data(Collection<RelationMemberData> primitiveData) {
036            CheckParameterUtil.ensureThat(primitiveData instanceof Serializable, "primitiveData must be instanceof Serializable");
037            this.relationMemberDatas = primitiveData;
038        }
039
040        /**
041         * Returns the contained {@link RelationMemberData}
042         * @return the contained {@link RelationMemberData}
043         */
044        public Collection<RelationMemberData> getRelationMemberData() {
045            return Collections.unmodifiableCollection(relationMemberDatas);
046        }
047
048        /**
049         * Gets the Data for the given list of members.
050         * @param members The collection. The order is preserved.
051         * @return The data.
052         */
053        public static Data getData(Collection<RelationMember> members) {
054            return new Data(members.stream()
055                    .map(m -> new RelationMemberData(m.getRole(), m.getType(), m.getUniqueId()))
056                    .collect(Collectors.toList()));
057        }
058    }
059
060    /**
061     * Data flavor for {@link RelationMemberData} which is wrapped in {@link Data}.
062     */
063    public static final DataFlavor RELATION_MEMBER_DATA = new DataFlavor(Data.class, "Relation member");
064    private final Collection<RelationMember> members;
065
066    /**
067     * Constructs a new {@code RelationMemberTransferable}.
068     * @param members list of relation members
069     */
070    public RelationMemberTransferable(Collection<RelationMember> members) {
071        this.members = new ArrayList<>(members);
072    }
073
074    @Override
075    public DataFlavor[] getTransferDataFlavors() {
076        return new DataFlavor[]{RELATION_MEMBER_DATA, PrimitiveTransferData.DATA_FLAVOR, DataFlavor.stringFlavor};
077    }
078
079    @Override
080    public boolean isDataFlavorSupported(DataFlavor flavor) {
081        return Arrays.asList(getTransferDataFlavors()).contains(flavor);
082    }
083
084    @Override
085    public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
086        if (DataFlavor.stringFlavor.equals(flavor)) {
087            return getStringData();
088        } else if (RELATION_MEMBER_DATA.equals(flavor)) {
089            return getRelationMemberData();
090        } else if (PrimitiveTransferData.DATA_FLAVOR.equals(flavor)) {
091            return getPrimitiveData();
092        }
093        throw new UnsupportedFlavorException(flavor);
094    }
095
096    private PrimitiveTransferData getPrimitiveData() {
097        Collection<OsmPrimitive> primitives = new HashSet<>();
098        for (RelationMember member : members) {
099            primitives.add(member.getMember());
100        }
101        return PrimitiveTransferData.getData(primitives);
102    }
103
104    protected String getStringData() {
105        final StringBuilder sb = new StringBuilder();
106        for (RelationMember member : members) {
107            sb.append(member.getType())
108              .append(' ').append(member.getUniqueId())
109              .append(' ').append(member.getRole())
110              .append(" # ").append(member.getMember().getDisplayName(DefaultNameFormatter.getInstance()))
111              .append('\n');
112        }
113        return sb.toString().replace("\u200E", "").replace("\u200F", "");
114    }
115
116    protected Data getRelationMemberData() {
117        return Data.getData(members);
118    }
119}