<?xml version="1.0" encoding="UTF-8"?>
<!--
   Copyright 2019-2024 DATA @ UHN. See the NOTICE file
   distributed with this work for additional information
   regarding copyright ownership.

   Licensed 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>io.uhndata.cards</groupId>
  <artifactId>cards-parent</artifactId>
  <version>1</version>
  <packaging>pom</packaging>

  <name>CARDS - Parent POM</name>
  <description>CARDS is a software tool providing an easy-to-use Web interface and standardized database back-end for collecting medical data.</description>
  <url>https://cards.uhndata.io/</url>
  <inceptionYear>2019</inceptionYear>

  <licenses>
    <license>
      <name>Apache License, Version 2.0</name>
      <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
      <distribution>repo</distribution>
    </license>
  </licenses>

  <scm>
    <connection>scm:git:git://github.com/data-team-uhn/cards-parent.git</connection>
    <developerConnection>scm:git:git@github.com:data-team-uhn/cards-parent.git</developerConnection>
    <url>https://github.com/data-team-uhn/cards-parent/tree/master/</url>
    <tag>cards-parent-1</tag>
  </scm>

  <organization>
    <name>DATA Team at UHN</name>
    <url>https://uhndata.io/</url>
  </organization>

  <distributionManagement>
    <site>
      <id>nexus.phenotips.org</id>
      <url>dav:https://nexus.phenotips.org/nexus/content/sites/site/${project.groupId}/${project.artifactId}/${project.version}</url>
    </site>
    <repository>
      <id>nexus.phenotips.org</id>
      <name>Maven2 Remote Repository for Releases</name>
      <url>https://nexus.phenotips.org/nexus/content/repositories/releases</url>
    </repository>
    <snapshotRepository>
      <id>nexus.phenotips.org</id>
      <name>Maven2 Development Repository for Snapshots</name>
      <url>https://nexus.phenotips.org/nexus/content/repositories/snapshots</url>
    </snapshotRepository>
  </distributionManagement>

  <repositories>
    <repository>
      <id>phenotips-releases</id>
      <name>PhenoTips Releases repository</name>
      <url>https://nexus.phenotips.org/nexus/content/repositories/releases/</url>
      <releases>
        <enabled>true</enabled>
        <checksumPolicy>fail</checksumPolicy>
      </releases>
      <snapshots>
        <enabled>false</enabled>
        <checksumPolicy>fail</checksumPolicy>
      </snapshots>
    </repository>
    <repository>
      <id>phenotips-snapshots</id>
      <name>PhenoTips Snapshots repository</name>
      <url>https://nexus.phenotips.org/nexus/content/repositories/snapshots/</url>
      <releases>
        <enabled>false</enabled>
        <checksumPolicy>fail</checksumPolicy>
      </releases>
      <snapshots>
        <enabled>true</enabled>
        <checksumPolicy>fail</checksumPolicy>
      </snapshots>
    </repository>
    <repository>
      <id>phenotips-externals</id>
      <name>PhenoTips external repositories mirror</name>
      <url>https://nexus.phenotips.org/nexus/content/groups/public/</url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
    <repository>
      <id>apache-snapshots</id>
      <name>Apache snapshots</name>
      <url>https://repository.apache.org/content/groups/snapshots/</url>
      <releases>
        <enabled>false</enabled>
      </releases>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </repository>
  </repositories>
  <pluginRepositories>
    <pluginRepository>
      <id>phenotips-externals</id>
      <name>PhenoTips external repositories mirror</name>
      <url>https://nexus.phenotips.org/nexus/content/groups/public/</url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </pluginRepository>
    <pluginRepository>
      <id>phenotips-external-snapshots</id>
      <name>PhenoTips external snapshot repositories mirror</name>
      <url>https://nexus.phenotips.org/nexus/content/groups/public-snapshots/</url>
      <releases>
        <enabled>false</enabled>
      </releases>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </pluginRepository>
  </pluginRepositories>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <app.name>Clinical ARchive for Data Science</app.name>
    <platform.name>CARDS</platform.name>

    <!-- Versions for commonly used dependencies -->
    <asm.version>9.3</asm.version>
    <composum.nodes.version>4.1.1</composum.nodes.version>
    <jackson.version>2.13.5</jackson.version>
    <groovy.version>3.0.10</groovy.version>
    <slf4j.version>1.7.36</slf4j.version>
    <jackrabbit.version>2.21.20</jackrabbit.version>
    <oak.version>1.44.0</oak.version>

    <!-- These influence optional parts the build process -->
    <enforcer.skip>false</enforcer.skip>
    <checkstyle.skip>false</checkstyle.skip>
    <dependencyCheck.skip>false</dependencyCheck.skip>
    <coverage.instructionRatio>1.00</coverage.instructionRatio>
    <webpackArguments>--mode=development</webpackArguments>
  </properties>

  <dependencyManagement>
    <dependencies>
      <!-- Common dependencies -->
      <dependency>
        <groupId>javax.json</groupId>
        <artifactId>javax.json-api</artifactId>
        <version>1.1.4</version>
      </dependency>
      <!-- Apache Commons -->
      <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.12.0</version>
      </dependency>
      <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.11.0</version>
      </dependency>
      <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-text</artifactId>
        <version>1.10.0</version>
      </dependency>
      <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-collections4</artifactId>
        <version>4.4</version>
      </dependency>
      <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.2</version>
      </dependency>
      <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-csv</artifactId>
        <version>1.9.0</version>
      </dependency>
      <!-- Everybody logs -->
      <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
      </dependency>
      <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>${slf4j.version}</version>
      </dependency>
      <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>log4j-over-slf4j</artifactId>
        <version>${slf4j.version}</version>
      </dependency>
      <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.11</version>
      </dependency>
      <!-- OSGI -->
      <dependency>
        <groupId>org.osgi</groupId>
        <artifactId>osgi.core</artifactId>
        <version>8.0.0</version>
      </dependency>
      <dependency>
        <groupId>org.osgi</groupId>
        <artifactId>org.osgi.service.component</artifactId>
        <version>1.4.0</version>
      </dependency>
      <dependency>
        <groupId>org.osgi</groupId>
        <artifactId>org.osgi.service.component.annotations</artifactId>
        <version>1.4.0</version>
      </dependency>
      <dependency>
        <groupId>org.osgi</groupId>
        <artifactId>org.osgi.service.event</artifactId>
        <version>1.4.1</version>
      </dependency>
      <dependency>
        <groupId>org.osgi</groupId>
        <artifactId>org.osgi.service.metatype.annotations</artifactId>
        <version>1.4.1</version>
      </dependency>
      <dependency>
        <groupId>org.osgi</groupId>
        <artifactId>org.osgi.annotation.versioning</artifactId>
        <version>1.1.2</version>
      </dependency>
      <dependency>
        <groupId>org.osgi</groupId>
        <artifactId>osgi.cmpn</artifactId>
        <version>6.0.0</version>
        <scope>provided</scope>
      </dependency>
      <!-- Platform dependencies -->
      <!-- Servlet engine -->
      <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
      </dependency>
      <!-- JCR -->
      <dependency>
        <groupId>javax.jcr</groupId>
        <artifactId>jcr</artifactId>
        <version>2.0</version>
      </dependency>
      <dependency>
        <groupId>org.apache.jackrabbit</groupId>
        <artifactId>jackrabbit-jcr-commons</artifactId>
        <version>${jackrabbit.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.jackrabbit</groupId>
        <artifactId>jackrabbit-spi-commons</artifactId>
        <version>${jackrabbit.version}</version>
      </dependency>
      <!-- Oak -->
      <dependency>
        <groupId>org.apache.jackrabbit</groupId>
        <artifactId>oak-jackrabbit-api</artifactId>
        <version>${oak.version}</version>
        <scope>provided</scope>
      </dependency>
      <dependency>
        <groupId>org.apache.jackrabbit</groupId>
        <artifactId>oak-api</artifactId>
        <version>${oak.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.jackrabbit</groupId>
        <artifactId>oak-core</artifactId>
        <version>${oak.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.jackrabbit</groupId>
        <artifactId>oak-core-spi</artifactId>
        <version>${oak.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.jackrabbit</groupId>
        <artifactId>oak-store-spi</artifactId>
        <version>${oak.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.jackrabbit</groupId>
        <artifactId>oak-security-spi</artifactId>
        <version>${oak.version}</version>
      </dependency>
      <!-- Sling -->
      <dependency>
        <groupId>org.apache.sling</groupId>
        <artifactId>org.apache.sling.api</artifactId>
        <version>2.27.0</version>
      </dependency>
      <dependency>
        <groupId>org.apache.sling</groupId>
        <artifactId>org.apache.sling.servlets.annotations</artifactId>
        <version>1.2.6</version>
      </dependency>
      <dependency>
        <groupId>org.apache.sling</groupId>
        <artifactId>org.apache.sling.servlets.post</artifactId>
        <version>2.5.0</version>
      </dependency>
      <dependency>
        <groupId>org.apache.sling</groupId>
        <artifactId>org.apache.sling.scripting.sightly.runtime</artifactId>
        <version>1.2.6-1.4.0</version>
      </dependency>
      <dependency>
        <groupId>org.apache.sling</groupId>
        <artifactId>org.apache.sling.commons.scheduler</artifactId>
        <version>2.7.12</version>
      </dependency>
      <dependency>
        <groupId>org.osgi</groupId>
        <artifactId>org.osgi.framework</artifactId>
        <version>1.9.0</version>
      </dependency>
      <!-- TEST -->
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
      </dependency>
      <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>1.10.19</version>
        <scope>test</scope>
      </dependency>
      <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>32.0.1-jre</version>
      </dependency>
      <dependency>
        <groupId>com.google.code.findbugs</groupId>
        <artifactId>jsr305</artifactId>
        <version>3.0.2</version>
      </dependency>
      <dependency>
        <groupId>net.jcip</groupId>
        <artifactId>jcip-annotations</artifactId>
        <version>1.0</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <defaultGoal>install</defaultGoal>
    <extensions>
      <extension>
        <groupId>org.apache.maven.wagon</groupId>
        <artifactId>wagon-webdav-jackrabbit</artifactId>
        <version>3.5.1</version>
      </extension>
    </extensions>
    <plugins>
      <!-- Enable the slingfeature packaging type -->
      <plugin>
        <groupId>org.apache.sling</groupId>
        <artifactId>slingfeature-maven-plugin</artifactId>
        <extensions>true</extensions>
      </plugin>

      <!-- Show compiler warnings -->
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <compilerArgument>-Xlint:all</compilerArgument>
          <showWarnings>true</showWarnings>
          <showDeprecation>true</showDeprecation>
          <failOnWarning>true</failOnWarning>
        </configuration>
      </plugin>

      <!-- Run Checkstyle on Java code-->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-checkstyle-plugin</artifactId>
      </plugin>

      <!-- Validate HTL files -->
      <plugin>
        <groupId>org.apache.sling</groupId>
        <artifactId>htl-maven-plugin</artifactId>
      </plugin>

      <!-- Check that declared dependencies match what's actually used -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <id>check-dependencies</id>
            <goals>
              <goal>analyze-only</goal>
            </goals>
            <configuration>
              <failOnWarning>true</failOnWarning>
              <ignoreNonCompile>true</ignoreNonCompile>
              <skip>${dependencyCheck.skip}</skip>
            </configuration>
          </execution>
        </executions>
      </plugin>

      <!-- Fail the build if the test coverage is below a given value. -->
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.7</version>
        <executions>
          <execution>
            <id>jacoco-prepare</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
          </execution>
          <execution>
            <id>jacoco-check</id>
            <goals>
              <goal>check</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <rules>
            <rule>
              <limits>
                <limit>
                  <counter>INSTRUCTION</counter>
                  <minimum>${coverage.instructionRatio}</minimum>
                </limit>
              </limits>
            </rule>
          </rules>
        </configuration>
      </plugin>

      <!-- Check that all Maven plugins have versions defined -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-enforcer-plugin</artifactId>
        <executions>
          <execution>
            <id>enforce-plugins</id>
            <goals>
              <goal>enforce</goal>
            </goals>
            <configuration>
              <rules>
                <requirePluginVersions>
                  <message>Best Practice is to always define plugin versions!</message>
                  <banLatest>false</banLatest>
                  <banRelease>false</banRelease>
                  <banSnapshots>false</banSnapshots>
                </requirePluginVersions>
              </rules>
            </configuration>
          </execution>
        </executions>
        <configuration>
          <skip>${enforcer.skip}</skip>
        </configuration>
      </plugin>

      <!-- Check that each source file has the right license header. -->
      <plugin>
        <groupId>org.apache.rat</groupId>
        <artifactId>apache-rat-plugin</artifactId>
        <version>0.13</version>
        <configuration>
          <excludes combine.children="append">
            <!-- Used by maven-remote-resources-plugin -->
            <exclude>src/main/appended-resources/META-INF/*</exclude>
            <!-- Don't check anything in target -->
            <exclude>**/target/**</exclude>
            <!-- Exclude frontend generated code -->
            <exclude>**/frontend/node/**</exclude>
            <exclude>**/node_modules/**</exclude>
            <exclude>**/frontend/dist/**</exclude>
            <exclude>**/webpack.config.js</exclude>
            <exclude>**/yarn.lock</exclude>
            <!-- Exclude JSON files since comments are not supported -->
            <exclude>**/*.json</exclude>
            <!-- Exclude CSV files since comments are not supported -->
            <exclude>**/*.csv</exclude>
            <!-- Exclude .token files since comments are not supported -->
            <exclude>**/*.token</exclude>
            <!-- Documentation files in markdown format -->
            <exclude>**/*.md</exclude>
            <!-- File hashes -->
            <exclude>**/*.sha256sum</exclude>
            <!-- Ignore "hidden" files and folders -->
            <exclude>**/.*</exclude>
            <exclude>**/.*/**</exclude>
            <!-- bnd -->
            <exclude>bnd.bnd</exclude>
            <!-- Ignore file with data for testing -->
            <exclude>**/hpo-test.obo</exclude>
            <exclude>**/chebi-test.obo</exclude>
            <!-- Ignore generated files that are not checked into git anyways -->
            <exclude>compose-cluster/docker-compose.yml</exclude>
            <exclude>compose-cluster/initializer/initialize_all.sh</exclude>
            <exclude>compose-cluster/mongos/mongo-router.conf</exclude>
            <exclude>compose-cluster/shard*/**</exclude>
            <exclude>compose-cluster/secrets/**</exclude>
            <exclude>compose-cluster/SSL_CONFIG/**</exclude>
            <exclude>compose-cluster/SLING/**</exclude>
            <exclude>compose-cluster/CARDS_LOGS/**</exclude>
            <!-- Ignore data/template files used for generating UI Extensions / ExtensionPoints -->
            <exclude>**/Development/ExtensionPointResources/**</exclude>
            <!-- Ignore email template files since we do not send a license in notification emails -->
            <exclude>**/mailTemplates/**</exclude>
            <!-- No license in mailcap file -->
            <exclude>mailcap</exclude>
            <!-- No license in the project-specific identifiers -->
            <exclude>project_code.txt</exclude>
            <exclude>project_name.txt</exclude>
          </excludes>
        </configuration>
        <executions>
          <execution>
            <id>rat-check</id>
            <phase>verify</phase>
            <goals>
              <goal>check</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

      <!-- Deploy a copy locally, to avoid coflicts with other builds -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-deploy-plugin</artifactId>
        <executions>
          <execution>
            <id>local-deploy</id>
            <phase>verify</phase>
            <goals>
              <goal>deploy</goal>
            </goals>
            <configuration>
              <altDeploymentRepository>localBuild::default::file://.mvnrepo</altDeploymentRepository>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>

    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-enforcer-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.0.0</version>
        </plugin>
        <!-- Apply checkstyle rules and fail the build in case of errors. -->
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-checkstyle-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.2.1</version>
          <dependencies>
            <dependency>
              <groupId>com.puppycrawl.tools</groupId>
              <artifactId>checkstyle</artifactId>
              <version>10.7.0</version>
            </dependency>
          </dependencies>
          <configuration>
            <consoleOutput>true</consoleOutput>
            <skip>${checkstyle.skip}</skip>
          </configuration>
          <executions>
            <execution>
              <id>source-checkstyle</id>
              <goals>
                <goal>check</goal>
              </goals>
              <configuration>
                <checkstyleRules>
                  <module name="Checker">

                    <!--
                       ======================================================================================
                         Checks that do not require a TreeWalker (sorted alphabetically)
                       ======================================================================================
                    -->

                    <module name="FileLength" />

                    <module name="FileTabCharacter" />

                    <!-- We don't use Checkstyle's facility to check license headers since it's too limited for our needs.
                         Instead we use http://code.google.com/p/maven-license-plugin/
                    <module name="Header">
                      <property name="headerFile" value="${checkstyle.header.file}" />
                      <property name="ignoreLines" value="4,5,6,7" />
                    </module>
                    -->

                    <module name="LineLength">
                      <!-- @(\w+\.)+\w+::\w+\( stands for JSNI method calls: @my.package.MyClass::myMethod() -->
                      <property name="ignorePattern" value="(@version|@see|@link|^import|@(\w+\.)+\w+::\w+\()" />
                      <property name="max" value="120" />
                    </module>

                    <module name="NewlineAtEndOfFile">
                      <property name="fileExtensions" value="java, xml, js, css, vm" />
                    </module>

                    <module name="NewlineAtEndOfFile">
                      <property name="lineSeparator" value="crlf" />
                      <property name="fileExtensions" value="bat" />
                    </module>

                    <module name="NewlineAtEndOfFile">
                      <property name="lineSeparator" value="lf" />
                      <property name="fileExtensions" value="sh" />
                    </module>

                    <!-- We'd like to use this one but there's no option to exclude our internal packages
                    <module name="PackageHtml" />
                    -->

                    <!-- No @author tags -->
                    <module name="RegexpSingleline">
                      <property name="format" value="@author" />
                      <property name="message" value="No @author tag allowed" />
                    </module>

                    <module name="RegexpSingleline">
                      <property name="format" value="\s+$" />
                    </module>


                    <module name="SuppressWarningsFilter" />

                    <!-- We cannot use this rule as it fails on our license headers, considering them as copy-pastes!
                    <module name="StrictDuplicateCode" />
                    -->

                    <!--  We actually have a lot of incomplete translations so we can't really afford this rule
                    <module name="Translation" />
                    -->

                    <module name="UniqueProperties" />

                    <!--
                       ======================================================================================
                         Checks that require a TreeWalker (sorted alphabetically)
                       ======================================================================================
                    -->
                    <module name="TreeWalker">

                      <!-- Note: for some checks we have defined a warning severity instead of the default error
                           severity. This is because we'd like to make the build fail on error for those checks
                           but there are errors to fix first -->

                      <!-- Not used because we want to use abstract classes as SPI declarations, without requiring an ugly Abstract* prefix -->
                      <!--module name="AbstractClassName"/-->

                      <module name="AnnotationLocation">
                        <property name="allowSamelineSingleParameterlessAnnotation" value="false" />
                      </module>

                      <!-- Not used because we prefer annotations on separate lines, as enforced by AnnotationLocation -->
                      <!--module name="AnnotationOnSameLine"/-->

                      <module name="AnonInnerLength" />

                      <!--module name="ArrayTrailingComma"/-->

                      <module name="ArrayTypeStyle" />

                      <module name="AtclauseOrder">
                        <property name="tagOrder" value="@param, @return, @throws, @exception, @see, @version, @since, @deprecated" />
                      </module>

                      <!-- We allow escapes so that the source code can be checked out on non-UTF systems -->
                      <!--module name="AvoidEscapedUnicodeCharacters"/-->

                      <!--module name="AvoidInlineConditionals"/-->

                      <module name="AvoidNestedBlocks" />

                      <module name="AvoidStarImport" />

                      <module name="AvoidStaticImport" />

                      <module name="BooleanExpressionComplexity" />

                      <module name="ClassDataAbstractionCoupling" />

                      <module name="ClassFanOutComplexity">
                        <property name="excludedPackages" value="java.io, java.math, java.text, java.util, java.util.concurrent, java.util.concurrent.atomic, java.util.function, java.util.stream, javax.annotation, javax.inject, javax.servlet, org.apache.commons.collections4, org.apache.commons.lang3, org.json, org.slf4j, org.xwiki.component.annotation, org.apache.sling.servlets.annotations, org.osgi.service.component.annotations" />
                      </module>

                      <!-- We use the opposite, RedundantModifier -->
                      <!--module name="ClassMemberImpliedModifier"/-->

                      <module name="ClassTypeParameterName" />

                      <module name="CommentsIndentation" />

                      <module name="ConstantName" />

                      <module name="CovariantEquals" />

                      <module name="CyclomaticComplexity" />

                      <module name="DeclarationOrder" />

                      <module name="DefaultComesLast" />

                      <!-- The default values for this one allow everything to pass. Unneeded.
                      <module name="DescendantToken" />
                      -->

                      <!--module name="DesignForExtension"/-->

                      <module name="EmptyBlock">
                        <property name="option" value="text" />
                      </module>

                      <module name="EmptyCatchBlock" />

                      <module name="EmptyForInitializerPad" />

                      <module name="EmptyForIteratorPad" />

                      <!-- TODO: Enable this after fixing violations
                      <module name="EmptyLineSeparator">
                        <property name="allowMultipleEmptyLines" value="false" />
                        <property name="allowMultipleEmptyLinesInsideClassMembers" value="false" />
                      </module>
                      -->

                      <module name="EmptyStatement" />

                      <module name="EqualsAvoidNull" />

                      <module name="EqualsHashCode" />

                      <module name="ExecutableStatementCount" />

                      <module name="ExplicitInitialization" />

                      <module name="FallThrough" />

                      <module name="FinalClass" />

                      <!--module name="FinalLocalVariable"/-->

                      <!-- TODO: Enable this after fixing violations
                      <module name="FinalParameters" />
                      -->

                      <module name="GenericWhitespace" />

                      <module name="HiddenField">
                        <property name="tokens" value="VARIABLE_DEF,LAMBDA" />
                      </module>

                      <module name="HideUtilityClassConstructor" />

                      <!--module name="IllegalCatch"/-->

                      <module name="IllegalImport">
                        <property name="illegalPkgs" value="sun,groovy,org.apache.commons.lang,org.apache.commons.codec.binary,antlr" />
                      </module>

                      <module name="IllegalInstantiation">
                        <property name="classes" value="java.lang.Boolean, java.lang.String" />
                      </module>

                      <module name="IllegalThrows" />

                      <module name="IllegalToken">
                        <property name="tokens" value="LITERAL_NATIVE,LABELED_STAT" />
                      </module>

                      <!--module name="IllegalTokenText"/-->

                      <module name="IllegalType" />

                      <!--module name="ImportControl"/-->

                      <module name="ImportOrder">
                        <property name="groups" value="org.phenotips,org.xwiki,java,javax,org" />
                        <property name="ordered" value="true" />
                        <property name="separated" value="true" />
                        <!-- Static imports -->
                        <property name="option" value="bottom" />
                      </module>

                      <module name="Indentation" />

                      <module name="InnerAssignment" />

                      <module name="InterfaceIsType" />

                      <module name="InterfaceTypeParameterName">
                        <property name="format" value="^[A-Z]{1,2}$" />
                      </module>

                      <module name="JavadocMethod">
                        <property name="accessModifiers" value="public" />
                      </module>

                      <!-- Too strict at the moment -->
                      <!--module name="JavadocParagraph"/-->

                      <module name="JavadocStyle" />

                      <module name="JavadocTagContinuationIndentation" />

                      <module name="JavadocType">
                        <property name="scope" value="public" />
                        <property name="versionFormat" value="\$Id.*\$" />
                      </module>

                      <module name="JavadocVariable">
                        <property name="scope" value="public" />
                      </module>

                      <module name="JavaNCSS" />

                      <module name="LambdaParameterName" />

                      <module name="LeftCurly">
                        <property name="option" value="nl" />
                        <property name="tokens" value="CLASS_DEF,INTERFACE_DEF,ANNOTATION_DEF,ENUM_DEF,CTOR_DEF,METHOD_DEF,OBJBLOCK" />
                      </module>

                      <module name="LocalFinalVariableName" />

                      <module name="LocalVariableName" />

                      <!--module name="MagicNumber"/-->

                      <module name="MemberName" />

                      <module name="MethodCount" />

                      <module name="MethodLength" />

                      <!-- Allow for UI methods generated by idea -->
                      <module name="MethodName">
                        <property name="format" value="^[a-z][a-zA-Z0-9]*$|^\$\$\$setupUI\$\$\$$" />
                      </module>

                      <module name="MethodParamPad" />

                      <module name="MethodTypeParameterName" />

                      <!--module name="MissingCtor"/-->

                      <module name="MissingDeprecated" />

                      <module name="MissingOverride" />

                      <module name="MissingSwitchDefault" />

                      <module name="ModifiedControlVariable" />

                      <module name="ModifierOrder" />

                      <module name="MultipleStringLiterals">
                        <property name="ignoreStringsRegexp" value="^(&amp;#34;&amp;#34;)|(&amp;#34;[0-9]&amp;#34;)|(&amp;#34; &amp;#34;)|(&amp;#34;\]&amp;#34;)|(&amp;#34;\[&amp;#34;)|(&amp;#34;,&amp;#34;)|(&amp;#34;, &amp;#34;)|(&amp;#34;/&amp;#34;)$" />
                        <property name="allowedDuplicates" value="4" />
                      </module>

                      <module name="MultipleStringLiterals">
                        <property name="ignoreStringsRegexp" value="^(&amp;#34;&amp;#34;)|(&amp;#34;[0-9]&amp;#34;)|(&amp;#34; &amp;#34;)|(&amp;#34;\]&amp;#34;)|(&amp;#34;\[&amp;#34;)|(&amp;#34;,&amp;#34;)|(&amp;#34;, &amp;#34;)|(&amp;#34;/&amp;#34;)$" />
                        <property name="severity" value="warning" />
                      </module>

                      <module name="MultipleVariableDeclarations" />

                      <module name="MutableException" />

                      <module name="NeedBraces" />

                      <module name="NestedForDepth">
                        <property name="max" value="2" />
                      </module>

                      <module name="NestedIfDepth">
                        <property name="max" value="2" />
                      </module>

                      <module name="NestedTryDepth" />

                      <!--module name="NoClone"/-->

                      <module name="NoFinalizer" />

                      <module name="NoLineWrap" />

                      <module name="NonEmptyAtclauseDescription" />

                      <module name="NoWhitespaceAfter">
                        <property name="tokens" value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS" />
                      </module>

                      <module name="NoWhitespaceBefore" />

                      <module name="NPathComplexity" />

                      <module name="OneStatementPerLine" />

                      <module name="OneTopLevelClass" />

                      <module name="OperatorWrap" />

                      <module name="OuterTypeFilename" />

                      <module name="OuterTypeNumber" />

                      <!-- This can clash with DeclarationOrder, since it forces methods with different modifiers close together. -->
                      <!--module name="OverloadMethodsDeclarationOrder"/-->

                      <module name="PackageAnnotation" />

                      <module name="PackageDeclaration" />

                      <module name="PackageName" />

                      <module name="ParameterAssignment" />

                      <module name="ParameterName" />

                      <module name="ParameterNumber" />

                      <module name="ParenPad" />

                      <module name="RedundantImport" />

                      <module name="RedundantModifier" />

                      <!-- No direct printing to System.out or System.err -->
                      <module name="RegexpSinglelineJava">
                        <!-- . matches any character, so we need to
                             escape it and use \. to match dots. -->
                        <property name="format" value="System\.(out|err)\." />
                        <property name="ignoreComments" value="true" />
                      </module>

                      <!--module name="Regexp"/-->

                      <!--module name="RegexpHeader"/-->

                      <module name="RequireThis">
                        <property name="checkMethods" value="false" />
                        <property name="validateOnlyOverlapping" value="false" />
                      </module>

                      <!--module name="RequiredRegexp"/-->

                      <!-- Increasing the maximum number of allowed return statements, as otherwise
                           the code will simply use workarounds to hide the same amount of exit points. -->
                      <module name="ReturnCount">
                        <property name="max" value="5" />
                        <property name="maxForVoid" value="5" />
                      </module>

                      <module name="RightCurly" />

                      <module name="SeparatorWrap">
                        <property name="tokens" value="COMMA" />
                        <property name="option" value="eol" />
                      </module>

                      <module name="SeparatorWrap">
                        <property name="tokens" value="DOT" />
                        <property name="option" value="nl" />
                      </module>

                      <module name="SimplifyBooleanExpression" />

                      <module name="SimplifyBooleanReturn" />

                      <module name="SingleSpaceSeparator" />

                      <module name="StaticVariableName" />

                      <module name="StringLiteralEquality" />

                      <module name="SuperClone" />

                      <module name="SuperFinalize" />

                      <module name="SuppressWarningsHolder" />

                      <!--module name="ThrowsCount"-->

                      <module name="TodoComment">
                        <property name="severity" value="warning" />
                        <property name="format" value="TODO" />
                      </module>
                      <module name="TodoComment">
                        <property name="severity" value="warning" />
                        <property name="format" value="FIXME" />
                      </module>
                      <module name="TodoComment">
                        <property name="severity" value="warning" />
                        <property name="format" value="@todo" />
                      </module>

                      <module name="TrailingComment" />

                      <module name="TypeName" />

                      <module name="TypecastParenPad" />

                      <module name="UncommentedMain">
                        <property name="excludedClasses" value=".*Main$" />
                      </module>

                      <!--module name="UnnecessaryParentheses"/-->

                      <module name="UnusedImports" />

                      <module name="UpperEll" />

                      <module name="VisibilityModifier">
                        <property name="protectedAllowed" value="true" />
                      </module>

                      <module name="WhitespaceAfter" />

                      <module name="WhitespaceAround" />

                    </module>
                  </module>
                </checkstyleRules>
              </configuration>
            </execution>
            <execution>
              <id>test-checkstyle</id>
              <goals>
                <goal>check</goal>
              </goals>
              <configuration>
                <includeTestSourceDirectory>true</includeTestSourceDirectory>
                <sourceDirectories>
                  <sourceDirectory>src/test/java/</sourceDirectory>
                </sourceDirectories>
                <checkstyleRules>
                  <module name="Checker">

                    <!--
                       ======================================================================================
                         Checks that do not require a TreeWalker (sorted alphabetically)
                       ======================================================================================
                    -->

                    <module name="FileLength" />

                    <module name="FileTabCharacter" />

                    <!-- We don't use Checkstyle's facility to check license headers since it's too limited for our needs.
                         Instead we use http://code.google.com/p/maven-license-plugin/
                    <module name="Header">
                      <property name="headerFile" value="${checkstyle.header.file}" />
                      <property name="ignoreLines" value="4,5,6,7" />
                    </module>
                    -->

                    <module name="LineLength">
                      <!-- @(\w+\.)+\w+::\w+\( stands for JSNI method calls: @my.package.MyClass::myMethod() -->
                      <property name="ignorePattern" value="(@version|@see|@link|^import|@(\w+\.)+\w+::\w+\()" />
                      <property name="max" value="120" />
                    </module>

                    <module name="NewlineAtEndOfFile">
                      <property name="fileExtensions" value="java, xml, js, css, vm" />
                    </module>

                    <module name="NewlineAtEndOfFile">
                      <property name="lineSeparator" value="crlf" />
                      <property name="fileExtensions" value="bat" />
                    </module>

                    <module name="NewlineAtEndOfFile">
                      <property name="lineSeparator" value="lf" />
                      <property name="fileExtensions" value="sh" />
                    </module>

                    <!-- We'd like to use this one but there's no option to exclude our internal packages
                    <module name="PackageHtml" />
                    -->

                    <!-- No @author tags -->
                    <module name="RegexpSingleline">
                      <property name="format" value="@author" />
                      <property name="message" value="No @author tag allowed" />
                    </module>

                    <module name="RegexpSingleline">
                      <property name="format" value="\s+$" />
                    </module>


                    <module name="SuppressWarningsFilter" />

                    <!-- We cannot use this rule as it fails on our license headers, considering them as copy-pastes!
                    <module name="StrictDuplicateCode" />
                    -->

                    <!--  We actually have a lot of incomplete translations so we can't really afford this rule
                    <module name="Translation" />
                    -->

                    <module name="UniqueProperties" />

                    <!--
                       ======================================================================================
                         Checks that require a TreeWalker (sorted alphabetically)
                       ======================================================================================
                    -->
                    <module name="TreeWalker">

                      <!-- Note: for some checks we have defined a warning severity instead of the default error
                           severity. This is because we'd like to make the build fail on error for those checks
                           but there are errors to fix first -->

                      <!-- Not used because we want to use abstract classes as SPI declarations, without requiring an ugly Abstract* prefix -->
                      <!--module name="AbstractClassName"/-->

                      <module name="AnnotationLocation">
                        <property name="allowSamelineSingleParameterlessAnnotation" value="false" />
                      </module>

                      <module name="AnonInnerLength">
                        <property name="max" value="100" />
                      </module>

                      <!--module name="ArrayTrailingComma"/-->

                      <module name="ArrayTypeStyle" />

                      <!--module name="AvoidInlineConditionals"/-->

                      <module name="AtclauseOrder">
                        <property name="tagOrder" value="@param, @return, @throws, @exception, @see, @version, @since, @deprecated" />
                      </module>

                      <!-- We allow escapes so that the source code can be checked out on non-UTF systems -->
                      <!--module name="AvoidEscapedUnicodeCharacters"/-->

                      <module name="AvoidNestedBlocks" />

                      <!--module name="AvoidStarImport"/-->

                      <!--module name="AvoidStaticImport"/-->

                      <module name="BooleanExpressionComplexity" />

                      <!--module name="ClassDataAbstractionCoupling"/-->

                      <!--module name="ClassFanOutComplexity">
                        <property name="excludedClasses" value="boolean, byte, char, double, float, int, long, short, void, Boolean, Byte, Character, Double, Float, Integer, Long, Short, Void, Object, Class, String, StringBuffer, StringBuilder,
                          ArrayIndexOutOfBoundsException, Exception, RuntimeException, IllegalArgumentException, IllegalStateException, IndexOutOfBoundsException, NullPointerException, Throwable, SecurityException, UnsupportedOperationException,
                          List, ArrayList, Deque, Queue, LinkedList, Set, HashSet, SortedSet, TreeSet, Map, HashMap, LinkedHashMap, SortedMap, TreeMap, Collections, Collection, Iterator, Iterable, Arrays,
                          Logger, LoggerFactory, StringUtils, Inject, Named, Component, Role, Singleton" />
                      </module-->

                      <module name="ClassTypeParameterName" />

                      <module name="CommentsIndentation" />

                      <module name="ConstantName" />

                      <module name="CovariantEquals" />

                      <module name="CyclomaticComplexity">
                        <property name="max" value="32" />
                      </module>

                      <module name="DeclarationOrder" />

                      <module name="DefaultComesLast" />

                      <!-- The default values for this one allow everything to pass. Unneeded.
                      <module name="DescendantToken" />
                      -->

                      <!--module name="DesignForExtension"/-->

                      <module name="EmptyBlock">
                        <property name="option" value="text" />
                      </module>

                      <module name="EmptyCatchBlock" />

                      <module name="EmptyForInitializerPad" />

                      <module name="EmptyForIteratorPad" />

                      <module name="EmptyStatement" />

                      <module name="EqualsAvoidNull" />

                      <module name="EqualsHashCode" />

                      <!--module name="ExecutableStatementCount"/-->

                      <module name="ExplicitInitialization" />

                      <module name="FallThrough" />

                      <module name="FinalClass" />

                      <!--module name="FinalLocalVariable"/-->

                      <!--module name="FinalParameters"/-->

                      <module name="GenericWhitespace" />

                      <module name="HiddenField">
                        <property name="tokens" value="VARIABLE_DEF" />
                      </module>

                      <module name="HideUtilityClassConstructor" />

                      <!--module name="IllegalCatch"/-->

                      <module name="IllegalImport">
                        <property name="illegalPkgs" value="sun,groovy,org.apache.commons.lang,org.apache.commons.codec.binary,antlr" />
                      </module>

                      <module name="IllegalInstantiation">
                        <property name="classes" value="java.lang.Boolean, java.lang.String" />
                      </module>

                      <module name="IllegalThrows" />

                      <module name="IllegalToken">
                        <property name="tokens" value="LITERAL_NATIVE,LABELED_STAT" />
                      </module>

                      <!--module name="IllegalTokenText"/-->

                      <module name="IllegalType" />

                      <!--module name="ImportControl"/-->

                      <module name="ImportOrder">
                        <property name="groups" value="org.phenotips,org.xwiki,java,javax,org" />
                        <property name="ordered" value="true" />
                        <property name="separated" value="true" />
                        <!-- Static imports -->
                        <property name="option" value="bottom" />
                      </module>

                      <module name="Indentation" />

                      <module name="InnerAssignment" />

                      <module name="InterfaceIsType" />

                      <module name="InterfaceTypeParameterName">
                        <property name="format" value="^[A-Z]{1,2}$" />
                      </module>

                      <!--module name="JavadocMethod">
                        <property name="scope" value="public" />
                        <property name="allowUndeclaredRTE" value="true" />
                      </module-->

                      <!-- Too strict at the moment -->
                      <!--module name="JavadocParagraph"/-->

                      <module name="JavadocStyle" />

                      <module name="JavadocTagContinuationIndentation" />

                      <!--module name="JavadocType">
                        <property name="scope" value="public" />
                        <property name="versionFormat" value="\$Id.*\$" />
                      </module-->

                      <!--module name="JavadocVariable">
                        <property name="scope" value="public" />
                      </module-->

                      <module name="JavaNCSS">
                        <property name="methodMaximum" value="200" />
                      </module>

                      <module name="LeftCurly">
                        <property name="option" value="nl" />
                        <property name="tokens" value="CLASS_DEF,INTERFACE_DEF,ANNOTATION_DEF,ENUM_DEF,CTOR_DEF,METHOD_DEF,OBJBLOCK" />
                      </module>

                      <module name="LocalFinalVariableName" />

                      <module name="LocalVariableName" />

                      <!--module name="MagicNumber"/-->

                      <module name="MemberName" />

                      <module name="MethodCount">
                        <property name="maxPublic" value="200" />
                        <property name="maxTotal" value="200" />
                      </module>

                      <module name="MethodLength">
                        <property name="max" value="300" />
                      </module>

                      <!-- Allow for UI methods generated by idea -->
                      <module name="MethodName">
                        <property name="format" value="^[a-z][a-zA-Z0-9]*$|^\$\$\$setupUI\$\$\$$" />
                      </module>

                      <module name="MethodParamPad" />

                      <module name="MethodTypeParameterName" />

                      <!--module name="MissingCtor"/-->

                      <module name="MissingDeprecated" />

                      <module name="MissingOverride" />

                      <module name="MissingSwitchDefault" />

                      <module name="ModifiedControlVariable" />

                      <module name="ModifierOrder" />

                      <module name="MultipleStringLiterals">
                        <property name="ignoreStringsRegexp" value="^(&amp;#34;&amp;#34;)|(&amp;#34;[0-9]&amp;#34;)|(&amp;#34; &amp;#34;)|(&amp;#34;\]&amp;#34;)|(&amp;#34;\[&amp;#34;)|(&amp;#34;,&amp;#34;)|(&amp;#34;, &amp;#34;)|(&amp;#34;/&amp;#34;)$" />
                        <property name="allowedDuplicates" value="20" />
                      </module>

                      <module name="MultipleVariableDeclarations" />

                      <module name="MutableException" />

                      <module name="NeedBraces" />

                      <module name="NestedForDepth">
                        <property name="max" value="2" />
                      </module>

                      <module name="NestedIfDepth">
                        <property name="max" value="2" />
                      </module>

                      <module name="NestedTryDepth" />

                      <!--module name="NoClone"/-->

                      <module name="NoLineWrap" />

                      <module name="NonEmptyAtclauseDescription" />

                      <module name="NoFinalizer" />

                      <module name="NoWhitespaceAfter">
                        <property name="tokens" value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS" />
                      </module>

                      <module name="NoWhitespaceBefore" />

                      <module name="NPathComplexity" />

                      <module name="OneStatementPerLine" />

                      <module name="OperatorWrap" />

                      <module name="OuterTypeFilename" />

                      <module name="OuterTypeNumber" />

                      <!-- This can clash with DeclarationOrder, since it forces methods with different modifiers close together. -->
                      <!--module name="OverloadMethodsDeclarationOrder"/-->

                      <module name="PackageAnnotation" />

                      <module name="PackageDeclaration" />

                      <module name="PackageName" />

                      <module name="ParameterAssignment" />

                      <module name="ParameterName" />

                      <module name="ParameterNumber" />

                      <module name="ParenPad" />

                      <module name="RedundantImport" />

                      <module name="RedundantModifier" />

                      <!-- No direct printing to System.out or System.err -->
                      <module name="RegexpSinglelineJava">
                        <!-- . matches any character, so we need to
                             escape it and use \. to match dots. -->
                        <property name="format" value="System\.(out|err)\." />
                        <property name="ignoreComments" value="true" />
                      </module>

                      <!--module name="Regexp"/-->

                      <!--module name="RegexpHeader"/-->

                      <module name="RequireThis">
                        <property name="checkMethods" value="false" />
                        <property name="validateOnlyOverlapping" value="false" />
                      </module>

                      <!--module name="RequiredRegexp"/-->

                      <!-- Increasing the maximum number of allowed return statements, as otherwise
                           the code will simply use workarounds to hide the same amount of exit points. -->
                      <module name="ReturnCount">
                        <property name="max" value="5" />
                        <property name="maxForVoid" value="5" />
                      </module>

                      <module name="RightCurly" />

                      <module name="SeparatorWrap">
                        <property name="tokens" value="COMMA" />
                        <property name="option" value="eol" />
                      </module>

                      <module name="SeparatorWrap">
                        <property name="tokens" value="DOT" />
                        <property name="option" value="nl" />
                      </module>

                      <module name="SimplifyBooleanExpression" />

                      <module name="SimplifyBooleanReturn" />

                      <module name="SingleSpaceSeparator" />

                      <module name="StaticVariableName" />

                      <module name="StringLiteralEquality" />

                      <module name="SuperClone" />

                      <module name="SuperFinalize" />

                      <module name="SuppressWarningsHolder" />

                      <!--module name="ThrowsCount"-->

                      <module name="TodoComment">
                        <property name="severity" value="warning" />
                        <property name="format" value="TODO" />
                      </module>
                      <module name="TodoComment">
                        <property name="severity" value="warning" />
                        <property name="format" value="FIXME" />
                      </module>
                      <module name="TodoComment">
                        <property name="severity" value="warning" />
                        <property name="format" value="@todo" />
                      </module>

                      <module name="TrailingComment" />

                      <module name="TypeName" />

                      <module name="TypecastParenPad" />

                      <module name="UncommentedMain">
                        <property name="excludedClasses" value=".*Main$" />
                      </module>

                      <!--module name="UnnecessaryParentheses"/-->

                      <module name="UnusedImports" />

                      <module name="UpperEll" />

                      <module name="VisibilityModifier">
                        <property name="protectedAllowed" value="true" />
                      </module>

                      <module name="WhitespaceAfter" />

                      <module name="WhitespaceAround" />

                    </module>
                  </module>
                </checkstyleRules>
              </configuration>
            </execution>
          </executions>
        </plugin>

        <!-- Validate HTL files -->
        <plugin>
          <groupId>org.apache.sling</groupId>
          <artifactId>htl-maven-plugin</artifactId>
          <version>2.0.4-1.4.0</version>
          <executions>
            <execution>
              <id>validate-htl</id>
              <goals>
                <goal>validate</goal>
              </goals>
            </execution>
          </executions>
          <configuration>
            <failOnWarnings>true</failOnWarnings>
            <sourceDirectory>src/main/resources/</sourceDirectory>
          </configuration>
        </plugin>

        <plugin>
          <groupId>org.apache.sling</groupId>
          <artifactId>slingfeature-maven-plugin</artifactId>
          <version>1.6.0</version>
          <extensions>true</extensions>
          <configuration>
            <replacePropertyVariables>asm.version,jackrabbit.version,groovy.version,oak.version,sling.saml.version,slf4j.version,composum.nodes.version,jackson.version,cards.version</replacePropertyVariables>
            <framework>
              <groupId>org.apache.felix</groupId>
              <artifactId>org.apache.felix.framework</artifactId>
              <version>7.0.3</version>
            </framework>
          </configuration>
          <executions>
            <execution>
              <id>attach-features</id>
              <phase>prepare-package</phase>
              <goals>
                <goal>attach-features</goal>
              </goals>
            </execution>
          </executions>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-resources-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.2.0</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-remote-resources-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>1.7.0</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-release-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>2.5.3</version>
          <configuration>
            <arguments>-Pquick</arguments>
            <preparationGoals>clean verify</preparationGoals>
            <!-- Avoid site generation during the release:perform to speed up release process -->
            <goals>deploy</goals>
            <mavenExecutorId>forked-path</mavenExecutorId>
            <autoVersionSubmodules>true</autoVersionSubmodules>
            <localCheckout>true</localCheckout>
            <pushChanges>false</pushChanges>
            <tagNameFormat>cards-@{project.version}</tagNameFormat>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-clean-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.1.0</version>
          <!-- Delete the transpiled fronted code -->
          <configuration>
            <filesets>
              <fileset>
                <directory>src/main/frontend/dist/</directory>
              </fileset>
              <fileset>
                <directory>.mvnrepo/</directory>
              </fileset>
            </filesets>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-source-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.2.1</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-plugin-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.6.4</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-install-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.9.0</version>
          <!-- Java 11 is required -->
          <configuration>
            <source>11</source>
            <target>11</target>
          </configuration>
        </plugin>
        <!-- Compile the React code -->
        <plugin>
          <groupId>com.github.eirslett</groupId>
          <artifactId>frontend-maven-plugin</artifactId>
          <version>1.12.1</version>
          <executions>
            <!-- Installs NodeJS and Yarn locally -->
            <execution>
              <id>install node and yarn</id>
              <goals>
                <goal>install-node-and-yarn</goal>
              </goals>
              <phase>initialize</phase>
            </execution>
            <!-- Brings in the dependencies using yarn -->
            <execution>
              <id>yarn install</id>
              <goals>
                <goal>yarn</goal>
              </goals>
            </execution>
            <!-- Runs webpack to compile the JS source code -->
            <execution>
              <id>webpack</id>
              <goals>
                <goal>webpack</goal>
              </goals>
              <configuration>
                <arguments>${webpackArguments}</arguments>
              </configuration>
            </execution>
          </executions>
          <configuration>
            <nodeVersion>v16.14.0</nodeVersion>
            <yarnVersion>v1.22.17</yarnVersion>
            <workingDirectory>src/main/frontend</workingDirectory>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>2.22.2</version>
          <!-- Rule is to put tests in *Test classes -->
          <configuration>
            <includes>
              <include>**/*Test.class</include>
            </includes>
            <parallel>classesAndMethods</parallel>
            <threadCount>4</threadCount>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-jar-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-assembly-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.3.0</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-dependency-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.5.0</version>
          <configuration>
            <ignoredUsedUndeclaredDependencies>
              <ignoredUsedUndeclaredDependency>javax.inject:javax.inject</ignoredUsedUndeclaredDependency>
              <ignoredUsedUndeclaredDependency>org.mockito:mockito-core</ignoredUsedUndeclaredDependency>
              <ignoredUsedUndeclaredDependency>junit:junit</ignoredUsedUndeclaredDependency>
              <ignoredUsedUndeclaredDependency>org.hamcrest:hamcrest-library</ignoredUsedUndeclaredDependency>
            </ignoredUsedUndeclaredDependencies>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-deploy-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>2.8.2</version>
          <!-- We're deploying to Nexus using the WebDAV protocol -->
          <dependencies>
            <dependency>
              <groupId>org.apache.maven.wagon</groupId>
              <artifactId>wagon-webdav-jackrabbit</artifactId>
              <version>3.5.1</version>
            </dependency>
          </dependencies>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.2.1</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-gpg-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.0.1</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-javadoc-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.3.2</version>
          <configuration>
            <!-- Always exclude the internal package since it's not user-public -->
            <excludePackageNames>*.internal.*</excludePackageNames>
            <!-- Make sure javadoc has enough memory -->
            <maxmemory>300m</maxmemory>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-site-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.10.0</version>
          <!-- Site Plugin doesn't automatically pull the Apache Wagon implementation -->
          <dependencies>
            <dependency>
              <groupId>org.apache.maven.wagon</groupId>
              <artifactId>wagon-webdav-jackrabbit</artifactId>
              <version>3.5.1</version>
            </dependency>
          </dependencies>
        </plugin>
        <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>exec-maven-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.0.0</version>
        </plugin>
        <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>build-helper-maven-plugin</artifactId>
          <!-- Lock down plugin version for build reproducibility -->
          <version>3.3.0</version>
        </plugin>
        <plugin>
          <groupId>org.apache.felix</groupId>
          <artifactId>maven-bundle-plugin</artifactId>
          <version>5.1.4</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

  <profiles>
    <profile>
      <!-- Use this ( mvn install -Pquick ) when trying to get a quicker test build, without running any quality control checks. -->
      <id>quick</id>
      <properties>
        <enforcer.skip>true</enforcer.skip>
        <checkstyle.skip>true</checkstyle.skip>
        <jacoco.skip>true</jacoco.skip>
        <skipTests>true</skipTests>
        <rat.skip>true</rat.skip>
        <dependencyCheck.skip>true</dependencyCheck.skip>
      </properties>
    </profile>

    <profile>
      <!-- Use this ( mvn install -Pskip-webpack ) when trying to get a quicker test build, without (re)installing any node dependencies. -->
      <id>skip-webpack</id>
      <properties>
        <skip.installyarn>true</skip.installyarn>
        <skip.yarn>true</skip.yarn>
        <skip.webpack>true</skip.webpack>
      </properties>
    </profile>

    <profile>
      <!-- By default the sling running instance is also cleaned. To disable this, use `mvn install -P-clean-instance` -->
      <id>clean-instance</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-clean-plugin</artifactId>
            <!-- Delete the running instance when cleaning -->
            <executions>
              <execution>
                <id>clean-instance</id>
                <phase>clean</phase>
                <goals>
                  <goal>clean</goal>
                </goals>
                <configuration>
                  <filesets>
                    <fileset>
                      <directory>sling/</directory>
                      <directory>.cards-data/</directory>
                    </fileset>
                  </filesets>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>

    <profile>
      <!-- Node resources are like binary dependencies, so they should be cleaned as well. However, re-downloading Node and its modules for every build is pointless, thus cleaning them is optional. -->
      <id>clean-node</id>
      <activation>
        <activeByDefault>false</activeByDefault>
      </activation>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-clean-plugin</artifactId>
            <!-- Delete node files when cleaning -->
            <executions>
              <execution>
                <id>clean-node</id>
                <phase>clean</phase>
                <goals>
                  <goal>clean</goal>
                </goals>
                <configuration>
                  <filesets>
                    <fileset>
                      <directory>src/main/frontend/</directory>
                      <includes>
                        <include>node/</include>
                        <include>node_modules/</include>
                        <include>yarn.lock</include>
                      </includes>
                    </fileset>
                  </filesets>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>

    <profile>
      <!-- Profile used when the release plugin executes. We want javadocs and source jars to be released
           + ensure we sign files using GPG. -->
      <id>release</id>
      <properties>
        <webpackArguments>--mode=production --devtool=source-map</webpackArguments>
      </properties>
      <activation>
        <property>
          <!-- This property is automatically defined by the Maven release plugin when executing
               a release. Thus this profile will be automatically enabled when releasing -->
          <name>performRelease</name>
          <value>true</value>
        </property>
      </activation>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <executions>
              <execution>
                <id>attach-sources</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <executions>
              <execution>
                <id>attach-javadocs</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-gpg-plugin</artifactId>
            <executions>
              <execution>
                <id>sign-artifacts</id>
                <phase>verify</phase>
                <goals>
                  <goal>sign</goal>
                </goals>
                <configuration>
                  <useAgent>true</useAgent>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>

    <!--
        Use this profile to install the built module automatically during development.
        Requires a running instance.
        By default it connects to http://localhost:8080 with admin:admin.
        To specify a different password, use `-Dsling.password=newPassword`
        To specify a different URL, use `-Dsling.url=https://cards.server:8443/system/console` (the URL must end with `/system/console` to work properly)

        TL;DR:
        mvn install -PautoInstallBundle
    -->
    <profile>
      <id>autoInstallBundle</id>
      <activation>
        <activeByDefault>false</activeByDefault>
      </activation>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.sling</groupId>
            <artifactId>maven-sling-plugin</artifactId>
            <version>2.4.0</version>
            <executions>
              <execution>
                <id>install-bundle</id>
                <goals>
                  <goal>install</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
</project>
