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