001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.dialogs.changeset; 003 004import java.util.ArrayList; 005import java.util.HashSet; 006import java.util.Iterator; 007import java.util.List; 008import java.util.Set; 009 010import javax.swing.DefaultListSelectionModel; 011import javax.swing.table.AbstractTableModel; 012 013import org.openstreetmap.josm.data.osm.ChangesetDataSet; 014import org.openstreetmap.josm.data.osm.ChangesetDataSet.ChangesetDataSetEntry; 015import org.openstreetmap.josm.data.osm.ChangesetDataSet.ChangesetModificationType; 016import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive; 017 018/** 019 * This is the table model for the content of a changeset. 020 * @since 2689 021 */ 022public class ChangesetContentTableModel extends AbstractTableModel { 023 024 private final transient List<ChangesetContentEntry> data = new ArrayList<>(); 025 private final DefaultListSelectionModel selectionModel; 026 027 /** 028 * Constructs a new {@code ChangesetContentTableModel}. 029 * @param selectionModel selection model 030 */ 031 public ChangesetContentTableModel(DefaultListSelectionModel selectionModel) { 032 this.selectionModel = selectionModel; 033 } 034 035 /** 036 * Replies true if there is at least one selected primitive in the table model 037 * 038 * @return true if there is at least one selected primitive in the table model 039 */ 040 public boolean hasSelectedPrimitives() { 041 return selectionModel.getMinSelectionIndex() >= 0; 042 } 043 044 /** 045 * Selects a single item by its index. 046 * @param row index 047 */ 048 public void setSelectedByIdx(int row) { 049 selectionModel.setSelectionInterval(row, row); 050 } 051 052 /** 053 * Replies the selection model 054 * @return the selection model 055 */ 056 public DefaultListSelectionModel getSelectionModel() { 057 return selectionModel; 058 } 059 060 /** 061 * Returns the selected history primitives. 062 * @return the selected history primitives 063 */ 064 public Set<HistoryOsmPrimitive> getSelectedPrimitives() { 065 Set<HistoryOsmPrimitive> ret = new HashSet<>(); 066 for (int i = 0; i < data.size(); i++) { 067 if (selectionModel.isSelectedIndex(i)) { 068 ret.add(data.get(i).getPrimitive()); 069 } 070 } 071 return ret; 072 } 073 074 /** 075 * Populates the model with the content of a changeset. If ds is null, the table is cleared. 076 * 077 * @param ds the changeset content. 078 */ 079 public void populate(ChangesetDataSet ds) { 080 this.data.clear(); 081 if (ds == null) { 082 fireTableDataChanged(); 083 return; 084 } 085 for (Iterator<ChangesetDataSetEntry> it = ds.iterator(); it.hasNext();) { 086 data.add(new ChangesetContentEntry(it.next())); 087 } 088 sort(); 089 fireTableDataChanged(); 090 } 091 092 /** 093 * Sort data. 094 */ 095 protected void sort() { 096 data.sort((c1, c2) -> { 097 if (c1.getModificationType() == c2.getModificationType()) { 098 long id1 = c1.getPrimitive().getId(); 099 long id2 = c2.getPrimitive().getId(); 100 101 if (id1 == id2) 102 return 0; 103 else if (id1 < id2) 104 return -1; 105 return 1; 106 } 107 switch(c1.getModificationType()) { 108 case CREATED: return -1; 109 case UPDATED: 110 switch(c2.getModificationType()) { 111 case CREATED: return 1; 112 default: return -1; 113 } 114 case DELETED: 115 return 1; 116 } 117 // should not happen 118 return 0; 119 } 120 ); 121 } 122 123 /* -------------------------------------------------------------- */ 124 /* interface TableModel */ 125 /* -------------------------------------------------------------- */ 126 @Override 127 public int getColumnCount() { 128 return 3; 129 } 130 131 @Override 132 public int getRowCount() { 133 return data.size(); 134 } 135 136 @Override 137 public Object getValueAt(int row, int col) { 138 switch(col) { 139 case 0: return data.get(row).getModificationType(); 140 default: return data.get(row).getPrimitive(); 141 } 142 } 143 144 /** 145 * The type used internally to keep information about {@link HistoryOsmPrimitive} 146 * with their {@link ChangesetModificationType}. 147 */ 148 private static class ChangesetContentEntry implements ChangesetDataSetEntry { 149 private final ChangesetModificationType modificationType; 150 private final HistoryOsmPrimitive primitive; 151 152 ChangesetContentEntry(ChangesetModificationType modificationType, HistoryOsmPrimitive primitive) { 153 this.modificationType = modificationType; 154 this.primitive = primitive; 155 } 156 157 ChangesetContentEntry(ChangesetDataSetEntry entry) { 158 this(entry.getModificationType(), entry.getPrimitive()); 159 } 160 161 @Override 162 public ChangesetModificationType getModificationType() { 163 return modificationType; 164 } 165 166 @Override 167 public HistoryOsmPrimitive getPrimitive() { 168 return primitive; 169 } 170 } 171}