View Javadoc
1   package org.apache.maven.plugins.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 java.util.ArrayList;
23  import java.util.List;
24  
25  import org.codehaus.plexus.util.StringUtils;
26  
27  import com.puppycrawl.tools.checkstyle.api.AuditEvent;
28  
29  /**
30   * Tooling for Checkstyle rules conventions: names, categories.
31   *
32   * @author Hervé Boutemy
33   * @since 2.13
34   */
35  public final class RuleUtil
36  {
37      private RuleUtil()
38      {
39          // hide utility class constructor
40      }
41      
42      private static final String CHECKSTYLE_PACKAGE = "com.puppycrawl.tools.checkstyle.checks";
43  
44      /**
45       * Get the rule name from an audit event.
46       *
47       * @param event the audit event
48       * @return the rule name, which is the class name without package and removed eventual "Check" suffix
49       */
50      public static String getName( AuditEvent event )
51      {
52          return getName( event.getSourceName() );
53      }
54      /**
55       * Get the rule name from an audit event source name.
56       *
57       * @param eventSrcName the audit event source name
58       * @return the rule name, which is the class name without package and removed eventual "Check" suffix
59       */
60      public static String getName( String eventSrcName )
61      {
62          if ( eventSrcName == null )
63          {
64              return null;
65          }
66  
67          if ( eventSrcName.endsWith( "Check" ) )
68          {
69              eventSrcName = eventSrcName.substring( 0, eventSrcName.length() - 5 );
70          }
71  
72          return eventSrcName.substring( eventSrcName.lastIndexOf( '.' ) + 1 );
73      }
74  
75      /**
76       * Get the rule category from an audit event.
77       *
78       * @param event the audit event
79       * @return the rule category, which is the last package name or "misc" or "extension"
80       */
81      public static String getCategory( AuditEvent event )
82      {
83          return getCategory( event.getSourceName() );
84      }
85  
86      /**
87       * Get the rule category from an audit event source name.
88       *
89       * @param eventSrcName the audit event source name
90       * @return the rule category, which is the last package name or "misc" or "extension"
91       */
92      public static String getCategory( String eventSrcName )
93      {
94          if ( eventSrcName == null )
95          {
96              return null;
97          }
98  
99          int end = eventSrcName.lastIndexOf( '.' );
100         eventSrcName = end == -1 ? eventSrcName : eventSrcName.substring( 0,  end );
101 
102         if ( CHECKSTYLE_PACKAGE.equals( eventSrcName ) )
103         {
104             return "misc";
105         }
106         else if ( !eventSrcName.startsWith( CHECKSTYLE_PACKAGE ) )
107         {
108             return "extension";
109         }
110 
111         return eventSrcName.substring( eventSrcName.lastIndexOf( '.' ) + 1 );
112     }
113 
114     public static List<Matcher> parseMatchers( String[] specs )
115     {
116         List<Matcher> matchers = new ArrayList<>();
117         for ( String spec : specs )
118         {
119             if ( StringUtils.isBlank( spec ) )
120             {
121                 continue;
122             }
123             spec = spec.trim();
124             Matcher matcher;
125             if ( Character.isUpperCase( spec.charAt( 0 ) ) )
126             {
127                 // spec starting with uppercase is a rule name
128                 matcher = new RuleMatcher( spec );
129             }
130             else if ( "misc".equals( spec ) )
131             {
132                 // "misc" is a special case
133                 matcher = new PackageMatcher( CHECKSTYLE_PACKAGE );
134             }
135             else if ( "extension".equals( spec ) )
136             {
137                 // "extension" is a special case
138                 matcher = new ExtensionMatcher();
139             }
140             else if ( !spec.contains( "." ) )
141             {
142                 matcher = new PackageMatcher( CHECKSTYLE_PACKAGE + '.' + spec );
143             }
144             else
145             {
146                 // by default, spec is a package name
147                 matcher = new PackageMatcher( spec );
148             }
149             matchers.add( matcher );
150         }
151         return matchers;
152     }
153 
154     /**
155      * Audit event source name matcher.
156      */
157     public interface Matcher
158     {
159         /**
160          * Does the event source name match?
161          * @param eventSrcName the event source name
162          * @return boolean
163          */
164         boolean match( String eventSrcName );
165     }
166 
167     private static class RuleMatcher
168         implements Matcher
169     {
170         private final String rule;
171 
172         RuleMatcher( String rule )
173         {
174             this.rule = rule;
175         }
176 
177         public boolean match( String eventSrcName )
178         {
179             return rule.equals( getName( eventSrcName ) );
180         }
181     }
182 
183     private static class PackageMatcher
184         implements Matcher
185     {
186         private final String packageName;
187 
188         PackageMatcher( String packageName )
189         {
190             this.packageName = packageName;
191         }
192 
193         public boolean match( String eventSrcName )
194         {
195             return eventSrcName.startsWith( packageName )
196                 && !eventSrcName.substring( packageName.length() + 1 ).contains( "." );
197         }
198     }
199 
200     /**
201      * An extension does not start with Checkstyle package.
202      */
203     private static class ExtensionMatcher
204         implements Matcher
205     {
206         public boolean match( String eventSrcName )
207         {
208             return !eventSrcName.startsWith( CHECKSTYLE_PACKAGE );
209         }
210     }
211 }