001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.datatransfer.data;
003
004import java.awt.datatransfer.DataFlavor;
005import java.io.Serializable;
006import java.util.Collection;
007import java.util.Collections;
008import java.util.EnumMap;
009import java.util.Map;
010
011import org.openstreetmap.josm.data.osm.OsmPrimitive;
012import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
013import org.openstreetmap.josm.data.osm.PrimitiveData;
014import org.openstreetmap.josm.data.osm.TagCollection;
015
016/**
017 * This is a variant of {@link TagTransferData} that holds tags that were copied from a collection of primitives.
018 * @author Michael Zangl
019 * @since 10737
020 */
021public class PrimitiveTagTransferData implements Serializable {
022
023    private static final long serialVersionUID = 1;
024
025    /**
026     * This is a data flavor added
027     */
028    public static final DataFlavor FLAVOR = new DataFlavor(TagTransferData.class, "OSM Primitive Tags");
029
030    private final EnumMap<OsmPrimitiveType, TagCollection> tags = new EnumMap<>(OsmPrimitiveType.class);
031    private final EnumMap<OsmPrimitiveType, Integer> counts = new EnumMap<>(OsmPrimitiveType.class);
032
033    /**
034     * Create a new {@link PrimitiveTagTransferData}
035     * @param source The primitives to initialize this object with.
036     */
037    public PrimitiveTagTransferData(Collection<? extends PrimitiveData> source) {
038        for (OsmPrimitiveType type : OsmPrimitiveType.dataValues()) {
039            tags.put(type, new TagCollection());
040        }
041
042        for (PrimitiveData primitive : source) {
043            tags.get(primitive.getType()).add(TagCollection.from(primitive));
044            counts.merge(primitive.getType(), 1, (a, b) -> a + b);
045        }
046    }
047
048    /**
049     * Create a new {@link PrimitiveTagTransferData}
050     * @param data The primitives to initialize this object with.
051     */
052    public PrimitiveTagTransferData(PrimitiveTransferData data) {
053        this(data.getDirectlyAdded());
054    }
055
056    /**
057     * Determines if the source for tag pasting is heterogeneous, i.e. if it doesn't consist of
058     * {@link OsmPrimitive}s of exactly one type
059     * @return true if the source for tag pasting is heterogeneous
060     */
061    public boolean isHeterogeneousSource() {
062        return counts.size() > 1;
063    }
064
065    /**
066     * Gets the tags used for this primitive type.
067     * @param type The primitive type
068     * @return The tags as collection. Empty if no such type was copied
069     */
070    public TagCollection getForPrimitives(OsmPrimitiveType type) {
071        return tags.get(type);
072    }
073
074    /**
075     * Gets the number of source primitives for the given type.
076     * @param type The type
077     * @return The number of source primitives of that type
078     */
079    public int getSourcePrimitiveCount(OsmPrimitiveType type) {
080        return counts.getOrDefault(type, 0);
081    }
082
083    /**
084     * Gets the statistics of the source primitive counts. May contain no entries for unused types.
085     * @return The statistics as map
086     */
087    public Map<OsmPrimitiveType, Integer> getStatistics() {
088        return Collections.unmodifiableMap(counts);
089    }
090}