001///////////////////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
003// Copyright (C) 2001-2026 the original author or authors.
004//
005// This library is free software; you can redistribute it and/or
006// modify it under the terms of the GNU Lesser General Public
007// License as published by the Free Software Foundation; either
008// version 2.1 of the License, or (at your option) any later version.
009//
010// This library is distributed in the hope that it will be useful,
011// but WITHOUT ANY WARRANTY; without even the implied warranty of
012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013// Lesser General Public License for more details.
014//
015// You should have received a copy of the GNU Lesser General Public
016// License along with this library; if not, write to the Free Software
017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
018///////////////////////////////////////////////////////////////////////////////////////////////
019
020package com.puppycrawl.tools.checkstyle.checks.naming;
021
022import com.puppycrawl.tools.checkstyle.api.DetailAST;
023import com.puppycrawl.tools.checkstyle.api.TokenTypes;
024import com.puppycrawl.tools.checkstyle.utils.ScopeUtil;
025
026/**
027 * Abstract class for checking a class member (field/method)'s name conforms to a specified pattern.
028 *
029 * <p>
030 * This class extends {@link AbstractNameCheck} with support for access level
031 * restrictions. This allows the check to be configured to be applied to one of
032 * the four Java access levels: {@code public}, {@code protected},
033 * {@code "package"}, and {@code private}.
034 * </p>
035 *
036 * <p>Level is configured using the following properties:
037 * <ol>
038 * <li>applyToPublic, default true;</li>
039 * <li>applyToProtected, default true;</li>
040 * <li>applyToPackage, default true;</li>
041 * <li>applyToPrivate, default true;</li>
042 * </ol>
043 *
044 */
045public abstract class AbstractAccessControlNameCheck extends AbstractNameCheck {
046
047    /** If true, applies the check be public members. */
048    private boolean applyToPublic = true;
049
050    /** If true, applies the check be protected members. */
051    private boolean applyToProtected = true;
052
053    /** If true, applies the check be "package" members. */
054    private boolean applyToPackage = true;
055
056    /** If true, applies the check be private members. */
057    private boolean applyToPrivate = true;
058
059    /**
060     * Creates a new {@code AbstractAccessControlNameCheck} instance.
061     *
062     * @param format
063     *                format to check with
064     * @param messageKey
065     *                the key for the message
066     */
067    protected AbstractAccessControlNameCheck(String format, String messageKey) {
068        super(format, messageKey);
069    }
070
071    @Override
072    protected boolean mustCheckName(DetailAST ast) {
073        return shouldCheckInScope(ast.findFirstToken(TokenTypes.MODIFIERS));
074    }
075
076    /**
077     * Should we check member with given modifiers.
078     *
079     * @param modifiers
080     *                modifiers of member to check.
081     * @return true if we should check such member.
082     */
083    protected boolean shouldCheckInScope(DetailAST modifiers) {
084        final boolean isProtected = modifiers
085                .findFirstToken(TokenTypes.LITERAL_PROTECTED) != null;
086        final boolean isPrivate = modifiers
087                .findFirstToken(TokenTypes.LITERAL_PRIVATE) != null;
088        final boolean isPublic = isPublic(modifiers);
089
090        final boolean isPackage = !(isPublic || isProtected || isPrivate);
091
092        return applyToPublic && isPublic
093                || applyToProtected && isProtected
094                || applyToPackage && isPackage
095                || applyToPrivate && isPrivate;
096    }
097
098    /**
099     * Checks if given modifiers has public access.
100     * There are 2 cases - it is either has explicit modifier, or it is in annotation or interface.
101     *
102     * @param modifiers - modifiers to check
103     * @return true if public
104     */
105    private static boolean isPublic(DetailAST modifiers) {
106        return modifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null
107                || ScopeUtil.isInAnnotationBlock(modifiers)
108                || ScopeUtil.isInInterfaceBlock(modifiers)
109                    // interface methods can be private
110                    && modifiers.findFirstToken(TokenTypes.LITERAL_PRIVATE) == null;
111    }
112
113    /**
114     * Setter to control if check should apply to public members.
115     *
116     * @param applyTo new value of the property.
117     */
118    public void setApplyToPublic(boolean applyTo) {
119        applyToPublic = applyTo;
120    }
121
122    /**
123     * Setter to control if check should apply to protected members.
124     *
125     * @param applyTo new value of the property.
126     */
127    public void setApplyToProtected(boolean applyTo) {
128        applyToProtected = applyTo;
129    }
130
131    /**
132     * Setter to control if check should apply to package-private members.
133     *
134     * @param applyTo new value of the property.
135     */
136    public void setApplyToPackage(boolean applyTo) {
137        applyToPackage = applyTo;
138    }
139
140    /**
141     * Setter to control if check should apply to private members.
142     *
143     * @param applyTo new value of the property.
144     */
145    public void setApplyToPrivate(boolean applyTo) {
146        applyToPrivate = applyTo;
147    }
148
149}