001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.dialogs.properties; 003 004import java.util.ArrayList; 005import java.util.Iterator; 006import java.util.List; 007import java.util.Map; 008 009import org.openstreetmap.josm.data.osm.Tag; 010import org.openstreetmap.josm.data.osm.search.SearchCompiler; 011import org.openstreetmap.josm.data.osm.search.SearchParseError; 012import org.openstreetmap.josm.data.osm.search.SearchSetting; 013import org.openstreetmap.josm.data.preferences.ListProperty; 014import org.openstreetmap.josm.gui.util.LruCache; 015import org.openstreetmap.josm.tools.Logging; 016 017/** 018 * Manages list of recently used tags that will be displayed in the {@link PropertiesDialog}. 019 */ 020class RecentTagCollection { 021 022 private final Map<Tag, Void> recentTags; 023 private SearchCompiler.Match tagsToIgnore; 024 025 RecentTagCollection(final int capacity) { 026 recentTags = new LruCache<>(capacity); 027 tagsToIgnore = SearchCompiler.Never.INSTANCE; 028 } 029 030 public void loadFromPreference(ListProperty property) { 031 recentTags.clear(); 032 List<String> list = property.get(); 033 Iterator<String> it = list.iterator(); 034 while (it.hasNext()) { 035 String key = it.next(); 036 if (it.hasNext()) { 037 String value = it.next(); 038 add(new Tag(key, value)); 039 } else { 040 Logging.error("Invalid or incomplete list property: " + list); 041 break; 042 } 043 } 044 } 045 046 public void saveToPreference(ListProperty property) { 047 List<String> c = new ArrayList<>(recentTags.size() * 2); 048 for (Tag t : recentTags.keySet()) { 049 c.add(t.getKey()); 050 c.add(t.getValue()); 051 } 052 property.put(c); 053 } 054 055 public void add(Tag tag) { 056 if (!tagsToIgnore.match(tag)) { 057 recentTags.put(tag, null); 058 } 059 } 060 061 public boolean isEmpty() { 062 return recentTags.isEmpty(); 063 } 064 065 public List<Tag> toList() { 066 return new ArrayList<>(recentTags.keySet()); 067 } 068 069 public void setTagsToIgnore(SearchCompiler.Match tagsToIgnore) { 070 this.tagsToIgnore = tagsToIgnore; 071 recentTags.keySet().removeIf(tagsToIgnore::match); 072 } 073 074 public void setTagsToIgnore(SearchSetting tagsToIgnore) throws SearchParseError { 075 setTagsToIgnore(tagsToIgnore.text.isEmpty() ? SearchCompiler.Never.INSTANCE : SearchCompiler.compile(tagsToIgnore)); 076 } 077 078 public SearchSetting ignoreTag(Tag tagToIgnore, SearchSetting settingToUpdate) throws SearchParseError { 079 final String forTag = SearchCompiler.buildSearchStringForTag(tagToIgnore.getKey(), tagToIgnore.getValue()); 080 settingToUpdate.text = settingToUpdate.text.isEmpty() 081 ? forTag 082 : settingToUpdate.text + " OR " + forTag; 083 setTagsToIgnore(settingToUpdate); 084 return settingToUpdate; 085 } 086}