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