1 package org.apache.maven.plugin.checkstyle;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import com.puppycrawl.tools.checkstyle.api.AuditEvent;
23
24 /**
25 * Tooling for Checkstyle rules conventions: names, categories.
26 *
27 * @author Hervé Boutemy
28 * @since 2.13
29 */
30 public final class RuleUtil
31 {
32 private RuleUtil()
33 {
34 // hide utility class constructor
35 }
36
37 private static final String CHECKSTYLE_PACKAGE = "com.puppycrawl.tools.checkstyle.checks";
38
39 /**
40 * Get the rule name from an audit event.
41 *
42 * @param event the audit event
43 * @return the rule name, which is the class name without package and removed eventual "Check" suffix
44 */
45 public static String getName( AuditEvent event )
46 {
47 return getName( event.getSourceName() );
48 }
49 /**
50 * Get the rule name from an audit event source name.
51 *
52 * @param eventSrcName the audit event source name
53 * @return the rule name, which is the class name without package and removed eventual "Check" suffix
54 */
55 public static String getName( String eventSrcName )
56 {
57 if ( eventSrcName == null )
58 {
59 return null;
60 }
61
62 if ( eventSrcName.endsWith( "Check" ) )
63 {
64 eventSrcName = eventSrcName.substring( 0, eventSrcName.length() - 5 );
65 }
66
67 return eventSrcName.substring( eventSrcName.lastIndexOf( '.' ) + 1 );
68 }
69
70 /**
71 * Get the rule category from an audit event.
72 *
73 * @param event the audit event
74 * @return the rule category, which is the last package name or "misc" or "extension"
75 */
76 public static String getCategory( AuditEvent event )
77 {
78 return getCategory( event.getSourceName() );
79 }
80
81 /**
82 * Get the rule category from an audit event source name.
83 *
84 * @param eventSrcName the audit event source name
85 * @return the rule category, which is the last package name or "misc" or "extension"
86 */
87 public static String getCategory( String eventSrcName )
88 {
89 if ( eventSrcName == null )
90 {
91 return null;
92 }
93
94 int end = eventSrcName.lastIndexOf( '.' );
95 eventSrcName = eventSrcName.substring( 0, end );
96
97 if ( CHECKSTYLE_PACKAGE.equals( eventSrcName ) )
98 {
99 return "misc";
100 }
101 else if ( !eventSrcName.startsWith( CHECKSTYLE_PACKAGE ) )
102 {
103 return "extension";
104 }
105
106 return eventSrcName.substring( eventSrcName.lastIndexOf( '.' ) + 1 );
107 }
108
109 public static Matcher[] parseMatchers( String[] specs )
110 {
111 Matcher[] matchers = new Matcher[specs.length];
112 int i = 0;
113 for ( String spec: specs )
114 {
115 spec = spec.trim();
116 Matcher matcher;
117 if ( Character.isUpperCase( spec.charAt( 0 ) ) )
118 {
119 // spec starting with uppercase is a rule name
120 matcher = new RuleMatcher( spec );
121 }
122 else if ( "misc".equals( spec ) )
123 {
124 // "misc" is a special case
125 matcher = new PackageMatcher( CHECKSTYLE_PACKAGE );
126 }
127 else if ( "extension".equals( spec ) )
128 {
129 // "extension" is a special case
130 matcher = new ExtensionMatcher();
131 }
132 else if ( !spec.contains( "." ) )
133 {
134 matcher = new PackageMatcher( CHECKSTYLE_PACKAGE + '.' + spec );
135 }
136 else
137 {
138 // by default, spec is a package name
139 matcher = new PackageMatcher( spec );
140 }
141 matchers[i++] = matcher;
142 }
143 return matchers;
144 }
145
146 /**
147 * Audit event source name matcher.
148 */
149 public interface Matcher
150 {
151 /**
152 * Does the event source name match?
153 * @param eventSrcName the event source name
154 * @return boolean
155 */
156 boolean match( String eventSrcName );
157 }
158
159 private static class RuleMatcher
160 implements Matcher
161 {
162 private final String rule;
163
164 public RuleMatcher( String rule )
165 {
166 this.rule = rule;
167 }
168
169 public boolean match( String eventSrcName )
170 {
171 return rule.equals( getName( eventSrcName ) );
172 }
173 }
174
175 private static class PackageMatcher
176 implements Matcher
177 {
178 private final String packageName;
179
180 public PackageMatcher( String packageName )
181 {
182 this.packageName = packageName;
183 }
184
185 public boolean match( String eventSrcName )
186 {
187 return eventSrcName.startsWith( packageName )
188 && !eventSrcName.substring( packageName.length() + 1 ).contains( "." );
189 }
190 }
191
192 /**
193 * An extension does not start with Checkstyle package.
194 */
195 private static class ExtensionMatcher
196 implements Matcher
197 {
198 public boolean match( String eventSrcName )
199 {
200 return !eventSrcName.startsWith( CHECKSTYLE_PACKAGE );
201 }
202 }
203 }