001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.gui.conflict.pair.relation;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.util.List;
007    import java.util.Map;
008    
009    import javax.swing.table.DefaultTableModel;
010    
011    import org.openstreetmap.josm.command.RelationMemberConflictResolverCommand;
012    import org.openstreetmap.josm.data.osm.OsmPrimitive;
013    import org.openstreetmap.josm.data.osm.PrimitiveId;
014    import org.openstreetmap.josm.data.osm.Relation;
015    import org.openstreetmap.josm.data.osm.RelationMember;
016    import org.openstreetmap.josm.gui.conflict.pair.ListMergeModel;
017    import org.openstreetmap.josm.gui.conflict.pair.ListRole;
018    import org.openstreetmap.josm.tools.CheckParameterUtil;
019    /**
020     * The model for merging two lists of relation members
021     *
022     */
023    public 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    }