[MCHECKSTYLE-289] enableRulesSummary option does not show Rules with
default configuration

Add parameter to explicitly show rules without any violations in the
Rules summary.
diff --git a/src/it/MCHECKSTYLE-289/checkstyle.xml b/src/it/MCHECKSTYLE-289/checkstyle.xml
new file mode 100644
index 0000000..564a7ab
--- /dev/null
+++ b/src/it/MCHECKSTYLE-289/checkstyle.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
+<module name="Checker">
+  <module name="TreeWalker">
+    <module name="OuterTypeFilename"/>
+  </module>
+  <!-- add module that is not a check to verify that it does not interfere -->
+  <module name="SuppressionCommentFilter"/>
+</module>
diff --git a/src/it/MCHECKSTYLE-289/pom.xml b/src/it/MCHECKSTYLE-289/pom.xml
new file mode 100644
index 0000000..1ad0dcb
--- /dev/null
+++ b/src/it/MCHECKSTYLE-289/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.maven.plugins.checkstyle</groupId>
+  <artifactId>mcheckstytle-289</artifactId>
+  <version>1.0</version>
+  <url>https://issues.apache.org/jira/browse/MCHECKSTYLE-289</url>
+  <description>Tests that setting skipEmptyViolationRules to false correctly shows rules with no violations</description>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>@pom.version@</version>
+        <configuration>
+          <configLocation>checkstyle.xml</configLocation>
+          <skipEmptyViolationRules>false</skipEmptyViolationRules>
+        </configuration>
+        <reportSets>
+          <reportSet>
+            <reports>
+              <report>checkstyle</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+    </plugins>
+  </reporting>
+</project>
diff --git a/src/it/MCHECKSTYLE-289/src/main/java/org/MyClass.java b/src/it/MCHECKSTYLE-289/src/main/java/org/MyClass.java
new file mode 100644
index 0000000..967d603
--- /dev/null
+++ b/src/it/MCHECKSTYLE-289/src/main/java/org/MyClass.java
@@ -0,0 +1,26 @@
+package org;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * My Class.
+ */
+public class MyClass {
+}
diff --git a/src/it/MCHECKSTYLE-289/verify.groovy b/src/it/MCHECKSTYLE-289/verify.groovy
new file mode 100644
index 0000000..c0f3700
--- /dev/null
+++ b/src/it/MCHECKSTYLE-289/verify.groovy
@@ -0,0 +1,22 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+def html = new File( basedir, 'target/site/checkstyle.html' ).text;
+assert html =~ /(?s)<td>misc<\/td>.*?<td>.*?OuterTypeFilename.*?<\/td>.*?<td>0<\/td>/
diff --git a/src/main/java/org/apache/maven/plugins/checkstyle/AbstractCheckstyleReport.java b/src/main/java/org/apache/maven/plugins/checkstyle/AbstractCheckstyleReport.java
index 3b958ff..a6ed116 100644
--- a/src/main/java/org/apache/maven/plugins/checkstyle/AbstractCheckstyleReport.java
+++ b/src/main/java/org/apache/maven/plugins/checkstyle/AbstractCheckstyleReport.java
@@ -360,6 +360,14 @@
     private boolean enableRSS;
 
     /**
+     * Specifies if rules with no violations should be skipped from the Rules summary.
+     *
+     * @since 3.0.1
+     */
+    @Parameter( property = "checkstyle.skipEmptyViolationRules", defaultValue = "true" )
+    private boolean skipEmptyViolationRules;
+
+    /**
      * SiteTool.
      *
      * @since 2.2
@@ -740,6 +748,7 @@
         generator.setEnableSeveritySummary( enableSeveritySummary );
         generator.setEnableFilesSummary( enableFilesSummary );
         generator.setEnableRSS( enableRSS );
+        generator.setSkipEmptyViolationRules( skipEmptyViolationRules );
         generator.setCheckstyleConfig( results.getConfiguration() );
         if ( linkXRef )
         {
diff --git a/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleReportGenerator.java b/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleReportGenerator.java
index aae277d..d179e81 100644
--- a/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleReportGenerator.java
+++ b/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleReportGenerator.java
@@ -65,6 +65,8 @@
 
     private boolean enableFilesSummary;
 
+    private boolean skipEmptyViolationRules;
+
     private boolean enableRSS;
 
     private final SiteTool siteTool;
@@ -740,6 +742,16 @@
         this.enableRSS = enableRSS;
     }
 
+    public boolean isSkipEmptyViolationRules()
+    {
+        return skipEmptyViolationRules;
+    }
+
+    public void setSkipEmptyViolationRules( boolean showEmptyViolationRules )
+    {
+        this.skipEmptyViolationRules = showEmptyViolationRules;
+    }
+
     public String getXrefLocation()
     {
         return xrefLocation;
@@ -814,24 +826,24 @@
 
                 // count rule violations
                 long violations = 0;
-                AuditEvent lastMatchedEvent = null;
                 for ( List<AuditEvent> errors : results.getFiles().values() )
                 {
                     for ( AuditEvent event : errors )
                     {
                         if ( matchRule( event, ruleName, fixedmessage, configSeverity ) )
                         {
-                            lastMatchedEvent = event;
                             violations++;
                         }
                     }
                 }
 
-                if ( violations > 0 ) // forget rules without violations
+                if ( violations > 0 || !skipEmptyViolationRules ) // forget rules without violations when not requested
                 {
-                    String category = RuleUtil.getCategory( lastMatchedEvent );
-
-                    result.add( new ConfReference( category, childConfig, parent, violations, result.size() ) );
+                    String category = RuleUtil.getCategory( results.getModuleNameMap().get( ruleName ) );
+                    if ( category != null )
+                    {
+                        result.add( new ConfReference( category, childConfig, parent, violations, result.size() ) );
+                    }
                 }
             }
         }
diff --git a/src/main/java/org/apache/maven/plugins/checkstyle/exec/CheckstyleModuleFactory.java b/src/main/java/org/apache/maven/plugins/checkstyle/exec/CheckstyleModuleFactory.java
new file mode 100644
index 0000000..a5ba0fd
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/checkstyle/exec/CheckstyleModuleFactory.java
@@ -0,0 +1,64 @@
+package org.apache.maven.plugins.checkstyle.exec;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.puppycrawl.tools.checkstyle.PackageObjectFactory;
+import com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter;
+import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
+
+/**
+ * Extension of the package object factory, which remembers the check class name from a given name.
+ *
+ * @author gboue
+ */
+public class CheckstyleModuleFactory
+    extends PackageObjectFactory
+{
+
+    private Map<String, String> moduleNameMap = new ConcurrentHashMap<>();
+
+    public CheckstyleModuleFactory( Set<String> packageNames, ClassLoader moduleClassLoader )
+    {
+        super( packageNames, moduleClassLoader );
+    }
+
+    @Override
+    public Object createModule( String name )
+        throws CheckstyleException
+    {
+        Object module = super.createModule( name );
+        if ( module instanceof AbstractViolationReporter )
+        {
+            moduleNameMap.put( name, module.getClass().getName() );
+        }
+        return module;
+    }
+
+    public Map<String, String> getModuleNameMap()
+    {
+        return Collections.unmodifiableMap( moduleNameMap );
+    }
+
+}
diff --git a/src/main/java/org/apache/maven/plugins/checkstyle/exec/CheckstyleResults.java b/src/main/java/org/apache/maven/plugins/checkstyle/exec/CheckstyleResults.java
index a82870f..6a85098 100644
--- a/src/main/java/org/apache/maven/plugins/checkstyle/exec/CheckstyleResults.java
+++ b/src/main/java/org/apache/maven/plugins/checkstyle/exec/CheckstyleResults.java
@@ -38,6 +38,7 @@
 public class CheckstyleResults
 {
     private Map<String, List<AuditEvent>> files;
+    private Map<String, String> moduleNameMap;
 
     private Configuration configuration;
 
@@ -141,4 +142,14 @@
     {
         this.configuration = configuration;
     }
+
+    public Map<String, String> getModuleNameMap()
+    {
+        return moduleNameMap;
+    }
+
+    public void setModuleNameMap( Map<String, String> moduleNameMap )
+    {
+        this.moduleNameMap = moduleNameMap;
+    }
 }
