/* * Copyright 2015 Lukas Krejci * * 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 org.revapi.java; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; import java.util.stream.Collectors; import org.jboss.dmr.ModelNode; /** * @author Lukas Krejci * @since 0.1 */ public final class AnalysisConfiguration { private final MissingClassReporting missingClassReporting; private final Set<String> useReportingCodes; private final boolean ignoreMissingAnnotations; private final Set<Pattern> classInclusionFilters; private final Set<Pattern> classExclusionFilters; private final Set<Pattern> packageInclusionFilters; private final Set<Pattern> packageExclusionFilters; public AnalysisConfiguration(MissingClassReporting missingClassReporting, Set<String> useReportingCodes, boolean ignoreMissingAnnotations, Set<Pattern> classInclusionFilters, Set<Pattern> classExclusionFilters, Set<Pattern> packageInclusionFilters, Set<Pattern> packageExclusionFilters) { this.missingClassReporting = missingClassReporting; this.useReportingCodes = useReportingCodes; this.ignoreMissingAnnotations = ignoreMissingAnnotations; this.classInclusionFilters = classInclusionFilters; this.classExclusionFilters = classExclusionFilters; this.packageInclusionFilters = packageInclusionFilters; this.packageExclusionFilters = packageExclusionFilters; } public static AnalysisConfiguration fromModel(ModelNode node) { MissingClassReporting reporting = readMissingClassReporting(node); Set<String> useReportingCodes = readUseReportingCodes(node); boolean ignoreMissingAnnotations = readIgnoreMissingAnnotations(node); ModelNode classesRegex = node.get("revapi", "java", "filter", "classes", "regex"); ModelNode packagesRegex = node.get("revapi", "java", "filter", "packages", "regex"); Set<Pattern> classInclusionFilters = readFilter(node.get("revapi", "java", "filter", "classes", "include"), classesRegex); Set<Pattern> classExclusionFilters = readFilter(node.get("revapi", "java", "filter", "classes", "exclude"), classesRegex); Set<Pattern> packageInclusionFilters = readFilter(node.get("revapi", "java", "filter", "packages", "include"), packagesRegex); Set<Pattern> packageExclusionFilters = readFilter(node.get("revapi", "java", "filter", "packages", "exclude"), packagesRegex); return new AnalysisConfiguration(reporting, useReportingCodes, ignoreMissingAnnotations, classInclusionFilters, classExclusionFilters, packageInclusionFilters, packageExclusionFilters); } public MissingClassReporting getMissingClassReporting() { return missingClassReporting; } public Set<String> getUseReportingCodes() { return useReportingCodes; } public boolean isIgnoreMissingAnnotations() { return ignoreMissingAnnotations; } public Set<Pattern> getClassExclusionFilters() { return classExclusionFilters; } public Set<Pattern> getClassInclusionFilters() { return classInclusionFilters; } public Set<Pattern> getPackageExclusionFilters() { return packageExclusionFilters; } public Set<Pattern> getPackageInclusionFilters() { return packageInclusionFilters; } private static MissingClassReporting readMissingClassReporting(ModelNode analysisConfig) { ModelNode config = analysisConfig.get("revapi", "java", "missing-classes", "behavior"); if (config.isDefined()) { switch (config.asString()) { case "report": return MissingClassReporting.REPORT; case "ignore": return MissingClassReporting.IGNORE; case "error": return MissingClassReporting.ERROR; default: throw new IllegalArgumentException("Unsupported value of revapi.java.missing-classes.behavior: '" + config.asString() + "'. Only 'report', 'ignore' and 'error' are recognized."); } } return MissingClassReporting.REPORT; } private static boolean readIgnoreMissingAnnotations(ModelNode analysisConfig) { ModelNode config = analysisConfig.get("revapi", "java", "missing-classes", "ignoreMissingAnnotations"); if (config.isDefined()) { return config.asBoolean(); } return false; } private static Set<String> readUseReportingCodes(ModelNode analysisConfig) { Set<String> ret = new HashSet<>(); ModelNode config = analysisConfig.get("revapi", "java", "reportUsesFor"); if (config.isDefined()) { for (ModelNode code : config.asList()) { ret.add(code.asString()); } } else { ret.add("java.missing.oldClass"); ret.add("java.missing.newClass"); ret.add("java.class.nonPublicPartOfAPI"); ret.add("java.class.externalClassExposedInAPI"); ret.add("java.class.externalClassNoLongerExposedInAPI"); } return ret; } private static Set<Pattern> readFilter(ModelNode filterNode, ModelNode regexNode) { if (!filterNode.isDefined()) { return Collections.emptySet(); } boolean isRegex = regexNode.isDefined() && regexNode.asBoolean(); return filterNode.asList().stream() .map(filter -> { if (isRegex) { return Pattern.compile(filter.asString()); } else { return Pattern.compile(Pattern.quote(filter.asString())); } }) .collect(Collectors.toSet()); } public enum MissingClassReporting { IGNORE, ERROR, REPORT } }