source: josm/trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java@ 10179

Last change on this file since 10179 was 10173, checked in by Don-vip, 8 years ago

sonar - squid:S1186 - Methods should not be empty

  • Property svn:eol-style set to native
File size: 30.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.history;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.text.DateFormat;
7import java.util.ArrayList;
8import java.util.Collections;
9import java.util.HashSet;
10import java.util.List;
11import java.util.Observable;
12import java.util.Set;
13
14import javax.swing.JTable;
15import javax.swing.table.AbstractTableModel;
16import javax.swing.table.TableModel;
17
18import org.openstreetmap.josm.Main;
19import org.openstreetmap.josm.data.osm.Node;
20import org.openstreetmap.josm.data.osm.OsmPrimitive;
21import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
22import org.openstreetmap.josm.data.osm.Relation;
23import org.openstreetmap.josm.data.osm.RelationMember;
24import org.openstreetmap.josm.data.osm.RelationMemberData;
25import org.openstreetmap.josm.data.osm.User;
26import org.openstreetmap.josm.data.osm.UserInfo;
27import org.openstreetmap.josm.data.osm.Way;
28import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
29import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
30import org.openstreetmap.josm.data.osm.event.DataSetListener;
31import org.openstreetmap.josm.data.osm.event.NodeMovedEvent;
32import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent;
33import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;
34import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent;
35import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
36import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
37import org.openstreetmap.josm.data.osm.history.History;
38import org.openstreetmap.josm.data.osm.history.HistoryNode;
39import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
40import org.openstreetmap.josm.data.osm.history.HistoryRelation;
41import org.openstreetmap.josm.data.osm.history.HistoryWay;
42import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
43import org.openstreetmap.josm.gui.JosmUserIdentityManager;
44import org.openstreetmap.josm.gui.MapView;
45import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
46import org.openstreetmap.josm.gui.layer.Layer;
47import org.openstreetmap.josm.gui.layer.OsmDataLayer;
48import org.openstreetmap.josm.tools.CheckParameterUtil;
49import org.openstreetmap.josm.tools.date.DateUtils;
50
51/**
52 * This is the model used by the history browser.
53 *
54 * The model state consists of the following elements:
55 * <ul>
56 * <li>the {@link History} of a specific {@link OsmPrimitive}</li>
57 * <li>a dedicated version in this {@link History} called the {@link PointInTimeType#REFERENCE_POINT_IN_TIME}</li>
58 * <li>another version in this {@link History} called the {@link PointInTimeType#CURRENT_POINT_IN_TIME}</li>
59 * </ul>
60 * {@link HistoryBrowser} always compares the {@link PointInTimeType#REFERENCE_POINT_IN_TIME} with the
61 * {@link PointInTimeType#CURRENT_POINT_IN_TIME}.
62
63 * This model provides various {@link TableModel}s for {@link JTable}s used in {@link HistoryBrowser}, for
64 * instance:
65 * <ul>
66 * <li>{@link #getTagTableModel(PointInTimeType)} replies a {@link TableModel} for the tags of either of
67 * the two selected versions</li>
68 * <li>{@link #getNodeListTableModel(PointInTimeType)} replies a {@link TableModel} for the list of nodes of
69 * the two selected versions (if the current history provides information about a {@link Way}</li>
70 * <li> {@link #getRelationMemberTableModel(PointInTimeType)} replies a {@link TableModel} for the list of relation
71 * members of the two selected versions (if the current history provides information about a {@link Relation}</li>
72 * </ul>
73 *
74 * @see HistoryBrowser
75 */
76public class HistoryBrowserModel extends Observable implements LayerChangeListener, DataSetListener {
77 /** the history of an OsmPrimitive */
78 private History history;
79 private HistoryOsmPrimitive reference;
80 private HistoryOsmPrimitive current;
81 /**
82 * latest isn't a reference of history. It's a clone of the currently edited
83 * {@link OsmPrimitive} in the current edit layer.
84 */
85 private HistoryOsmPrimitive latest;
86
87 private final VersionTableModel versionTableModel;
88 private final TagTableModel currentTagTableModel;
89 private final TagTableModel referenceTagTableModel;
90 private final DiffTableModel currentRelationMemberTableModel;
91 private final DiffTableModel referenceRelationMemberTableModel;
92 private final DiffTableModel referenceNodeListTableModel;
93 private final DiffTableModel currentNodeListTableModel;
94
95 /**
96 * constructor
97 */
98 public HistoryBrowserModel() {
99 versionTableModel = new VersionTableModel();
100 currentTagTableModel = new TagTableModel(PointInTimeType.CURRENT_POINT_IN_TIME);
101 referenceTagTableModel = new TagTableModel(PointInTimeType.REFERENCE_POINT_IN_TIME);
102 referenceNodeListTableModel = new DiffTableModel();
103 currentNodeListTableModel = new DiffTableModel();
104 currentRelationMemberTableModel = new DiffTableModel();
105 referenceRelationMemberTableModel = new DiffTableModel();
106
107 if (Main.main != null) {
108 OsmDataLayer editLayer = Main.main.getEditLayer();
109 if (editLayer != null) {
110 editLayer.data.addDataSetListener(this);
111 }
112 }
113 MapView.addLayerChangeListener(this);
114 }
115
116 /**
117 * Creates a new history browser model for a given history.
118 *
119 * @param history the history. Must not be null.
120 * @throws IllegalArgumentException if history is null
121 */
122 public HistoryBrowserModel(History history) {
123 this();
124 CheckParameterUtil.ensureParameterNotNull(history, "history");
125 setHistory(history);
126 }
127
128 /**
129 * replies the history managed by this model
130 * @return the history
131 */
132 public History getHistory() {
133 return history;
134 }
135
136 protected boolean canShowAsLatest(OsmPrimitive primitive) {
137 if (primitive == null) return false;
138 if (primitive.isNew() || !primitive.isUsable()) return false;
139
140 //try creating a history primitive. if that fails, the primitive cannot be used.
141 try {
142 HistoryOsmPrimitive.forOsmPrimitive(primitive);
143 } catch (Exception ign) {
144 return false;
145 }
146
147 if (history == null) return false;
148 // only show latest of the same version if it is modified
149 if (history.getByVersion(primitive.getVersion()) != null)
150 return primitive.isModified();
151
152 // if latest version from history is higher than a non existing primitive version,
153 // that means this version has been redacted and the primitive cannot be used.
154 if (history.getLatest().getVersion() > primitive.getVersion())
155 return false;
156
157 // latest has a higher version than one of the primitives
158 // in the history (probably because the history got out of sync
159 // with uploaded data) -> show the primitive as latest
160 return true;
161 }
162
163 /**
164 * sets the history to be managed by this model
165 *
166 * @param history the history
167 *
168 */
169 public void setHistory(History history) {
170 this.history = history;
171 if (history.getNumVersions() > 0) {
172 HistoryOsmPrimitive newLatest = null;
173 OsmDataLayer editLayer = Main.main.getEditLayer();
174 if (editLayer != null) {
175 OsmPrimitive p = editLayer.data.getPrimitiveById(history.getId(), history.getType());
176 if (canShowAsLatest(p)) {
177 newLatest = new HistoryPrimitiveBuilder().build(p);
178 }
179 }
180 if (newLatest == null) {
181 current = history.getLatest();
182 int prevIndex = history.getNumVersions() - 2;
183 reference = prevIndex < 0 ? history.getEarliest() : history.get(prevIndex);
184 } else {
185 reference = history.getLatest();
186 current = newLatest;
187 }
188 setLatest(newLatest);
189 }
190 initTagTableModels();
191 fireModelChange();
192 }
193
194 protected void fireModelChange() {
195 initNodeListTableModels();
196 initMemberListTableModels();
197 setChanged();
198 notifyObservers();
199 versionTableModel.fireTableDataChanged();
200 }
201
202 /**
203 * Replies the table model to be used in a {@link JTable} which
204 * shows the list of versions in this history.
205 *
206 * @return the table model
207 */
208 public VersionTableModel getVersionTableModel() {
209 return versionTableModel;
210 }
211
212 protected void initTagTableModels() {
213 currentTagTableModel.initKeyList();
214 referenceTagTableModel.initKeyList();
215 }
216
217 /**
218 * Should be called everytime either reference of current changes to update the diff.
219 * TODO: Maybe rename to reflect this? eg. updateNodeListTableModels
220 */
221 protected void initNodeListTableModels() {
222 if (current == null || current.getType() != OsmPrimitiveType.WAY
223 || reference == null || reference.getType() != OsmPrimitiveType.WAY)
224 return;
225 TwoColumnDiff diff = new TwoColumnDiff(
226 ((HistoryWay) reference).getNodes().toArray(),
227 ((HistoryWay) current).getNodes().toArray());
228 referenceNodeListTableModel.setRows(diff.referenceDiff, diff.referenceReversed);
229 currentNodeListTableModel.setRows(diff.currentDiff, false);
230 }
231
232 protected void initMemberListTableModels() {
233 if (current == null || current.getType() != OsmPrimitiveType.RELATION
234 || reference == null || reference.getType() != OsmPrimitiveType.RELATION)
235 return;
236 TwoColumnDiff diff = new TwoColumnDiff(
237 ((HistoryRelation) reference).getMembers().toArray(),
238 ((HistoryRelation) current).getMembers().toArray());
239 referenceRelationMemberTableModel.setRows(diff.referenceDiff, diff.referenceReversed);
240 currentRelationMemberTableModel.setRows(diff.currentDiff, false);
241 }
242
243 /**
244 * Replies the tag table model for the respective point in time.
245 *
246 * @param pointInTimeType the type of the point in time (must not be null)
247 * @return the tag table model
248 * @throws IllegalArgumentException if pointInTimeType is null
249 */
250 public TagTableModel getTagTableModel(PointInTimeType pointInTimeType) {
251 CheckParameterUtil.ensureParameterNotNull(pointInTimeType, "pointInTimeType");
252 if (pointInTimeType.equals(PointInTimeType.CURRENT_POINT_IN_TIME))
253 return currentTagTableModel;
254 else // REFERENCE_POINT_IN_TIME
255 return referenceTagTableModel;
256 }
257
258 /**
259 * Replies the node list table model for the respective point in time.
260 *
261 * @param pointInTimeType the type of the point in time (must not be null)
262 * @return the node list table model
263 * @throws IllegalArgumentException if pointInTimeType is null
264 */
265 public DiffTableModel getNodeListTableModel(PointInTimeType pointInTimeType) {
266 CheckParameterUtil.ensureParameterNotNull(pointInTimeType, "pointInTimeType");
267 if (pointInTimeType.equals(PointInTimeType.CURRENT_POINT_IN_TIME))
268 return currentNodeListTableModel;
269 else // REFERENCE_POINT_IN_TIME
270 return referenceNodeListTableModel;
271 }
272
273 /**
274 * Replies the relation member table model for the respective point in time.
275 *
276 * @param pointInTimeType the type of the point in time (must not be null)
277 * @return the relation member table model
278 * @throws IllegalArgumentException if pointInTimeType is null
279 */
280 public DiffTableModel getRelationMemberTableModel(PointInTimeType pointInTimeType) {
281 CheckParameterUtil.ensureParameterNotNull(pointInTimeType, "pointInTimeType");
282 if (pointInTimeType.equals(PointInTimeType.CURRENT_POINT_IN_TIME))
283 return currentRelationMemberTableModel;
284 else // REFERENCE_POINT_IN_TIME
285 return referenceRelationMemberTableModel;
286 }
287
288 /**
289 * Sets the {@link HistoryOsmPrimitive} which plays the role of a reference point
290 * in time (see {@link PointInTimeType}).
291 *
292 * @param reference the reference history primitive. Must not be null.
293 * @throws IllegalArgumentException if reference is null
294 * @throws IllegalStateException if this model isn't a assigned a history yet
295 * @throws IllegalArgumentException if reference isn't an history primitive for the history managed by this mode
296 *
297 * @see #setHistory(History)
298 * @see PointInTimeType
299 */
300 public void setReferencePointInTime(HistoryOsmPrimitive reference) {
301 CheckParameterUtil.ensureParameterNotNull(reference, "reference");
302 if (history == null)
303 throw new IllegalStateException(tr("History not initialized yet. Failed to set reference primitive."));
304 if (reference.getId() != history.getId())
305 throw new IllegalArgumentException(
306 tr("Failed to set reference. Reference ID {0} does not match history ID {1}.", reference.getId(), history.getId()));
307 HistoryOsmPrimitive primitive = history.getByVersion(reference.getVersion());
308 if (primitive == null)
309 throw new IllegalArgumentException(
310 tr("Failed to set reference. Reference version {0} not available in history.", reference.getVersion()));
311
312 this.reference = reference;
313 initTagTableModels();
314 initNodeListTableModels();
315 initMemberListTableModels();
316 setChanged();
317 notifyObservers();
318 }
319
320 /**
321 * Sets the {@link HistoryOsmPrimitive} which plays the role of the current point
322 * in time (see {@link PointInTimeType}).
323 *
324 * @param current the reference history primitive. Must not be {@code null}.
325 * @throws IllegalArgumentException if reference is {@code null}
326 * @throws IllegalStateException if this model isn't a assigned a history yet
327 * @throws IllegalArgumentException if reference isn't an history primitive for the history managed by this mode
328 *
329 * @see #setHistory(History)
330 * @see PointInTimeType
331 */
332 public void setCurrentPointInTime(HistoryOsmPrimitive current) {
333 CheckParameterUtil.ensureParameterNotNull(current, "current");
334 if (history == null)
335 throw new IllegalStateException(tr("History not initialized yet. Failed to set current primitive."));
336 if (current.getId() != history.getId())
337 throw new IllegalArgumentException(
338 tr("Failed to set reference. Reference ID {0} does not match history ID {1}.", current.getId(), history.getId()));
339 HistoryOsmPrimitive primitive = history.getByVersion(current.getVersion());
340 if (primitive == null)
341 throw new IllegalArgumentException(
342 tr("Failed to set current primitive. Current version {0} not available in history.", current.getVersion()));
343 this.current = current;
344 initTagTableModels();
345 initNodeListTableModels();
346 initMemberListTableModels();
347 setChanged();
348 notifyObservers();
349 }
350
351 /**
352 * Replies the history OSM primitive for the {@link PointInTimeType#CURRENT_POINT_IN_TIME}
353 *
354 * @return the history OSM primitive for the {@link PointInTimeType#CURRENT_POINT_IN_TIME} (may be null)
355 */
356 public HistoryOsmPrimitive getCurrentPointInTime() {
357 return getPointInTime(PointInTimeType.CURRENT_POINT_IN_TIME);
358 }
359
360 /**
361 * Replies the history OSM primitive for the {@link PointInTimeType#REFERENCE_POINT_IN_TIME}
362 *
363 * @return the history OSM primitive for the {@link PointInTimeType#REFERENCE_POINT_IN_TIME} (may be null)
364 */
365 public HistoryOsmPrimitive getReferencePointInTime() {
366 return getPointInTime(PointInTimeType.REFERENCE_POINT_IN_TIME);
367 }
368
369 /**
370 * replies the history OSM primitive for a given point in time
371 *
372 * @param type the type of the point in time (must not be null)
373 * @return the respective primitive. Can be null.
374 * @throws IllegalArgumentException if type is null
375 */
376 public HistoryOsmPrimitive getPointInTime(PointInTimeType type) {
377 CheckParameterUtil.ensureParameterNotNull(type, "type");
378 if (type.equals(PointInTimeType.CURRENT_POINT_IN_TIME))
379 return current;
380 else if (type.equals(PointInTimeType.REFERENCE_POINT_IN_TIME))
381 return reference;
382
383 // should not happen
384 return null;
385 }
386
387 /**
388 * Returns true if <code>primitive</code> is the latest primitive
389 * representing the version currently edited in the current data
390 * layer.
391 *
392 * @param primitive the primitive to check
393 * @return true if <code>primitive</code> is the latest primitive
394 */
395 public boolean isLatest(HistoryOsmPrimitive primitive) {
396 if (primitive == null) return false;
397 return primitive == latest;
398 }
399
400 /**
401 * The table model for the list of versions in the current history
402 *
403 */
404 public final class VersionTableModel extends AbstractTableModel {
405
406 private VersionTableModel() {
407 }
408
409 @Override
410 public int getRowCount() {
411 if (history == null)
412 return 0;
413 int ret = history.getNumVersions();
414 if (latest != null) {
415 ret++;
416 }
417 return ret;
418 }
419
420 @Override
421 public Object getValueAt(int row, int column) {
422 switch (column) {
423 case 0:
424 return Long.toString(getPrimitive(row).getVersion());
425 case 1:
426 return isReferencePointInTime(row);
427 case 2:
428 return isCurrentPointInTime(row);
429 case 3:
430 HistoryOsmPrimitive p3 = getPrimitive(row);
431 if (p3 != null && p3.getTimestamp() != null)
432 return DateUtils.formatDateTime(p3.getTimestamp(), DateFormat.SHORT, DateFormat.SHORT);
433 return null;
434 case 4:
435 HistoryOsmPrimitive p4 = getPrimitive(row);
436 if (p4 != null) {
437 User user = p4.getUser();
438 if (user != null)
439 return user.getName();
440 }
441 return null;
442 }
443 return null;
444 }
445
446 @Override
447 public void setValueAt(Object aValue, int row, int column) {
448 if (!((Boolean) aValue)) return;
449 switch (column) {
450 case 1:
451 setReferencePointInTime(row);
452 break;
453 case 2:
454 setCurrentPointInTime(row);
455 break;
456 default:
457 return;
458 }
459 fireTableDataChanged();
460 }
461
462 @Override
463 public boolean isCellEditable(int row, int column) {
464 return column >= 1 && column <= 2;
465 }
466
467 public void setReferencePointInTime(int row) {
468 if (history == null) return;
469 if (row == history.getNumVersions()) {
470 if (latest != null) {
471 HistoryBrowserModel.this.setReferencePointInTime(latest);
472 }
473 return;
474 }
475 if (row < 0 || row > history.getNumVersions()) return;
476 HistoryOsmPrimitive reference = history.get(row);
477 HistoryBrowserModel.this.setReferencePointInTime(reference);
478 }
479
480 public void setCurrentPointInTime(int row) {
481 if (history == null) return;
482 if (row == history.getNumVersions()) {
483 if (latest != null) {
484 HistoryBrowserModel.this.setCurrentPointInTime(latest);
485 }
486 return;
487 }
488 if (row < 0 || row > history.getNumVersions()) return;
489 HistoryOsmPrimitive current = history.get(row);
490 HistoryBrowserModel.this.setCurrentPointInTime(current);
491 }
492
493 public boolean isReferencePointInTime(int row) {
494 if (history == null) return false;
495 if (row == history.getNumVersions())
496 return latest == reference;
497 if (row < 0 || row > history.getNumVersions()) return false;
498 HistoryOsmPrimitive p = history.get(row);
499 return p == reference;
500 }
501
502 public boolean isCurrentPointInTime(int row) {
503 if (history == null) return false;
504 if (row == history.getNumVersions())
505 return latest == current;
506 if (row < 0 || row > history.getNumVersions()) return false;
507 HistoryOsmPrimitive p = history.get(row);
508 return p == current;
509 }
510
511 public HistoryOsmPrimitive getPrimitive(int row) {
512 if (history == null)
513 return null;
514 return isLatest(row) ? latest : history.get(row);
515 }
516
517 public boolean isLatest(int row) {
518 return row >= history.getNumVersions();
519 }
520
521 public OsmPrimitive getLatest() {
522 if (latest == null) return null;
523 OsmDataLayer editLayer = Main.main.getEditLayer();
524 if (editLayer == null) return null;
525 return editLayer.data.getPrimitiveById(latest.getId(), latest.getType());
526 }
527
528 @Override
529 public int getColumnCount() {
530 return 6;
531 }
532 }
533
534 /**
535 * The table model for the tags of the version at {@link PointInTimeType#REFERENCE_POINT_IN_TIME}
536 * or {@link PointInTimeType#CURRENT_POINT_IN_TIME}
537 *
538 */
539 public class TagTableModel extends AbstractTableModel {
540
541 private List<String> keys;
542 private final PointInTimeType pointInTimeType;
543
544 protected void initKeyList() {
545 Set<String> keySet = new HashSet<>();
546 if (current != null) {
547 keySet.addAll(current.getTags().keySet());
548 }
549 if (reference != null) {
550 keySet.addAll(reference.getTags().keySet());
551 }
552 keys = new ArrayList<>(keySet);
553 Collections.sort(keys);
554 fireTableDataChanged();
555 }
556
557 protected TagTableModel(PointInTimeType type) {
558 pointInTimeType = type;
559 initKeyList();
560 }
561
562 @Override
563 public int getRowCount() {
564 if (keys == null) return 0;
565 return keys.size();
566 }
567
568 @Override
569 public Object getValueAt(int row, int column) {
570 return keys.get(row);
571 }
572
573 public boolean hasTag(String key) {
574 HistoryOsmPrimitive primitive = getPointInTime(pointInTimeType);
575 if (primitive == null)
576 return false;
577 return primitive.hasTag(key);
578 }
579
580 public String getValue(String key) {
581 HistoryOsmPrimitive primitive = getPointInTime(pointInTimeType);
582 if (primitive == null)
583 return null;
584 return primitive.get(key);
585 }
586
587 public boolean oppositeHasTag(String key) {
588 PointInTimeType opposite = pointInTimeType.opposite();
589 HistoryOsmPrimitive primitive = getPointInTime(opposite);
590 if (primitive == null)
591 return false;
592 return primitive.hasTag(key);
593 }
594
595 public String getOppositeValue(String key) {
596 PointInTimeType opposite = pointInTimeType.opposite();
597 HistoryOsmPrimitive primitive = getPointInTime(opposite);
598 if (primitive == null)
599 return null;
600 return primitive.get(key);
601 }
602
603 public boolean hasSameValueAsOpposite(String key) {
604 String value = getValue(key);
605 String oppositeValue = getOppositeValue(key);
606 if (value == null || oppositeValue == null)
607 return false;
608 return value.equals(oppositeValue);
609 }
610
611 public PointInTimeType getPointInTimeType() {
612 return pointInTimeType;
613 }
614
615 public boolean isCurrentPointInTime() {
616 return pointInTimeType.equals(PointInTimeType.CURRENT_POINT_IN_TIME);
617 }
618
619 public boolean isReferencePointInTime() {
620 return pointInTimeType.equals(PointInTimeType.REFERENCE_POINT_IN_TIME);
621 }
622
623 @Override
624 public int getColumnCount() {
625 return 1;
626 }
627 }
628
629 protected void setLatest(HistoryOsmPrimitive latest) {
630 if (latest == null) {
631 if (this.current == this.latest) {
632 this.current = history != null ? history.getLatest() : null;
633 }
634 if (this.reference == this.latest) {
635 this.reference = history != null ? history.getLatest() : null;
636 }
637 this.latest = null;
638 } else {
639 if (this.current == this.latest) {
640 this.current = latest;
641 }
642 if (this.reference == this.latest) {
643 this.reference = latest;
644 }
645 this.latest = latest;
646 }
647 fireModelChange();
648 }
649
650 /**
651 * Removes this model as listener for data change and layer change events.
652 *
653 */
654 public void unlinkAsListener() {
655 OsmDataLayer editLayer = Main.main.getEditLayer();
656 if (editLayer != null) {
657 editLayer.data.removeDataSetListener(this);
658 }
659 MapView.removeLayerChangeListener(this);
660 }
661
662 /* ---------------------------------------------------------------------- */
663 /* DataSetListener */
664 /* ---------------------------------------------------------------------- */
665 @Override
666 public void nodeMoved(NodeMovedEvent event) {
667 Node node = event.getNode();
668 if (!node.isNew() && node.getId() == history.getId()) {
669 setLatest(new HistoryPrimitiveBuilder().build(node));
670 }
671 }
672
673 @Override
674 public void primitivesAdded(PrimitivesAddedEvent event) {
675 for (OsmPrimitive p: event.getPrimitives()) {
676 if (canShowAsLatest(p)) {
677 setLatest(new HistoryPrimitiveBuilder().build(p));
678 }
679 }
680 }
681
682 @Override
683 public void primitivesRemoved(PrimitivesRemovedEvent event) {
684 for (OsmPrimitive p: event.getPrimitives()) {
685 if (!p.isNew() && p.getId() == history.getId()) {
686 setLatest(null);
687 }
688 }
689 }
690
691 @Override
692 public void relationMembersChanged(RelationMembersChangedEvent event) {
693 Relation r = event.getRelation();
694 if (!r.isNew() && r.getId() == history.getId()) {
695 setLatest(new HistoryPrimitiveBuilder().build(r));
696 }
697 }
698
699 @Override
700 public void tagsChanged(TagsChangedEvent event) {
701 OsmPrimitive prim = event.getPrimitive();
702 if (!prim.isNew() && prim.getId() == history.getId()) {
703 setLatest(new HistoryPrimitiveBuilder().build(prim));
704 }
705 }
706
707 @Override
708 public void wayNodesChanged(WayNodesChangedEvent event) {
709 Way way = event.getChangedWay();
710 if (!way.isNew() && way.getId() == history.getId()) {
711 setLatest(new HistoryPrimitiveBuilder().build(way));
712 }
713 }
714
715 @Override
716 public void dataChanged(DataChangedEvent event) {
717 if (history == null)
718 return;
719 OsmPrimitive primitive = event.getDataset().getPrimitiveById(history.getId(), history.getType());
720 HistoryOsmPrimitive latest;
721 if (canShowAsLatest(primitive)) {
722 latest = new HistoryPrimitiveBuilder().build(primitive);
723 } else {
724 latest = null;
725 }
726 setLatest(latest);
727 fireModelChange();
728 }
729
730 @Override
731 public void otherDatasetChange(AbstractDatasetChangedEvent event) {
732 // Irrelevant
733 }
734
735 /* ---------------------------------------------------------------------- */
736 /* LayerChangeListener */
737 /* ---------------------------------------------------------------------- */
738 @Override
739 public void activeLayerChange(Layer oldLayer, Layer newLayer) {
740 if (oldLayer instanceof OsmDataLayer) {
741 OsmDataLayer l = (OsmDataLayer) oldLayer;
742 l.data.removeDataSetListener(this);
743 }
744 if (!(newLayer instanceof OsmDataLayer)) {
745 latest = null;
746 fireModelChange();
747 return;
748 }
749 OsmDataLayer l = (OsmDataLayer) newLayer;
750 l.data.addDataSetListener(this);
751 OsmPrimitive primitive = history != null ? l.data.getPrimitiveById(history.getId(), history.getType()) : null;
752 HistoryOsmPrimitive latest;
753 if (canShowAsLatest(primitive)) {
754 latest = new HistoryPrimitiveBuilder().build(primitive);
755 } else {
756 latest = null;
757 }
758 setLatest(latest);
759 fireModelChange();
760 }
761
762 @Override
763 public void layerAdded(Layer newLayer) {
764 // Do nothing
765 }
766
767 @Override
768 public void layerRemoved(Layer oldLayer) {
769 // Do nothing
770 }
771
772 /**
773 * Creates a {@link HistoryOsmPrimitive} from a {@link OsmPrimitive}
774 *
775 */
776 static class HistoryPrimitiveBuilder extends AbstractVisitor {
777 private HistoryOsmPrimitive clone;
778
779 @Override
780 public void visit(Node n) {
781 clone = new HistoryNode(n.getId(), n.getVersion(), n.isVisible(), getCurrentUser(), 0, null, n.getCoor(), false);
782 clone.setTags(n.getKeys());
783 }
784
785 @Override
786 public void visit(Relation r) {
787 clone = new HistoryRelation(r.getId(), r.getVersion(), r.isVisible(), getCurrentUser(), 0, null, false);
788 clone.setTags(r.getKeys());
789 HistoryRelation hr = (HistoryRelation) clone;
790 for (RelationMember rm : r.getMembers()) {
791 hr.addMember(new RelationMemberData(rm.getRole(), rm.getType(), rm.getUniqueId()));
792 }
793 }
794
795 @Override
796 public void visit(Way w) {
797 clone = new HistoryWay(w.getId(), w.getVersion(), w.isVisible(), getCurrentUser(), 0, null, false);
798 clone.setTags(w.getKeys());
799 for (Node n: w.getNodes()) {
800 ((HistoryWay) clone).addNode(n.getUniqueId());
801 }
802 }
803
804 private static User getCurrentUser() {
805 UserInfo info = JosmUserIdentityManager.getInstance().getUserInfo();
806 return info == null ? User.getAnonymous() : User.createOsmUser(info.getId(), info.getDisplayName());
807 }
808
809 public HistoryOsmPrimitive build(OsmPrimitive primitive) {
810 primitive.accept(this);
811 return clone;
812 }
813 }
814}
Note: See TracBrowser for help on using the repository browser.