source: osm/applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/hack/MyRelationMemberConflictResolverModel.java@ 30712

Last change on this file since 30712 was 30712, checked in by donvip, 10 years ago

[josm_mege_overlap] move duplicated code to "hack" package and move inner classes into separate files + code alignment of MyTagConflictResolver* to latest version of JOSM classes

File size: 12.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package mergeoverlap.hack;
3
4import java.beans.PropertyChangeListener;
5import java.beans.PropertyChangeSupport;
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.HashSet;
9import java.util.LinkedList;
10import java.util.List;
11import java.util.Map;
12import java.util.Set;
13
14import javax.swing.table.DefaultTableModel;
15
16import mergeoverlap.MergeOverlapAction;
17
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
19import org.openstreetmap.josm.data.osm.Relation;
20import org.openstreetmap.josm.data.osm.RelationMember;
21import org.openstreetmap.josm.data.osm.RelationToChildReference;
22import org.openstreetmap.josm.data.osm.Way;
23import org.openstreetmap.josm.gui.conflict.tags.RelationMemberConflictDecision;
24import org.openstreetmap.josm.gui.conflict.tags.RelationMemberConflictDecisionType;
25
26/**
27 * This model manages a list of conflicting relation members.
28 *
29 * It can be used as {@see TableModel}.
30 *
31 *
32 */
33 public class MyRelationMemberConflictResolverModel extends DefaultTableModel {
34 /** the property name for the number conflicts managed by this model */
35 static public final String NUM_CONFLICTS_PROP = MyRelationMemberConflictResolverModel.class.getName() + ".numConflicts";
36
37 /** the list of conflict decisions */
38 private List<RelationMemberConflictDecision> decisions;
39 /** the collection of relations for which we manage conflicts */
40 private Collection<Relation> relations;
41 /** the number of conflicts */
42 private int numConflicts;
43 private PropertyChangeSupport support;
44
45 /**
46 * Replies the current number of conflicts
47 *
48 * @return the current number of conflicts
49 */
50 public int getNumConflicts() {
51 return numConflicts;
52 }
53
54 /**
55 * Updates the current number of conflicts from list of decisions and emits
56 * a property change event if necessary.
57 *
58 */
59 protected void updateNumConflicts() {
60 int count = 0;
61 for (RelationMemberConflictDecision decision: decisions) {
62 if (!decision.isDecided()) {
63 count++;
64 }
65 }
66 int oldValue = numConflicts;
67 numConflicts = count;
68 if (numConflicts != oldValue) {
69 support.firePropertyChange(NUM_CONFLICTS_PROP, oldValue, numConflicts);
70 }
71 }
72
73 public void addPropertyChangeListener(PropertyChangeListener l) {
74 support.addPropertyChangeListener(l);
75 }
76
77 public void removePropertyChangeListener(PropertyChangeListener l) {
78 support.removePropertyChangeListener(l);
79 }
80
81 public MyRelationMemberConflictResolverModel() {
82 decisions = new ArrayList<RelationMemberConflictDecision>();
83 support = new PropertyChangeSupport(this);
84 }
85
86 @Override
87 public int getRowCount() {
88 if (decisions == null) return 0;
89 return decisions.size();
90 }
91
92 @Override
93 public Object getValueAt(int row, int column) {
94 if (decisions == null) return null;
95
96 RelationMemberConflictDecision d = decisions.get(row);
97 switch(column) {
98 case 0: /* relation */ return d.getRelation();
99 case 1: /* pos */ return Integer.toString(d.getPos() + 1); // position in "user space" starting at 1
100 case 2: /* role */ return d.getRole();
101 case 3: /* original */ return d.getOriginalPrimitive();
102 case 4: /* decision */ return d.getDecision();
103 }
104 return null;
105 }
106
107 @Override
108 public void setValueAt(Object value, int row, int column) {
109 RelationMemberConflictDecision d = decisions.get(row);
110 switch(column) {
111 case 2: /* role */
112 d.setRole((String)value);
113 break;
114 case 4: /* decision */
115 d.decide((RelationMemberConflictDecisionType)value);
116 refresh();
117 break;
118 }
119 fireTableDataChanged();
120 }
121
122 /**
123 * Populates the model with the members of the relation <code>relation</code>
124 * referring to <code>primitive</code>.
125 *
126 * @param relation the parent relation
127 * @param primitive the child primitive
128 */
129 protected void populate(Relation relation, OsmPrimitive primitive, Map<Way, Way> oldWays) {
130 for (int i = 0; i<relation.getMembersCount(); i++) {
131 if (MergeOverlapAction.getOld(relation.getMember(i).getWay(), oldWays) == MergeOverlapAction.getOld((Way)primitive, oldWays)) {
132 decisions.add(new RelationMemberConflictDecision(relation, i));
133 }
134 }
135 }
136
137 /**
138 * Populates the model with the relation members belonging to one of the relations in <code>relations</code>
139 * and referring to one of the primitives in <code>memberPrimitives</code>.
140 *
141 * @param relations the parent relations. Empty list assumed if null.
142 * @param memberPrimitives the child primitives. Empty list assumed if null.
143 */
144 public void populate(Collection<Relation> relations, Collection<? extends OsmPrimitive> memberPrimitives, Map<Way, Way> oldWays) {
145 decisions.clear();
146
147 relations = relations == null ? new LinkedList<Relation>() : relations;
148 memberPrimitives = memberPrimitives == null ? new LinkedList<OsmPrimitive>() : memberPrimitives;
149 for (Relation r : relations) {
150 for (OsmPrimitive p: memberPrimitives) {
151 populate(r, p, oldWays);
152 }
153 }
154 this.relations = relations;
155 refresh();
156 }
157
158 /**
159 * Populates the model with the relation members represented as a collection of
160 * {@see RelationToChildReference}s.
161 *
162 * @param references the references. Empty list assumed if null.
163 */
164 public void populate(Collection<RelationToChildReference> references) {
165 references = references == null ? new LinkedList<RelationToChildReference>() : references;
166 decisions.clear();
167 this.relations = new HashSet<Relation>(references.size());
168 for (RelationToChildReference reference: references) {
169 decisions.add(new RelationMemberConflictDecision(reference.getParent(), reference.getPosition()));
170 relations.add(reference.getParent());
171 }
172 refresh();
173 }
174
175 /**
176 * Replies the decision at position <code>row</code>
177 *
178 * @param row
179 * @return the decision at position <code>row</code>
180 */
181 public RelationMemberConflictDecision getDecision(int row) {
182 return decisions.get(row);
183 }
184
185 /**
186 * Replies the number of decisions managed by this model
187 *
188 * @return the number of decisions managed by this model
189 */
190 public int getNumDecisions() {
191 return getRowCount();
192 }
193
194 /**
195 * Refreshes the model state. Invoke this method to trigger necessary change
196 * events after an update of the model data.
197 *
198 */
199 public void refresh() {
200 updateNumConflicts();
201 fireTableDataChanged();
202 }
203
204 /**
205 * Apply a role to all member managed by this model.
206 *
207 * @param role the role. Empty string assumed if null.
208 */
209 public void applyRole(String role) {
210 role = role == null ? "" : role;
211 for (RelationMemberConflictDecision decision : decisions) {
212 decision.setRole(role);
213 }
214 refresh();
215 }
216
217 protected RelationMemberConflictDecision getDecision(Relation relation, int pos) {
218 for(RelationMemberConflictDecision decision: decisions) {
219 if (decision.matches(relation, pos)) return decision;
220 }
221 return null;
222 }
223
224 protected void buildResolveCorrespondance(Relation relation, OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) {
225
226 List<RelationMember> relationsMembers = relation.getMembers();
227 Relation modifiedRelation = MergeOverlapAction.getNew(relation, newRelations);
228 modifiedRelation.setMembers(null);
229// boolean isChanged = false;
230 for (int i=0; i < relationsMembers.size(); i++) {
231 RelationMember rm = relationsMembers.get(i);
232// RelationMember rm = relation.getMember(i);
233// RelationMember rmNew;
234 RelationMemberConflictDecision decision = getDecision(relation, i);
235 if (decision == null) {
236 modifiedRelation.addMember(rm);
237 } else {
238 System.out.println(modifiedRelation);
239 System.out.println(111);
240 switch(decision.getDecision()) {
241 case KEEP:
242// modifiedRelation.removeMembersFor(newPrimitive);
243 System.out.println(222);
244 if (newPrimitive instanceof Way) {
245 modifiedRelation.addMember(new RelationMember(decision.getRole(), MergeOverlapAction.getOld((Way)newPrimitive, oldWays)));
246 }
247 else {
248 modifiedRelation.addMember(new RelationMember(decision.getRole(), newPrimitive));
249 }
250// modifiedRelation.addMember(new RelationMember(decision.getRole(), newPrimitive));
251 break;
252 case REMOVE:
253 System.out.println(333);
254// modifiedRelation.removeMembersFor(rm.getMember());
255// isChanged = true;
256 // do nothing
257 break;
258 case UNDECIDED:
259 // FIXME: this is an error
260 break;
261 }
262 }
263 }
264 }
265
266 /**
267 * Builds a collection of commands executing the decisions made in this model.
268 *
269 * @param newPrimitive the primitive which members shall refer to if the
270 * decision is {@see RelationMemberConflictDecisionType#REPLACE}
271 * @return a list of commands
272 */
273 public void buildRelationCorrespondance(OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) {
274 for (Relation relation : relations) {
275 buildResolveCorrespondance(relation, newPrimitive, newRelations, oldWays);
276 }
277 }
278
279 protected boolean isChanged(Relation relation, OsmPrimitive newPrimitive) {
280 for (int i=0; i < relation.getMembersCount(); i++) {
281 RelationMemberConflictDecision decision = getDecision(relation, i);
282 if (decision == null) {
283 continue;
284 }
285 switch(decision.getDecision()) {
286 case REMOVE: return true;
287 case KEEP:
288 if (!relation.getMember(i).getRole().equals(decision.getRole()))
289 return true;
290 if (relation.getMember(i).getMember() != newPrimitive)
291 return true;
292 case UNDECIDED:
293 // FIXME: handle error
294 }
295 }
296 return false;
297 }
298
299 /**
300 * Replies the set of relations which have to be modified according
301 * to the decisions managed by this model.
302 *
303 * @param newPrimitive the primitive which members shall refer to if the
304 * decision is {@see RelationMemberConflictDecisionType#REPLACE}
305 *
306 * @return the set of relations which have to be modified according
307 * to the decisions managed by this model
308 */
309 public Set<Relation> getModifiedRelations(OsmPrimitive newPrimitive) {
310 HashSet<Relation> ret = new HashSet<Relation>();
311 for (Relation relation: relations) {
312 if (isChanged(relation, newPrimitive)) {
313 ret.add(relation);
314 }
315 }
316 return ret;
317 }
318 }
Note: See TracBrowser for help on using the repository browser.