![JAR search and dependency download from the Maven repository](/logo.png)
com.thomasjensen.checkstyle.addons.checks.misc.MdlJsonConfig Maven / Gradle / Ivy
The newest version!
package com.thomasjensen.checkstyle.addons.checks.misc;
/*
* Checkstyle-Addons - Additional Checkstyle checks
* Copyright (c) 2015-2022, the Checkstyle Addons contributors
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 3, as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see .
*/
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import com.thomasjensen.checkstyle.addons.util.Util;
/**
* Deserialized version of the directories.json.
*/
@SuppressWarnings("unused")
public class MdlJsonConfig
implements SelfValidating
{
@JsonProperty
private String comment;
@JsonProperty
private Settings settings;
@JsonProperty
private Map structure;
/**
* Encapsulates the general settings which are supported in a directories.json.
*/
@SuppressWarnings("FieldMayBeFinal")
public static class Settings
implements SelfValidating
{
@JsonProperty
private int formatVersion = 1;
@JsonProperty
private String moduleRegex = "";
@JsonProperty
private String excludeRegex = Util.NEVER_MATCH.pattern();
@JsonProperty
private boolean allowNestedSrcFolder = false;
public int getFormatVersion()
{
return formatVersion;
}
public String getModuleRegex()
{
return moduleRegex;
}
public String getExcludeRegex()
{
return excludeRegex;
}
public boolean isAllowNestedSrcFolder()
{
return allowNestedSrcFolder;
}
@Override
public void validate()
throws ConfigValidationException
{
if (getFormatVersion() != 1) {
throw new ConfigValidationException("The settings field 'formatVersion' must be present unchanged");
}
ensureRegexSyntax("moduleRegex", moduleRegex);
ensureRegexSyntax("excludeRegex", excludeRegex);
}
}
/**
* An MDL Spec specifies the characteristics of one directory in the module directory layout, for example
* src/main/java
.
*/
@SuppressWarnings("FieldMayBeFinal")
@SuppressFBWarnings("EI_EXPOSE_REP")
public static class MdlSpec
implements SelfValidating
{
@JsonProperty
private String comment;
@JsonProperty
private String modules;
@JsonProperty
private boolean whitelist = false;
@JsonProperty
private List allow;
@JsonProperty
private List deny;
@CheckForNull
public String getComment()
{
return comment;
}
@JsonIgnore
@CheckForNull
public Pattern getModules()
{
return modules != null ? Pattern.compile(modules) : null;
}
public boolean isWhitelist()
{
return whitelist;
}
@CheckForNull
public List getAllow()
{
return allow;
}
@CheckForNull
public List getDeny()
{
return deny;
}
@Override
public void validate()
throws ConfigValidationException
{
if (modules != null) {
ensureRegexSyntax("modules", modules);
}
for (List list : Arrays.asList(allow, deny)) {
if (list != null) {
for (SpecElement element : list) {
element.validate();
}
}
}
}
}
/**
* The allow and deny lists in each MDL path specification are composed of elements of SpecElement
s.
*/
public static class SpecElement
implements SelfValidating
{
@JsonProperty
private MdlContentSpecType type = null;
@JsonProperty
private String spec = null;
/**
* No-args constructor.
*/
public SpecElement()
{
super();
}
/**
* Constructor for test cases.
*
* @param pType value of type
* @param pSpec value of spec
*/
SpecElement(@Nullable final MdlContentSpecType pType, @Nullable final String pSpec)
{
type = pType;
spec = pSpec;
}
public MdlContentSpecType getType()
{
return type;
}
public String getSpec()
{
return spec;
}
@Override
public void validate()
throws ConfigValidationException
{
if (spec == null) {
throw new ConfigValidationException("Required field 'spec' not set in SpecElement");
}
if (type == null) {
throw new ConfigValidationException("Required field 'type' not set in SpecElement");
}
if (type == MdlContentSpecType.SpecificPathRegex) {
ensureRegexSyntax("spec", spec);
}
}
@Override
public String toString()
{
final StringBuilder sb = new StringBuilder("{");
sb.append(type);
sb.append(", ");
if (spec != null) {
sb.append('\"').append(spec).append('\"');
}
else {
sb.append("null");
}
sb.append('}');
return sb.toString();
}
}
@CheckForNull
public String getComment()
{
return comment;
}
@Nonnull
public Settings getSettings()
{
return settings;
}
@Nonnull
@SuppressFBWarnings("EI_EXPOSE_REP")
public Map getStructure()
{
return structure;
}
@Override
public void validate()
throws ConfigValidationException
{
if (settings == null) {
throw new ConfigValidationException("Missing top-level field 'settings'");
}
settings.validate();
if (structure == null) {
throw new ConfigValidationException("Missing top-level field 'structure'");
}
for (String key1 : structure.keySet()) {
if (key1.length() == 0) {
throw new ConfigValidationException("Empty String used as MDL path");
}
if (key1.charAt(0) == '/' || key1.charAt(0) == '\\' || key1.charAt(key1.length() - 1) == '/' || key1.charAt(
key1.length() - 1) == '\\') {
throw new ConfigValidationException("Leading or trailing (back)slashes on MDL path: " + key1);
}
for (String key2 : structure.keySet()) {
if (!key1.equals(key2)) {
if (key1.startsWith(key2) || key2.startsWith(key1)) {
throw new ConfigValidationException("MDL paths '" + key1 + "' and '" + key2 + "' are nested");
}
}
}
}
for (final Map.Entry entry : structure.entrySet()) {
final MdlSpec mdlSpec = entry.getValue();
mdlSpec.validate();
if (mdlSpec.getDeny() != null) {
for (final SpecElement se : mdlSpec.getDeny()) {
if (se.getType() == MdlContentSpecType.FromPath) {
if (!structure.containsKey(se.getSpec())) {
throw new ConfigValidationException("Reference to unknown MDL path '" + se.getSpec() + "'");
}
if (entry.getKey().equals(se.getSpec())) {
throw new ConfigValidationException(
"Circular reference to MDL path '" + se.getSpec() + "'");
}
}
}
}
if (mdlSpec.getAllow() != null) {
for (final SpecElement se : mdlSpec.getAllow()) {
if (se.getType() == MdlContentSpecType.FromPath) {
throw new ConfigValidationException(
"\"" + MdlContentSpecType.FromPath + "\" may only occur in deny lists");
}
}
}
}
}
private static void ensureRegexSyntax(@Nonnull final String pFieldName, @Nonnull final String pRegex)
throws ConfigValidationException
{
try {
Pattern.compile(pRegex);
}
catch (PatternSyntaxException e) {
throw new ConfigValidationException("Invalid pattern in '" + pFieldName + "' field: " + pRegex, e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy