001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.history;
003
004import java.util.ArrayList;
005import java.util.Collections;
006import java.util.List;
007
008import javax.swing.table.AbstractTableModel;
009
010import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
011
012/**
013 * The table model for the tags of the version
014 * at {@link PointInTimeType#REFERENCE_POINT_IN_TIME}
015 * or {@link PointInTimeType#CURRENT_POINT_IN_TIME}
016 * @since 11647 (extracted from HistoryBrowserModel)
017 */
018public final class TagTableModel extends AbstractTableModel {
019
020    private List<String> keys;
021    private final PointInTimeType pointInTimeType;
022    private final HistoryBrowserModel model;
023
024    /**
025     * Constructs a new {@code TagTableModel}.
026     * @param historyModel parent {@code HistoryBrowserModel}
027     * @param type type of point in time
028     */
029    public TagTableModel(HistoryBrowserModel historyModel, PointInTimeType type) {
030        model = historyModel;
031        pointInTimeType = type;
032        initKeyList();
033    }
034
035    void initKeyList() {
036        keys = new ArrayList<>(model.getKeySet());
037        Collections.sort(keys);
038        fireTableDataChanged();
039    }
040
041    @Override
042    public int getRowCount() {
043        if (keys == null)
044            return 0;
045        return keys.size();
046    }
047
048    @Override
049    public Object getValueAt(int row, int column) {
050        return getKeyAt(row);
051    }
052
053    /**
054     * Get the key for the given row.
055     * @param row The row
056     * @return The key in that row.
057     * @since 10637
058     */
059    public String getKeyAt(int row) {
060        return keys.get(row);
061    }
062
063    /**
064     * Determines if a tag exists for the given key.
065     * @param key tag key
066     * @return {@code true} if a tag exists for the given key
067     */
068    public boolean hasTag(String key) {
069        HistoryOsmPrimitive primitive = model.getPointInTime(pointInTimeType);
070        return primitive != null && primitive.hasKey(key);
071    }
072
073    /**
074     * Returns the tag value for the given key.
075     * @param key tag key
076     * @return tag value, or null
077     */
078    public String getValue(String key) {
079        HistoryOsmPrimitive primitive = model.getPointInTime(pointInTimeType);
080        if (primitive == null)
081            return null;
082        return primitive.get(key);
083    }
084
085    /**
086     * Determines if a tag exists in the opposite point in time for the given key.
087     * @param key tag key
088     * @return {@code true} if a tag exists for the given key
089     */
090    public boolean oppositeHasTag(String key) {
091        HistoryOsmPrimitive primitive = model.getPointInTime(pointInTimeType.opposite());
092        return primitive != null && primitive.hasKey(key);
093    }
094
095    /**
096     * Returns the tag value in the opposite point in time for the given key.
097     * @param key tag key
098     * @return tag value, or null
099     */
100    public String getOppositeValue(String key) {
101        HistoryOsmPrimitive primitive = model.getPointInTime(pointInTimeType.opposite());
102        if (primitive == null)
103            return null;
104        return primitive.get(key);
105    }
106
107    /**
108     * Determines if the tag value is the same in the opposite point in time for the given key.
109     * @param key tag key
110     * @return {@code true} if the tag value is the same in the opposite point in time for the given key
111     */
112    public boolean hasSameValueAsOpposite(String key) {
113        String value = getValue(key);
114        String oppositeValue = getOppositeValue(key);
115        return value != null && value.equals(oppositeValue);
116    }
117
118    /**
119     * Returns the type of point in time.
120     * @return the type of point in time
121     */
122    public PointInTimeType getPointInTimeType() {
123        return pointInTimeType;
124    }
125
126    /**
127     * Determines if this is the current point in time.
128     * @return {@code true} if this is the current point in time
129     */
130    public boolean isCurrentPointInTime() {
131        return pointInTimeType.equals(PointInTimeType.CURRENT_POINT_IN_TIME);
132    }
133
134    /**
135     * Determines if this is the reference point in time.
136     * @return {@code true} if this is the reference point in time
137     */
138    public boolean isReferencePointInTime() {
139        return pointInTimeType.equals(PointInTimeType.REFERENCE_POINT_IN_TIME);
140    }
141
142    @Override
143    public int getColumnCount() {
144        return 2;
145    }
146}