001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.osm; 003 004import java.util.Collection; 005import java.util.Collections; 006 007import org.openstreetmap.josm.data.osm.FilterMatcher.FilterType; 008import org.openstreetmap.josm.data.osm.search.SearchParseError; 009import org.openstreetmap.josm.tools.SubclassFilteredCollection; 010 011/** 012 * Class for applying {@link Filter}s to {@link OsmPrimitive}s. 013 * 014 * Provides a bridge between Filter GUI and the data. 015 * 016 * @author Petr_DlouhĂ˝ 017 */ 018public final class FilterWorker { 019 020 private FilterWorker() { 021 // Hide default constructor for utils classes 022 } 023 024 /** 025 * Apply the filters to the primitives of the data set. 026 * 027 * @param all the collection of primitives for that the filter state should be updated 028 * @param filters the filters 029 * @return true, if the filter state (normal / disabled / hidden) of any primitive has changed in the process 030 * @throws SearchParseError if the search expression in a filter cannot be parsed 031 * @since 12383 032 */ 033 public static boolean executeFilters(Collection<OsmPrimitive> all, Filter... filters) throws SearchParseError { 034 return executeFilters(all, FilterMatcher.of(filters)); 035 } 036 037 /** 038 * Apply the filters to the primitives of the data set. 039 * 040 * @param all the collection of primitives for that the filter state should be updated 041 * @param filterMatcher the FilterMatcher 042 * @return true, if the filter state (normal / disabled / hidden) of any primitive has changed in the process 043 */ 044 public static boolean executeFilters(Collection<OsmPrimitive> all, FilterMatcher filterMatcher) { 045 boolean changed; 046 // first relations, then ways and nodes last; this is required to resolve dependencies 047 changed = doExecuteFilters(SubclassFilteredCollection.filter(all, Relation.class::isInstance), filterMatcher); 048 changed |= doExecuteFilters(SubclassFilteredCollection.filter(all, Way.class::isInstance), filterMatcher); 049 changed |= doExecuteFilters(SubclassFilteredCollection.filter(all, Node.class::isInstance), filterMatcher); 050 return changed; 051 } 052 053 private static boolean doExecuteFilters(Collection<OsmPrimitive> all, FilterMatcher filterMatcher) { 054 055 boolean changed = false; 056 057 for (OsmPrimitive primitive: all) { 058 FilterType hiddenType = filterMatcher.isHidden(primitive); 059 if (hiddenType != FilterType.NOT_FILTERED) { 060 changed |= primitive.setDisabledState(true); 061 primitive.setHiddenType(hiddenType == FilterType.EXPLICIT); 062 } else { 063 FilterType disabledType = filterMatcher.isDisabled(primitive); 064 if (disabledType != FilterType.NOT_FILTERED) { 065 changed |= primitive.setDisabledState(false); 066 primitive.setDisabledType(disabledType == FilterType.EXPLICIT); 067 } else { 068 changed |= primitive.unsetDisabledState(); 069 } 070 } 071 } 072 return changed; 073 } 074 075 /** 076 * Apply the filters to a single primitive. 077 * 078 * @param primitive the primitive 079 * @param filterMatcher the FilterMatcher 080 * @return true, if the filter state (normal / disabled / hidden) 081 * of the primitive has changed in the process 082 */ 083 public static boolean executeFilters(OsmPrimitive primitive, FilterMatcher filterMatcher) { 084 return doExecuteFilters(Collections.singleton(primitive), filterMatcher); 085 } 086 087 /** 088 * Clear all filter flags, i.e. turn off filters. 089 * @param prims the primitives 090 * @return true, if the filter state (normal / disabled / hidden) of any primitive has changed in the process 091 * @since 12388 (signature) 092 */ 093 public static boolean clearFilterFlags(Collection<OsmPrimitive> prims) { 094 boolean changed = false; 095 for (OsmPrimitive osm : prims) { 096 changed |= osm.unsetDisabledState(); 097 } 098 return changed; 099 } 100}