001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.command.conflict;
003
004import static org.openstreetmap.josm.tools.I18n.trn;
005
006import java.util.Collection;
007import java.util.List;
008import java.util.Objects;
009
010import javax.swing.Icon;
011
012import org.openstreetmap.josm.data.conflict.Conflict;
013import org.openstreetmap.josm.data.osm.OsmPrimitive;
014import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
015import org.openstreetmap.josm.gui.conflict.pair.MergeDecisionType;
016import org.openstreetmap.josm.gui.conflict.pair.tags.TagMergeItem;
017import org.openstreetmap.josm.tools.ImageProvider;
018
019/**
020 * Represents the resolution of a tag conflict in an {@link OsmPrimitive}.
021 *
022 */
023public class TagConflictResolveCommand extends ConflictResolveCommand {
024    /** the conflict to resolve */
025    private final Conflict<? extends OsmPrimitive> conflict;
026
027    /** the list of merge decisions, represented as {@link TagMergeItem}s */
028    private final List<TagMergeItem> mergeItems;
029
030    /**
031     * replies the number of decided conflicts
032     *
033     * @return the number of decided conflicts
034     */
035    public int getNumDecidedConflicts() {
036        return (int) mergeItems.stream().filter(item -> item.getMergeDecision() != MergeDecisionType.UNDECIDED).count();
037    }
038
039    /**
040     * constructor
041     *
042     * @param conflict the conflict data set
043     * @param mergeItems the list of merge decisions, represented as {@link TagMergeItem}s
044     */
045    public TagConflictResolveCommand(Conflict<? extends OsmPrimitive> conflict, List<TagMergeItem> mergeItems) {
046        super(conflict.getMy().getDataSet());
047        this.conflict = conflict;
048        this.mergeItems = mergeItems;
049    }
050
051    @Override
052    public String getDescriptionText() {
053        switch (OsmPrimitiveType.from(conflict.getMy())) {
054            case NODE:
055                /* for correct i18n of plural forms - see #9110 */
056                return trn("Resolve {0} tag conflict in node {1}", "Resolve {0} tag conflicts in node {1}",
057                        getNumDecidedConflicts(), getNumDecidedConflicts(), conflict.getMy().getId());
058            case WAY:
059                /* for correct i18n of plural forms - see #9110 */
060                return trn("Resolve {0} tag conflict in way {1}", "Resolve {0} tag conflicts in way {1}",
061                        getNumDecidedConflicts(), getNumDecidedConflicts(), conflict.getMy().getId());
062            case RELATION:
063                /* for correct i18n of plural forms - see #9110 */
064                return trn("Resolve {0} tag conflict in relation {1}", "Resolve {0} tag conflicts in relation {1}",
065                        getNumDecidedConflicts(), getNumDecidedConflicts(), conflict.getMy().getId());
066            default:
067                return "";
068        }
069    }
070
071    @Override
072    public Icon getDescriptionIcon() {
073        return ImageProvider.get("data", "object");
074    }
075
076    @Override
077    public boolean executeCommand() {
078        // remember the current state of modified primitives, i.e. of
079        // OSM primitive 'my'
080        //
081        super.executeCommand();
082
083        // apply the merge decisions to OSM primitive 'my'
084        //
085        for (TagMergeItem item: mergeItems) {
086            if (item.getMergeDecision() != MergeDecisionType.UNDECIDED) {
087                item.applyToMyPrimitive(conflict.getMy());
088            }
089        }
090        rememberConflict(conflict);
091        return true;
092    }
093
094    @Override
095    public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
096            Collection<OsmPrimitive> added) {
097        modified.add(conflict.getMy());
098    }
099
100    @Override
101    public int hashCode() {
102        return Objects.hash(super.hashCode(), conflict, mergeItems);
103    }
104
105    @Override
106    public boolean equals(Object obj) {
107        if (this == obj) return true;
108        if (obj == null || getClass() != obj.getClass()) return false;
109        if (!super.equals(obj)) return false;
110        TagConflictResolveCommand that = (TagConflictResolveCommand) obj;
111        return Objects.equals(conflict, that.conflict) &&
112                Objects.equals(mergeItems, that.mergeItems);
113    }
114}