Commit 998a802c authored by Hallvard Trætteberg's avatar Hallvard Trætteberg
Browse files

Fjernet simple-example, konfigurert pages

parent 30f6732a
image: gradle:jdk12
image: gradle:jdk16-hotspot
before_script:
- export GRADLE_USER_HOME=`pwd`/.gradle
......@@ -14,5 +14,9 @@ build:
- ./gradlew -Pci=gitlab build
artifacts:
paths:
- lectures/build/docs
expire_in: 1 week
- public/lectures/build/docs
pages:
script:
- ./gradlew -Pci=gitlab build
- cp -r lectures/build/docs/asciidoc public/lectures
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "gradle run",
"type": "shell",
"command": "gradle",
"args": ["run"]
},
{
"label": "gradle version",
"type": "shell",
"command": "gradle",
"args": ["--version"]
},
{
"label": "java -version",
"type": "shell",
"command": "java",
"args": ["-version"]
},
{
"label": "sdk use java 12.0.2-open",
"type": "shell",
"command": "sdk",
"args": ["use", "java", "12.0.2-open"]
}
]
}
\ No newline at end of file
rootProject.name = 'course-material'
include 'lectures'
include 'simpleexample'
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="bin/main" path="src/main/java">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/main" path="src/main/resources">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/java">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/resources">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-10/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build/
bin/
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>simpleexample</name>
<comment>Project simpleexample created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>
connection.project.dir=
eclipse.preferences.version=1
# Simpleexample
Dette prosjektet er et eksempel på en nokså minimalistisk trelagsapplikasjon, altså med et domenelag, brukergrensesnitt (UI) og persistens (lagring). Prosjektet inneholder tester for alle lagene, med rimelig god dekningsgrad. Prosjektet er konfigurert med gradle som byggesystem.
## Organisering av koden
Prosjektet er organisert med 2 * 2 = 4 kildekodemapper, kode og ressurser for henholdsvis applikasjonen selv og testene:
- **src/main/java** for koden til applikasjonen
- **src/main/resources** for tilhørende ressurser, f.eks. data-filer og FXML-filer, som brukes av applikasjonen.
- **src/test/java** for testkoden
- **src/test/resources** for tilhørende ressurser, f.eks. data-filer og FXML-filer, som brukes av testene.
Dette er en vanlig organisering for prosjekter som bygges med gradle (og maven).
## Domenelaget
Domenelaget inneholder alle klasser og logikk knyttet til dataene som applikasjonen handler om og håndterer. Dette laget skal være helt uavhengig av brukergrensesnittet eller lagingsteknikken som brukes.
Vår app handler om samlinger av såkalte geo-lokasjoner, altså steder identifisert med lengde- og breddegrader. Domenelaget inneholder klasser for å representere og håndtere slike, og disse finnes i **[simpleex.core](src/main/java/simpleex/core/README.md)**-pakken.
## Brukergrensesnittlaget
Brukergrensesnittlaget inneholder alle klasser og logikk knyttet til visning og handlinger på dataene i domenelaget. Brukergrensesnittet til vår app viser frem en liste av geo-lokasjoner, den som velges vises på et kart. En flytte og legge til geo-lokasjoner. Samlingen med geo-lokasjoner kan lagres og evt. leses inn igjen.
Brukergrensesnittet er laget med JavaFX og FXML og finnes i **[simpleex.ui](src/main/java/simpleex/ui/README.md)**-pakken (JavaFX-koden i **src/main/java** og FXML-filen i **src/main/resources**)
## Persistenslaget
Persistenslaget inneholder alle klasser og logikk for lagring (skriving og lesing) av dataene i domenelaget. Vårt persistenslag implementerer fillagring med JSON-syntaks.
Persistenslaget finnes i **[simpleex.json](src/main/java/simpleex/json/README.md)**-pakken.
## Bygging med gradle
For litt mer komplekse prosjekter, er det lurt å bruke et såkalt byggeverktøy, f.eks. gradle eller maven, for å automatisere oppgaver som kjøring av tester, sjekk av ulike typer kvalitet osv. Vårt prosjekt er konfigurert til å bruke [gradle](https://gradle.org), og følgelig har prosjektet en del filer og mapper spesifikt for det:
- gradle, gradlew og gradlew.bat - mappe og filer for kjøring av gradle, som regel rigget opp en gang for alle ved opprettelse av prosjektet
- settings.gradle - inneholder navnet på prosjektet og evt. navnet på mapper for delprosjekter (ikke brukt her)
- build.gradle - konfigurasjon av gradle-tillegg basert på typen prosjekt
Av disse er det build.gradle som krever mest forklaring, settings.gradle trenger bare å inneholde én linje, som navngir prosjektet: `rootProject.name = 'simpleexample'`. For litt bakgrunn om bygging generelt og gradle spesielt, se [her](ci-gradle.md).
Vårt gradle-bygg er satt opp med tillegg for java-applikasjoner generelt (**application**) og med JavaFX spesielt (**org.openjfx.javafxplugin**). Vi trenger (minst) java-versjon 10 og javafx-version 11.
I tillegg bruker vi diverse kodekvalitetsanalyseverktøy ([jacoco](https://github.com/jacoco/jacoco) med **[jacoco](https://docs.gradle.org/current/userguide/jacoco_plugin.html)**, [PMD](https://pmd.github.io) med **[pmd](https://docs.gradle.org/current/userguide/pmd_plugin.html)**, [spotbugs](https://spotbugs.github.io) med **[com.github.spotbugs](https://spotbugs.readthedocs.io/en/latest/gradle.html)** og [checkstyle](https://checkstyle.sourceforge.io) med **[checkstyle](https://docs.gradle.org/current/userguide/checkstyle_plugin.html)**). Disse er satt opp slik at de ikke stopper bygget om ikke alt er på stell. spotbugs er satt opp til å lage rapport med html i stedet for xml.
De fleste avhengighetene hentes fra de vanlige sentrale repo-ene, med unntak av FxMapControl som er lagt ved som jar-fil i **libs**-mappa.
plugins {
// java application with main method
id 'application'
// use javafx modules
id 'org.openjfx.javafxplugin' version '0.0.8'
// test coverage
id 'jacoco'
// code quality with PMD
id 'pmd'
// code quality with SpotBugs
id 'com.github.spotbugs' version '2.0.0'
// code quality with checkstyle
id 'checkstyle'
}
repositories {
jcenter()
maven {
url "https://plugins.gradle.org/m2/"
}
flatDir {
dirs 'libs'
}
}
application {
sourceCompatibility = JavaVersion.VERSION_1_10
targetCompatibility = JavaVersion.VERSION_1_10
mainClassName = 'simpleex.ui.FxApp' // application plugin
}
// javafx specific way of specifying dependencies
javafx {
version = '11'
modules = [ 'javafx.controls', 'javafx.fxml' ]
// run with --debug-jvm flag and
// launch debugger using Remote Java Application debug launch configuration
}
test {
// don't run UI test on server (that cannot run javafx)
if (project.hasProperty('ci') && "$ci" == 'gitlab') {
exclude 'simpleex/ui/*'
}
}
pmd {
// See https://docs.gradle.org/current/dsl/org.gradle.api.plugins.quality.PmdExtension.html
ignoreFailures = true
// Consider turning these off
// <rule ref="category/java/errorprone.xml/BeanMembersShouldSerialize" />
// <rule ref="category/java/errorprone.xml/DataflowAnomalyAnalysis" />
}
spotbugs {
// see http://gradle.monochromeroad.com/docs/dsl/org.gradle.api.plugins.quality.FindBugsExtension.html
ignoreFailures = true
}
// To generate an HTML report instead of XML
tasks.withType(com.github.spotbugs.SpotBugsTask) {
reports {
xml.enabled = false
html.enabled = true
}
}
checkstyle {
configFile = project.file("config/checkstyle/google_checks.xml")
}
dependencies {
// persistens
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
// brukergrensesnitt
implementation name: 'fx-map-control-1.0'
testImplementation 'junit:junit:4.12'
// brukergrensesnitt
testImplementation 'org.testfx:testfx-core:4.0.16-alpha'
testImplementation 'org.testfx:testfx-junit:4.0.16-alpha'
testImplementation 'org.mockito:mockito-core:2.28.2'
}
# Bygging med gradle
## Hva er bygging?
Moderne IDE-er gjør det nokså greit å sett opp et prosjekt slik at kompilering gjøres automatisk og kontinuerlig og kjøring gjøres med et tastetrykk eller klikk. I det skjulte håndteres riktig oppsett og bruk av biblioteker, tilsvarende å kalle java-kompilatoren med riktig classpath (evt. modulepath med den siste versjonenen av java). Så mens man i gamle dager måtte skrive inn kompileringskommandoer i terminal, så gjøres det nå automatisk. I tillegg kommer editoren med alskens automatiske forslag til koden basert på full oversikt over tilgjengelige API-er.
Dette er vel og bra, men utvikling av applikasjoner handler ikke bare om å skrive kode, det er mange relaterte aktiviteter som er med og sikrer kvaliteten. Hvis en f.eks. skriver tester, så må disse forholde seg til egne testbibliotek (som [junit](https://junit.org/) og [mockito](https://site.mockito.org)) og kjøres jevnlig. Testkjøring av systemer som består av mange moduler, kanskje én av dem er en web-server som skal startes som en del av en test, gjør det mer komplisert.
Det er lurt å måle hvor stor del av koden som faktisk kjøres av tester, f.eks. med [jacoco](https://github.com/jacoco/jacoco). Noen prosjekter består av mange deler som både testes hver for seg og sammen. Det finnes andre kvaliteter enn korrekthet som også kan analyseres av diverse verktøy, f.eks. ryddighet, om man har fulgt konvensjoner for koding og unngått typiske kodingsfeil.
Hvis alt dette skal gjøres/kjøres manuelt, så gidder man ikke å gjøre det (ofte nok). IDE-er kan riktignok være til hjelp, men da blir det til gjengjeld opp til hver utvikler å sette det opp og det kan kreve nokså mye konfigurasjon. I stedet konfigurerer man prosjektet til å bruke et såkalt *byggeverktøy*, som lar deg kjøre utvalgte *byggeoppgaver* i riktig sekvens, basert på deklarasjoner om hva slags prosjekt en har, hvilke byggetrinn som skal være med og detaljer ved disse. Innstillingene er uavhengig av hvilken IDE du bruker, skrevet i et (mer eller mindre) leselig format og kan sjekkes inn i kode-repo og deles med alle.
## Gradle
[Gradle](https://docs.gradle.org/current/userguide/userguide.html) er et slikt byggesystem, som automatiserer oppgaver knyttet til utvikling og kvalitetssikring av programvare, f.eks.
kompilering, kjøring av enhetstester og integrasjonstester, konvertering av dokumentasjon til HTML, pakking som kjørbart program, osv. Det finnes teknisk sett ikke grenser for hva byggesystem som gradle kan gjøre, generelt handler det om å automatisere bort alt praktisk fikkel, som ellers hindrer en å jobbe effektivt.
Det finnes flere byggesystem, de viktigste i Java-verdenen er [Maven](https://maven.apache.org) og altså Gradle, mens Javascript-verdenen har sine, bl.a. [npm](https://docs.npmjs.com). Når vi velger å bruke gradle, så er det fordi det er enklere å skrive og lese oppsettet og trigge kjøring, mer fleksiblet, og det vi ønsker å automatisere i akkurat dette prosjektet håndteres godt av Gradle. For andre Java-prosjekter [kan Maven være et bedre alternativ](https://phauer.com/2018/moving-back-from-gradle-to-maven/).
Gradle er bygget rundt tre sentrale elementer:
- oppgaver (tasks) - det som automatiseres, f.eks. kompilering, kjøring av tester, osv.
- prosjekter - enhetene som oppgaver utføres innenfor
- tillegg (plugins) - angir hvilke oppgaver som hører til et visst type prosjekt
Disse tre elementene beskrives i to filer. **settings.gradle**-fila angir navn på prosjektet og eventuelle delprosjekter. Resten angis i **build.gradle**-fila, bl.a. hvilke avhengigheter det er til eksterne moduler og mellom prosjektene, hvilke tillegg som bør aktiveres for disse prosjektene (basert på hva slags type prosjekt det er) og hvordan hver type oppgave skal konfigureres.
Det litt spesielle med Gradle er at filene for å sette opp et Gradle-bygg egentlig er [kode skrevet i det Java-lignende språket Groovy](https://docs.gradle.org/current/userguide/groovy_build_script_primer.html). Koden brukes primært til konfigurasjon, altså bygge opp beskrivelsen av oppgavene, prosjektene og tilleggene og. API-et er utformet slik at koden skal se deklarativ ut.
En kan flette inn vanlig kode også, hvis en skjønner litt om hvordan API-et virker. Dette gir enorm fleksibilitet, men kan også gjøre filene vanskelige å forstå.
## Gradle-tillegg
`plugins`-blokken i **build.gradle** angir hvilke tillegg som skal aktiveres for prosjektet. Det handler dels om hva slags prosjekt en har, f.eks. om det er et Java-prosjekt og evt. bruker JavaFX, dels om hva som skal automatiseres. Deklarasjonen under angir at prosjektet er et Java-applikasjonsprosjekt og en ønsker å automatisere måling av testdekningsgrad (code coverage) med **jacoco**.
```
plugins {
// java application with main method
id 'application'
// test coverage
id 'jacoco'
}
```
## Konfigurasjon av oppgaver
For hvert tillegg vil en gjerne ha ytterligere konfigurasjon, enten som enkeltinstruksjoner eller blokker. F.eks. angir instruksjonen `mainClassName = ...` hvilken klasse som inneholder `main`-metoden, og dette brukes av `application`-tillegget. Detaljene finner en typisk ved å google, prøv f.eks. å søke på `gradle application plugin`.
## Avhengigheter
En av de viktigste blokkene i **build.gradle** er `dependencies`, altså *avhengigheter*. Her lister man opp hvilke kodebiblioteker (jar-filer) ens egen kode er avhengig av og til hva slags formål. Dette hjelper ulike tillegg å bruke riktig classpath til kompilering og kjøring av både vanlig kode og testkoden. Blokken under angir f.eks. at koden bruker `jackson-databind`-biblioteket og at en til testing også trenger `junit`-biblioteket:
```
dependencies {
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
testImplementation 'junit:junit:4.12'
}
```
Denne blokken angir hvilke biblioteker en trenger, men ikke hvor de finnes. Med `repositories`-blokken lister en opp hvor Gradle vil søke etter biblioteker (inkludert Gradle-tilleggene). De fleste vanlige bibliotek finnes i `jcenter()`, men det hender en må inkludere jar-filer (i mapper) i prosjektet. Med blokken under vil Gradle først søke etter biblioteker i `jcenter()` og deretter i mappa `libs`.
```
repositories {
jcenter()
flatDir {
dirs 'libs'
}
}
```
Formatet for identifikasjon av et bibliotek er avhengig av hvor (hva slags sted) det finnes. `jcenter()` bruker såkalte *maven-koordinater* på formatet *gruppe*:*navn*:*versjon*. Så siden `jackson`-biblioteket finnes i `jcenter()` så brukes `com.fasterxml.jackson.core:jackson-databind:2.9.8` i eksemplet over. Hvis en har et bibliotek i en lokal mappe, så brukes `name:` etterfulgt av jar-filnavnet (uten .jar).
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<!--
Checkstyle configuration that checks the Google coding conventions from Google Java Style
that can be found at https://google.github.io/styleguide/javaguide.html
Checkstyle is very configurable. Be sure to read the documentation at
http://checkstyle.sf.net (or in your downloaded distribution).
To completely disable a check, just comment it out or delete it from the file.
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
-->
<module name = "Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Excludes all 'module-info.java' files -->
<!-- See https://checkstyle.org/config_filefilters.html -->
<module name="BeforeExecutionExclusionFileFilter">
<property name="fileNamePattern" value="module\-info\.java$"/>
</module>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="TreeWalker">
<module name="OuterTypeFilename"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="LineLength">
<property name="max" value="100"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="AvoidStarImport"/>
<module name="OneTopLevelClass"/>
<module name="NoLineWrap"/>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces"/>
<module name="LeftCurly"/>
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
LITERAL_DO"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/>
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyLambdas" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapDot"/>
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapComma"/>
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/258 -->
<property name="id" value="SeparatorWrapEllipsis"/>
<property name="tokens" value="ELLIPSIS"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/259 -->
<property name="id" value="SeparatorWrapArrayDeclarator"/>
<property name="tokens" value="ARRAY_DECLARATOR"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapMethodRef"/>
<property name="tokens" value="METHOD_REF"/>
<property name="option" value="nl"/>
</module>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="Indentation">
<property name="basicOffset" value="2"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="2"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
<property name="arrayInitIndent" value="2"/>
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
</module>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
<module name="CustomImportOrder">
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="separateLineBetweenGroups" value="true"/>
<property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
</module>
<module name="MethodParamPad"/>
<module name="NoWhitespaceBefore">
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, DOT, ELLIPSIS, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="ParenPad"/>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<!-- Removed due to instantiation exception
<module name="InvalidJavadocPosition"/>
-->
<module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<module name="JavadocMethod">
<property name="scope" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingThrowsTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="allowThrowsTagsForSubclasses" value="true"/>
</module>
<!-- Removed due to instantiation exception
<module name="MissingJavadocMethod">
<property name="scope" value="public"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/>
</module>
-->
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc">
<property name="ignoreInlineTags" value="false"/>
</module>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>
<module name="CommentsIndentation"/>