diff --git a/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java b/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java index 1d3449640f..0d837f560a 100644 --- a/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java +++ b/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java @@ -352,11 +352,11 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable } }; } - StringBuilder nmFilter = new StringBuilder(); String[] items = filter.split(" "); boolean allTime = false; boolean open = false; List poiAdditionalsFilter = null; + List unknownFilters = null; for (String s : items) { s = s.trim(); if (!Algorithms.isEmpty(s)) { @@ -373,110 +373,179 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable poiAdditionalsFilter.add(pt); } } else { - nmFilter.append(s).append(" "); + if (unknownFilters == null) { + unknownFilters = new ArrayList<>(); + } + unknownFilters.add(s); } } } - return getNameFilterInternal(nmFilter, allTime, open, poiAdditionalsFilter); + return getNameFilterInternal(unknownFilters, allTime, open, poiAdditionalsFilter); } - private AmenityNameFilter getNameFilterInternal(StringBuilder nmFilter, - final boolean allTime, final boolean open, final List poiAdditionals) { - final CollatorStringMatcher sm = nmFilter.length() > 0 ? - new CollatorStringMatcher(nmFilter.toString().trim(), StringMatcherMode.CHECK_CONTAINS) : null; + private AmenityNameFilter getNameFilterInternal( + final List unknownFilters, final boolean shouldBeAllTime, + final boolean shouldBeOpened, final List selectedFilters + ) { return new AmenityNameFilter() { @Override - public boolean accept(Amenity a) { - if (sm != null) { - List names = OsmAndFormatter.getPoiStringsWithoutType(a, - app.getSettings().MAP_PREFERRED_LOCALE.get(), app.getSettings().MAP_TRANSLITERATE_NAMES.get()); - boolean match = false; - for (String name : names) { - if (sm.matches(name)) { - match = true; - break; - } - } - if (!match) { + public boolean accept(Amenity amenity) { + if (shouldBeAllTime) { + if (!"24/7".equalsIgnoreCase(amenity.getOpeningHours()) && + !"Mo-Su 00:00-24:00".equalsIgnoreCase(amenity.getOpeningHours())) { return false; } } - if (poiAdditionals != null) { - Map textPoiAdditionalsMap = new HashMap<>(); - Map> poiAdditionalCategoriesMap = new HashMap<>(); - for (PoiType pt : poiAdditionals) { - String category = pt.getPoiAdditionalCategory(); - List types = poiAdditionalCategoriesMap.get(category); - if (types == null) { - types = new ArrayList<>(); - poiAdditionalCategoriesMap.put(category, types); - } - types.add(pt); - String osmTag = pt.getOsmTag(); - if (osmTag.length() < pt.getKeyName().length()) { - PoiType textPoiType = poiTypes.getTextPoiAdditionalByKey(osmTag); - if (textPoiType != null) { - textPoiAdditionalsMap.put(pt, textPoiType); - } - } - } - for (List types : poiAdditionalCategoriesMap.values()) { - boolean acceptedAnyInCategory = false; - for (PoiType p : types) { - String inf = a.getAdditionalInfo(p.getKeyName()); - if (inf != null) { - acceptedAnyInCategory = true; - break; - } else { - PoiType textPoiType = textPoiAdditionalsMap.get(p); - if (textPoiType != null) { - inf = a.getAdditionalInfo(textPoiType.getKeyName()); - if (!Algorithms.isEmpty(inf)) { - String[] items = inf.split(";"); - String val = p.getOsmValue().trim().toLowerCase(); - for (String item : items) { - if (item.trim().toLowerCase().equals(val)) { - acceptedAnyInCategory = true; - break; - } - } - if (acceptedAnyInCategory) { - break; - } - } - } - } - } - if (!acceptedAnyInCategory) { - return false; - } - } + if (shouldBeOpened && !isOpened(amenity)) { + return false; } - if (allTime) { - if (!"24/7".equalsIgnoreCase(a.getOpeningHours()) && !"Mo-Su 00:00-24:00".equalsIgnoreCase(a.getOpeningHours())) { - return false; - } + + String nameFilter = extractNameFilter(amenity, unknownFilters); + if (!matchesAnyAmenityName(amenity, nameFilter)) { + return false; } - if (open) { - OpeningHours rs = OpeningHoursParser.parseOpenedHours(a.getOpeningHours()); - if (rs != null) { - Calendar inst = Calendar.getInstance(); - inst.setTimeInMillis(System.currentTimeMillis()); - boolean work = rs.isOpenedForTime(inst); - if (!work) { - return false; - } - } else { - return false; - } + + if (!acceptedAnyFilterOfEachCategory(amenity, selectedFilters)) { + return false; } + return true; } }; } + private boolean isOpened(Amenity amenity) { + OpeningHours openedHours = OpeningHoursParser.parseOpenedHours(amenity.getOpeningHours()); + if (openedHours == null) { + return false; + } + + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(System.currentTimeMillis()); + + return openedHours.isOpenedForTime(calendar); + } + + private String extractNameFilter(Amenity amenity, List unknownFilters) { + if (unknownFilters == null) { + return ""; + } + + StringBuilder nameFilter = new StringBuilder(); + for (String filter : unknownFilters) { + String formattedFilter = filter.replace(':', '_').toLowerCase(); + if (amenity.getAdditionalInfo(formattedFilter) == null) { + nameFilter.append(filter).append(" "); + } + } + + return nameFilter.toString(); + } + + private boolean matchesAnyAmenityName(Amenity amenity, String nameFilter) { + if (nameFilter.length() == 0) { + return true; + } + + final CollatorStringMatcher sm = + new CollatorStringMatcher(nameFilter.trim(), StringMatcherMode.CHECK_CONTAINS); + + List names = OsmAndFormatter.getPoiStringsWithoutType( + amenity, app.getSettings().MAP_PREFERRED_LOCALE.get(), + app.getSettings().MAP_TRANSLITERATE_NAMES.get()); + for (String name : names) { + if (sm.matches(name)) { + return true; + } + } + return false; + } + + private boolean acceptedAnyFilterOfEachCategory(Amenity amenity, List selectedFilters) { + if (selectedFilters == null) { + return true; + } + + Map> filterCategories = new HashMap<>(); + Map textFilters = new HashMap<>(); + + fillFilterCategories(selectedFilters, filterCategories, textFilters); + + for (List category : filterCategories.values()) { + if (!acceptedAnyFilterOfCategory(amenity, category, textFilters)) { + return false; + } + } + + return true; + } + + private void fillFilterCategories( + List selectedFilters, + Map> filterCategories, Map textFilters + ) { + for (PoiType filter : selectedFilters) { + String category = filter.getPoiAdditionalCategory(); + List filtersOfCategory = filterCategories.get(category); + if (filtersOfCategory == null) { + filtersOfCategory = new ArrayList<>(); + filterCategories.put(category, filtersOfCategory); + } + filtersOfCategory.add(filter); + + String osmTag = filter.getOsmTag(); + if (osmTag.length() < filter.getKeyName().length()) { + PoiType textFilter = poiTypes.getTextPoiAdditionalByKey(osmTag); + if (textFilter != null) { + textFilters.put(filter, textFilter); + } + } + } + } + + private boolean acceptedAnyFilterOfCategory( + Amenity amenity, List category, Map textFilters) { + for (PoiType filter : category) { + if (acceptedFilter(amenity, filter, textFilters)) { + return true; + } + } + + return false; + } + + private boolean acceptedFilter( + Amenity amenity, PoiType filter, Map textFilterCategories + ) { + String filterValue = amenity.getAdditionalInfo(filter.getKeyName()); + + if (filterValue != null) { + return true; + } + + PoiType textPoiType = textFilterCategories.get(filter); + if (textPoiType == null) { + return false; + } + + filterValue = amenity.getAdditionalInfo(textPoiType.getKeyName()); + if (Algorithms.isEmpty(filterValue)) { + return false; + } + + String[] items = filterValue.split(";"); + String val = filter.getOsmValue().trim().toLowerCase(); + for (String item : items) { + if (item.trim().toLowerCase().equals(val)) { + return true; + } + } + + return false; + } + public String getNameToken24H() { return app.getString(R.string.shared_string_is_open_24_7).replace(' ', '_').toLowerCase(); }