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 IPrimitive}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 <T> The primitive type 028 * @param all the collection of primitives for that the filter state should be updated 029 * @param filters the filters 030 * @return true, if the filter state (normal / disabled / hidden) of any primitive has changed in the process 031 * @throws SearchParseError if the search expression in a filter cannot be parsed 032 * @since 12383, 17862 (generics) 033 */ 034 public static <T extends IPrimitive & IFilterablePrimitive> boolean executeFilters(Collection<T> all, Filter... filters) 035 throws SearchParseError { 036 return executeFilters(all, FilterMatcher.of(filters)); 037 } 038 039 /** 040 * Apply the filters to the primitives of the data set. 041 * 042 * @param <T> The primitive type 043 * @param all the collection of primitives for that the filter state should be updated 044 * @param filterMatcher the FilterMatcher 045 * @return true, if the filter state (normal / disabled / hidden) of any primitive has changed in the process 046 * @since 17862 (generics) 047 */ 048 public static <T extends IPrimitive & IFilterablePrimitive> boolean executeFilters(Collection<T> all, FilterMatcher filterMatcher) { 049 boolean changed; 050 // first relations, then ways and nodes last; this is required to resolve dependencies 051 changed = doExecuteFilters(SubclassFilteredCollection.filter(all, IRelation.class::isInstance), filterMatcher); 052 changed |= doExecuteFilters(SubclassFilteredCollection.filter(all, IWay.class::isInstance), filterMatcher); 053 changed |= doExecuteFilters(SubclassFilteredCollection.filter(all, INode.class::isInstance), filterMatcher); 054 return changed; 055 } 056 057 private static <T extends IPrimitive & IFilterablePrimitive> boolean doExecuteFilters(Collection<T> all, FilterMatcher filterMatcher) { 058 059 boolean changed = false; 060 061 for (T primitive : all) { 062 FilterType hiddenType = filterMatcher.isHidden(primitive); 063 if (hiddenType != FilterType.NOT_FILTERED) { 064 changed |= primitive.setDisabledState(true); 065 primitive.setHiddenType(hiddenType == FilterType.EXPLICIT); 066 } else { 067 FilterType disabledType = filterMatcher.isDisabled(primitive); 068 if (disabledType != FilterType.NOT_FILTERED) { 069 changed |= primitive.setDisabledState(false); 070 primitive.setDisabledType(disabledType == FilterType.EXPLICIT); 071 } else { 072 changed |= primitive.unsetDisabledState(); 073 } 074 } 075 } 076 return changed; 077 } 078 079 /** 080 * Apply the filters to a single primitive. 081 * 082 * @param <T> the primitive type 083 * @param primitive the primitive 084 * @param filterMatcher the FilterMatcher 085 * @return true, if the filter state (normal / disabled / hidden) 086 * of the primitive has changed in the process 087 * @since 17862 (generics) 088 */ 089 public static <T extends IPrimitive & IFilterablePrimitive> boolean executeFilters(T primitive, FilterMatcher filterMatcher) { 090 return doExecuteFilters(Collections.singleton(primitive), filterMatcher); 091 } 092 093 /** 094 * Clear all filter flags, i.e. turn off filters. 095 * @param <T> the primitive type 096 * @param prims the primitives 097 * @return true, if the filter state (normal / disabled / hidden) of any primitive has changed in the process 098 * @since 12388 (signature) 099 */ 100 public static <T extends IPrimitive & IFilterablePrimitive> boolean clearFilterFlags(Collection<T> prims) { 101 boolean changed = false; 102 for (T osm : prims) { 103 changed |= osm.unsetDisabledState(); 104 } 105 return changed; 106 } 107}