source: josm/trunk/src/org/openstreetmap/josm/gui/conflict/pair/tags/TagMergeModel.java@ 7005

Last change on this file since 7005 was 7005, checked in by Don-vip, 10 years ago

see #8465 - use diamond operator where applicable

  • Property svn:eol-style set to native
File size: 7.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.conflict.pair.tags;
3
4import java.beans.PropertyChangeEvent;
5import java.beans.PropertyChangeListener;
6import java.util.ArrayList;
7import java.util.HashSet;
8import java.util.List;
9import java.util.Set;
10
11import javax.swing.table.DefaultTableModel;
12
13import org.openstreetmap.josm.command.conflict.TagConflictResolveCommand;
14import org.openstreetmap.josm.data.conflict.Conflict;
15import org.openstreetmap.josm.data.osm.OsmPrimitive;
16import org.openstreetmap.josm.gui.conflict.pair.MergeDecisionType;
17
18/**
19 * This is the {@link javax.swing.table.TableModel} used in the tables of the {@link TagMerger}.
20 *
21 * The model can {@link #populate(OsmPrimitive, OsmPrimitive)} itself from the conflicts
22 * in the tag sets of two {@link OsmPrimitive}s. Internally, it keeps a list of {@link TagMergeItem}s.
23 *
24 * {@link #decide(int, MergeDecisionType)} and {@link #decide(int[], MergeDecisionType)} can be used
25 * to remember a merge decision for a specific row in the model.
26 *
27 * The model notifies {@link PropertyChangeListener}s about updates of the number of
28 * undecided tags (see {@link #PROP_NUM_UNDECIDED_TAGS}).
29 *
30 */
31public class TagMergeModel extends DefaultTableModel {
32 public static final String PROP_NUM_UNDECIDED_TAGS = TagMergeModel.class.getName() + ".numUndecidedTags";
33
34 /** the list of tag merge items */
35 private final List<TagMergeItem> tagMergeItems;
36
37 /** the property change listeners */
38 private final List<PropertyChangeListener> listeners;
39
40 private int numUndecidedTags = 0;
41
42 public TagMergeModel() {
43 tagMergeItems = new ArrayList<>();
44 listeners = new ArrayList<>();
45 }
46
47 public void addPropertyChangeListener(PropertyChangeListener listener) {
48 synchronized(listeners) {
49 if (listener == null) return;
50 if (listeners.contains(listener)) return;
51 listeners.add(listener);
52 }
53 }
54
55 public void removePropertyChangeListener(PropertyChangeListener listener) {
56 synchronized(listeners) {
57 if (listener == null) return;
58 if (!listeners.contains(listener)) return;
59 listeners.remove(listener);
60 }
61 }
62
63 /**
64 * notifies {@link PropertyChangeListener}s about an update of {@link TagMergeModel#PROP_NUM_UNDECIDED_TAGS}
65
66 * @param oldValue the old value
67 * @param newValue the new value
68 */
69 protected void fireNumUndecidedTagsChanged(int oldValue, int newValue) {
70 PropertyChangeEvent evt = new PropertyChangeEvent(this,PROP_NUM_UNDECIDED_TAGS,oldValue, newValue);
71 synchronized(listeners) {
72 for(PropertyChangeListener l : listeners) {
73 l.propertyChange(evt);
74 }
75 }
76 }
77
78 /**
79 * refreshes the number of undecided tag conflicts after an update in the list of
80 * {@link TagMergeItem}s. Notifies {@link PropertyChangeListener} if necessary.
81 *
82 */
83 protected void refreshNumUndecidedTags() {
84 int newValue=0;
85 for(TagMergeItem item: tagMergeItems) {
86 if (MergeDecisionType.UNDECIDED.equals(item.getMergeDecision())) {
87 newValue++;
88 }
89 }
90 int oldValue = numUndecidedTags;
91 numUndecidedTags = newValue;
92 fireNumUndecidedTagsChanged(oldValue, numUndecidedTags);
93
94 }
95
96 /**
97 * Populate the model with conflicts between the tag sets of the two
98 * {@link OsmPrimitive} <code>my</code> and <code>their</code>.
99 *
100 * @param my my primitive (i.e. the primitive from the local dataset)
101 * @param their their primitive (i.e. the primitive from the server dataset)
102 *
103 */
104 public void populate(OsmPrimitive my, OsmPrimitive their) {
105 tagMergeItems.clear();
106 Set<String> keys = new HashSet<>();
107 keys.addAll(my.keySet());
108 keys.addAll(their.keySet());
109 for(String key : keys) {
110 String myValue = my.get(key);
111 String theirValue = their.get(key);
112 if (myValue == null || theirValue == null || ! myValue.equals(theirValue)) {
113 tagMergeItems.add(
114 new TagMergeItem(key, my, their)
115 );
116 }
117 }
118 fireTableDataChanged();
119 refreshNumUndecidedTags();
120 }
121
122 /**
123 * add a {@link TagMergeItem} to the model
124 *
125 * @param item the item
126 */
127 public void addItem(TagMergeItem item) {
128 if (item != null) {
129 tagMergeItems.add(item);
130 fireTableDataChanged();
131 refreshNumUndecidedTags();
132 }
133 }
134
135 protected void rememberDecision(int row, MergeDecisionType decision) {
136 TagMergeItem item = tagMergeItems.get(row);
137 item.decide(decision);
138 }
139
140 /**
141 * set the merge decision of the {@link TagMergeItem} in row <code>row</code>
142 * to <code>decision</code>.
143 *
144 * @param row the row
145 * @param decision the decision
146 */
147 public void decide(int row, MergeDecisionType decision) {
148 rememberDecision(row, decision);
149 fireTableRowsUpdated(row, row);
150 refreshNumUndecidedTags();
151 }
152
153 /**
154 * set the merge decision of all {@link TagMergeItem} given by indices in <code>rows</code>
155 * to <code>decision</code>.
156 *
157 * @param rows the array of row indices
158 * @param decision the decision
159 */
160 public void decide(int [] rows, MergeDecisionType decision) {
161 if (rows == null || rows.length == 0)
162 return;
163 for (int row : rows) {
164 rememberDecision(row, decision);
165 }
166 fireTableDataChanged();
167 refreshNumUndecidedTags();
168 }
169
170 @Override
171 public int getRowCount() {
172 return tagMergeItems == null ? 0 : tagMergeItems.size();
173 }
174
175 @Override
176 public Object getValueAt(int row, int column) {
177 // return the tagMergeItem for both columns. The cell
178 // renderer will dispatch on the column index and get
179 // the key or the value from the TagMergeItem
180 //
181 return tagMergeItems.get(row);
182 }
183
184 @Override
185 public boolean isCellEditable(int row, int column) {
186 return false;
187 }
188
189 public TagConflictResolveCommand buildResolveCommand(Conflict<? extends OsmPrimitive> conflict) {
190 return new TagConflictResolveCommand(conflict, tagMergeItems);
191 }
192
193 public boolean isResolvedCompletely() {
194 for (TagMergeItem item: tagMergeItems) {
195 if (item.getMergeDecision().equals(MergeDecisionType.UNDECIDED))
196 return false;
197 }
198 return true;
199 }
200
201 public int getNumResolvedConflicts() {
202 int n = 0;
203 for (TagMergeItem item: tagMergeItems) {
204 if (!item.getMergeDecision().equals(MergeDecisionType.UNDECIDED)) {
205 n++;
206 }
207 }
208 return n;
209
210 }
211
212 public int getFirstUndecided(int startIndex) {
213 for (int i=startIndex; i<tagMergeItems.size(); i++) {
214 if (tagMergeItems.get(i).getMergeDecision() == MergeDecisionType.UNDECIDED)
215 return i;
216 }
217 return -1;
218 }
219}
Note: See TracBrowser for help on using the repository browser.