001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs.properties;
003
004import java.awt.event.ActionEvent;
005import java.util.Arrays;
006import java.util.Collection;
007import java.util.Objects;
008import java.util.function.IntFunction;
009import java.util.function.Supplier;
010import java.util.stream.Collectors;
011import java.util.stream.Stream;
012
013import javax.swing.AbstractAction;
014import javax.swing.JTable;
015
016import org.openstreetmap.josm.data.osm.Tagged;
017import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils;
018import org.openstreetmap.josm.tools.Utils;
019
020/**
021 * Super class of all copy actions from tag table.
022 * @since 13521
023 */
024public abstract class AbstractCopyAction extends AbstractAction {
025
026    private final JTable tagTable;
027    private final IntFunction<String> keySupplier;
028    private final Supplier<Collection<? extends Tagged>> objectSupplier;
029
030    /**
031     * Constructs a new {@code AbstractCopyAction}.
032     * @param tagTable the tag table
033     * @param keySupplier a supplier which returns the selected key for a given row index
034     * @param objectSupplier a supplier which returns the selected tagged object(s)
035     */
036    protected AbstractCopyAction(JTable tagTable, IntFunction<String> keySupplier, Supplier<Collection<? extends Tagged>> objectSupplier) {
037        this.tagTable = Objects.requireNonNull(tagTable);
038        this.keySupplier = Objects.requireNonNull(keySupplier);
039        this.objectSupplier = Objects.requireNonNull(objectSupplier);
040    }
041
042    protected abstract Collection<String> getString(Tagged p, String key);
043
044    protected Stream<String> valueStream() {
045        int[] rows = tagTable.getSelectedRows();
046        Collection<? extends Tagged> sel = objectSupplier.get();
047        if (rows.length == 0 || Utils.isEmpty(sel)) return Stream.empty();
048        return Arrays.stream(rows)
049                .mapToObj(keySupplier)
050                .flatMap(key -> sel.stream().map(p -> getString(p, key)))
051                .filter(Objects::nonNull)
052                .flatMap(Collection::stream)
053                .distinct();
054    }
055
056    @Override
057    public void actionPerformed(ActionEvent ae) {
058        final String values = valueStream()
059                .sorted()
060                .collect(Collectors.joining("\n"));
061        if (!values.isEmpty()) {
062            ClipboardUtils.copyString(values);
063        }
064    }
065}