001package jmri.util.datatransfer;
002
003import java.awt.datatransfer.Clipboard;
004import java.awt.datatransfer.ClipboardOwner;
005import java.awt.datatransfer.DataFlavor;
006import java.awt.datatransfer.Transferable;
007import java.awt.datatransfer.UnsupportedFlavorException;
008import java.io.IOException;
009import java.util.ArrayList;
010import java.util.Arrays;
011import java.util.List;
012import jmri.jmrit.roster.Roster;
013import jmri.jmrit.roster.RosterEntry;
014
015/**
016 * Transfer roster entries either via drag-and-drop or via the clipboard.
017 * <p>
018 * Note that roster entries can only be transfered within a single JVM instance,
019 * and cannot be shared between programs via this mechanism.
020 *
021 * <hr>
022 * This file is part of JMRI.
023 * <p>
024 * JMRI is free software; you can redistribute it and/or modify it under the
025 * terms of version 2 of the GNU General Public License as published by the Free
026 * Software Foundation. See the "COPYING" file for a copy of this license.
027 * <p>
028 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
029 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
030 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
031 *
032 * @author Randall Wood Copyright (C) 2011
033 */
034public class RosterEntrySelection implements Transferable, ClipboardOwner {
035
036    private final ArrayList<String> Ids;
037
038    public static final DataFlavor rosterEntryFlavor = new DataFlavor(ArrayList.class, "RosterEntryIDs");
039
040    private static final DataFlavor[] FLAVORS = {
041        RosterEntrySelection.rosterEntryFlavor
042    };
043
044    private static final List<DataFlavor> FLAVOR_LIST = Arrays.asList(FLAVORS);
045
046    /**
047     * Create the transferable.
048     * <p>
049     * Takes as a parameter an ArrayList containing Strings representing
050     * RosterEntry Ids.
051     *
052     * @param rosterEntries  an ArrayList of RosterEntry Ids
053     */
054    public RosterEntrySelection(ArrayList<String> rosterEntries) {
055        this.Ids = rosterEntries;
056    }
057
058    /**
059     * Create a transferable with a list of RosterEntries.
060     *
061     * @param rosterEntries entries to include in the selection
062     * @return a new selection with the given entries
063     */
064    public static RosterEntrySelection createRosterEntrySelection(ArrayList<RosterEntry> rosterEntries) {
065        ArrayList<String> Ids = new ArrayList<>(rosterEntries.size());
066        rosterEntries.stream().forEach((re) -> {
067            Ids.add(re.getId());
068        });
069        return new RosterEntrySelection(Ids);
070    }
071
072    @Override
073    public synchronized DataFlavor[] getTransferDataFlavors() {
074        return java.util.Arrays.copyOf(FLAVORS, FLAVORS.length);
075    }
076
077    @Override
078    public boolean isDataFlavorSupported(DataFlavor df) {
079        return (FLAVOR_LIST.contains(df));
080    }
081
082    @Override
083    public Object getTransferData(DataFlavor df) throws UnsupportedFlavorException, IOException {
084        if (df.equals(rosterEntryFlavor)) {
085            return Ids;
086        }
087        throw new UnsupportedFlavorException(df);
088    }
089
090    @Override
091    public void lostOwnership(Clipboard clpbrd, Transferable t) {
092        // if we need to take an action when something else if posted on the
093        // clipboard, we would do so now.
094    }
095
096    /**
097     * Get an ArrayList of RosterEntries from a RosterEntrySelection.
098     *
099     * @param t a Transferable object. This should be a RosterEntrySelection,
100     *          but for simplicity, will accept any Transferable object.
101     * @return the transfered roster entries
102     * @throws java.awt.datatransfer.UnsupportedFlavorException if the
103     *                                                          transferable is
104     *                                                          incorrect
105     * @throws java.io.IOException                              if unable to
106     *                                                          transfer the
107     *                                                          entries
108     */
109    public static ArrayList<RosterEntry> getRosterEntries(Transferable t) throws UnsupportedFlavorException, IOException {
110        if (t.isDataFlavorSupported(rosterEntryFlavor)) {
111            @SuppressWarnings("unchecked")
112            ArrayList<String> Ids = (ArrayList<String>) t.getTransferData(rosterEntryFlavor);
113            ArrayList<RosterEntry> REs = new ArrayList<>(Ids.size());
114            for (String Id : Ids) {
115                RosterEntry re = Roster.getDefault().entryFromTitle(Id);
116                if (re != null) {
117                    REs.add(re);
118                }
119            }
120            return REs;
121        }
122        throw new UnsupportedFlavorException(t.getTransferDataFlavors()[0]);
123    }
124
125}