001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.conflict.pair.relation;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.util.List;
007import java.util.Map;
008
009import javax.swing.table.DefaultTableModel;
010
011import org.openstreetmap.josm.command.RelationMemberConflictResolverCommand;
012import org.openstreetmap.josm.data.osm.OsmPrimitive;
013import org.openstreetmap.josm.data.osm.PrimitiveId;
014import org.openstreetmap.josm.data.osm.Relation;
015import org.openstreetmap.josm.data.osm.RelationMember;
016import org.openstreetmap.josm.gui.conflict.pair.ListMergeModel;
017import org.openstreetmap.josm.gui.conflict.pair.ListRole;
018import org.openstreetmap.josm.tools.CheckParameterUtil;
019/**
020 * The model for merging two lists of relation members
021 *
022 */
023public class RelationMemberListMergeModel extends ListMergeModel<RelationMember>{
024
025    @Override
026    public boolean isEqualEntry(RelationMember e1, RelationMember e2) {
027        return e1.equals(e2);
028    }
029
030    @Override
031    protected void buildMergedEntriesTableModel() {
032        // the table model for merged entries is different because it supports
033        // editing cells in the first column
034        //
035        mergedEntriesTableModel = this.new EntriesTableModel(ListRole.MERGED_ENTRIES) {
036            @Override
037            public boolean isCellEditable(int row, int column) {
038                switch(column) {
039                case 1: return true;
040                default: return false;
041                }
042            }
043        };
044    }
045
046    @Override
047    protected void setValueAt(DefaultTableModel model, Object value, int row, int col) {
048        if (model == getMergedTableModel() && col == 1) {
049            RelationMember memberOld = getMergedEntries().get(row);
050            RelationMember memberNew = new RelationMember((String)value,memberOld.getMember());
051            getMergedEntries().remove(row);
052            getMergedEntries().add(row,memberNew);
053            fireModelDataChanged();
054        }
055    }
056
057    /**
058     * populates the model with the relation members in relation my and their
059     *
060     * @param my my relation. Must not be null.
061     * @param their their relation. Must not be null.
062     * @param mergedMap The map of merged primitives if the conflict results from merging two layers
063     *
064     * @throws IllegalArgumentException if my is null
065     * @throws IllegalArgumentException if their is null
066     */
067    public void populate(Relation my, Relation their, Map<PrimitiveId, PrimitiveId> mergedMap) {
068        initPopulate(my, their, mergedMap);
069
070        for (RelationMember n : my.getMembers()) {
071            getMyEntries().add(n);
072        }
073        for (RelationMember n : their.getMembers()) {
074            getTheirEntries().add(n);
075        }
076        if (myAndTheirEntriesEqual()) {
077            for (RelationMember m : getMyEntries()) {
078                getMergedEntries().add(cloneEntryForMergedList(m));
079            }
080            setFrozen(true);
081        } else {
082            setFrozen(false);
083        }
084
085        fireModelDataChanged();
086    }
087
088    @Override
089    protected RelationMember cloneEntryForMergedList(RelationMember entry) {
090        return new RelationMember(entry.getRole(), getMyPrimitive(entry));
091    }
092
093    @Override
094    public OsmPrimitive getMyPrimitive(RelationMember entry) {
095        return getMyPrimitiveById(entry.getMember());
096    }
097
098    /**
099     * Builds the command to resolve conflicts in the node list of a way
100     *
101     * @param my  my relation. Must not be null.
102     * @param their  their relation. Must not be null
103     * @return the command
104     * @exception IllegalArgumentException thrown, if my is null
105     * @exception IllegalArgumentException thrown, if their is null
106     * @exception IllegalStateException thrown, if the merge is not yet frozen
107     */
108    public RelationMemberConflictResolverCommand buildResolveCommand(Relation my, Relation their) {
109        CheckParameterUtil.ensureParameterNotNull(my, "my");
110        CheckParameterUtil.ensureParameterNotNull(their, "their");
111        if (! isFrozen())
112            throw new IllegalArgumentException(tr("Merged nodes not frozen yet. Cannot build resolution command"));
113        List<RelationMember> entries = getMergedEntries();
114        return new RelationMemberConflictResolverCommand(my, their, entries);
115    }
116}