001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.actions.relation;
003
004import java.util.Collection;
005import java.util.Collections;
006
007import javax.swing.AbstractAction;
008
009import org.openstreetmap.josm.actions.IPrimitiveAction;
010import org.openstreetmap.josm.data.osm.DownloadPolicy;
011import org.openstreetmap.josm.data.osm.IPrimitive;
012import org.openstreetmap.josm.data.osm.IRelation;
013import org.openstreetmap.josm.data.osm.OsmData;
014import org.openstreetmap.josm.data.osm.OsmUtils;
015import org.openstreetmap.josm.data.osm.Relation;
016import org.openstreetmap.josm.io.NetworkManager;
017import org.openstreetmap.josm.io.OnlineResource;
018import org.openstreetmap.josm.tools.SubclassFilteredCollection;
019import org.openstreetmap.josm.tools.Utils;
020
021/**
022 * Ancestor for all actions that want to work with relation collection and
023 * to be disabled if the collection is empty
024 * @since 5793
025 * @since 13957 (signature)
026 */
027public abstract class AbstractRelationAction extends AbstractAction implements IPrimitiveAction {
028    /** relation collection */
029    protected transient Collection<IRelation<?>> relations = Collections.<IRelation<?>>emptySet();
030
031    /**
032     * Returns the relations contained in the given collection.
033     * @param primitives collection of primitives
034     * @return the relation contained in {@code primitives}
035     */
036    protected static final Collection<IRelation<?>> getRelations(Collection<? extends IPrimitive> primitives) {
037        if (primitives == null || primitives.isEmpty()) {
038            return Collections.<IRelation<?>>emptySet();
039        } else {
040            return new SubclassFilteredCollection<>(primitives, IRelation.class::isInstance);
041        }
042    }
043
044    @Override
045    public void setPrimitives(Collection<? extends IPrimitive> primitives) {
046        this.relations = getRelations(primitives);
047        updateEnabledState();
048    }
049
050    /**
051     * Override in subclasses to update the enabled state of the action when something changes.
052     */
053    protected void updateEnabledState() {
054        setEnabled(!relations.isEmpty());
055    }
056
057    protected final boolean canModify() {
058        SubclassFilteredCollection<IRelation<?>, Relation> filteredRelations = Utils.filteredCollection(relations, Relation.class);
059        return OsmUtils.isOsmCollectionEditable(filteredRelations) && filteredRelations.parallelStream().anyMatch(r -> !r.isDeleted());
060    }
061
062    protected final boolean canDownload() {
063        if (relations.isEmpty()) {
064            return false;
065        }
066        OsmData<?, ?, ?, ?> ds = relations.iterator().next().getDataSet();
067        return !NetworkManager.isOffline(OnlineResource.OSM_API)
068            && ds != null && !ds.isLocked() && DownloadPolicy.BLOCKED != ds.getDownloadPolicy();
069    }
070
071    protected void setHelpId(String helpId) {
072        putValue("help", helpId);
073    }
074}