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