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

Last change on this file since 16694 was 16694, checked in by simon04, 4 years ago

see #19367 - History browser: do not reset UI after (re)loading of history (version table)

  • Property svn:eol-style set to native
File size: 26.5 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.util.HashSet;
7import java.util.Objects;
8import java.util.Set;
9
10import javax.swing.JTable;
11import javax.swing.table.TableModel;
12
13import org.openstreetmap.josm.data.UserIdentityManager;
14import org.openstreetmap.josm.data.osm.DataSet;
15import org.openstreetmap.josm.data.osm.Node;
16import org.openstreetmap.josm.data.osm.OsmPrimitive;
17import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
18import org.openstreetmap.josm.data.osm.Relation;
19import org.openstreetmap.josm.data.osm.RelationMember;
20import org.openstreetmap.josm.data.osm.RelationMemberData;
21import org.openstreetmap.josm.data.osm.User;
22import org.openstreetmap.josm.data.osm.UserInfo;
23import org.openstreetmap.josm.data.osm.Way;
24import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
25import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
26import org.openstreetmap.josm.data.osm.event.DataSetListener;
27import org.openstreetmap.josm.data.osm.event.NodeMovedEvent;
28import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent;
29import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;
30import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent;
31import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
32import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
33import org.openstreetmap.josm.data.osm.history.History;
34import org.openstreetmap.josm.data.osm.history.HistoryNode;
35import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
36import org.openstreetmap.josm.data.osm.history.HistoryRelation;
37import org.openstreetmap.josm.data.osm.history.HistoryWay;
38import org.openstreetmap.josm.data.osm.visitor.OsmPrimitiveVisitor;
39import org.openstreetmap.josm.gui.MainApplication;
40import org.openstreetmap.josm.gui.layer.Layer;
41import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
42import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
43import org.openstreetmap.josm.gui.layer.OsmDataLayer;
44import org.openstreetmap.josm.gui.util.ChangeNotifier;
45import org.openstreetmap.josm.tools.CheckParameterUtil;
46import org.openstreetmap.josm.tools.Logging;
47
48/**
49 * This is the model used by the history browser.
50 *
51 * The model state consists of the following elements:
52 * <ul>
53 * <li>the {@link History} of a specific {@link OsmPrimitive}</li>
54 * <li>a dedicated version in this {@link History} called the {@link PointInTimeType#REFERENCE_POINT_IN_TIME}</li>
55 * <li>another version in this {@link History} called the {@link PointInTimeType#CURRENT_POINT_IN_TIME}</li>
56 * </ul>
57 * {@link HistoryBrowser} always compares the {@link PointInTimeType#REFERENCE_POINT_IN_TIME} with the
58 * {@link PointInTimeType#CURRENT_POINT_IN_TIME}.
59
60 * This model provides various {@link TableModel}s for {@link JTable}s used in {@link HistoryBrowser}, for
61 * instance:
62 * <ul>
63 * <li>{@link #getTagTableModel(PointInTimeType)} replies a {@link TableModel} for the tags of either of
64 * the two selected versions</li>
65 * <li>{@link #getNodeListTableModel(PointInTimeType)} replies a {@link TableModel} for the list of nodes of
66 * the two selected versions (if the current history provides information about a {@link Way}</li>
67 * <li> {@link #getRelationMemberTableModel(PointInTimeType)} replies a {@link TableModel} for the list of relation
68 * members of the two selected versions (if the current history provides information about a {@link Relation}</li>
69 * </ul>
70 *
71 * @see HistoryBrowser
72 */
73public class HistoryBrowserModel extends ChangeNotifier implements ActiveLayerChangeListener, DataSetListener {
74 /** the history of an OsmPrimitive */
75 private History history;
76 private HistoryOsmPrimitive reference;
77 private HistoryOsmPrimitive current;
78 /**
79 * latest isn't a reference of history. It's a clone of the currently edited
80 * {@link OsmPrimitive} in the current edit layer.
81 */
82 private HistoryOsmPrimitive latest;
83
84 private final VersionTableModel versionTableModel;
85 private final TagTableModel currentTagTableModel;
86 private final TagTableModel referenceTagTableModel;
87 private final DiffTableModel currentRelationMemberTableModel;
88 private final DiffTableModel referenceRelationMemberTableModel;
89 private final DiffTableModel referenceNodeListTableModel;
90 private final DiffTableModel currentNodeListTableModel;
91
92 /**
93 * constructor
94 */
95 public HistoryBrowserModel() {
96 versionTableModel = new VersionTableModel(this);
97 currentTagTableModel = new TagTableModel(this, PointInTimeType.CURRENT_POINT_IN_TIME);
98 referenceTagTableModel = new TagTableModel(this, PointInTimeType.REFERENCE_POINT_IN_TIME);
99 referenceNodeListTableModel = new DiffTableModel();
100 currentNodeListTableModel = new DiffTableModel();
101 currentRelationMemberTableModel = new DiffTableModel();
102 referenceRelationMemberTableModel = new DiffTableModel();
103
104 DataSet ds = MainApplication.getLayerManager().getActiveDataSet();
105 if (ds != null) {
106 ds.addDataSetListener(this);
107 }
108 MainApplication.getLayerManager().addActiveLayerChangeListener(this);
109 }
110
111 /**
112 * Creates a new history browser model for a given history.
113 *
114 * @param history the history. Must not be null.
115 * @throws IllegalArgumentException if history is null
116 */
117 public HistoryBrowserModel(History history) {
118 this();
119 CheckParameterUtil.ensureParameterNotNull(history, "history");
120 setHistory(history);
121 }
122
123 /**
124 * replies the history managed by this model
125 * @return the history
126 */
127 public History getHistory() {
128 return history;
129 }
130
131 boolean isSamePrimitive(History history) {
132 return getHistory() != null && Objects.equals(getHistory().getPrimitiveId(), history.getPrimitiveId());
133 }
134
135 private boolean canShowAsLatest(OsmPrimitive primitive) {
136 if (primitive == null)
137 return false;
138 if (primitive.isNew() || !primitive.isUsable())
139 return false;
140
141 //try creating a history primitive. if that fails, the primitive cannot be used.
142 try {
143 HistoryOsmPrimitive.forOsmPrimitive(primitive);
144 } catch (IllegalArgumentException ign) {
145 Logging.trace(ign);
146 return false;
147 }
148
149 if (history == null)
150 return false;
151 // only show latest of the same version if it is modified
152 if (history.getByVersion(primitive.getVersion()) != null)
153 return primitive.isModified();
154
155 // if latest version from history is higher than a non existing primitive version,
156 // that means this version has been redacted and the primitive cannot be used.
157 return history.getLatest().getVersion() <= primitive.getVersion();
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 }
163
164 /**
165 * sets the history to be managed by this model
166 *
167 * @param history the history
168 *
169 */
170 public void setHistory(History history) {
171 boolean samePrimitive = isSamePrimitive(history); // needs to be before `this.history = history`
172 this.history = history;
173 if (samePrimitive && history.getNumVersions() > 0) {
174 reference = history.getByVersion(reference.getVersion());
175 current = history.getByVersion(current.getVersion());
176 } else if (history.getNumVersions() > 0) {
177 HistoryOsmPrimitive newLatest = null;
178 DataSet ds = MainApplication.getLayerManager().getActiveDataSet();
179 if (ds != null) {
180 OsmPrimitive p = ds.getPrimitiveById(history.getId(), history.getType());
181 if (canShowAsLatest(p)) {
182 newLatest = new HistoryPrimitiveBuilder().build(p);
183 }
184 }
185 if (newLatest == null) {
186 current = history.getLatest();
187 int prevIndex = history.getNumVersions() - 2;
188 reference = prevIndex < 0 ? history.getEarliest() : history.get(prevIndex);
189 } else {
190 reference = history.getLatest();
191 current = newLatest;
192 }
193 setLatest(newLatest);
194 }
195 initTagTableModels();
196 fireModelChange();
197 }
198
199 private void fireModelChange() {
200 initNodeListTableModels();
201 initMemberListTableModels();
202 fireStateChanged();
203 versionTableModel.fireTableDataChanged();
204 }
205
206 /**
207 * Replies the table model to be used in a {@link JTable} which
208 * shows the list of versions in this history.
209 *
210 * @return the table model
211 */
212 public VersionTableModel getVersionTableModel() {
213 return versionTableModel;
214 }
215
216 private void initTagTableModels() {
217 currentTagTableModel.initKeyList();
218 referenceTagTableModel.initKeyList();
219 }
220
221 /**
222 * Should be called every time either reference of current changes to update the diff.
223 * TODO: Maybe rename to reflect this? eg. updateNodeListTableModels
224 */
225 private void initNodeListTableModels() {
226 if (current == null || current.getType() != OsmPrimitiveType.WAY
227 || reference == null || reference.getType() != OsmPrimitiveType.WAY)
228 return;
229 TwoColumnDiff diff = new TwoColumnDiff(
230 ((HistoryWay) reference).getNodes().toArray(),
231 ((HistoryWay) current).getNodes().toArray());
232 referenceNodeListTableModel.setRows(diff.referenceDiff, diff.referenceReversed);
233 currentNodeListTableModel.setRows(diff.currentDiff, false);
234 }
235
236 private void initMemberListTableModels() {
237 if (current == null || current.getType() != OsmPrimitiveType.RELATION
238 || reference == null || reference.getType() != OsmPrimitiveType.RELATION)
239 return;
240 TwoColumnDiff diff = new TwoColumnDiff(
241 ((HistoryRelation) reference).getMembers().toArray(),
242 ((HistoryRelation) current).getMembers().toArray());
243 referenceRelationMemberTableModel.setRows(diff.referenceDiff, diff.referenceReversed);
244 currentRelationMemberTableModel.setRows(diff.currentDiff, false);
245 }
246
247 /**
248 * Replies the tag table model for the respective point in time.
249 *
250 * @param pointInTimeType the type of the point in time (must not be null)
251 * @return the tag table model
252 * @throws IllegalArgumentException if pointInTimeType is null
253 */
254 public TagTableModel getTagTableModel(PointInTimeType pointInTimeType) {
255 CheckParameterUtil.ensureParameterNotNull(pointInTimeType, "pointInTimeType");
256 if (pointInTimeType == PointInTimeType.CURRENT_POINT_IN_TIME)
257 return currentTagTableModel;
258 else // REFERENCE_POINT_IN_TIME
259 return referenceTagTableModel;
260 }
261
262 /**
263 * Replies the node list table model for the respective point in time.
264 *
265 * @param pointInTimeType the type of the point in time (must not be null)
266 * @return the node list table model
267 * @throws IllegalArgumentException if pointInTimeType is null
268 */
269 public DiffTableModel getNodeListTableModel(PointInTimeType pointInTimeType) {
270 CheckParameterUtil.ensureParameterNotNull(pointInTimeType, "pointInTimeType");
271 if (pointInTimeType == PointInTimeType.CURRENT_POINT_IN_TIME)
272 return currentNodeListTableModel;
273 else // REFERENCE_POINT_IN_TIME
274 return referenceNodeListTableModel;
275 }
276
277 /**
278 * Replies the relation member table model for the respective point in time.
279 *
280 * @param pointInTimeType the type of the point in time (must not be null)
281 * @return the relation member table model
282 * @throws IllegalArgumentException if pointInTimeType is null
283 */
284 public DiffTableModel getRelationMemberTableModel(PointInTimeType pointInTimeType) {
285 CheckParameterUtil.ensureParameterNotNull(pointInTimeType, "pointInTimeType");
286 if (pointInTimeType == PointInTimeType.CURRENT_POINT_IN_TIME)
287 return currentRelationMemberTableModel;
288 else // REFERENCE_POINT_IN_TIME
289 return referenceRelationMemberTableModel;
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 if reference is null
298 * @throws IllegalStateException 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) {
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(
310 tr("Failed to set reference. Reference ID {0} does not match history ID {1}.", reference.getId(), history.getId()));
311 if (history.getByVersion(reference.getVersion()) == null)
312 throw new IllegalArgumentException(
313 tr("Failed to set reference. Reference version {0} not available in history.", reference.getVersion()));
314
315 this.reference = reference;
316 initTagTableModels();
317 initNodeListTableModels();
318 initMemberListTableModels();
319 fireStateChanged();
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 if reference is {@code null}
328 * @throws IllegalStateException 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) {
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(
340 tr("Failed to set reference. Reference ID {0} does not match history ID {1}.", current.getId(), history.getId()));
341 if (history.getByVersion(current.getVersion()) == null)
342 throw new IllegalArgumentException(
343 tr("Failed to set current primitive. Current version {0} not available in history.", current.getVersion()));
344 this.current = current;
345 initTagTableModels();
346 initNodeListTableModels();
347 initMemberListTableModels();
348 fireStateChanged();
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 == PointInTimeType.CURRENT_POINT_IN_TIME)
379 return current;
380 else if (type == 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 layer.
390 *
391 * @param primitive the primitive to check
392 * @return true if <code>primitive</code> is the latest primitive
393 */
394 public boolean isLatest(HistoryOsmPrimitive primitive) {
395 return primitive != null && primitive == latest;
396 }
397
398 /**
399 * Sets the reference point in time to the given row.
400 * @param row row number
401 */
402 public void setReferencePointInTime(int row) {
403 if (history == null)
404 return;
405 if (row == history.getNumVersions()) {
406 if (latest != null) {
407 setReferencePointInTime(latest);
408 }
409 return;
410 }
411 if (row < 0 || row > history.getNumVersions())
412 return;
413 setReferencePointInTime(history.get(row));
414 }
415
416 /**
417 * Sets the current point in time to the given row.
418 * @param row row number
419 */
420 public void setCurrentPointInTime(int row) {
421 if (history == null)
422 return;
423 if (row == history.getNumVersions()) {
424 if (latest != null) {
425 setCurrentPointInTime(latest);
426 }
427 return;
428 }
429 if (row < 0 || row > history.getNumVersions())
430 return;
431 setCurrentPointInTime(history.get(row));
432 }
433
434 /**
435 * Determines if the given row is the reference point in time.
436 * @param row row number
437 * @return {@code true} if the given row is the reference point in time
438 */
439 public boolean isReferencePointInTime(int row) {
440 if (history == null)
441 return false;
442 if (row == history.getNumVersions())
443 return latest == reference;
444 if (row < 0 || row > history.getNumVersions())
445 return false;
446 return history.get(row) == reference;
447 }
448
449 /**
450 * Determines if the given row is the current point in time.
451 * @param row row number
452 * @return {@code true} if the given row is the current point in time
453 */
454 public boolean isCurrentPointInTime(int row) {
455 if (history == null)
456 return false;
457 if (row == history.getNumVersions())
458 return latest == current;
459 if (row < 0 || row > history.getNumVersions())
460 return false;
461 return history.get(row) == current;
462 }
463
464 /**
465 * Returns the {@code HistoryPrimitive} at the given row.
466 * @param row row number
467 * @return the {@code HistoryPrimitive} at the given row
468 */
469 public HistoryOsmPrimitive getPrimitive(int row) {
470 if (history == null)
471 return null;
472 return isLatest(row) ? latest : history.get(row);
473 }
474
475 /**
476 * Determines if the given row is the latest.
477 * @param row row number
478 * @return {@code true} if the given row is the latest
479 */
480 public boolean isLatest(int row) {
481 return row >= history.getNumVersions();
482 }
483
484 /**
485 * Returns the latest {@code HistoryOsmPrimitive}.
486 * @return the latest {@code HistoryOsmPrimitive}
487 * @since 11646
488 */
489 public HistoryOsmPrimitive getLatest() {
490 return latest;
491 }
492
493 /**
494 * Returns the key set (union of current and reference point in type key sets).
495 * @return the key set (union of current and reference point in type key sets)
496 * @since 11647
497 */
498 public Set<String> getKeySet() {
499 Set<String> keySet = new HashSet<>();
500 if (current != null) {
501 keySet.addAll(current.getTags().keySet());
502 }
503 if (reference != null) {
504 keySet.addAll(reference.getTags().keySet());
505 }
506 return keySet;
507 }
508
509 /**
510 * Sets the latest {@code HistoryOsmPrimitive}.
511 * @param latest the latest {@code HistoryOsmPrimitive}
512 */
513 protected void setLatest(HistoryOsmPrimitive latest) {
514 if (latest == null) {
515 if (this.current == this.latest) {
516 this.current = history != null ? history.getLatest() : null;
517 }
518 if (this.reference == this.latest) {
519 this.reference = history != null ? history.getLatest() : null;
520 }
521 this.latest = null;
522 } else {
523 if (this.current == this.latest) {
524 this.current = latest;
525 }
526 if (this.reference == this.latest) {
527 this.reference = latest;
528 }
529 this.latest = latest;
530 }
531 fireModelChange();
532 }
533
534 /**
535 * Removes this model as listener for data change and layer change events.
536 *
537 */
538 public void unlinkAsListener() {
539 DataSet ds = MainApplication.getLayerManager().getActiveDataSet();
540 if (ds != null) {
541 ds.removeDataSetListener(this);
542 }
543 MainApplication.getLayerManager().removeActiveLayerChangeListener(this);
544 }
545
546 /* ---------------------------------------------------------------------- */
547 /* DataSetListener */
548 /* ---------------------------------------------------------------------- */
549 @Override
550 public void nodeMoved(NodeMovedEvent event) {
551 Node node = event.getNode();
552 if (!node.isNew() && node.getId() == history.getId()) {
553 setLatest(new HistoryPrimitiveBuilder().build(node));
554 }
555 }
556
557 @Override
558 public void primitivesAdded(PrimitivesAddedEvent event) {
559 for (OsmPrimitive p: event.getPrimitives()) {
560 if (canShowAsLatest(p)) {
561 setLatest(new HistoryPrimitiveBuilder().build(p));
562 }
563 }
564 }
565
566 @Override
567 public void primitivesRemoved(PrimitivesRemovedEvent event) {
568 for (OsmPrimitive p: event.getPrimitives()) {
569 if (!p.isNew() && p.getId() == history.getId()) {
570 setLatest(null);
571 }
572 }
573 }
574
575 @Override
576 public void relationMembersChanged(RelationMembersChangedEvent event) {
577 Relation r = event.getRelation();
578 if (!r.isNew() && r.getId() == history.getId()) {
579 setLatest(new HistoryPrimitiveBuilder().build(r));
580 }
581 }
582
583 @Override
584 public void tagsChanged(TagsChangedEvent event) {
585 OsmPrimitive prim = event.getPrimitive();
586 if (!prim.isNew() && prim.getId() == history.getId()) {
587 setLatest(new HistoryPrimitiveBuilder().build(prim));
588 }
589 }
590
591 @Override
592 public void wayNodesChanged(WayNodesChangedEvent event) {
593 Way way = event.getChangedWay();
594 if (!way.isNew() && way.getId() == history.getId()) {
595 setLatest(new HistoryPrimitiveBuilder().build(way));
596 }
597 }
598
599 @Override
600 public void dataChanged(DataChangedEvent event) {
601 if (history == null)
602 return;
603 OsmPrimitive primitive = event.getDataset().getPrimitiveById(history.getId(), history.getType());
604 HistoryOsmPrimitive newLatest;
605 if (canShowAsLatest(primitive)) {
606 newLatest = new HistoryPrimitiveBuilder().build(primitive);
607 } else {
608 newLatest = null;
609 }
610 setLatest(newLatest);
611 fireModelChange();
612 }
613
614 @Override
615 public void otherDatasetChange(AbstractDatasetChangedEvent event) {
616 // Irrelevant
617 }
618
619 /* ---------------------------------------------------------------------- */
620 /* ActiveLayerChangeListener */
621 /* ---------------------------------------------------------------------- */
622 @Override
623 public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
624 Layer oldLayer = e.getPreviousActiveLayer();
625 if (oldLayer instanceof OsmDataLayer) {
626 OsmDataLayer l = (OsmDataLayer) oldLayer;
627 l.getDataSet().removeDataSetListener(this);
628 }
629 Layer newLayer = e.getSource().getActiveLayer();
630 if (!(newLayer instanceof OsmDataLayer)) {
631 latest = null;
632 fireModelChange();
633 return;
634 }
635 OsmDataLayer l = (OsmDataLayer) newLayer;
636 l.getDataSet().addDataSetListener(this);
637 OsmPrimitive primitive = history != null ? l.data.getPrimitiveById(history.getId(), history.getType()) : null;
638 HistoryOsmPrimitive newLatest;
639 if (canShowAsLatest(primitive)) {
640 newLatest = new HistoryPrimitiveBuilder().build(primitive);
641 } else {
642 newLatest = null;
643 }
644 setLatest(newLatest);
645 fireModelChange();
646 }
647
648 /**
649 * Creates a {@link HistoryOsmPrimitive} from a {@link OsmPrimitive}
650 *
651 */
652 static class HistoryPrimitiveBuilder implements OsmPrimitiveVisitor {
653 private HistoryOsmPrimitive clone;
654
655 @Override
656 public void visit(Node n) {
657 clone = new HistoryNode(n.getId(), n.getVersion(), n.isVisible(), getCurrentUser(), 0, null, n.getCoor(), false);
658 clone.setTags(n.getKeys());
659 }
660
661 @Override
662 public void visit(Relation r) {
663 clone = new HistoryRelation(r.getId(), r.getVersion(), r.isVisible(), getCurrentUser(), 0, null, false);
664 clone.setTags(r.getKeys());
665 HistoryRelation hr = (HistoryRelation) clone;
666 for (RelationMember rm : r.getMembers()) {
667 hr.addMember(new RelationMemberData(rm.getRole(), rm.getType(), rm.getUniqueId()));
668 }
669 }
670
671 @Override
672 public void visit(Way w) {
673 clone = new HistoryWay(w.getId(), w.getVersion(), w.isVisible(), getCurrentUser(), 0, null, false);
674 clone.setTags(w.getKeys());
675 for (Node n: w.getNodes()) {
676 ((HistoryWay) clone).addNode(n.getUniqueId());
677 }
678 }
679
680 private static User getCurrentUser() {
681 UserInfo info = UserIdentityManager.getInstance().getUserInfo();
682 return info == null ? User.getAnonymous() : User.createOsmUser(info.getId(), info.getDisplayName());
683 }
684
685 HistoryOsmPrimitive build(OsmPrimitive primitive) {
686 primitive.accept(this);
687 return clone;
688 }
689 }
690
691}
Note: See TracBrowser for help on using the repository browser.