com.facebook.buck.android.ClassNameFilter.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.android.ClassNameFilter.java

Source

/*
 * Copyright 2012-present Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package com.facebook.buck.android;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

/**
 * Filter for internal class names.
 *
 * <p>We use this to determine if a class must be placed in our primary dex.
 * It supports prefix, suffix, substring, and exact matches.
 */
public class ClassNameFilter {
    // We use naive algorithms for prefix, suffix, and substring, but these could easily be
    // optimzied using RE2 or some other more specialized search algorithms.
    private final ImmutableList<String> prefixes;
    private final ImmutableList<String> suffixes;
    private final ImmutableList<String> substrings;
    private final ImmutableSet<String> exactMatches;

    private ClassNameFilter(Iterable<String> prefixes, Iterable<String> suffixes, Iterable<String> substrings,
            Iterable<String> exactMatches) {
        this.prefixes = ImmutableList.copyOf(prefixes);
        this.suffixes = ImmutableList.copyOf(suffixes);
        this.substrings = ImmutableList.copyOf(substrings);
        this.exactMatches = ImmutableSet.copyOf(exactMatches);
    }

    /**
     * Convenience factory to produce a filter from a very simple pattern language.
     *
     * <p>patterns are substrings by default, but {@code ^} at the start or end of a pattern
     * anchors it to the start or end of the class name.
     *
     * @param patterns  Patterns to include in the filter.
     * @return  A new filter.
     */
    public static ClassNameFilter fromConfiguration(Iterable<String> patterns) {
        ImmutableList.Builder<String> prefixes = ImmutableList.builder();
        ImmutableList.Builder<String> suffixes = ImmutableList.builder();
        ImmutableList.Builder<String> substrings = ImmutableList.builder();
        ImmutableSet.Builder<String> exactMatches = ImmutableSet.builder();

        for (String pattern : patterns) {
            boolean isPrefix = pattern.charAt(0) == '^';
            boolean isSuffix = pattern.charAt(pattern.length() - 1) == '^';
            if (isPrefix && isSuffix) {
                exactMatches.add(pattern.substring(1, pattern.length() - 1));
            } else if (isPrefix) {
                prefixes.add(pattern.substring(1));
            } else if (isSuffix) {
                suffixes.add(pattern.substring(0, pattern.length() - 1));
            } else {
                substrings.add(pattern);
            }
        }

        return new ClassNameFilter(prefixes.build(), suffixes.build(), substrings.build(), exactMatches.build());
    }

    public boolean matches(String internalClassName) {
        if (exactMatches.contains(internalClassName)) {
            return true;
        }

        for (String prefix : prefixes) {
            if (internalClassName.startsWith(prefix)) {
                return true;
            }
        }

        for (String suffix : suffixes) {
            if (internalClassName.endsWith(suffix)) {
                return true;
            }
        }

        for (String substring : substrings) {
            if (internalClassName.contains(substring)) {
                return true;
            }
        }

        return false;
    }
}