001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs.relation;
003
004import java.util.ArrayList;
005import java.util.List;
006import java.util.Objects;
007
008import javax.swing.AbstractListModel;
009
010import org.openstreetmap.josm.data.osm.DataSet;
011import org.openstreetmap.josm.data.osm.DownloadPolicy;
012import org.openstreetmap.josm.data.osm.Relation;
013import org.openstreetmap.josm.data.osm.RelationMember;
014
015/**
016 * This is the model for the {@link ReferringRelationsBrowser}.
017 * <p>
018 * It holds all referrers to a given relation
019 */
020public class ReferringRelationsBrowserModel extends AbstractListModel<Relation> {
021
022    /** the relation */
023    private transient Relation relation;
024    private final transient List<Relation> referrers = new ArrayList<>();
025
026    /**
027     * Constructs a new {@code ReferringRelationsBrowserModel}.
028     * @param relation relation
029     */
030    public ReferringRelationsBrowserModel(Relation relation) {
031        this.relation = relation;
032    }
033
034    protected void fireModelUpdate() {
035        int upper = Math.max(0, referrers.size() -1);
036        fireContentsChanged(this, 0, upper);
037    }
038
039    /**
040     * Sets the relation.
041     * @param relation the relation
042     */
043    public void setRelation(Relation relation) {
044        this.relation = relation;
045        referrers.clear();
046        fireModelUpdate();
047    }
048
049    @Override
050    public Relation getElementAt(int index) {
051        return referrers.get(index);
052    }
053
054    @Override
055    public int getSize() {
056        return referrers.size();
057    }
058
059    protected boolean isReferringRelation(Relation parent) {
060        return parent != null && parent.getMembers().stream()
061                .filter(RelationMember::isRelation)
062                .map(RelationMember::getRelation)
063                .anyMatch(child -> Objects.equals(child, relation));
064    }
065
066    /**
067     * Populates the model with parent referrers.
068     * @param parents parent referrers
069     */
070    public void populate(List<Relation> parents) {
071        referrers.clear();
072        if (parents != null) {
073            for (Relation relation: parents) {
074                if (isReferringRelation(relation)) {
075                    referrers.add(relation);
076                }
077            }
078        }
079        fireModelUpdate();
080    }
081
082    /**
083     * Populates the browser with the list of referring relations in the {@link DataSet} ds.
084     *
085     * @param ds the data set
086     */
087    public void populate(DataSet ds) {
088        referrers.clear();
089        if (ds == null) {
090            fireModelUpdate();
091            return;
092        }
093        for (Relation parent : ds.getRelations()) {
094            if (isReferringRelation(parent)) {
095                referrers.add(parent);
096            }
097        }
098        fireModelUpdate();
099    }
100
101    /**
102     * Determines if reloading the relation is possible/authorized.
103     * @return {@code true} if reloading the relation is possible/authorized
104     */
105    public boolean canReload() {
106        return relation != null && !relation.isNew()
107                && !relation.getDataSet().isLocked()
108                && DownloadPolicy.BLOCKED != relation.getDataSet().getDownloadPolicy();
109    }
110
111    /**
112     * Returns the relation.
113     * @return the relation
114     */
115    public Relation getRelation() {
116        return relation;
117    }
118}