diff --git a/src/main/java/org/apache/maven/plugins/checkstyle/exec/DefaultCheckstyleExecutor.java b/src/main/java/org/apache/maven/plugins/checkstyle/exec/DefaultCheckstyleExecutor.java
index 94a01e0..d7be0a4 100644
--- a/src/main/java/org/apache/maven/plugins/checkstyle/exec/DefaultCheckstyleExecutor.java
+++ b/src/main/java/org/apache/maven/plugins/checkstyle/exec/DefaultCheckstyleExecutor.java
@@ -157,7 +157,10 @@
 
         setUpCheckstyleClassloader( checker, classPathStrings, outputDirectories );
 
-        checker.setModuleClassLoader( Thread.currentThread().getContextClassLoader() );
+        ClassLoader moduleClassLoader = Thread.currentThread().getContextClassLoader();
+        CheckstyleModuleFactory moduleFactory =
+            new CheckstyleModuleFactory( PackageNamesLoader.getPackageNames( moduleClassLoader ), moduleClassLoader );
+        checker.setModuleFactory( moduleFactory );
 
         if ( filterSet != null )
         {
@@ -254,7 +257,9 @@
             }
         }
 
-        return checkerListener.getResults();
+        CheckstyleResults results = checkerListener.getResults();
+        results.setModuleNameMap( moduleFactory.getModuleNameMap() );
+        return results;
     }
 
     private void setUpCheckstyleClassloader( Checker checker,