<?xml version="1.0"?>
<!--

     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
        "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
        "https://checkstyle.org/dtds/configuration_1_3.dtd">
<!--

  A Checkstyle configuration that checks against most of the recommendations
  in Joshua Bloch, Effective Java (highly recommended read!)

  This file does NOT duplicate the checks for whitespace settings,
  placement of curly braces, etc.  Only the rules that are explicitly
  mentioned in the book are enforced.

  Currently the amount of rules that can be automatically checked by
  Checkstyle is not very large, but adding more checks of this quality
  is a high priority goal for the development team.

-->

<module name="Checker">
    <property name="localeCountry" value="en"/>
    <property name="localeLanguage" value="en"/>

    <module name="TreeWalker">

        <!-- Item 4 - Avoid creating duplicate objects -->
        <module name="IllegalInstantiation">
            <property name="classes" value="java.lang.Boolean, java.lang.String"/>
        </module>

        <!-- Item 8 - Always override hashCode when you override equals -->
        <module name="EqualsHashCode"/>

        <!-- Item 12 - Make all fields private -->
        <module name="VisibilityModifier">
            <!-- TODO: add one or both of these back in? -->
            <property name="protectedAllowed" value="true"/>
            <property name="packageAllowed" value="true"/>
        </module>

        <!-- Item 15 - Design and document for inheritance or else prohibit it -->
        <!-- the module actually implements a very strict rule, it would be
             interesting to know whether Joshua meant what checkstyle implements.
             We feel this implementation is well suited as a warning,
             i.e. if you get error messages from this check you should be
             able to name a good reason to implement your code the way you do it,
             especially if you are designing a library and not an application.

        <module name="DesignForExtension">
          <property name="severity" value="warning"/>
        </module>
          -->

        <!-- Item 17 - Use interfaces only to define types -->
        <module name="InterfaceIsType"/>

        <!-- Item 25 - Design method signatures carefully -->
        <!-- Avoid long parameter lists -->
        <module name="ParameterNumber">
            <property name="max" value="6"/>
        </module>

        <!-- Item 28 - Write doc comments for all exposed API elements

        <module name="JavadocType">
          <property name="scope" value="protected"/>
        </module>
        <module name="JavadocMethod">
          <property name="scope" value="protected"/>
        </module>
        <module name="JavadocVariable">
          <property name="scope" value="protected"/>
        </module>
        -->


        <!-- Item 38 - Adhere to generally accepted naming conventions -->
        <module name="PackageName">
            <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]{1,22})*$"/>
        </module>
        <module name="TypeName"/>
        <module name="ConstantName"/>
        <module name="LocalFinalVariableName"/>
        <module name="LocalVariableName"/>
        <module name="MemberName"/>
        <module name="MethodName"/>
        <module name="ParameterName"/>
        <module name="StaticVariableName"/>

        <!-- Item 47 - Don't ignore exceptions -->
        <module name="EmptyBlock">
            <property name="tokens" value="LITERAL_CATCH"/>
            <!-- require a comment, change to stmt to require a statement -->
            <property name="option" value="text"/>
        </module>

        <!-- other sun checks -->
        <module name="RedundantImport"/>
        <module name="UnusedImports"/>
        <module name="ModifierOrder"/>
        <module name="RedundantModifier"/>
        <!-- current style has lots of occurrences of this, off for now -->
        <!--<module name="HiddenField"/>-->
        <module name="MissingSwitchDefault"/>
        <module name="DefaultComesLast"/>
        <!-- very liberal values for metrics, perhaps tighten some later -->
        <module name="JavaNCSS">
            <property name="severity" value="warning"/>
            <property name="methodMaximum" value="80"/>
            <property name="classMaximum" value="300"/>
        </module>
        <module name="ClassFanOutComplexity">
            <property name="severity" value="warning"/>
            <property name="max" value="22"/>
        </module>
        <module name="ClassDataAbstractionCoupling">
            <property name="severity" value="warning"/>
            <property name="max" value="14"/>
        </module>
        <module name="CyclomaticComplexity">
            <property name="severity" value="warning"/>
            <property name="max" value="14"/>
        </module>
        <!-- TODO: turn this back on? -->
        <!--<module name="ExplicitInitialization"/>-->
        <!-- turned off - instead, keep methods short and make
             parameters final in cases where confusion is possible -->
        <!--<module name="ParameterAssignment"/>-->
        <module name="IllegalType">
            <property name="illegalAbstractClassNameFormat" value="^$"/>
            <!-- otherwise default of '*Abstract' is illegal -->
            <property name="illegalClassNames" value="java.util.GregorianCalendar, java.util.Hashtable, java.util.HashSet, java.util.HashMap, java.util.ArrayList, java.util.LinkedHashMap, java.util.LinkedHashSet, java.util.TreeSet, java.util.TreeMap, java.util.Vector"/>
        </module>
        <module name="UpperEll"/>
        <!-- off for now - to allow parentheses which add clarity -->
        <!--<module name="UnnecessaryParentheses"/>-->
        <module name="FinalClass"/>
        <!-- good to have but pollutes coverage -->
        <!--<module name="HideUtilityClassConstructor"/>-->
        <module name="MutableException"/>
        <!-- add below in eventually? -->
        <!--<module name="LeftCurly">-->
        <!--<property name="option" value="nl"/>-->
        <!--<property name="tokens" value="CLASS_DEF,INTERFACE_DEF"/>-->
        <!--</module>-->
        <!-- add below in eventually for consistency -->
        <!--<module name="ArrayTypeStyle"/>-->

        <module name="SuppressionCommentFilter">
            <property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)"/>
            <property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
            <property name="checkFormat" value="$1"/>
        </module>

    </module>
    <!-- Item 6 - Avoid finalizers -->
    <!-- this will not find violations that contain linebreaks -->
    <module name="RegexpMultiline">
        <property name="format"
                  value="((public)|(protected))\s+void\s+finalize\(\s*\)"/>
    </module>
    <module name="RegexpHeader">
        <property name="headerFile" value="${rootProject.projectDir}/config/checkstyle/codeHeader.txt"/>
    </module>
    <module name="JavadocPackage">
        <property name="severity" value="info"/>
        <property name="allowLegacy" value="true"/>
    </module>

<!--
    <module name="au.com.redhillconsulting.simian.SimianCheck">
        <property name="threshold" value="8"/>
        &lt;!&ndash; remove language once Simian understands Groovy &ndash;&gt;
        <property name="language" value="java"/>
    </module>
-->
</module>
