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

Last change on this file since 3083 was 3083, checked in by bastiK, 14 years ago

added svn:eol-style=native to source files

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