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
028 * a specified pattern.
029 *
030 * <p>
031 * This class extends {@link AbstractNameCheck} with support for access level
032 * restrictions. This allows the check to be configured to be applied to one of
033 * the four Java access levels: {@code public}, {@code protected},
034 * {@code "package"}, and {@code private}.
035 * </p>
036 *
037 * <p>Level is configured using the following properties:
038 * <ol>
039 * <li>applyToPublic, default true;</li>
040 * <li>applyToProtected, default true;</li>
041 * <li>applyToPackage, default true;</li>
042 * <li>applyToPrivate, default true;</li>
043 * </ol>
044 *
045 */
046public abstract class AbstractAccessControlNameCheck
047    extends AbstractNameCheck {
048
049    /** If true, applies the check be public members. */
050    private boolean applyToPublic = true;
051
052    /** If true, applies the check be protected members. */
053    private boolean applyToProtected = true;
054
055    /** If true, applies the check be "package" members. */
056    private boolean applyToPackage = true;
057
058    /** If true, applies the check be private members. */
059    private boolean applyToPrivate = true;
060
061    /**
062     * Creates a new {@code AbstractAccessControlNameCheck} instance.
063     *
064     * @param format
065     *                format to check with
066     * @param messageKey
067     *                the key for the message
068     */
069    protected AbstractAccessControlNameCheck(String format, String messageKey) {
070        super(format, messageKey);
071    }
072
073    @Override
074    protected boolean mustCheckName(DetailAST ast) {
075        return shouldCheckInScope(ast.findFirstToken(TokenTypes.MODIFIERS));
076    }
077
078    /**
079     * Should we check member with given modifiers.
080     *
081     * @param modifiers
082     *                modifiers of member to check.
083     * @return true if we should check such member.
084     */
085    protected boolean shouldCheckInScope(DetailAST modifiers) {
086        final boolean isProtected = modifiers
087                .findFirstToken(TokenTypes.LITERAL_PROTECTED) != null;
088        final boolean isPrivate = modifiers
089                .findFirstToken(TokenTypes.LITERAL_PRIVATE) != null;
090        final boolean isPublic = isPublic(modifiers);
091
092        final boolean isPackage = !(isPublic || isProtected || isPrivate);
093
094        return applyToPublic && isPublic
095                || applyToProtected && isProtected
096                || applyToPackage && isPackage
097                || applyToPrivate && isPrivate;
098    }
099
100    /**
101     * Checks if given modifiers has public access.
102     * There are 2 cases - it is either has explicit modifier, or it is
103     * in annotation or interface.
104     *
105     * @param modifiers - modifiers to check
106     * @return true if public
107     */
108    private static boolean isPublic(DetailAST modifiers) {
109        return modifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null
110                || ScopeUtil.isInAnnotationBlock(modifiers)
111                || ScopeUtil.isInInterfaceBlock(modifiers)
112                    // interface methods can be private
113                    && modifiers.findFirstToken(TokenTypes.LITERAL_PRIVATE) == null;
114    }
115
116    /**
117     * Setter to control if check should apply to public members.
118     *
119     * @param applyTo new value of the property.
120     */
121    public void setApplyToPublic(boolean applyTo) {
122        applyToPublic = applyTo;
123    }
124
125    /**
126     * Setter to control if check should apply to protected members.
127     *
128     * @param applyTo new value of the property.
129     */
130    public void setApplyToProtected(boolean applyTo) {
131        applyToProtected = applyTo;
132    }
133
134    /**
135     * Setter to control if check should apply to package-private members.
136     *
137     * @param applyTo new value of the property.
138     */
139    public void setApplyToPackage(boolean applyTo) {
140        applyToPackage = applyTo;
141    }
142
143    /**
144     * Setter to control if check should apply to private members.
145     *
146     * @param applyTo new value of the property.
147     */
148    public void setApplyToPrivate(boolean applyTo) {
149        applyToPrivate = applyTo;
150    }
151
152}