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.LinkedHashMap; 007import java.util.List; 008import java.util.Map; 009 010import org.openstreetmap.josm.actions.search.SearchAction; 011import org.openstreetmap.josm.actions.search.SearchCompiler; 012import org.openstreetmap.josm.data.osm.Tag; 013import org.openstreetmap.josm.data.preferences.CollectionProperty; 014 015class RecentTagCollection { 016 017 private final Map<Tag, Void> recentTags; 018 private SearchCompiler.Match tagsToIgnore; 019 020 RecentTagCollection(final int capacity) { 021 // LRU cache for recently added tags (http://java-planet.blogspot.com/2005/08/how-to-set-up-simple-lru-cache-using.html) 022 recentTags = new LinkedHashMap<Tag, Void>(capacity + 1, 1.1f, true) { 023 @Override 024 protected boolean removeEldestEntry(Map.Entry<Tag, Void> eldest) { 025 return size() > capacity; 026 } 027 }; 028 tagsToIgnore = SearchCompiler.Never.INSTANCE; 029 } 030 031 public void loadFromPreference(CollectionProperty property) { 032 recentTags.clear(); 033 Iterator<String> it = property.get().iterator(); 034 while (it.hasNext()) { 035 String key = it.next(); 036 String value = it.next(); 037 add(new Tag(key, value)); 038 } 039 } 040 041 public void saveToPreference(CollectionProperty property) { 042 List<String> c = new ArrayList<>(recentTags.size() * 2); 043 for (Tag t : recentTags.keySet()) { 044 c.add(t.getKey()); 045 c.add(t.getValue()); 046 } 047 property.put(c); 048 } 049 050 public void add(Tag tag) { 051 if (!tagsToIgnore.match(tag)) { 052 recentTags.put(tag, null); 053 } 054 } 055 056 public boolean isEmpty() { 057 return recentTags.isEmpty(); 058 } 059 060 public List<Tag> toList() { 061 return new ArrayList<>(recentTags.keySet()); 062 } 063 064 public void setTagsToIgnore(SearchCompiler.Match tagsToIgnore) { 065 this.tagsToIgnore = tagsToIgnore; 066 final Iterator<Tag> it = recentTags.keySet().iterator(); 067 while (it.hasNext()) { 068 if (tagsToIgnore.match(it.next())) { 069 it.remove(); 070 } 071 } 072 } 073 074 public void setTagsToIgnore(SearchAction.SearchSetting tagsToIgnore) throws SearchCompiler.ParseError { 075 setTagsToIgnore(tagsToIgnore.text.isEmpty() ? SearchCompiler.Never.INSTANCE : SearchCompiler.compile(tagsToIgnore)); 076 } 077 078 public SearchAction.SearchSetting ignoreTag(Tag tagToIgnore, SearchAction.SearchSetting settingToUpdate) throws SearchCompiler.ParseError { 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}