001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.preferences.imagery;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.GridBagLayout;
007import java.util.List;
008import java.util.Map;
009import java.util.concurrent.ConcurrentHashMap;
010import java.util.stream.Collectors;
011
012import javax.swing.JPanel;
013import javax.swing.JScrollPane;
014import javax.swing.JTable;
015import javax.swing.ListSelectionModel;
016import javax.swing.table.AbstractTableModel;
017
018import org.openstreetmap.josm.tools.GBC;
019
020/**
021 * Simple table for editing HTTP headers
022 * @author Wiktor Niesiobedzki
023 *
024 */
025public class HeadersTable extends JPanel {
026
027    private final class HeaderTableModel extends AbstractTableModel {
028        @Override
029        public String getColumnName(int column) {
030            switch (column) {
031            case 0:
032                return tr("Header name");
033            case 1:
034                return tr("Header value");
035            default:
036                return "";
037            }
038        }
039
040        @Override
041        public int getRowCount() {
042            return headers.size() + 1;
043        }
044
045        @Override
046        public int getColumnCount() {
047            return 2;
048        }
049
050        @Override
051        public Object getValueAt(int row, int col) {
052            if (row < headers.size()) {
053                return headers.get(row)[col];
054            }
055            return "";
056        }
057
058        @Override
059        public boolean isCellEditable(int row, int column) {
060            return true;
061        }
062
063        @Override
064        public void setValueAt(Object value, int row, int col) {
065            if (row < headers.size()) {
066                String[] headerRow = headers.get(row);
067                headerRow[col] = (String) value;
068                if ("".equals(headerRow[0]) && "".equals(headerRow[1])) {
069                    headers.remove(row);
070                    fireTableRowsDeleted(row, row);
071                }
072
073            } else if (row == headers.size()) {
074                String[] entry = {"", ""};
075                entry[col] = (String) value;
076                headers.add(entry);
077                fireTableRowsInserted(row + 1, row + 1);
078            }
079            fireTableCellUpdated(row, col);
080        }
081    }
082
083    private final List<String[]> headers;
084
085    /**
086     * Creates empty table
087     */
088    public HeadersTable() {
089        this(new ConcurrentHashMap<>());
090    }
091
092    /**
093     * Create table prefilled with headers
094     * @param headers contents of table
095     */
096    public HeadersTable(Map<String, String> headers) {
097        super(new GridBagLayout());
098        this.headers = getHeadersAsVector(headers);
099        JTable table = new JTable(new HeaderTableModel());
100        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
101        table.setAutoCreateRowSorter(true);
102        table.setRowSelectionAllowed(false);
103        table.setColumnSelectionAllowed(false);
104        add(new JScrollPane(table), GBC.eol().fill());
105    }
106
107    private static List<String[]> getHeadersAsVector(Map<String, String> headers) {
108        return headers.entrySet().stream().sorted(Map.Entry.comparingByKey())
109                .map(e -> new String[] {e.getKey(), e.getValue()}).collect(Collectors.toList());
110    }
111
112    /**
113     * Returns headers provided by user.
114     * @return headers provided by user
115     */
116    public Map<String, String> getHeaders() {
117        return headers.stream().distinct().collect(Collectors.toMap(x -> x[0], x -> x[1]));
118    }
119
120}