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.&nbsp;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}