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

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

Sonar - fix various issues

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