jQA logo

The powerful Quality Assurance Tool for your Java application.

This document describes the concepts of jQAssistant and usage information.

Overview

jQAssistant is a QA tool which allows the definition and validation of project specific rules on a structural level. It is built upon the graph database Neo4j and can easily be plugged into the build process to automate detection of constraint violations and generate reports about user defined concepts and metrics.

Example use cases:

  • Enforce naming conventions, e.g. EJBs, JPA entities, test classes, packages, maven modules etc.

  • Validate dependencies between modules of your project

  • Separate API and implementation packages

  • Detect common problems like cyclic dependencies or tests without assertions

The rules are expressed in Cypher - the easy-to-learn query language of Neo4j:

MATCH
  (t:Test:Method)
WHERE NOT
  (t)-[:INVOKES]->(:Assert:Method)
RETURN
  t AS TestWithoutAssertion

License

jQAssistant is contributed under GNU General Public License, v3.

Quickstart

Command Line

Installation

  • Download and unpack the distribution, a directory "jqassistant.distribution-1.0.0-RC1" will be created.

Scan

Windows
bin/jqassistant.cmd scan -f lib
Linux
bin/jqassistant.sh scan -f lib
  • The JAR files contained in the lib/ folder will be scanned.

Explore

Windows
bin/jqassistant.cmd server
Linux
bin/jqassistant.sh server
  • Open a browser and navigate to http://localhost:7474

  • Enter the following query in the top level area and hit Ctrl-Enter:

MATCH
  (t:Type)-[:DECLARES]->(m:Method)
RETURN
  t.fqn AS Type, count(t) AS DeclaredMethods
ORDER BY
  DeclaredMethods DESC
LIMIT 20

Maven

Add the plugin

Add the following lines to the parent pom.xml file of your project:

<build>
    <plugins>
        <plugin>
            <groupId>com.buschmais.jqassistant.scm</groupId>
            <artifactId>jqassistant-maven-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>scan</goal>
                        <goal>analyze</goal>
                    </goals>
                    <configuration>
                        <failOnViolations>true</failOnViolations>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

<reporting>
    <plugins>
        <plugin>
            <groupId>com.buschmais.jqassistant.scm</groupId>
            <artifactId>jqassistant-maven-plugin</artifactId>
            <reportSets>
                <reportSet>
                    <reports>
                        <report>report</report>
                    </reports>
                </reportSet>
            </reportSets>
        </plugin>
    </plugins>
</reporting>

Add a rule

Within your parent module create a directory "jqassistant" and a rules file "my-rules.xml" in it:

jqassistant/my-rules.xml
<jqa:jqassistant-rules xmlns:jqa="http://www.buschmais.com/jqassistant/core/analysis/rules/schema/v1.0">

    <constraint id="my-rules:TestClassName">
        <requiresConcept refId="junit4:TestClass" />
        <description>All JUnit test classes must have a name with suffix "Test".</description>
        <cypher><![CDATA[
            MATCH
                (t:Junit4:Test:Class)
            WHERE NOT
                t.name =~ ".*Test"
            RETURN
                t AS InvalidTestClass
        ]]></cypher>
    </constraint>

    <group id="default">
        <includeConstraint refId="my-rules:TestClassName" />
    </group>

</jqa:jqassistant-rules>

Run the build

Execute the following command from your parent module:

mvn install

The build will fail with the message specified by your rule if it is violated. If everything is fine you can also create a report as part of your Maven site:

mvn site

Explore your application

jQAssistant comes with an integrated Neo4j server, you can run it using

mvn jqassistant:server
  • Open a browser and navigate to http://localhost:7474

  • Enter the follwoing query in the top level area and hit Ctrl-Enter:

MATCH
  (t:Type)-[:DECLARES]->(m:Method)
RETURN
  t.fqn AS Type, count(t) AS DeclaredMethods
ORDER BY
  DeclaredMethods DESC
LIMIT 20

Introduction

This chapter provides an introduction to the concepts of jQAssistant.

How it works

The basic idea behind jQAssistant is to integrate the following steps into the build process of a software system:

  1. Scan the generated artifacts and store structural information about them into a database

  2. Analyze the structures using rules which are represented by queries

  3. Report violations

jQAssistant itself is a plugin based framework. It comes with a pre-defined set of plugins containing scanners, rules and reports but can be easily extended by custom rules or implementations.

As database an embedded instance of Neo4j Community Edition is managed and used by jQAssistant. This means that no setup or configuration of a dedicated server is required. Neo4j has been chosen because:

  • it is a mature open source graph database

  • it allows easy modelling of structural elements of a software and their relations

  • it comes with a very expressive and easy to learn query language (Cypher)

Scanner

Scanners are used to import software structures into the database. They are provided by plugins and may support several types of artifacts, e.g. Java classes, XML files, database structures and much more. The jQAssistant framework (including the command line or Maven plugin) only provides the infrastructure to trigger a scan operation on a set of items, e.g. files, directories or URLs. Every active plugin decides itself if it accepts and imports a given item by checking several conditions, e.g. by file name extension or a provided scope. The latter is an extra information which provides more specific context information like "java:classpath" for a directory containing Java classes or "maven:repository" for URLs.

Rules

Rules are expressed as Cypher queries and are specified either in XML or AsciiDoc files:

XML example

my-rules.xml
<jqa:jqassistant-rules xmlns:jqa="http://www.buschmais.com/jqassistant/core/analysis/rules/schema/v1.0">

    <group id="default">
        <includeConstraint refId="my-rules:MyConstraint"/>
    </group>

    <constraint id="my-rules:MyConcept">
        <description>A human readable description of the concept.</description>
        <cypher><![CDATA[
            MATCH
              ...
            WHERE
              ...
            SET
              ...
            CREATE
              ...
            RETURN
              ...
        ]]></cypher>
    </constraint>

    <constraint id="my-rules:MyConstraint" severity="blocker">
        <requiresConcept refId="my-rules:MyConcept" />
        <description>A human readable description of the constraint.</description>
        <cypher><![CDATA[
            MATCH
                ...
            WHERE
                ...
            RETURN
                ...
        ]]></cypher>
    </constraint>

</jqa:jqassistant-rules>

AsciiDoc example

my-rules.adoc
[[my-rules:MyConcept]]
.A human readable description of the concept.
[source,cypher,role=concept]
----
MATCH
  ...
WHERE
  ...
SET
  ...
CREATE
  ...
RETURN
  ...
----

[[my-rules:MyConstraint]]
.A human readable description of the constraint.
[source,cypher,role=constraint,depends="my-rules:MyConcept",severity=blocker]
----
MATCH
  ...
WHERE
  ...
RETURN
  ...
----

Each rule comes with an unique id (e.g. "my-rules:MyConstraint") which can be referenced by other rules. jQAssistant will take care about executing the rules in the correct order. Furthermore a human readable description shall help developers to understand the rationale behind them.

A rule can optionally define the severity level. jQAssistant allows to break the build if there are violations in the configured severity level (or higher). For example, if the severity is set to critical, and if there are violated constraints with blocker and/or critical severity; the build will break. This feature allows projects to pay down their technical debt in an iterative manner.

Following severity levels are supported:

  • info

  • minor

  • major

  • critical

  • blocker

Groups

A group is a set of rules that shall be executed together. This allows to adjust analysis depth for different types of builds, e.g. a Continuous Integration build (CI) can be configured to only execute rules with low costs (i.e. execution times) whereas a report build is allowed to run for a longer time with more expensive checks.

Note
Currently groups can only be defined in XML documents.

Concepts

The information created by the scanner represents the structure of a software project on a raw level. Concept rules allow enriching the database with higher level information to ease the process of writing queries that check for violations (i.e. constraints) . This typically means adding labels, properties or relations.

jQAssistant comes with language and framework plugins which include general technical concepts, e.g.

  • "jpa2:Entity" provided by the JPA2 plugin adds a label "Entity" to a node if it represents a class which is annotated by "@javax.persistence.Entity".

  • "java:MethodOverrides" provided by the Java plugin adds a relation "OVERRIDES" between a method of a sub class to the super class methods it overrides.

It is recommended to use concepts to enrich the database with information which is specific for the concrete project, e.g. labels can be added to

  • package nodes representing modules of the application ("Module")

  • package nodes that represent technical layers ("UI", "EJB")

  • class nodes representing elements with a specific role ("Controller", "Model")

NOTE Even if the primary intention of a concept is to enrich data it still must provide a return clause. If a concept returns an empty result a warning will be generated by jQAssistant. The rationale is that in such case the concept does not match the structure of the application and other rules which depend on it will probably not work as expected. The return clause of the concept shall preferably return a node/relation itself instead of an attribute of it. Similarly, return clauses with only count of matching nodes shall be avoided. With this, XML and HTML reports can provide additional information about the concept.

Constraints

A Constraint is a query which detects violations, e.g.

  • classes with specific roles (e.g. entity, controller, etc.) that are either located in the wrong packages or have names that do not fit defined conventions

  • invocations of methods which are deprecated and/or forbidden (e.g. constructors of java.util.Date)

  • dependencies to other modules which are not allowed

A constraint can depend on one or more concepts and usually is referenced by one or more groups.

NOTE If a constraint returns a result jQAssistant will report an error including the provided description and information about the returned elements. This information shall help the developer to understand and fix the problem.

Script Languages

Instead of cypher scripting languages like JavaScript, Ruby or Groovy may be used for writing concepts or constraints:

my-scripting-rules.xml
<jqa:jqassistant-rules xmlns:jqa="http://www.buschmais.com/jqassistant/core/analysis/rules/schema/v1.0">

    <constraint id="my-scripting-rules:MyConcept">
        <description>A JavaScript based concept.</description>
        <script language="JavaScript">
          ...
        </script>
    </constraint>

</jqa:jqassistant-rules>
my-scripting-rules.adoc
[[my-scripting-rules:MyConcept]]
.A JavaScript based concept.
[source,javascript,role=constraint]
----
  ...
----

Refer to the examples section for a detailed explanation.

Command Line

Shell scripts are provided for executing jQAssistant from the command line of Microsoft Windows® or Unix compatible systems. They are located in the bin/ directory of the distribution:

  • jqassistant.cmd

  • jqassistant.sh

The command line accepts tasks and their specific options:

jqassistant.sh <task1> <task2> <task3> -<option1> -<option2>

The following example will scan the content of the directories classes/ and test-classes/:

jqassistant.sh scan -f classes,test-classes

Tasks

scan

Description

Scans files or directories and stores the gathered information in database. Files or URLs are accepted and may be specified further by scopes, e.g.

jqassistant.sh scan -f lib/,plugins/
jqassistant.sh scan -f java:classpath::classes/
jqassistant.sh scan -u maven:repository::http://my.maven.repository
Options
  • -s, --storeDirectory <directory>

  • -f [<scope>::]<file1>,[<scope>::]<file2> or --files [<scope>::]<file1>,[<scope>::]<file2>

    • specifies a list of files or directories to scan

    • a scope may be used as prefix for each file argument

  • -u [<scope>::]<url1>,[<scope>::]<url2> or --urls [<scope>::]<url1>,[<scope>::]<url2>

    • specifies a list of URLs to scan

    • a scope may be used as prefix for each url argument

  • -reset

    • reset the database before scanning

available-scopes

Description

List all available scopes which may be specified for scanning.

analyze

Description

Executes an analysis.

Options

available-rules

Description

List all available rules.

effective-rules

Description

List the rules which would be executed for an analysis and the given concepts, constraints or groups.

report

Description

Transforms an XML report into HTML.

server

Description

Starts the integrated Neo4j web server (http://localhost:7474).

Common options

-s, --storeDirectory <directory>
  • specifies the location of the database to use

  • default: './jqassistant/store'

-concepts <concept1>,<concept2>
  • specifies the ids of the concepts to be applied

-constraints <constraint1>,<constraint2>
  • specifies the ids of the constraints to be validated

-groups <group1>,<group2>
  • specifies the ids of the groups to be executed

  • default: 'default'

-r, --ruleDirectory <directory>
  • specifies the directory where rule files are located

  • default: './jqassistant/rules'

-reportDirectory
  • specifies the directory where reports (XML, HTML) will be stored

  • default: './jqassistant/report'

Maven Plugin

jQAssistant provides a plugin for Apache Maven which can be used to provide either fully automated scanning and analysis during the build process or manual execution from a command line.

Setup

Project Scope

Software projects often consist of several modules which are assembled to executable or deployable artifacts. In a Maven project these modules are usually organized hierarchically with a common parent module which is referenced directly or indirectly by all sub-modules. For each project jQAssistant uses a separate database with its own set of rules. Thus if a goal is executed within a Maven structure jQAssistant first determines the project scope, i.e. the root module, by searching within the tree starting from the current module following the parent relation until either a module is found where a directory "jqassistant/" exists or no parent is defined. The determined root module defines the location of

  • the set of rules to apply (from the directory "jqassistant/")

  • the database, default "{project.build.directory}/jqassistant/store"

  • the generated native report, default: "{project.build.directory}/jqassistant/jqassistant-report.xml")

  • and the generated HTML report, default "{project.build.directory}/site/jqassistant.html")

The following examples demonstrate different scenarios, the root modules as detected by jQAssistant are marked using asterisks.

Single project consisting of two modules
root*
   |-pom.xml
   |
   |-jqassistant
   |           |-rules.xml
   |
   |-module1
   |       |-pom.xml
   |
   |-module2
           |-pom.xml
Multiple projects, each consisting of two modules
root
   |-pom.xml
   |
   |-project1*
   |        |-jqassistant
   |        |           |-rules1.xml
   |        |
   |        |-pom.xml
   |        |-module1
   |        |       |-pom.xml
   |        |
   |        |-module2
   |                |-pom.xml
   |
   |-project2*
            |-jqassistant
            |           |-rules2.xml
            |-pom.xml
            |-module1
            |       |-pom.xml
            |
            |-module2
                    |-pom.xml

Plugin Configuration

The jQAssistant Maven plugin must be configured in the pom.xml of the root module, it should not be overwritten by sub-modules.

Setup of the jQAssistant Maven plugin
<project ...>
    ...
    <build>
        <plugins>
            <plugin>
            <groupId>com.buschmais.jqassistant.scm</groupId>
                <artifactId>jqassistant-maven-plugin</artifactId>
                <version>1.0.0-RC1</version>
                <executions>
                    <execution>
                        <id>scan</id>
                        <goals>
                            <goal>scan</goal>
                        </goals>
                        <!--
                        <configuration>
                            <scanIncludes>
                                <scanInclude>
                                    <path>config</path>
                                </scanInclude>
                                <scanInclude>
                                    <path>target/extra-classes</path>
                                    <scope>java:classpath</scope>
                                </scanInclude>
                            </scanIncludes>
                            <scanProperties>
                                <customScanner.property>value</customScanner.property>
                            </scanProperties>
                        </configuration>
                        -->
                    </execution>
                    <execution>
                        <id>analyze</id>
                        <goals>
                            <goal>analyze</goal>
                        </goals>
                        <!--
                        <configuration>
                            <concepts>
                                <concept>junit4:TestClass</concept>
                            </concepts>
                            <constraints>
                                <constraint>junit4:TestMethodWithoutAssertion</constraints>
                            </constraints>
                            <groups>
                                <group>default</group>
                            </groups>
                            <failOnViolations>true</failOnViolations>
                            <severity>critical</severity>
                        </configuration>
                         -->
                    </execution>
                </executions>
                <!--
                <configuration>
                    <skip>false</skip>
                    <storeLifecycle>REACTOR</storeLifecycle>
                    <rulesDirectory>jqassistant</rulesDirectory>
                    <rulesDirectories>
                        <rulesDirectory>target/generated-rules</rulesDirectory>
                    </rulesDirectories>
                    <xmlReportFile>target/jqassistant/jqassistant-report.xml</xmlReportFile>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>com.buschmais.jqassistant.plugin</groupId>
                        <artifactId>jqassistant.plugin.jpa2</artifactId>
                        <version>1.0.0-RC1</version>
                    </dependency>
                </dependencies>
                -->
            </plugin>
        </plugins>
    </build>

    <reporting>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-project-info-reports-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>com.buschmais.jqassistant.scm</groupId>
                <artifactId>jqassistant-maven-plugin</artifactId>
                <version>1.0.0-RC1</version>
                <reportSets>
                    <reportSet>
                        <reports>
                            <report>report</report>
                        </reports>
                    </reportSet>
                </reportSets>
                <!--
                <configuration>
                    <reportProperties>
                        <customReport.fileName>target/customReport.txt</customReport.fileName>
                    </reportProperties>
                </configuration>
                -->
            </plugin>
        </plugins>
    </reporting>
    ...
</project>

Command Line

Goals may also be executed from the command line:

mvn com.buschmais.jqassistant.scm:jqassistant-maven-plugin:available-rules

Adding the following lines to the file settings.xml (usually located in the $HOME/.m2) eases execution of jQAssistant goals from the command line:

<pluginGroups>
    <pluginGroup>com.buschmais.jqassistant.scm</pluginGroup>
</pluginGroups>

The same goal can now be executed using the following command line statement:

mvn jqassistant:available-rules

Goals

jqassistant:scan

Description

Scans the directories of compiled classes and test classes and stores the gathered information in database.

Configuration

jqassistant:available-scopes

Description

List all available scopes which may be specified for scanInclude properties.

jqassistant:reset

Description

Resets the database by deleting all nodes and relationships.

jqassistant:server

Description

Starts the integrated Neo4j web server (http://localhost:7474).

jqassistant:analyze

Description

Executes an analysis.

Configuration

jqassistant:effective-rules

Description

List the rules which would be executed for an analysis and the given concepts, constraints or groups.

jqassistant:available-rules

Description

List all available rules.

jqassistant:report

Description

Transforms the XML report into HTML (i.e. for generating a Maven site).

Common Configuration Properties

Execution

skip (-Djqassistant.skip)
  • skip execution of the plugin

  • default: 'false'

Store

storeDirectory (-Djqassistant.store.directory)
  • specifies the location of the database

  • default: '{rootModule}/target/jqassistant/store'

storeLifecycle (-Djqassistant.store.lifecycle)
  • specifies the lifecycle of the data store

    • 'REACTOR': cache the store for the execution time of the reactor for fast operations

    • 'MODULE': open and close the store for each module

  • default: 'REACTOR'

Analysis And Report

concepts (-Djqassistant.concepts)
  • specifies the ids of the concepts to be applied

constraints (-Djqassistant.constraints)
  • specifies the ids of the constraints to be validated

groups (-Djqassistant.groups)
  • specifies the ids of the groups to be executed

  • default: 'default'

rulesDirectory (-Djqassistant.rules.directory)
  • specifies the name of the directory which contains rules

  • this directory is also used to identify the root module of a project, see Project Scope

  • default: 'jqassistant'

rulesDirectories (-Djqassistant.rules.directories)
  • specifies a list of directory names relative to the root module containing additional rules

xmlReportFile (-Djqassistant.report.xml)
  • specifes the target file for writing the XML report

  • default: '{rootModule}/target/jqassistant/jqassistant-report.xml'

Examples

Rules

Forbidden Method

Demonstrates a constraint to define methods which must not be invoked by the application. The example denies usage of all constructors of java.util.Date.

jqassistant/default.xml
<jqa:jqassistant-rules xmlns:jqa="http://www.buschmais.com/jqassistant/core/analysis/rules/schema/v1.0">

    <constraint id="example:ConstructorOfDateMustNotBeUsed">
        <description>Constructors of java.util.Date must not be used.</description>
        <cypher><![CDATA[
            MATCH
                (dateType:Type)-[:DECLARES]->(forbiddenMethod:Method),
                (type:Type)-[:DECLARES]->(method:Method)-[:INVOKES]->(forbiddenMethod)
            WHERE
                dateType.fqn = 'java.util.Date'
                AND forbiddenMethod:Constructor
            RETURN
                method AS Method
        ]]></cypher>
    </constraint>

    <group id="default">
        <includeConstraint refId="example:ConstructorOfDateMustNotBeUsed"/>
    </group>

</jqa:jqassistant-rules>

Naming

The following rules demonstrate concepts and constraints to enforce names and locations of classes with dedicated roles. These are identified either by an implemented interface or an annotation.

Interface
jqassistant/controller.xml
<jqa:jqassistant-rules xmlns:jqa="http://www.buschmais.com/jqassistant/core/analysis/rules/schema/v1.0">

    <concept id="controller:ControllerClass">
        <description>Labels all classes implementing the Controller interface as "Controller".</description>
        <cypher><![CDATA[
            MATCH
                (controllerClass:Type:Class)-[:IMPLEMENTS*]->(controllerType:Type)
            WHERE
                controllerType.fqn = "com.buschmais.jqassistant.examples.rules.naming.Controller"
            SET
                controllerClass:Controller
            RETURN
                controllerClass
        ]]></cypher>
    </concept>

    <constraint id="controller:ClassNameMustHaveControllerSuffix">
        <requiresConcept refId="controller:ControllerClass"/>
        <description>All controller implementations must have a name suffix "Controller".</description>
        <cypher><![CDATA[
            MATCH
                (controllerClass:Class:Controller)
            WHERE
                NOT controllerClass.name =~ ".*Controller"
            RETURN
                controllerClass AS ControllerClass
        ]]></cypher>
    </constraint>

    <constraint id="controller:ClassesMustBeLocatedInControllerPackage">
        <requiresConcept refId="controller:ControllerClass"/>
        <description>All controller implementations must be located in the package "model".</description>
        <cypher><![CDATA[
            MATCH
                (package:PACKAGE)-[:CONTAINS]->(controllerClass:Class:Controller)
            WHERE
                NOT package.name = "controller"
            RETURN
                controllerClass AS ControllerClass, package AS InvalidPackage
        ]]></cypher>
    </constraint>

</jqa:jqassistant-rules>
Annotation
jqassistant/model.xml
<jqa:jqassistant-rules xmlns:jqa="http://www.buschmais.com/jqassistant/core/analysis/rules/schema/v1.0">

    <concept id="model:ModelClass">
        <description>Labels all classes annotated with @Model as "Model".</description>
        <cypher><![CDATA[
            MATCH
                (modelClass:Type:Class)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(modelAnnotationType:Type)
            WHERE
                modelAnnotationType.fqn = "com.buschmais.jqassistant.examples.rules.naming.Model"
            SET
                modelClass:Model
            RETURN
                modelClass AS ModelClass
        ]]></cypher>
    </concept>

    <constraint id="model:ClassNameMustHaveModelSuffix">
        <requiresConcept refId="model:ModelClass"/>
        <description>All model classes must have a name suffix "Model".</description>
        <cypher><![CDATA[
            MATCH
                (modelClass:Class:Model)
            WHERE
                NOT modelClass.name =~ ".*Model"
            RETURN
                modelClass AS ModelClass
        ]]></cypher>
    </constraint>

    <constraint id="model:ClassesMustBeLocatedInModelPackage">
        <requiresConcept refId="model:ModelClass"/>
        <description>All model classes must be located in the package "model".</description>
        <cypher><![CDATA[
            MATCH
                (package:PACKAGE)-[:CONTAINS]->(modelClass:Class:Model)
            WHERE
                NOT package.name = "model"
            RETURN
                modelClass AS ModelClass, package AS InvalidPackage
        ]]></cypher>
    </constraint>

</jqa:jqassistant-rules>

Scripting

Demonstrates a constraint implemented using JavaScript.

jqassistant/default.xml
<jqa:jqassistant-rules xmlns:jqa="http://www.buschmais.com/jqassistant/core/analysis/rules/schema/v1.0">

    <group id="default">
        <includeConstraint refId="xmlExample:JavaScriptConstraint"/>
        <includeConstraint refId="asciiDocExample:JavaScriptConstraint"/>
    </group>

    <constraint id="xmlExample:JavaScriptConstraint">
        <description>JavaScript example constraint: returns a result containing the number
            of declared methods for each class.</description>
        <script language="JavaScript">
            // Define the columns returned by the constraint
            var columnNames = java.util.Arrays.asList("Type", "MethodsOfType");
            // Define the list of rows returned by the constraint
            var rows = new java.util.ArrayList();
            // Execute a query using the store
            var typeIterator = store.executeQuery("match (t:Type:Class) return t").iterator();
            while(typeIterator.hasNext()) {
                // Get the next row from the query result
                var typeRow = typeIterator.next();
                // Get the column "t" from the row, it represents a type
                // descriptor as defined by the Java plugin
                var type = typeRow.get("t",
                    com.buschmais.jqassistant.plugin.java.api.model.TypeDescriptor.class);
                // Get the declared methods of the type and count them
                var methodIterator = type.getDeclaredMethods().iterator();
                var methodsOfType = 0;
                while( methodIterator.hasNext()) {
                    methodIterator.next();
                    methodsOfType++;
                }
                // Define the row for the result and put the value for each defined column
                var resultRow = new java.util.HashMap();
                resultRow.put("Class", type);
                resultRow.put("MethodsOfType", methodsOfType);
                rows.add(resultRow);
            }
            // Return the result
            new com.buschmais.jqassistant.core.analysis.api.Result(rule, severity, columnNames, rows);
        </script>
    </constraint>

</jqa:jqassistant-rules>

Other scripting languages may be used as well if they integrate with the Java Scripting API (JSR-223), e.g. Groovy or JRuby. The corresponding libraries must be available on the classpath of jQAssistant, e.g. by adding a dependency to the Maven plugin:

pom.xml
    <plugins>
        <plugin>
            <groupId>com.buschmais.jqassistant.scm</groupId>
            <artifactId>jqassistant-maven-plugin</artifactId>
            <version>1.0.0-RC1</version>
            <dependencies>
                <dependency>
                    <groupId>org.codehaus.groovy</groupId>
                    <artifactId>groovy-jsr223</artifactId>
                    <version>2.4.0</version>
                </dependency>
                <dependency>
                    <groupId>org.jruby</groupId>
                    <artifactId>jruby-core</artifactId>
                    <version>1.7.18</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

The following global variables are provided to the script:

store

The store instance of type com.buschmais.jqassistant.core.store.api.Store which provides access to the graph database.

rule

The rule to be executed, i.e. a an instance of com.buschmais.jqassistant.core.analysis.api.rule.ExecutableRule.

severity

The effective severity.

The script must return a result which is structured like a database result consisting of rows each represented by a map of named columns and their values. Therefore an instance of com.buschmais.jqassistant.core.analysis.api.Result must be created which takes the following constructor arguments:

rule

The rule as provided to the script.

severity

The severity to report, a value of the enum type com.buschmais.jqassistant.core.analysis.api.rule.Severity.

columnNames

A java.util.List containing strings representing the column names.

rows

A java.util.List containing instances of java.util.Map where each map represents a single row consisting of the column name as key and a corresponding value.

Tip
The rule can also be specified in an AsciiDoc document:
jqassistant/default.adoc
= Using script languages as rules

[[asciiDocExample:JavaScriptConstraint]]
.JavaScript example constraint: returns a result containing the number of declared methods for each class.
[source,javascript,role=constraint]
----
// Define the columns returned by the constraint
var columnNames = java.util.Arrays.asList("Type", "MethodsOfType");
// Define the list of rows returned by the constraint
var rows = new java.util.ArrayList();
// Execute a query using the store
var typeIterator = store.executeQuery("match (t:Type:Class) return t").iterator();
while(typeIterator.hasNext()) {
    // Get the next row from the query result
    var typeRow = typeIterator.next();
    // Get the column "t" from the row, it represents a type
    // descriptor as defined by the Java plugin
    var type = typeRow.get("t",
        com.buschmais.jqassistant.plugin.java.api.model.TypeDescriptor.class);
    // Get the declared methods of the type and count them
    var methodIterator = type.getDeclaredMethods().iterator();
    var methodsOfType = 0;
    while( methodIterator.hasNext()) {
        methodIterator.next();
        methodsOfType++;
    }
    // Define the row for the result and put the value for each defined column
    var resultRow = new java.util.HashMap();
    resultRow.put("Class", type);
    resultRow.put("MethodsOfType", methodsOfType);
    rows.add(resultRow);
}
// Return the result
new com.buschmais.jqassistant.core.analysis.api.Result(rule, severity, columnNames, rows);
----

Plugins

Custom Scanner Plugin

A custom scanner plugin allows extending the functionality of jQAssistant to read arbitrary structures (e.g. from files) and create the corresponding information in the database. The following example demonstrates this for CSV files.

The plugin is an artifact which contains the scanner implementation, model classes and a plugin descriptor. The project needs to declare the following dependencies:

pom.xml
<dependencies>
    <dependency>
        <groupId>com.buschmais.jqassistant.core</groupId>
        <artifactId>jqassistant.core.scanner</artifactId>
        <version>1.0.0-RC1</version>
    </dependency>
    <dependency>
        <groupId>com.buschmais.jqassistant.plugin</groupId>
        <artifactId>jqassistant.plugin.common</artifactId>
        <version>1.0.0-RC1</version>
    </dependency>
    <dependency>
        <groupId>au.com.bytecode</groupId>
        <artifactId>opencsv</artifactId>
        <version>2.4</version>
    </dependency>
</dependencies>

The artifact 'jqassistant.core.scanner' provides the scanner plugin API, 'jqassistant.plugin.common' contains common functionality shared by plugins, the library 'opencsv' is used to read CSV files.

The model to be stored in the database is defined using the approach provided by eXtended Objects. It is based on annotated interfaces declaring methods representing properties and relations.

First a label "CSV" is defined which is going to be used for all nodes created by the scanner:

com.buschmais.jqassistant.examples.plugins.scanner.model.CSVDescriptor
@Label("CSV")
public interface CSVDescriptor extends Descriptor {
}

A CSV file is represented by CSVFileDescriptor which inherits from CSVDescriptor and FileDescriptor (part of the scanner API). Thus a node of this type will carry the labels "CSV" and "File". Furthermore a list of "HAS_ROW" relations is defined by the property "rows".

com.buschmais.jqassistant.examples.plugins.scanner.model.CSVFileDescriptor
public interface CSVFileDescriptor extends CSVDescriptor, FileDescriptor {

    @Relation("HAS_ROW")
    List<CSVRowDescriptor> getRows();

}

A single row is a node defined by the type CSVRowDescriptor which inherits the label "CSV" from CSVDescriptor and provides its own label "Row", a property "lineNumber" and a list of "HAS_COLUMN" relations.

com.buschmais.jqassistant.examples.plugins.scanner.model.CSVRowDescriptor
@Label("Row")
public interface CSVRowDescriptor extends CSVDescriptor {

    int getLineNumber();

    void setLineNumber(int lineNumber);

    @Relation("HAS_COLUMN")
    List<CSVColumnDescriptor> getColumns();
}

CSVColumnDescriptor finally defines a column of a row following the principles explained above:

com.buschmais.jqassistant.examples.plugins.scanner.model.CSVColumnDescriptor
@Label("Column")
public interface CSVColumnDescriptor extends CSVDescriptor {

    String getValue();

    void setValue(String value);

    int getIndex();

    void setIndex(int index);

}

The implementation of the plugin itself inherits from AbstractScannerPlugin which requires generic type parameters for the item type it handles and the descriptor type it creates. In the example FileResource is used which represents a file contained in a directory or archive. This allows plugins to be independent of the source where files or directories are picked up by the scanner.

The method accepts is called by the scanner to determine if the plugin can handle the given item. The example matches the value of the parameter path against the file extension ".csv". The scope parameter may be used to further restrict executions of the plugin, e.g. by checking equality against JavaScope.CLASSPATH.

The scan method actually reads the CSV file and stores the gathered data into the database using the interface Store provided by the scanner context.

com.buschmais.jqassistant.examples.plugins.scanner.CSVFileScannerPlugin
public class CSVFileScannerPlugin extends AbstractScannerPlugin<FileResource, CSVFileDescriptor> {

    @Override
    public boolean accepts(FileResource item, String path, Scope scope) throws IOException {
        return path.toLowerCase().endsWith(".csv");
    }

    @Override
    public CSVFileDescriptor scan(FileResource item, String path, Scope scope, Scanner scanner) throws IOException {
        // Open the input stream for reading the file.
        try (InputStream stream = item.createStream()) {
            // Create the node for a CSV file.
            final Store store = scanner.getContext().getStore();
            final CSVFileDescriptor fileDescriptor = store.create(CSVFileDescriptor.class);
            // Parse the stream using OpenCSV.
            CSV csv = CSV.create();
            csv.read(stream, new CSVReadProc() {

                @Override
                public void procRow(int rowIndex, String... values) {
                    // Create the node for a row
                    CSVRowDescriptor rowDescriptor = store.create(CSVRowDescriptor.class);
                    fileDescriptor.getRows().add(rowDescriptor);
                    rowDescriptor.setLineNumber(rowIndex);
                    for (int i = 0; i < values.length; i++) {
                        // Create the node for a column
                        CSVColumnDescriptor columnDescriptor = store.create(CSVColumnDescriptor.class);
                        rowDescriptor.getColumns().add(columnDescriptor);
                        columnDescriptor.setIndex(i);
                        columnDescriptor.setValue(values[i]);
                    }
                }

            });
            return fileDescriptor;
        }
    }
}

Finally the model and the plugin implementation must be declared in the jQAssistant plugin descriptor:

/META-INF/jqassistant-plugin.xml
<jqa-plugin:jqassistant-plugin
        xmlns:jqa-plugin="http://www.buschmais.com/jqassistant/core/plugin/schema/v1.0" name="CSV Example">
    <description>Provides a scanner for CSV file.</description>
    <model>
        <class>com.buschmais.jqassistant.examples.plugins.scanner.model.CSVFileDescriptor</class>
        <class>com.buschmais.jqassistant.examples.plugins.scanner.model.CSVRowDescriptor</class>
        <class>com.buschmais.jqassistant.examples.plugins.scanner.model.CSVColumnDescriptor</class>
    </model>
    <scanner>
        <class>com.buschmais.jqassistant.examples.plugins.scanner.CSVFileScannerPlugin</class>
    </scanner>
</jqa-plugin:jqassistant-plugin>

The plugin is automatically loaded by the scanner if it can be found on the classpath, e.g. by adding it as dependency to the maven plugin.

Custom Rule Plugin

Rules (i.e. concepts, constraints or groups) can be shared between projects by packaging their rule descriptors in JAR artifacts as a classpath resources under /META-INF/jqassistant-rules/, e.g.

/META-INF/jqassistant-rules/common.xml
<jqa:jqassistant-rules xmlns:jqa="http://www.buschmais.com/jqassistant/core/analysis/rules/schema/v1.0">

    <constraint id="common:TopLevelPackage">
        <description>All types defined in a project must use "com.buschmais" as top level package.</description>
        <cypher><![CDATA[
            MATCH
              (:Artifact)-[:CONTAINS]->(type:Type)
            WHERE
              NOT type.fqn =~ "com\\.buschmais\\..*"
            RETURN
              type AS TypeInWrongPackage
        ]]></cypher>
    </constraint>

</jqa:jqassistant-rules>

Furthermore these resources must be declared in the jQAssistant plugin descriptor /META-INF/jqassistant-plugin.xml:

/META-INF/jqassistant-plugin.xml
<jqa-plugin:jqassistant-plugin xmlns:jqa-plugin="http://www.buschmais.com/jqassistant/core/plugin/schema/v1.0"
                               name="Custom Rules">
    <description>Example plugin defining a set of custom rules.</description>
    <rules>
        <resource>common.xml</resource>
    </rules>
</jqa-plugin:jqassistant-plugin>

The plugin and its rules are automatically loaded by the analyzer if it can be found on the classpath, e.g. by adding it as dependency to the maven plugin.

Custom Report Plugin

A custom report plugin may be implemented to create custom representations of analysis results. Such a plugin must be provided as an artifact which contains a Java class and a plugin descriptor. Therefore a project is required which declares the required dependencies:

pom.xml
<dependencies>
    <dependency>
        <groupId>com.buschmais.jqassistant.core</groupId>
        <artifactId>jqassistant.core.report</artifactId>
        <version>1.0.0-RC1</version>
    </dependency>
    <dependency>
        <groupId>com.buschmais.jqassistant.plugin</groupId>
        <artifactId>jqassistant.plugin.java</artifactId>
        <version>1.0.0-RC1</version>
    </dependency>
</dependencies>

The artifact 'jqassistant.core.report' provides the report plugin API, 'jqassistant.plugin.java' provides interfaces representing Java types which might be used by the plugin implementation:

com.buschmais.jqassistant.examples.plugins.report.CustomReportPlugin
import com.buschmais.jqassistant.core.report.api.ReportPlugin;
import com.buschmais.jqassistant.plugin.java.api.model.TypeDescriptor;

public class CustomReportPlugin implements ReportPlugin {

    private static final String PROPERTY_FILENAME = "customReport.fileName";

    private String fileName;

    @Override
    public void initialize(Map<String, Object> properties) throws ReportException {
        this.fileName = (String) properties.get(PROPERTY_FILENAME);
        if (this.fileName == null) {
            throw new ReportException("Property " + PROPERTY_FILENAME + " is not specified.");
        }
    }

    @Override
    public void begin() throws ReportException {
    }

    @Override
    public void end() throws ReportException {
    }

    @Override
    public void beginConcept(Concept concept) throws ReportException {
    }

    @Override
    public void endConcept() throws ReportException {
    }

    @Override
    public void beginGroup(Group group) throws ReportException {
    }

    @Override
    public void endGroup() throws ReportException {
    }

    @Override
    public void beginConstraint(Constraint constraint) throws ReportException {
    }

    @Override
    public void endConstraint() throws ReportException {
    }

    @Override
    public void setResult(Result<? extends Rule> result) throws ReportException {
        Rule rule = result.getRule();
        if (rule instanceof Concept && "example:MethodsPerType".equals(rule.getId())) {
            try {
                PrintWriter writer = new PrintWriter(new FileWriter(fileName));
                writer.println("Methods per Type");
                writer.println("================");
                for (Map<String, Object> row : result.getRows()) {
                    TypeDescriptor type = (TypeDescriptor) row.get("Type");
                    Long methodCount = (Long) row.get("MethodCount");
                    writer.println(type.getFullQualifiedName() + ":" + methodCount);
                }
                writer.close();
            } catch (IOException e) {
                throw new ReportException("Cannot write custom report.", e);
            }
        }
    }
}

The plugin implementation must be declared in the jQAssistant plugin descriptor:

/META-INF/jqassistant-plugin.xml
<jqa-plugin:jqassistant-plugin xmlns:jqa-plugin="http://www.buschmais.com/jqassistant/core/plugin/schema/v1.0" name="Custom Report">
    <description>Example plugin defining a custom report.</description>
    <report>
        <class>com.buschmais.jqassistant.examples.plugins.report.CustomReportPlugin</class>
    </report>
</jqa-plugin:jqassistant-plugin>

The plugin is automatically loaded by the analyzer if it can be found on the classpath, e.g. by adding it as dependency to the maven plugin.

Using Custom Plugins

Custom plugins containing rules, scanners or reporters must be specified as dependency of the Maven plugin. It is also possible to specify plugin specific properties:

pom.xml
<build>
    <plugins>
        <plugin>
            <groupId>com.buschmais.jqassistant.scm</groupId>
            <artifactId>jqassistant-maven-plugin</artifactId>
            <version>1.0.0-RC1</version>
            <configuration>
                <reportProperties>
                    <customReport.fileName>target/customReport.txt</customReport.fileName>
                </reportProperties>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>com.buschmais.jqassistant.examples</groupId>
                    <artifactId>jqassistant.examples.plugins.scanner</artifactId>
                    <version>1.0.0-RC1</version>
                </dependency>
                <dependency>
                    <groupId>com.buschmais.jqassistant.examples</groupId>
                    <artifactId>jqassistant.examples.plugins.rule</artifactId>
                    <version>1.0.0-RC1</version>
                </dependency>
                <dependency>
                    <groupId>com.buschmais.jqassistant.examples</groupId>
                    <artifactId>jqassistant.examples.plugins.report</artifactId>
                    <version>1.0.0-RC1</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

SonarQube

jQAssistant Plugin

Projects may retrieve jQAssistant rules from a SonarQube instance using a permalink. Furthermore a sensor is provided which will create issues on violated constraints.

The plugin is available from the standalone distribution in the folder "sonar/" and must be copied to the directory "extensions/plugins" of the SonarQube server. After startup a repository 'jQAssistant' is available in the view 'Coding rules' providing all rules which are distributed with jQAssistant.

New rules can be added or created in the following ways:

  • by creating new concepts and constraints from the pre-defined templates (i.e. "Concept Template" and "Constraint Template")

  • by deploying a custom rule extension (demonstrated by the example "Custom Rule Extension")

Next the following settings must be applied to the jQAssistant Maven plugin in the pom.xml of the project to be analyzed:

pom.xml
            <build>
                <plugins>
                    <plugin>
                        <groupId>com.buschmais.jqassistant.scm</groupId>
                        <artifactId>jqassistant-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>scan</id>
                                <goals>
                                    <goal>scan</goal>
                                </goals>
                            </execution>
                            <execution>
                                <id>analyze</id>
                                <goals>
                                    <goal>analyze</goal>
                                </goals>
                                <configuration>
                                    <rulesUrl>http://localhost:9000/profiles/export?format=jqassistant&amp;language=java&amp;name=MyQualityProfile</rulesUrl>
                                    <groups>
                                        <group>MyQualityProfile</group>
                                    </groups>
                                    <failOnViolations>false</failOnViolations>
                                    <severity>critical</severity>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
  • Rules are retrieved from the SonarQube server using the URL specified in 'rulesUrl'. The value is the jQAssistant permalink available within the quality profile from the SonarQube UI. Note that special characters must be replaced by XML entities.

  • The specified 'group' must be the name of the quality profile used to analyze the project.

  • The build shall break if a violation is detected, therefore 'failOnViolations' is set to 'true'.

  • The build shall break only if violation is detected with severity equal to or higher than critical, therefore severity is set to critical

Custom Rule Extension

A custom rule extension can be implemented to make user defined jQAssistant rules available for SonarQube. It is a Maven project which declares packaging 'sonar-plugin':

pom.xml
<project ...>
...


<properties>
    <org.codehaus.sonar_version>3.7.4</org.codehaus.sonar_version>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>com.buschmais.jqassistant.scm</groupId>
            <artifactId>jqassistant-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.codehaus.sonar</groupId>
            <artifactId>sonar-packaging-maven-plugin</artifactId>
            <version>1.9</version>
            <extensions>true</extensions>
            <configuration>
                <basePlugin>jqassistant</basePlugin>
                <pluginClass>com.buschmais.jqassistant.examples.sonar.ruleextension.MyJQAssistantExtension</pluginClass>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>native2ascii-maven-plugin</artifactId>
            <version>1.0-beta-1</version>
            <executions>
                <execution>
                    <goals>
                        <goal>native2ascii</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

<dependencies>
    <dependency>
        <groupId>com.buschmais.jqassistant.sonar</groupId>
        <artifactId>jqassistant.sonar.plugin</artifactId>
        <version>1.0.0-RC1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.codehaus.sonar</groupId>
        <artifactId>sonar-plugin-api</artifactId>
        <version>3.7.4</version>
    </dependency>
</dependencies>


...
</project>

Notes on the sonar plugin configuration:

  • 'basePlugin' must be set to 'jQAssistant' to indicate which plugin shall be extended.

  • The implementation of 'pluginClass' (i.e. 'MyJQAssistantExtension') returns an empty list of extensions. It must be specified as this is required by SonarQube.

MyJQAssistantExtension.java
package com.buschmais.jqassistant.examples.sonar.ruleextension;

import java.util.Collections;
import java.util.List;

import org.sonar.api.SonarPlugin;

/**
 * Defines a sonar extension.
 */
public class MyJQAssistantExtension extends SonarPlugin {

    @SuppressWarnings("rawtypes")
    @Override
    public List getExtensions() {
        return Collections.emptyList();
    }

}

The rules itself are packaged according to the following structure:

/META-INF/jqassistant-plugin.xml
<v1:jqassistant-plugin xmlns:v1="http://www.buschmais.com/jqassistant/core/plugin/schema/v1.0"
                       name="Sonar Rule Extension">
    <description>An example plugin.</description>
    <rules>
        <resource>example.xml</resource>
    </rules>
</v1:jqassistant-plugin>
  • example.xml specifies the path to a jQAssistant rule file relative to /META-INF/jqassistant-rules

/META-INF/jqassistant-rules/example.xml
<jqa:jqassistant-rules xmlns:jqa="http://www.buschmais.com/jqassistant/core/analysis/rules/schema/v1.0">

    <!-- Don't take these constraints serious - they are just here to illustrate integration with SonarQube -->

    <constraint id="example:AllClassesMustBeNamedFoo">
        <description>All classes must be named 'Foo'.</description>
        <cypher><![CDATA[
            MATCH
              (type:Class)
            WHERE NOT
              type.name = 'Foo'
            RETURN
              type AS InvalidClass
        ]]></cypher>
    </constraint>

    <constraint id="example:FieldsMustBeReadOnly" severity="critical">
        <description>All declared fields must be read-only (i.e. not be written).</description>
        <cypher><![CDATA[
            MATCH
              (m:Method)-[w:WRITES]->(f:Field)
            RETURN
              w AS WriteAccess
        ]]></cypher>
    </constraint>
</jqa:jqassistant-rules>

The created JAR archive and the jQAssistant must be copied to the folder 'extensions/plugins' of the SonarQube installation. The defined rules will be visible in the repository "jQAssistant".

Plugins

This section provides detailed descriptions of all distributed plugins.

CDI

Provides rules for CDI.

Scanner for beans.xml files

Imports beans descriptors from META-INF/beans.xml or WEB-INF/beans.xml files.

:File:Cdi:Beans

Represents a beans.xml file.

Table 1. Properties of :File:Cdi:Beans
Name Description

fileName

The file name

version

The version of the CDI specification this descriptor represents, e.g. '1.0'

beanDiscoveryMode

The bean discovery mode, i.e. "all", "annotated" or "none"

Table 2. Relations of :File:Cdi:Beans
Name Target label(s) Cardinality Description

HAS_INTERCEPTOR

:Java:Type

0..n

References an interceptor type which is activated

HAS_DECORATOR

:Java:Type

0..n

References a decorator type which is activated

HAS_ALTERNATIVE

:Java:Type

0..n

References an alternative type (class or stereotype annotation) which is activated

Refer to the plugin Javadoc for details about the model.

cdi.xml

Concepts
cdi:Alternative

Labels all types annotated by @javax.enterprise.inject.Alternative with "Cdi" and "Alternative".

MATCH
  (alternative:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(alternativeType:Type)
WHERE
  alternativeType.fqn="javax.enterprise.inject.Alternative"
SET
  alternative:Cdi:Alternative
RETURN
  alternative AS Alternative
cdi:Any

Labels all elements annotated by "javax.enterprise.inject.Any" with "Cdi" and "Any".

MATCH
  (e)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(anyType:Type)
WHERE
  anyType.fqn = "javax.enterprise.inject.Any"
SET
  e:Cdi:Any
RETURN
  e AS Any
cdi:ApplicationScoped

Labels all beans, fields or methods annotated by @javax.enterprise.context.ApplicationScoped with "Cdi" and "ApplicationScoped".

MATCH
  (e)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(scopeType:Type)
WHERE
  (e:Type or e:Method or e:Field)
  and scopeType.fqn="javax.enterprise.context.ApplicationScoped"
SET
  e:Cdi:ApplicationScoped
RETURN
  e AS ApplicationScopedElement
cdi:ConversationScoped

Labels all beans, fields or methods annotated by @javax.enterprise.context.ConversationScoped with "Cdi" and "ConversationScoped".

MATCH
  (e)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(scopeType:Type)
WHERE
  (e:Type or e:Method or e:Field)
  and scopeType.fqn="javax.enterprise.context.ConversationScoped"
SET
  e:Cdi:ConversationScoped
RETURN
  e AS ConversationScopedElement
cdi:Decorator

Requires concepts:

Labels all types annotated by @javax.decorator.Decorator with "Cdi" and "Decorator".

MATCH
  (decorator:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(decoratorType:Type)
WHERE
  decoratorType.fqn="javax.decorator.Decorator"
SET
  decorator:Cdi:Decorator
RETURN
  decorator AS Decorator
cdi:Default

Labels all elements annotated by "javax.enterprise.inject.Default" with "Cdi" and "Default".

MATCH
  (e)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(defaultType:Type)
WHERE
  defaultType.fqn = "javax.enterprise.inject.Default"
SET
  e:Cdi:Default
RETURN
  e AS Default
cdi:Delegate

Labels all fields annotated annotated by @javax.decorator.Delegate with "Cdi" and "Delegate".

MATCH
  (delegate:Field)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(delegateType:Type)
WHERE
  delegateType.fqn="javax.decorator.Delegate"
SET
  delegate:Cdi:Delegate
RETURN
  delegate AS Delegate
cdi:Dependent

Labels all beans, fields or methods annotated by @javax.enterprise.context.Dependent with "Cdi" and "Dependent".

MATCH
  (e)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(scopeType:Type)
WHERE
  (e:Type or e:Method or e:Field)
  and scopeType.fqn="javax.enterprise.context.Dependent"
SET
  e:Cdi:Dependent
RETURN
  e AS DependentElement
cdi:Disposes

Creates a relation DISPOSES between a parameter and its type if the parameter is annotated by @javax.enterprise.inject.Disposes.

MATCH
  (:Type)-[:DECLARES]->(disposeMethod:Method)-[:HAS]->(parameter:Parameter),
  (parameter)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(disposesType:Type),
  (parameter)-[:OF_TYPE]->(type)
WHERE
  disposesType.fqn="javax.enterprise.inject.Disposes"
CREATE UNIQUE
  (parameter)-[:DISPOSES]->(type)
RETURN
  disposeMethod AS DisposeMethod
cdi:EventConsumer

Requires concepts:

Labels all beans declaring method that has parameter of type "javax.enterprise.event.Observes" with "Cdi" and "EventConsumer".

MATCH
  (a:Type)-[:DECLARES]->(member:Method)-[:HAS]->(param:Parameter),
  (param)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(injectType:Type)
WHERE
  injectType.fqn = "javax.enterprise.event.Observes"
SET
  a:Cdi:EventConsumer
RETURN
  DISTINCT a.fqn AS cdiEventConsumer
cdi:EventProducer

Requires concepts:

Labels all beans declaring "InjectionPoint" of type "javax.enterprise.event.Event" with "Cdi" and "EventProducer".

MATCH
  (a:Type)-[:DECLARES]->(member:Field:Cdi:InjectionPoint),
  (member)-[:OF_TYPE]->(injectType:Type)
WHERE
  injectType.fqn = "javax.enterprise.event.Event"
SET
  a:Cdi:EventProducer
RETURN
  DISTINCT a.fqn AS cdiEventProducers
cdi:InjectionPoint

Labels all fields or methods annotated by @javax.inject.Inject with "Cdi" and "InjectionPoint".

MATCH
  (:Type)-[:DECLARES]->(member),
  (member)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(injectType:Type)
WHERE
  (member:Field or member:Method)
  and injectType.fqn="javax.inject.Inject"
SET
  member:Cdi:InjectionPoint
RETURN
  member AS InjectionPoint
cdi:Named

Labels all types or methods annotated by "javax.inject.Named" with "Cdi" and "Named".

MATCH
  (e)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(namedType:Type)
WHERE
  namedType.fqn = "javax.inject.Named"
SET
  e:Cdi:Named
RETURN
  e AS Named
cdi:New

Labels all elements annotated by "javax.enterprise.inject.New" with "Cdi" and "New".

MATCH
  (e)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(newType:Type)
WHERE
  newType.fqn = "javax.enterprise.inject.New"
SET
  e:Cdi:New
RETURN
  e AS New
cdi:Produces

Creates a relation PRODUCES between a field and its type or a method and its return type if the parameter is annotated by @javax.enterprise.inject.Disposes.

MATCH
  (:Type)-[:DECLARES]->(member),
  (member)-[:OF_TYPE|RETURNS]->(type),
  (member)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(producesType:Type)
WHERE
  (member:Field or member:Method)
  and producesType.fqn="javax.enterprise.inject.Produces"
CREATE UNIQUE
  (member)-[:PRODUCES]->(type)
RETURN
  member AS Producer
cdi:Qualifier

Labels all annotation types annotated by @javax.inject.Qualifier with "Cdi" and "Qualifier" and adds the labels "Cdi" and "Nonbinding" to all non-binding annotation values (i.e. which are annotated by @javax.enterprise.util.Nonbinding).

MATCH
  (qualifier:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(qualifierType:Type)
WHERE
  qualifierType.fqn = "javax.inject.Qualifier"
SET
  qualifier:Cdi:Qualifier
WITH
  qualifier
MATCH
  (qualifier)-[:DECLARES]->(attribute:Method),
  (attribute)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(nonbindingType:Type)
WHERE
  nonbindingType.fqn = "javax.enterprise.util.Nonbinding"
SET
  attribute:Cdi:Nonbinding
RETURN
  distinct qualifier AS Qualifier
cdi:RequestScoped

Labels all beans, fields or methods annotated by @javax.enterprise.context.RequestScoped with "Cdi" and "RequestScoped".

MATCH
  (e)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(scopeType:Type)
WHERE
  (e:Type or e:Method or e:Field)
  and scopeType.fqn="javax.enterprise.context.RequestScoped"
SET
  e:Cdi:RequestScoped
RETURN
  e AS RequestScopedElement
cdi:SessionScoped

Labels all beans, fields or methods annotated by @javax.enterprise.context.SessionScoped with "Cdi" and "SessionScoped".

MATCH
  (e)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(scopeType:Type)
WHERE
  (e:Type or e:Method or e:Field)
  and scopeType.fqn="javax.enterprise.context.SessionScoped"
SET
  e:Cdi:SessionScoped
RETURN
  e AS SessionScopedElement
cdi:SingletonScoped

Labels all beans annotated by @javax.inject.Singleton with "Cdi" and "SingletonScoped".

MATCH
  (t:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn = "javax.inject.Singleton"
SET
  t:Cdi:SingletonScoped
RETURN
  t AS cdiSingleton
cdi:Specializes

Labels all types and methods annotated by @javax.enterprise.inject.Specializes with "Cdi" and "Specializes".

MATCH
  (specializes)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(specializesType:Type)
WHERE
  (specializes:Type or specializes:Method)
  and specializesType.fqn="javax.enterprise.inject.Specializes"
SET
  specializes:Cdi:Specializes
RETURN
  specializes AS Specialization
cdi:Stereotype

Labels all annotation types annotated by @javax.enterprise.inject.Stereotype with "Cdi" and "Stereotype".

MATCH
  (stereotype:Type:Annotation)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(stereotypeType:Type)
WHERE
  stereotypeType.fqn="javax.enterprise.inject.Stereotype"
SET
  stereotype:Cdi:Stereotype
RETURN
  stereotype AS Stereotype
Constraints
cdi:BeansMustNotUseFieldInjection

Requires concepts:

CDI beans shall not use field injection (constructor and setter injections are fine.).

MATCH
  (a:Type)-[:DECLARES]->(member:Field:Cdi:InjectionPoint)
RETURN
  DISTINCT a.fqn AS invalidBean
cdi:BeansMustUseConstructorInjection

Requires concepts:

All CDI beans must use constructor injection.

MATCH
  (a:Type)-[:DECLARES]->(member:Cdi:InjectionPoint)
WHERE
  NOT member:Constructor
RETURN
  DISTINCT a.fqn AS invalidBean

decorator.xml

Concepts
decorator:Decorator

Requires concepts:

Labels all types annotated by @javax.decorator.Decorator with "Decorator".

MATCH
  (decorator:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(decoratorType:Type)
WHERE
  decoratorType.fqn="javax.decorator.Decorator"
SET
  decorator:Decorator
RETURN
  decorator AS Decorator
decorator:Delegate

Labels all fields annotated annotated by @javax.decorator.Delegate with "Decorator" and "Delegate".

MATCH
  (delegate:Field)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(delegateType:Type)
WHERE
  delegateType.fqn="javax.decorator.Delegate"
SET
  delegate:Decorator:Delegate
RETURN
  delegate AS Delegate

interceptor.xml

Concepts
interceptor:Binding

Labels all annotations annotated by "javax.interceptor.InterceptorBinding" with "Interceptor" and "Binding".

MATCH
  (binding:Type:Annotation)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(bindingType:Type)
WHERE
  bindingType.fqn = "javax.interceptor.InterceptorBinding"
SET
  binding:Interceptor:Binding
RETURN
  binding AS InterceptorBinding
interceptor:Interceptor

Labels all classes annotated by "javax.interceptor.Interceptor" with "Interceptor".

MATCH
  (interceptor:Type:Class)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(interceptorType:Type)
WHERE
  interceptorType.fqn = "javax.interceptor.Interceptor"
SET
  interceptor:Interceptor
RETURN
  interceptor AS Interceptor

EJB3

Provides rules for EJB3.

ejb3.xml

Concepts
ejb3:Local

Labels all types annotated with @javax.ejb.Local with "Ejb" and "Local".

MATCH (t:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE a.fqn="javax.ejb.Local"
SET t:Ejb:Local
RETURN t AS LocalBean
ejb3:MessageDrivenBean

Labels all types annotated with @javax.ejb.MessageDriven with "Ejb" and "MessageDriven".

MATCH (t:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE a.fqn="javax.ejb.MessageDriven"
SET t:Ejb:MessageDriven
RETURN t AS MessageDrivenBean
ejb3:Remote

Labels all types annotated with @javax.ejb.Remote with "Ejb" and "Remote".

MATCH (t:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE a.fqn="javax.ejb.Remote"
SET t:Ejb:Remote
RETURN t AS RemoteBean
ejb3:SingletonBean

Labels all classes annotated with @javax.ejb.Singleton with "Ejb" and "Singleton".

MATCH (t:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE a.fqn="javax.ejb.Singleton"
SET t:Ejb:Singleton
RETURN t AS SingletonEjb
ejb3:StatefulSessionBean

Labels all types annotated with @javax.ejb.Stateful with "Ejb" and "Stateful".

MATCH (t:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE a.fqn="javax.ejb.Stateful"
SET t:Ejb:Stateful
RETURN t AS StatefulEjb
ejb3:StatelessSessionBean

Labels all types annotated with @javax.ejb.Stateless with "Ejb" and "Stateless".

MATCH (t:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE a.fqn="javax.ejb.Stateless"
SET t:Ejb:Stateless
RETURN t AS StatelessEjb

Facelet

Provides a scanner for JSF template files.

Scanner for JSF-template files

Imports JSF template files (e.g. *.jspx) and builds references between them (template/includes).

Configuration
Table 3. Configuration properties
Property Description Default

facelet.file.pattern

Regular expression that describes scanable JSF template files.

.*\\.jspx

:File:Jsf:Facelet

A JSF template file.

Table 4. Properties of :File:Jsf:Facelet
Name Description

fileName

The file name

Table 5. Relations of :File:Jsf:Facelet
Name Target label(s) Cardinality Description

INCLUDES

:File:Jsf:Facelet

0..n

References a included JSF template file (e.g. <ui:include src="include.jspx"/>)

WITH_TEMPLATE

:File:Jsf:Facelet

0..1

References a used JSF template file (e.g. <ui:composition template="template.jspx" …​>)

Refer to the plugin Javadoc for details about the model.

JAX-RS

Provides rules for JAX-RS.

jaxrs-resource.xml

Concepts
jaxrs:DeleteResourceMethod

Requires concepts:

Finds resource methods annotated with "@javax.ws.rs.DELETE" and labels them with 'DeleteResourceMethod'.

MATCH
  (m:JaxRS:ResourceMethod)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:JaxRS:RequestMethodDesignator)
WHERE
  a.fqn = "javax.ws.rs.DELETE"
SET
  m:DeleteResourceMethod
RETURN
  m AS DeleteMethod
jaxrs:GetResourceMethod

Requires concepts:

Finds resource methods annotated with "@javax.ws.rs.GET" and labels them with 'GetResourceMethod'.

MATCH
  (m:JaxRS:ResourceMethod)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:JaxRS:RequestMethodDesignator)
WHERE
  a.fqn = "javax.ws.rs.GET"
SET
  m:GetResourceMethod
RETURN
  m AS GetMethod
jaxrs:HeadResourceMethod

Requires concepts:

Finds resource methods annotated with "@javax.ws.rs.HEAD" and labels them with 'HeadResourceMethod'.

MATCH
  (m:JaxRS:ResourceMethod)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:JaxRS:RequestMethodDesignator)
WHERE
  a.fqn = "javax.ws.rs.HEAD"
SET
  m:HeadResourceMethod
RETURN
  m AS HeadMethod
jaxrs:OptionsResourceMethod

Requires concepts:

Finds resource methods annotated with "@javax.ws.rs.OPTIONS" and labels them with 'OptionsResourceMethod'.

MATCH
  (m:JaxRS:ResourceMethod)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:JaxRS:RequestMethodDesignator)
WHERE
  a.fqn = "javax.ws.rs.OPTIONS"
SET
  m:OptionsResourceMethod
RETURN
  m AS OptionsMethod
jaxrs:PostResourceMethod

Requires concepts:

Finds resource methods annotated with "@javax.ws.rs.POST" and labels them with 'PostResourceMethod'.

MATCH
  (m:JaxRS:ResourceMethod)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:JaxRS:RequestMethodDesignator)
WHERE
  a.fqn = "javax.ws.rs.POST"
SET
  m:PostResourceMethod
RETURN
  m AS PostMethod
jaxrs:PutResourceMethod

Requires concepts:

Finds resource methods annotated with "@javax.ws.rs.PUT" and labels them with 'PutResourceMethod'.

MATCH
  (m:JaxRS:ResourceMethod)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:JaxRS:RequestMethodDesignator)
WHERE
  a.fqn = "javax.ws.rs.PUT"
SET
  m:PutResourceMethod
RETURN
  m AS PutMethod
jaxrs:RequestMethodDesignator

Finds request method designator annotations (i.e. @GET, @POST, @PUT, @DELETE, @HEAD, @OPTIONS) and labels them with 'JaxRS' and 'RequestMethodDesignator'

MATCH
  (a:Type)
WHERE
  a.fqn IN ["javax.ws.rs.GET", "javax.ws.rs.POST", "javax.ws.rs.PUT", "javax.ws.rs.DELETE", "javax.ws.rs.HEAD", "javax.ws.rs.OPTIONS"]
SET
  a:JaxRS:RequestMethodDesignator
RETURN
  a AS RequestMethodDesignator
jaxrs:Resource

Requires concepts:

Finds classes or interfaces with atleast one method annotated with "@javax.ws.rs.Path" or with request method designator (i.e. @GET, @POST, @PUT, @DELETE, @HEAD, @OPTIONS) and labels them with 'JaxRS' and 'Resource'.

MATCH
  (t:Type)-[:DECLARES]->(m:Method)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:Type)
WHERE
  (a:JaxRS:RequestMethodDesignator OR a.fqn="javax.ws.rs.Path")
AND
  (t:Class OR t:Interface)
SET
  t:JaxRS:Resource
RETURN
  DISTINCT t AS RestResource
jaxrs:ResourceMethod

Requires concepts:

Finds methods that belong to resource class or interface and annotated with request method designator (i.e. @GET, @POST, @PUT, @DELETE, @HEAD, @OPTIONS) and labels them with 'JaxRS' and 'ResourceMethod'.

MATCH
  (c:JaxRS:Resource)-[:DECLARES]->(m:Method)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:JaxRS:RequestMethodDesignator)
SET
  m:JaxRS:ResourceMethod
RETURN
  m AS ResourceMethod
jaxrs:SubResourceLocator

Requires concepts:

Finds classes or interfaces with method annotated with "@javax.ws.rs.Path" but no request method designator and no entity parameters and labels the methods with 'JaxRS' and 'SubResourceLocator'.

MATCH
  (t:Type)-[:DECLARES]->(m:Method)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn = "javax.ws.rs.Path"
AND
  (t:Class OR t:Interface)
AND
  NOT (m)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(:JaxRS:RequestMethodDesignator)
AND
  (m)-[:HAS]->(:Parameter)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(:Type)
SET
  m:JaxRS:SubResourceLocator
RETURN
  DISTINCT m AS RestSubResourceLocator

jaxrs-provider.xml

Concepts
jaxrs:ContextProvider

Finds classes that implement "javax.ws.rs.ext.ContextResolver" and labels them with 'JaxRS' and 'ContextProvider'

MATCH
  (c:Type:Class)-[:IMPLEMENTS]->(a:Type)
WHERE
  a.fqn = "javax.ws.rs.ext.ContextResolver"
SET
  c:JaxRS:ContextProvider
RETURN
  DISTINCT c AS ContextProvider
jaxrs:EntityProvider

Finds classes that implement "javax.ws.rs.ext.MessageBodyReader" or "javax.ws.rs.ext.MessageBodyWriter" and labels them with 'JaxRS' and 'EntityProvider'

MATCH
  (c:Type:Class)-[:IMPLEMENTS]->(a:Type)
WHERE
  a.fqn IN ["javax.ws.rs.ext.MessageBodyReader", "javax.ws.rs.ext.MessageBodyWriter"]
SET
  c:JaxRS:EntityProvider
RETURN
  DISTINCT c AS EntityProvider
jaxrs:ExceptionMappingProvider

Finds classes that implement "javax.ws.rs.ext.ExceptionMapper" and labels them with 'JaxRS' and 'ExceptionMappingProvider'

MATCH
  (c:Type:Class)-[:IMPLEMENTS]->(a:Type)
WHERE
  a.fqn = "javax.ws.rs.ext.ExceptionMapper"
SET
  c:JaxRS:ExceptionMappingProvider
RETURN
  DISTINCT c AS ExceptionMappingProvider

Java

Provides scanner for Java elements (e.g. packages, classes, manifest and property files) and rules for common language concepts (e.g. Deprecation), dependencies and metrics.

Artifact Scanner

:Java:Artifact

A directory or archive containing packages, classes and resources.

Table 6. Properties of :Java:Artifact
Name Description

fqn

Fully qualified name, e.g. 'java.lang'

fileName

The file name of the artifact.

Table 7. Relations of :Java:Artifact
Name Target label(s) Cardinality Description

CONTAINS

[:File]

0..n

References contained files, e.g. packages, classes or resources

REQUIRES

:Java:Type

0..n

References a type which is required by a class in this artifact

:Java:Artifact:Directory

A directory representing a Java artifact.

:Java:Artifact:Jar:Archive

A JAR file representing a Java artifact.

Package Scanner

Imports Java packages.

:Java:Package

A Java package, i.e. a directory containing '.class' files or other directories.

Table 8. Properties of :Java:Package
Name Description

fqn

Fully qualified name, e.g. 'java.lang'

name

The local name, e.g. 'lang'

Table 9. Relations of :Java:Package
Name Target label(s) Cardinality Description

CONTAINS

:Java:Type

0..n

References a type located in the package

CONTAINS

:Java:Package

0..n

References a package located in the package

Class Scanner

Imports Java classes, i.e. all scanned files having a '.class' suffix. Nodes with following labels will be created:

NOTE Some of these labels may be further qualified with other labels, see the description below.

NOTE The full set of information is only available for class files which have actually been scanned. Types which are only referenced (i.e. from external libraries not included in the scan) are represented by ':TYPE' nodes with a property 'fqn' and 'DECLARES' relations to their members. These are ':FIELD' or ':METHOD' labeled nodes which only provide the property 'signature'.

:Java:Type

A Java type. Can be qualified by either ':Class', ':Interface', ':Enum' or ':Annotation'

Table 10. Properties of :Java:Type
Name Description

fqn

Fully qualified name, e.g. 'java.lang.Object'

name

The local name, e.g. 'Object'

visibility

optional, the visibility of the type, can be either 'public', 'protected', 'default' or 'private'

abstract

optional, 'true' indicates that the type is abstract, e.g. 'public abstract class …​'

static

optional, 'true' indicates that the type has the static modifier, e.g. 'private static class …​'

final

optional, 'true' indicates that the type is final, e.g. 'public final class…​'

synthetic

optional, 'true' indicates that the type is synthetic, i.e. it has been generated

Table 11. Relations of :Java:Type
Name Target label(s) Cardinality Description

DECLARES

:Java:Type

0..n

Declares an inner type of the type

DECLARES

:Java:Method

0..n

Declares a method of the type

DECLARES

:Java:Field

0..n

Declares a field of the type

EXTENDS

:Java:Type

0..1

References a type this type extends from

IMPLEMENTS

:Java:Type

0..1

References an "Interface" type this type implements

ANNOTATED_BY

:Java:Value:Annotation

0..n

References an annotation which is present on the type

DEPENDS_ON

:Java:Type

0..n

References a type which this type depends on (i.e. every reference to another class)

NOTE Types which are referenced by scanned classes but have not been scanned themselves will only provide the property "fqn" and the relation "DECLARES".

NOTE Inheritance between interfaces (i.e. "public interface A extends B { …​ }") is represented using IMPLEMENTS relations, i.e. queries must use (a:Type:Interface)-[:IMPLEMENTS]→(b:Type:Interface) for pattern matching.

:Java:Type:Class

Qualifies a Java type as class.

:Java:Type:Interface

Qualifies a Java type node as interface.

:Java:Type:Enum

Qualifies a Java type as enumeration.

:Java:Type:Annotation

Qualifies a Java type as annotation.

:Java:Field

A field declared in a Java type.

Table 12. Properties of :Java:Field
Name Description

name

The field name, e.g. 'id'

signature

The raw signature of the field, e.g. 'int id', 'java.lang.String toString()'

visibility

optional, The visibility of the field, can be either 'public', 'protected', 'default' or 'private'

static

optional, 'true' indicates that the field has the static modifier, e.g. 'static int id;'

final

optional, 'true' indicates that the field is final, e.g. 'final int id;'

transient

optional, 'true' indicates that the field is transient, e.g. 'transient int id;'

volatile

optional, 'true' indicates that the field is volatile, e.g. 'volatile int id;'

synthetic

optional, 'true' indicates that the field is synthetic, i.e. it has been generated

Table 13. Relations of :Java:Field
Name Target label(s) Cardinality Description

OF_TYPE

:Java:Type

1

References the type of the field

ANNOTATED_BY

:Java:Value:Annotation

0..n

References an annotation which is present on the field

NOTE Fields which are referenced by scanned classes but have not been scanned themselves will only provide the property "signature".

:Java:Method

A method declared in a Java type.

Table 14. Properties of :Java:Method
Name Description

name

The method name, e.g. 'getId'

signature

The raw signature of the method, e.g. 'int getId()', 'java.lang.String concat(java.lang.String,java.lang.String)'

visibility

optional, The visibility of the method, can be either 'public', 'protected', 'default' or 'private'

static

optional, 'true' indicates that the method has the static modifier, e.g. 'static int getId();'

final

optional, 'true' indicates that the method is final, e.g. 'final int getId();'

native

optional, 'true' indicates that the method is native, e.g. 'native int getId();'

synthetic

optional, 'true' indicates that the method is synthetic, i.e. it has been generated

Table 15. Relations of :Java:Method
Name Target label(s) Cardinality Description

HAS

:Java:Parameter

0..n

References a parameter of the method

THROWS

:Java:Type

0..n

References the exception type thrown by the method

RETURNS

:Java:Type

0..n

References the return type of the method

ANNOTATED_BY

:Java:Value:Annotation

0..n

References an annotation which is present on the method declaration

READS

:Java:Field

0..n

References a field which is read by the method

WRITES

:Java:Field

0..n

References a field which is written by the method

INVOKES

:Java:Method

0..n

References a method which is invoked by the method

NOTE Methods which are referenced by scanned classes but have not been scanned themselves will only provide the property "signature".

:Java:Method:Constructor

Qualifies a method as constructor.

:Java:Parameter

A method parameter.

Table 16. Properties of :Java:Parameter
Name Description

index

The index of the parameter according to the method signature (starting with 0)

Table 17. Properties of :Java:Parameter
Name Target label(s) Cardinality Description

OF_TYPE

:Java:Type

1

References the type of the parameter

ANNOTATED_BY

:Java:Value:Annotation

0..n

References an annotation which is present on the parameter

:Java:Value

A value, can be qualified by either ':Primitive', ':Annotation', ':Class', ':Enum' or ':Array'.

Table 18. Properties of :Java:Value
Name Description

name

The method name, e.g. 'value'

:Value:Primitive

A primitive value.

Table 19. Properties of :Java:Value:Primitive
Name Description

value

The value

:Java:Value:Annotation

Represents a annotation on a Java element, e.g. '@Entity public class …​'

Table 20. Relations of :Java:Value:Annotation:
Name Target label(s) Cardinality Description

OF_TYPE

:Java:Type

1

References the type of the annotation

HAS

:Java:Value

0..n

References an attribute of the annotation, e.g. '@Entity(name="MyEntity")'

:Java:Value:Class

Represents a class instance, e.g. as specified by annotation attribute.

Table 21. Relations of :Java:Value:Class:
Name Target label(s) Cardinality Description

IS

:Java:Type

1

References the type

:Java:Value:Enum

Represents an enum value.

Table 22. Relations of :Java:Value:Enum:
Name Target label(s) Cardinality Description

IS

:Java:Field

1

References the field representing the enumeration value

:Java:Value:Array

Represents an array value, i.e. a node referencing value nodes.

Table 23. Relations of :Java:Value:Array:
Name Target label(s) Cardinality Description

CONTAINS

:Java:Value

0..n

References a value contained in the array

Manifest File Scanner

Imports manifest descriptors from META-INF/MANIFEST.MF files.

:File:Java:Manifest

A MANIFEST.MF file containing sections.

Table 24. Properties of :File:Java:Manifest
Name Description

fileName

The file name

Table 25. Relations of :File:Java:Manifest
Name Target label(s) Cardinality Description

DECLARES

:Java:ManifestSection

0..n

References a manifest section

:Java:ManifestSection

A manifest section.

Table 26. Relations of :Java:ManifestSection
Name Target label(s) Cardinality Description

HAS

:Java:Value:ManifestEntry

0..n

References a manifest entry in the section

:Java:Value:ManifestEntry

A manifest entry.

Table 27. Properties of :Java:Value:ManifestEntry
Name Description

name

The name of the entry, e.g. 'Main-Class'

value

The value of the entry, e.g. 'com.buschmais.jqassistant.scm.cli.Main'

Property File Scanner

Imports property files, i.e. all files having a suffix '.properties'.

:File:Properties

A property file containing key/value pairs.

Table 28. Properties of :File:Java:Properties
Name Description

fileName

The file name

Table 29. Relations of :File:Java:Properties
Name Target label(s) Cardinality Description

HAS

:Java:Value:Property

0..n

References a property value

:Java:Value:Property

A key value/pair.

Table 30. Properties of :Java:Value:Property
Name Description

name

The name of the property

value

The value of the property

Service Loader File Scanner

Imports service loader descriptors from "META-INF/services" directories.

:File:Java:ServiceLoader

A file containing the implementation class names for a service interface

Table 31. Properties of :File:Java:ServiceLoader
Name Description

fileName

The file name

Table 32. Relations of :File:Java:ServiceLoader
Name Target label(s) Cardinality Description

OF_TYPE

:Java:Type

1

The type representing the service interface

CONTAINS

:Java:Type

0..n

References a type which implements the service interface

Refer to the plugin Javadoc for details about the model.

dependency.xml

Concepts
dependency:Artifact

Creates a DEPENDS_ON relationship between artifacts if there are type dependencies between them.

MATCH
    (a1:Artifact)-[:REQUIRES]->(t1:Type),
    (a2:Artifact)-[:CONTAINS]-(t2:Type)
WHERE
    t1.fqn=t2.fqn
CREATE UNIQUE
    (a1)-[:DEPENDS_ON]->(a2)
RETURN
    a1 AS Artifact, COLLECT(DISTINCT a2.name) AS Dependencies
dependency:Package

Creates a DEPENDS_ON relationship between a packages if there are type dependencies between them.

MATCH
    (p1:Package)-[:CONTAINS]->(t1:Type)-[:DEPENDS_ON]->(t2:Type)<-[:CONTAINS]-(p2:Package)
WHERE
    p1<>p2
CREATE UNIQUE
    (p1)-[:DEPENDS_ON]->(p2)
RETURN
    p1 AS package, COUNT(DISTINCT p2) AS PackageDependencyCount
Constraints
dependency:ArtifactCycles

Requires concepts:

There must be no cyclic artifact dependencies.

MATCH
    (a1:Artifact)-[:DEPENDS_ON]->(a2:Artifact),
    path=shortestPath((a2)-[:DEPENDS_ON*]->(a1))
WHERE
    a1<>a2
RETURN
    a1 AS Artifact, EXTRACT(a IN nodes(path) | a.fqn) AS Cycle
ORDER BY
    Artifact.fqn
dependency:PackageCycles

Requires concepts:

There must be no cyclic package dependencies.

MATCH
    (p1:Package)-[:DEPENDS_ON]->(p2:Package),
    path=shortestPath((p2)-[:DEPENDS_ON*]->(p1))
WHERE
    p1<>p2
RETURN
    p1 AS Package, EXTRACT(p IN nodes(path) | p.fqn) AS Cycle
ORDER BY
    Package.fqn
dependency:TypeCycles

Requires concepts:

There must be no cyclic type dependencies.

MATCH
    (p1:Package)-[:DEPENDS_ON*0..1]->(p2:Package),
    shortestPath((p2)-[:DEPENDS_ON*]->(p1))
WITH
    p1, p2
MATCH
    (p1)-[:CONTAINS]->(t1:Type),
    (p2)-[:CONTAINS]->(t2:Type),
    (t1)-[:DEPENDS_ON]->(t2),
    path=shortestPath((t2)-[:DEPENDS_ON*]->(t1))
WHERE
    NOT (
      t1 = t2 OR (t1)-[:DECLARES]-(t2)
    )
RETURN
    LENGTH(path) AS Length, EXTRACT(p IN nodes (path) | p.fqn) AS Cycle

java.xml

Concepts
java:AnonymousInnerType

Requires concepts:

Sets a label "Anonymous" on anonymous inner types, i.e. types without a name.

MATCH
  (innerType:Inner:Type)
WHERE
  innerType.name =~ ".*\\$[0-9]*"
SET
  innerType:Anonymous
RETURN
  innerType AS AnonymousInnerType
java:Deprecated

Labels all nodes representing deprecated elements (types, fields, methods, packages or parameters) with "Deprecated".

MATCH
  (e)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(dt:Type)
WHERE
  dt.fqn='java.lang.Deprecated'
SET
  e:Deprecated
RETURN
  e AS DeprecatedElement
java:Error

Labels types deriving from java.lang.Error as "Error".

MATCH
  (throwable)-[:EXTENDS*]->(t:Type)
WHERE
  t.fqn = 'java.lang.Error'
SET
  throwable:Error
RETURN
  throwable AS Error
java:Exception

Labels types deriving from java.lang.Exception as "Exception".

MATCH
  (exception)-[:EXTENDS*]->(t:Type)
WHERE
  t.fqn = 'java.lang.Exception'
SET
  exception:Exception
RETURN
  exception AS Exception
java:InnerType

Sets a label "Inner" on inner types.

MATCH
  (:Type)-[:DECLARES]->(innerType:Type)
SET
  innerType:Inner
RETURN
  innerType AS InnerType
java:InvokesOverriddenMethod

Requires concepts:

Propagates INVOKES relationships to methods which implement or override the invoked method.

MATCH
  (method:Method)-[invocation:INVOKES]->(invokedMethod:Method),
  (overridingMethod:Method)-[:OVERRIDES]->(invokedMethod)
CREATE UNIQUE
  (method)-[r:INVOKES{lineNumber:invocation.lineNumber}]->(overridingMethod)
RETURN count(r) AS OverridingInvocations
java:MethodOverloads

Creates a relationship OVERLOADS between two "Method" labeled nodes if one method overloads another one from the same type (i.e. the methods have the same name but not the same signature).

MATCH
  (type:Type)-[:DECLARES]->(method:Method),
  (type)-[:DECLARES]->(otherMethod:Method)
WHERE
  method <> otherMethod
  AND method.name = otherMethod.name
  AND method.signature <> otherMethod.signature
CREATE UNIQUE
    (method)-[:OVERLOADS]->(otherMethod)
RETURN method AS OverloadedMethod, type AS DeclaringType
java:MethodOverrides

Requires concepts:

Creates a relationship OVERRIDES between two "Method" labeled nodes if one method overrides another one from a super type (i.e. the methods have the same signature).

MATCH
  (type:Type)-[:DECLARES]->(method:Method),
  (superType:Type)-[:DECLARES]->(otherMethod:Method),
  (superType)-[:ASSIGNABLE_FROM]->(type)
WHERE
  method.name = otherMethod.name
  AND method.signature = otherMethod.signature
  AND method.visibility <> 'private'
CREATE UNIQUE
  (method)-[:OVERRIDES]->(otherMethod)
RETURN method AS OverriddenMethod, type AS DeclaringType, superType AS SuperType
java:RuntimeException

Labels types deriving from java.lang.RuntimeException as "RuntimeException".

MATCH
  (runtimeException)-[:EXTENDS*]->(t:Type)
WHERE
  t.fqn = 'java.lang.RuntimeException'
SET
  runtimeException:RuntimeException
RETURN
  runtimeException AS RuntimeException
java:Throwable

Labels types deriving from java.lang.Throwable as "Throwable".

MATCH
  (throwable)-[:EXTENDS*]->(t:Type)
WHERE
  t.fqn = 'java.lang.Throwable'
SET
  throwable:Throwable
RETURN
  throwable AS Throwable
java:TypeAssignableFrom

Creates a relationship ASSIGNABLE_FROM between two "Type" labeled nodes if one type is assignable from the other (i.e. a super class or interface).

MATCH
  (type:Type)
CREATE UNIQUE
  (type)-[:ASSIGNABLE_FROM]->(type)
WITH
  type
MATCH
  (type)-[:IMPLEMENTS|EXTENDS*]->(superType:Type)
CREATE UNIQUE
  (superType)-[:ASSIGNABLE_FROM]->(type)
RETURN type AS AssignableType, superType AS AssignableFrom

metric.xml

Concepts
metric:Top10FieldsPerType

Returns the top 10 types regarding to the number of declared fields.

MATCH
    (t:Type:File)-[:DECLARES]->(f:Field)
RETURN
    t.fqn as Type, COUNT(f) as FieldCount
ORDER BY
    FieldCount DESC
LIMIT 10
metric:Top10MethodsPerType

Returns the top 10 types regarding to the number of declared methods (including constructors).

MATCH
    (t:Type:File)-[:DECLARES]->(m:Method)
RETURN
    t.fqn as Type, COUNT(m) as MethodCount
ORDER BY
    MethodCount DESC
LIMIT 10
metric:Top10TypeFanIn

Returns the top 10 types regarding the number of other types depending on them.

MATCH
    (t:Type:File)<-[:DEPENDS_ON]-(dependent:Type)
RETURN
    t.fqn as Type, COUNT(dependent) as Dependents
ORDER BY
    Dependents DESC
LIMIT 10
metric:Top10TypeFanOut

Returns the top 10 types regarding the number of other types they depend on.

MATCH
    (t:Type:File)-[:DEPENDS_ON]->(dependency:Type)
RETURN
    t.fqn as Type, COUNT(dependency) as Dependencies
ORDER BY
    Dependencies DESC
LIMIT 10
metric:Top10TypesPerArtifact

Returns the top 10 artifacts regarding the number of contained types.

MATCH
    (a:Artifact:File)-[:CONTAINS]->(t:Type:File)
RETURN
    a.fqn as Artifact, COUNT(t) as Types
ORDER BY
    Types DESC
LIMIT 10
metric:Top10TypesPerPackage

Returns the top 10 packages regarding the number of contained types.

MATCH
    (p:Package:File)-[:CONTAINS]->(t:Type:File)
RETURN
    p.fqn as Package, COUNT(t) as Types
ORDER BY
    Types DESC
LIMIT 10

Java 8

Provides Java 8 specific rules, e.g. concepts for functional interfaces and default methods.

java8.xml

Concepts
java8:DefaultMethod

Labels default methods of interfaces with "Default".

MATCH
  (type:Type:Interface)-[:DECLARES]->(defaultMethod:Method)
WHERE NOT
  has(defaultMethod.abstract)
SET
  defaultMethod:Default
RETURN
  defaultMethod AS DefaultMethod, type AS Interface
java8:FunctionalInterface

Labels functional interfaces (i.e. to be used as lambda expressions) with "FunctionalInterface".

MATCH
  (functionalInterface:Interface)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(functionalInterfaceType)
WHERE
  functionalInterfaceType.fqn = 'java.lang.FunctionalInterface'
SET
  functionalInterface:FunctionalInterface
RETURN
  functionalInterface AS FunctionalInterface

JPA 2

Provides a scanner for persistence.xml descriptors and rules for JPA2 specific elements (e.g. entities).

Scanner for persistence.xml files

Imports persistence descriptors from META-INF/persistence.xml or WEB-INF/persistence.xml files.

:File:Jpa:Persistence

A persistence.xml file containing persistence units.

Table 33. Properties of :File:Jpa:Persistence
Name Description

fileName

The file name

version

The version of the JPA specification this descriptor represents, e.g. '2.0'

Table 34. Relations of :File:Jpa:Persistence
Name Target label(s) Cardinality Description

CONTAINS

:Jpa:PersistenceUnit

0..n

References a contained persistence unit

:Jpa:PersistenceUnit

A persistence unit.

Table 35. Properties of :Jpa:PersistenceUnit
Name Description

description

The description of the persistence unit.

transactionType

The transaction type, can be 'RESOURCE_LOCAL' or 'JTA'

provider

The class name of the JPA provider.

jtaDatasource

The JNDI name of the transactional datasource

nonJtaDatasource

The JNDI name of the non-transactional datasource

validationMode

The validation mode, can be 'NONE', 'CALLBACK' or 'AUTO'

sharedCacheMode

The shared cache mode, e.g. 'NONE'

Table 36. Relations of :Jpa:PersistenceUnit
Name Target label(s) Cardinality Description

CONTAINS

:Java:Type

0..n

References a persistent type (entity) contained in the persistence unit

HAS

[:Value:Property]

0..n

References a property of the persistence unit

Refer to the plugin Javadoc for details about the model.

jpa2.xml

Concepts
jpa2:Embeddable

Labels all types annotated with @javax.persistence.Embeddable with "Jpa" and "Embeddable".

MATCH
  (t:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="javax.persistence.Embeddable"
SET
  t:Jpa:Embeddable
RETURN
  t AS JpaEmbeddable
jpa2:Embedded

Labels all fields or methods annotated with @javax.persistence.Embedded with "Jpa" and "Embedded".

MATCH
  (t:Type)-[:DECLARES]->(member),
  (member)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  (member:Field or member:Method)
  and a.fqn="javax.persistence.Embedded"
SET
  member:Jpa:Embedded
RETURN
  member AS JpaEmbedded
jpa2:EmbeddedId

Labels all fields or methods annotated with @javax.persistence.EmbeddedId with "Jpa" and "Embedded".

MATCH
  (t:Type)-[:DECLARES]->(member),
  (member)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  (member:Field or member:Method)
  and a.fqn="javax.persistence.EmbeddedId"
SET
  member:Jpa:EmbeddedId
RETURN
  member AS EmbeddedId
jpa2:Entity

Labels all types annotated with @javax.persistence.Entity with "Jpa" and "Entity".

MATCH
  (t:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="javax.persistence.Entity"
SET
  t:Jpa:Entity
RETURN
  t AS JpaEntity
jpa2:NamedQuery

Requires concepts:

Creates a node labeled with "Jpa" and "NamedQuery" for each @NamedQuery defined for an entity. Furthermore a relation DEFINES is created between the entity and the named query.

MATCH
  (entity:Jpa:Entity)-[:ANNOTATED_BY]->(namedQueries)-[:OF_TYPE]->(namedQueriesType:Type),
  (namedQueries)-[:HAS]->(:Value:Array)-[:CONTAINS]->(namedQuery:Value:Annotation)-[:OF_TYPE]->(namedQueryType:Type),
  (namedQuery)-[:HAS]->(nameAttribute:Value),
  (namedQuery)-[:HAS]->(queryAttribute:Value)
WHERE
  namedQueriesType.fqn = 'javax.persistence.NamedQueries'
  and namedQueryType.fqn = 'javax.persistence.NamedQuery'
  and nameAttribute.name = 'name'
  and queryAttribute.name = 'query'
CREATE UNIQUE
  (entity)-[:DEFINES]->(n:Jpa:NamedQuery {name:nameAttribute.value, query:queryAttribute.value})
RETURN
  entity AS Entity, n.name AS Name, n.query AS Query
Constraints
jpa2:ValidationModeMustBeExplicitlySpecified

The validation mode of all persistence units must be explicitly specified and either set to CALLBACK or NONE.

MATCH
  (pu:PersistenceUnit)
WHERE
  not has(pu.validationMode)
  OR NOT (
    pu.validationMode='CALLBACK'
    OR pu.validationMode='NONE'
  )
RETURN
  pu AS PersistenceUnit

Java EE 6

Aggregates plugins providing scanners and rules for Java EE 6 technologies (e.g. JPA2, EJB3).

Scanner for EAR files

Imports EAR (Enterprise ARchive) files.

:File:Enterprise:Application:Archive

A file representing an EAR file.

Table 37. Properties of :File:Enterprise:Application:Archive
Name Description

fileName

The file name

Table 38. Relations of :File:Enterprise:Application:Archive
Name Target label(s) Cardinality Description

CONTAINS

[:File]

0..n

References the files contained in the archive.

Scanner for WAR files

Imports WAR (Web Application Archive) files.

:File:Web:Application:Archive

A file representing WAR file.

Table 39. Properties of :File:Web:Application:Archive
Name Description

fileName

The file name

Table 40. Relations of :File:Web:Application:Archive
Name Target label(s) Cardinality Description

CONTAINS

[:File]

0..n

References the files contained in the archive.

:File:Enterprise:Application:Xml

Represents a Java EE application.xml descriptor.

Table 41. Properties of :File:Enterprise:Application:Xml
Name Description

fileName

The file name

initializeInOrder

If initialize-in-order is true, modules must be initialized in the order they’re listed in the deployment descriptor

libraryDirectory

The path to the library directory.

Table 42. Relations of :File:Enterprise:Application:Xml
Name Target label(s) Cardinality Description

HAS_DESCRIPTION

:Description

0..n

References a description of this descriptor.

HAS_DISPLAY_NAME

:DisplayName

0..n

References a display name of this descriptor.

HAS_ICON

:Icon

0..n

References an icon of this descriptor.

HAS_MODULE

:Enterprise:Application:Module

1..n

References a module specified by this descriptor.

HAS_SECURITY_ROLE

:SecurityRole

0..n

References a security role defined by this descriptor.

:Enterprise:Application:Module

Represents a declared module of a Java EE Java application. Can be qualified by either :Ejb, :Web, :Connector or :JavaClient.

Table 43. Properties of :Enterprise:Application:Module
Name Description

path

The path to the module archive within the enterprise application archive.

:Enterprise:Application:Module:Web

Represents a declared web module of a Java EE Java application.

Table 44. Properties of :Enterprise:Application:Module:Web
Name Description

contextRoot

The context root path to use for the web module.

:File:Web:Xml

Represents a web application descriptor.

Table 45. Relations of :File:Web:Xml
Name Target label(s) Cardinality Description

HAS_SESSION_CONFIG

:SessionConfig

0..1

References the session configuration.

HAS_SERVLET

:Servlet

0..n

References a servlet declaration.

HAS_SERVLET_MAPPING

ServletMapping

0..n

References a servlet mapping declaration.

HAS_FILTER

Filter

0..n

References a filter declaration.

HAS_FILTER_MAPPING

FilterMapping

0..n

References a filter mapping declaration.

HAS_LISTENER

Listener

0..n

References a listener declaration.

HAS_CONTEXT_PARAM

<<.ParamValue>>

0..n

References a context parameter declaration.

HAS_ERROR_PAGE

ErrorPage

0..n

References an error page declaration.

HAS_SECURITY_CONSTRAINT

SecurityConstraint

0..n

References a security constraint declaration.

HAS_SECURITY_ROLE

:SecurityRole

0..n

References a security role declaration.

HAS_LOGIN_CONFIG

LoginConfig

0..n

References a login configuration.

:SessionConfig

Represents a session configuration.

Table 46. Properties of :SessionConfig
Name Description

sessionTimeout

The session timeout.

:Servlet

Represents a servlet declaration.

Table 47. Properties of :Servlet
Name Description

enabled

Indicates if this servlet is enabled.

jspFile

The JSP file representing the servlet.

loadOnStartup

Indicates whether the servlet will be loaded on startup.

Table 48. Relations of :Servlet
Name Target label(s) Cardinality Description

HAS_DESCRIPTION

:Description

0..n

References a description of this descriptor.

HAS_DISPLAY_NAME

:DisplayName

0..n

References a display name of this descriptor.

HAS_ICON

:Icon

0..n

References an icon of this descriptor.

HAS_INIT_PARAM

[:ParamValue]

0..n

References a init parameter.

:Description

Represents an internationalized description.

Table 49. Properties of :Description
Name Description

lang

The language, e.g. "en"

value

The description.

:DisplayName

Represents an internationalized display name.

Table 50. Properties of :DisplayName
Name Description

lang

The language, e.g. "en"

value

The description.

:Icon

Represents an icon.

Table 51. Properties of :Icon
Name Description

smallIcon

The file name of the small icon, e.g. "smallIcon.png".

largeIcon

The file name of the large icon, e.g. "largeIcon.png".

:SecurityRole

Represents a security role.

Table 52. Relations of :SecurityRole
Name Target label(s) Cardinality Description

HAS_DESCRIPTION

:Description

0..n

References a description of this security role.

HAS_ROLE_NAME

:Description

1

References the role name.

:RoleName

Represents a role name.

Table 53. Properties of :RoleName
Name Description

name

The name of the role.

Refer to the plugin Javadoc for details about the model.

JUnit

Provides scanner for JUnit test reports and rules (e.g. for test classes/methods and ignored tests).

Scanner for JUnit4 test suite results

Imports results from JUnit4 test suites matching the file name 'TEST-.xml'.

:File:TestSuite

A file containing results of a JUnit4 test suite.

Table 54. Properties of :File:TestSuite
Name Description

fileName

The file name

name

The name of the test suite, e.g. the name of the class defining the suite

tests

The number of executed tests

failures

The number of failed tests

errors

The number of tests in error

skipped

The number of skipped tests

time

The time it took to run the suite

Table 55. Relations of :File:TestSuite
Name Target label(s) Cardinality Description

CONTAINS

:TestCase

0..n

References a test case

:TestCase

A test case.

Table 56. Properties of :TestCase
Name Description

name

The name of the test, e.g. the name of the test method

className

The name of the class containing the test

time

The time it took to run the test

result

The result of the test, either 'SUCCESS', 'FAILURE', 'ERROR' or 'SKIPPED'

Refer to the plugin Javadoc for details about the model.

junit3.xml

Concepts
junit3:SetUpMethod

Requires concepts:

Labels all setUp methods declared by a test class with "SetUp" and "Junit3".

MATCH
  (c:Class:Test:Junit3)-[:DECLARES]->(m:Method)
WHERE
  m.signature = "void setUp()"
SET
  m:SetUp:Junit3
RETURN
  m AS SetUpMethod, c AS TestClass
junit3:TearDownMethod

Requires concepts:

Labels all tearDown methods declared by a test class with "TearDown" and "Junit3".

MATCH
  (c:Class:Test:Junit3)-[:DECLARES]->(m:Method)
WHERE
  m.signature = "void tearDown()"
SET
  m:TearDown:Junit3
RETURN
  m AS TearDownMethod, c AS TestClass
junit3:TestClass

Labels all non-abstract classes extending from junit.framework.TestCase "Test" and "Junit3".

MATCH
  (c:Type:Class)-[:EXTENDS*]->(testCaseType:Type)
WHERE
  testCaseType.fqn = "junit.framework.TestCase"
SET
  c:Test:Junit3
RETURN
  c AS TestClass
junit3:TestMethod

Requires concepts:

Labels all test methods declared by a test class with "Test" and "Junit3".

MATCH
  (c:Class:Test:Junit3)-[:DECLARES]->(m:Method)
WHERE
  m.signature =~ "void test.*\\(.*\\)"
SET
  m:Test:Junit3
RETURN
  m AS Test, c AS TestClass

junit4.xml

Concepts
junit4:AfterClassMethod

Labels all methods annotated by "@org.junit.AfterClass" with "Junit4" and "AfterClass".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method),
  (m:Method)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.junit.AfterClass"
SET
  m:Junit4:AfterClass
RETURN
  m AS AfterClassMethod, c AS TestClass
junit4:AfterMethod

Labels all methods annotated by "@org.junit.After" with "Junit4" and "After".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method),
  (m:Method)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.junit.After"
SET
  m:Junit4:After
RETURN
  m AS AfterMethod, c AS TestClass
junit4:AssertMethod

Labels all assertion methods declared by org.junit.Assert with "Junit4" and "Assert".

MATCH
  (assertType:Type)-[:DECLARES]->(assertMethod)
WHERE
  assertType.fqn = 'org.junit.Assert'
  and assertMethod.signature =~ 'void assert.*'
SET
  assertMethod:Junit4:Assert
RETURN
  assertMethod
junit4:BeforeClassMethod

Labels all methods annotated by "@org.junit.BeforeClass" with "Junit4" and "BeforeClass".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method),
  (m:Method)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.junit.BeforeClass"
SET
  m:Junit4:BeforeClass
RETURN
  m AS BeforeClassMethod, c AS TestClass
junit4:BeforeMethod

Labels all methods annotated by "@org.junit.Before" with "Junit4" and "Before".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method),
  (m:Method)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.junit.Before"
SET
  m:Junit4:Before
RETURN
  m AS BeforeMethod, c AS TestClass
junit4:IgnoreTestClassOrMethod

Labels all classes or methods annotated with "@org.junit.Ignore" with "Junit4" and "Ignore".

MATCH
  (e)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.junit.Ignore"
SET
  e:Junit4:Ignore
RETURN
  e AS IgnoredElement
junit4:SuiteClass

Labels all classes annotated by "@org.junit.runners.Suite.SuiteClasses" with "Junit4" and "Suite" and creates a relation "CONTAINS_TESTCLASS" to all referenced classes.

MATCH
  (suite:Type)-[:ANNOTATED_BY]->(suiteClasses)-[:OF_TYPE]->(suiteClassesType:Type)
WHERE
  suiteClassesType.fqn = "org.junit.runners.Suite$SuiteClasses"
SET
  suite:Junit4:Suite
WITH
  suite, suiteClasses
MATCH
  (suiteClasses)-[:HAS]->(:Array:Value)-[:CONTAINS]->(Class:Value)-[:IS]->(testClass:Type)
CREATE UNIQUE
  (suite)-[c:CONTAINS_TESTCLASS]->(testClass)
RETURN
  suite, collect(testClass)
junit4:TestCaseImplementedByMethod

Creates a relation IMPLEMENTED_BY between all test cases from test reports and their implementing methods.

MATCH
  (testcase:TestCase)
WITH
  testcase
MATCH
  (testclass:Type)-[:DECLARES]->(testmethod:Method)
WHERE
  testclass.fqn = testcase.className
  and testmethod.name = testcase.name
CREATE UNIQUE
  (testcase)-[:IMPLEMENTED_BY]->(testmethod)
RETURN
  testcase AS TestCase
junit4:TestClass

Requires concepts:

Labels all classes containing test methods with "Test" and "Junit4".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method:Junit4:Test)
SET
  c:Test:Junit4
RETURN
  c AS TestClass, COLLECT(m) AS TestMethods
junit4:TestClassOrMethod
_The rule is deprecated: This concept has been replaced by "junit4:TestMethod" and "junit4:TestClass"._

Requires concepts:

Finds test methods (i.e. annotated with "@org.junit.Test") and labels them and their containing classes with "Test" and "Junit4".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method:Junit4:Test)
RETURN
  c AS TestClass, COLLECT(m) AS TestMethods
junit4:TestMethod

Finds all test methods (i.e. annotated with "@org.junit.Test") and labels them with "Test" and "Junit4".

MATCH
  (m:Method)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.junit.Test"
SET
  m:Test:Junit4
RETURN
  m AS Test
Constraints
junit4:AssertionMustProvideMessage

Requires concepts:

All assertions must provide a message.

MATCH
  (testType:Type)-[:DECLARES]->(testMethod:Method),
  (testMethod)-[invocation:INVOKES]->(assertMethod:Assert:Method)
WHERE
  NOT assertMethod.signature =~ 'void assert.*\\(java.lang.String,.*\\)'
RETURN
  invocation AS Invocation,
  testType AS DeclaringType,
  testMethod AS Method
junit4:IgnoreWithoutMessage

All @Ignore annotations must provide a message.

MATCH
  (e)-[:ANNOTATED_BY]->(ignore:Annotation)-[:OF_TYPE]->(ignoreType:Type)
WHERE
  ignoreType.fqn= "org.junit.Ignore"
  AND NOT (ignore)-[:HAS]->(:Value{name:"value"})
RETURN
  e AS IgnoreWithoutMessage
junit4:TestMethodWithoutAssertion

Requires concepts:

All test methods must perform assertions (within a call hierarchy of max. 3 steps).

MATCH
  (testType:Type)-[:DECLARES]->(testMethod:Test:Method)
WHERE
  NOT (testMethod)-[:INVOKES*..3]->(:Method:Assert)
RETURN
  testType AS DeclaringType,
  testMethod AS Method

TestNG

Provides rules for TestNG.

testng.xml

Concepts
testng:AfterClassMethod

Labels all methods annotated by "@org.testng.annotations.AfterClass" with "TestNG" and "AfterClassMethod".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method),
  (m:Method)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.testng.annotations.AfterClass"
SET
  m:TestNG:AfterClassMethod
RETURN
  m AS AfterClassMethod, c AS TestClass
testng:AfterMethod

Labels all methods annotated by "@org.testng.annotations.AfterMethod" with "TestNG" and "AfterMethod".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method),
  (m:Method)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.testng.annotations.AfterMethod"
SET
  m:TestNG:AfterMethod
RETURN
  m AS AfterMethod, c AS TestClass
testng:AfterTestMethod

Labels all methods annotated by "@org.testng.annotations.AfterTest" with "TestNG" and "AfterTestMethod".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method),
  (m:Method)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.testng.annotations.AfterTest"
SET
  m:TestNG:AfterTestMethod
RETURN
  m AS AfterTestMethod, c AS TestClass
testng:BeforeClassMethod

Labels all methods annotated by "@org.testng.annotations.BeforeClass" with "TestNG" and "BeforeClassMethod".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method),
  (m:Method)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.testng.annotations.BeforeClass"
SET
  m:TestNG:BeforeClassMethod
RETURN
  m AS BeforeClassMethod, c AS TestClass
testng:BeforeMethod

Labels all methods annotated by "@org.testng.annotations.BeforeMethod" with "TestNG" and "BeforeMethod".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method),
  (m:Method)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.testng.annotations.BeforeMethod"
SET
  m:TestNG:BeforeMethod
RETURN
  m AS BeforeMethod, c AS TestClass
testng:BeforeTestMethod

Labels all methods annotated by "@org.testng.annotations.BeforeTest" with "TestNG" and "BeforeTestMethod".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method),
  (m:Method)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.testng.annotations.BeforeTest"
SET
  m:TestNG:BeforeTestMethod
RETURN
  m AS BeforeTestMethod, c AS TestClass
testng:TestClass

Requires concepts:

Labels all classes containing test methods with "Test" and "TestNG".

MATCH
  (c:Type:Class)-[:DECLARES]->(m:Method:TestNG:Test)
SET
  c:Test:TestNG
RETURN
  c AS TestClass, COLLECT(m) AS TestMethods
testng:TestMethod

Finds all test methods (i.e. annotated with "@org.testng.annotations.Test") and labels them with "Test" and "TestNG".

MATCH
  (m:Method)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="org.testng.annotations.Test"
SET
  m:Test:TestNG
RETURN
  m AS Test

Maven 2 Repository

Provides a scanner for maven repositories.

Scanner for remote maven repositories

Downloads the repository index and retrieves all available new artifacts for scanning.

This plugin should be triggered on the command line by providing an URL and a specific scope:

Examples:

>jqassistant.cmd scan -u maven:repository::http://[<user>:<password>@]<repository url>
>jqassistant.cmd scan -u maven:repository::http://foo:bar@example.com/m2repo
Tip
The plugin supports incremental runs on a maven repository. In this case only new artifacts will be downloaded and scanned. Old snapshot artifacts will be handled as predecessors (see below). Note that such predecessor artifacts will have no direct relationship to the :Maven:Repository node.
Tip
For incremental scanning it is necessary that the exactly the same URL is provided on sub-sequent scans.
Configuration
Table 57. Configuration properties
Property Description Default

m2repo.directory

A directory path. This directory is the target for Maven indices and artifacts.

./jqassistant/data/m2repo

m2repo.delete.artifacts

A boolean value. If true then all downloaded artifacts where deleted after scanning.

false

:Maven:Repository

A remote Maven repository.

Table 58. Properties of :Maven:Repository
Name Description

url

the remote URL

lastScanDate

timestamp of the last successful scan

Table 59. Relations of :Maven:Repository
Name Target label(s) Cardinality Description

CONTAINS_ARTIFACT

:RepositoryArtifact:Maven

0..n

References repository artifacts

:RepositoryArtifact:Maven

A Maven artifact (e.g. *.pom, *.jar).

Table 60. Properties of :RepositoryArtifact:Maven
Name Description

mavenCoordinates

The maven coordinates <groupId>:<artifactId>:<type>:(<classifier>:)<version>.

group

The group id

name

The artifact id

type

The type, e.g. "jar"

classifier

The classifier

version

The version

Table 61. Relations of :RepositoryArtifact:Maven
Name Target label(s) Cardinality Description

HAS_PREDECESSOR

:RepositoryArtifact:Maven

0..1

References a predecessor snapshot repository artifact

Refer to the plugin Javadoc for details about the model.

Maven 3

Provides a scanner for Maven 3 modules.

Scanner for Maven projects

Imports information from Maven projects.

:Maven:Project:File:Directory

A pom.xml file describing a single Maven project.

Table 62. Properties of :Maven:Project:File:Directory
Name Description

fileName

The directory of the project.

name

The name

groupId

The group id

artifactId

The artifact id

packaging

The packaging type, e.g. "jar"

version

The version

Table 63. Relations of :Maven:Project:File:Directory
Name Target label(s) Cardinality Description

CREATES

:Artifact

0..n

References an artifact created by the project

HAS_PARENT

:Maven:Project:File:Directory

0..1

References the parent project (optional)

HAS_MODULE

:Maven:Project:File:Directory

0..n

References modules of this project (optional)

:Artifact

Represents an artifact, e.g. a JAR-File.

Table 64. Properties of :Artifact
Name Description

group

The group id

name

The artifact id

type

The type, e.g. "jar"

classifier

The classifier

version

The version

Table 65. Relations of :Artifact
Name Target label(s) Cardinality Description

CONTAINS

:File

0..n

References a file contained in the artifact

DEPENDS_ON

:Artifact

0..n

References an artifact which is a declared dependency

Table 66. Properties of :DEPENDS_ON
Name Description

scope

The declared scope, e.g. "compile"

optional

"true" indicates that this dependency is optional.

Scanner for Maven pom.xml files

Imports raw information from Maven pom.xml files.

:Maven:Artifact:Pom:Xml:File

A pom.xml file describing a single Maven project.

Table 67. Properties of :Maven:Artifact:Pom:Xml:File
Name Description

group

The group id

name

The artifact id

type

The type, e.g. "jar"

classifier

The classifiert

version

The version

Table 68. Relations of :Maven:Artifact:Pom:Xml:File
Name Target label(s) Cardinality Description

HAS_PARENT

:Maven:Artifact:Pom

0..1

References a parent aritfact

HAS_PROPERTY

:Value:Property

0..n

References a property

HAS_PROFILE

:Maven:Profile

0..n

References defined profiles

USES_LICENSE

:Maven:License

0..n

References used licenses

MANAGES_DEPENDENCY

:Maven:Artifact

0..n

References an artifact which is a managed dependency

DEPENDS_ON

:Maven:Artifact

0..n

References an artifact which is a declared dependency

HAS_MODULE

:Maven:Module

0..n

References a sub module

MANAGES_PLUGIN

:Maven:Plugin

0..n

References a managed plugin

USES_PLUGIN

:Maven:Plugin

0..n

References a plugin that is used during maven lifecycle

:Maven:Profile

A maven profile

Table 69. Properties of :Maven:Profile
Name Description

id

The profile id

Table 70. Relations of :Maven:Profile
Name Target label(s) Cardinality Description

HAS_PROPERTY

:Value:Property

0..n

References a property

MANAGES_DEPENDENCY

:Maven:Artifact

0..n

References an artifact which is a managed dependency

DEPENDS_ON

:Maven:Artifact

0..n

References an artifact which is a declared dependency

HAS_MODULE

:Maven:Module

0..n

References a sub module

MANAGES_PLUGIN

:Maven:Plugin

0..n

References a managed plugin

USES_PLUGIN

:Maven:Plugin

0..n

References a plugin that is used during maven lifecycle

HAS_ACTIVATION

:Maven:ProfileActivation

0..1

References the conditions which will trigger the profile.

:Maven:ProfileActivation

A maven profile activation

Table 71. Properties of :Maven:ProfileActivation
Name Description

activeByDefault

Specifies if the profile is activated by default

jdk

Specifies jdk needed to activate the profile

Table 72. Relations of :Maven:ProfileActivation
Name Target label(s) Cardinality Description

HAS_PROPERTY

:Value:Property

0..1

References a property

ACTIVATED_BY_FILE

:Maven:ActivationFile

0..1

References file specification used to activate a profile

ACTIVATED_BY_OS

:Maven:ActivationOS

0..1

References os specification used to activate a profile

:Maven:ActivationFile

File specification used to activate a profile

Table 73. Properties of :Maven:ActivationFile
Name Description

exists

Specifies the name of the file that should exist to activate a profile

missing

Specifies the name of the file that should be missing to activate a profile

:Maven:ActivationOS

Defines operating system’s attributes to activate a profile

Table 74. Properties of :Maven:ActivationOS
Name Description

arch

Specifies the architecture of the OS to be used to activate a profile

family

Specifies the general family of the OS to be used to activate a profile

name

Specifies the name of the OS to be used to activate a profile

version

Specifies the version of the OS to be used to activate a profile

:Maven:Module

A maven module

Table 75. Properties of :Maven:Module
Name Description

name

The module name

:Maven:Plugin

A maven plugin

Table 76. Properties of :Maven:Plugin
Name Description

group

The group id

name

The artifact id

type

The type, e.g. "jar"

classifier

The classifiert

version

The version

inherited

Whether any configuration should be propagated to child POMs

Table 77. Relations of :Maven:Plugin
Name Target label(s) Cardinality Description

HAS_EXECUTION

:Maven:PluginExecution

0..n

References a PluginExecution

HAS_CONFIGURATION

:Maven:Configuration

0..1

References the configuration for the plugin

:Maven:License

A used license

Table 78. Properties of :Maven:License
Name Description

name

The full legal name of the license.

url

The official url for the license text.

comments

Addendum information pertaining to this license.

distribution

The primary method by which this project may be distributed.

:Maven:PluginExecution

A plugin execution

Table 79. Properties of :Maven:PluginExecution
Name Description

id

The plugin id

inherited

Whether any configuration should be propagated to child POMs.

phase

The build lifecycle phase to bind the goals in this execution to.

Table 80. Relations of :Maven:PluginExecution
Name Target label(s) Cardinality Description

HAS_GOAL

:Maven:ExecutionGoal

0..n

The goals to execute with the given configuration

HAS_CONFIGURATION

:Maven:Configuration

0..1

References the configuration for the plugin

:Maven:Configuration

A configuration for plugins, executions

Table 81. Relations of :Maven:Configuration
Name Target label(s) Cardinality Description

CONTAINS

:Java:Value

0..n

References a value or a list of values

:Maven:ExecutionGoal

A goal for plugin executions

Table 82. Properties of :Maven:ExecutionGoal
Name Description

name

The name of the goal

Refer to the plugin Javadoc for details about the model.

maven3.xml

Constraints
maven3:HierarchicalParentModuleRelation

If a parent Maven project declares a module then the parent project must also be declared as the parent of the module (i.e. to keep the project hierarchy consistent).

match
  (parent:Maven:Project)-[:HAS_MODULE]->(module:Maven:Project)
where
  not (module)-[:HAS_PARENT]->(parent)
return
  module as InvalidModule

OSGi

Provides rules for OSGi bundles (e.g. Bundles, Activator).

osgi-bundle.xml

Concepts
osgi-bundle:Activator

Requires concepts:

Creates an ACTIVATES relation between a class and the bundle artifact if the class is declared as "Bundle-Activator" in the bundle manifest.

match
  (bundle:Osgi:Bundle)-[:CONTAINS]->(manifest:File:Manifest),
  (manifest)-[:DECLARES]->(section:ManifestSection),
  (section)-[:HAS]->(entry:ManifestEntry),
  (bundle)-[:CONTAINS]->(activator:Class)
where
  entry.name = "Bundle-Activator"
  and entry.value = activator.fqn
create unique
  (activator)-[:ACTIVATES]->(bundle)
return
  activator as Activator, bundle as Bundle
osgi-bundle:Bundle

Labels all artifacts with a manifest declaring a bundle name as "Osgi" and "Bundle" and adds the properties "bundleSymbolicName" and "bundleVersion".

MATCH
  (bundle:Artifact)-[:CONTAINS]->(manifest:Manifest:File),
  (manifest)-[DECLARES]->(section:ManifestSection),
  (section)-[:HAS]->(nameEntry:ManifestEntry),
  (section)-[:HAS]->(versionEntry:ManifestEntry)
WHERE
  nameEntry.name = "Bundle-SymbolicName"
  AND versionEntry.name = "Bundle-Version"
SET
  bundle:Osgi:Bundle,
  bundle.bundleSymbolicName = nameEntry.value,
  bundle.bundleVersion = versionEntry.value
RETURN
  bundle as Bundle, bundle.bundleSymbolicName as BundleSymbolicName, bundle.bundleVersion as BundleVersion
osgi-bundle:ExportPackage

Requires concepts:

Creates an EXPORTS relation from a bundle artifact to all packages which are declared as "Export-Package" in the bundle manifest.

match
 (bundle:Osgi:Bundle)-[:CONTAINS]->(package:Package)
with
  bundle, package, "(^|.*,)\\s*"+ replace(package.fqn, ".", "\\.")+"\\s*((;|,).*|$)" as pattern
match
  (bundle)-[:CONTAINS]->(manifest:File:Manifest),
  (manifest)-[:DECLARES]->(section:ManifestSection),
  (section)-[:HAS]->(entry:ManifestEntry)
where
  entry.name = "Export-Package"
  AND entry.value=~ pattern
create unique
  (bundle)-[:EXPORTS]->(package)
return
  bundle as Bundle, collect(package) as ExportedPackages
osgi-bundle:ImportPackage

Requires concepts:

Creates an IMPORTS relation from a bundle artifact to all packages which are declared as "Import-Package" in the bundle manifest.

match
 (package:Package)
with
  package, "(^|.*,)\\s*"+ replace(package.fqn, ".", "\\.")+"\\s*((;|,).*|$)" as pattern
match
  (bundle:Osgi:Bundle)-[:CONTAINS]->(manifest:File:Manifest),
  (manifest)-[:DECLARES]->(section:ManifestSection),
  (section)-[:HAS]->(entry:ManifestEntry)
where
  entry.name = "Import-Package"
  and entry.value =~ pattern
create unique
  (bundle)-[:IMPORTS]->(package)
return
  bundle as Bundle, collect(package) as ImportedPackages
osgi-bundle:InternalType

Requires concepts:

Labels all internal types (i.e. which are not located in an exported package) as "Internal".

match
  (bundle:Bundle:Osgi)-[:CONTAINS]->(internalPackage:Package),
  (bundle)-[:CONTAINS]->(internalType:Type),
  (internalPackage)-[:CONTAINS]->(internalType:Type)
where not
    (bundle)-[:EXPORTS]->(internalPackage)
set
  internalType:Internal
return bundle as Bundle, collect(internalType) as InternalTypes
Constraints
osgi-bundle:InternalTypeMustNotBePublic

Requires concepts:

Internal types must not be public if no depending types exist in other packages of the bundle.

match
  (bundle:Osgi:Bundle)-[:CONTAINS]->(internalType:Type:Internal),
  (internalPackage:Package)-[:CONTAINS]->(internalType)
optional match
  (bundle)-[:CONTAINS]->(otherPackage:Package),
  (otherPackage)-[:CONTAINS]->()-[:DEPENDS_ON]->(internalType)
where
  internalType.visibility='public'
with
  bundle, internalPackage, internalType, collect(otherPackage) as otherPackages
where
  all(otherPackage in otherPackages where internalPackage = otherPackage)
  and not
    (internalType)-[:ACTIVATES]->(bundle)
return
  bundle as Bundle, internalType as InternalType
osgi-bundle:UnusedInternalType

Requires concepts:

A bundle must not contain internal types which are not used by other types in the bundle.

match
  (bundle:Osgi:Bundle)-[:CONTAINS]->(internalType:Type:Internal)
where not (
    (internalType)-[:ACTIVATES]->(bundle)
  or
    (bundle)-[:CONTAINS]->(:Type)-[:DEPENDS_ON]->(internalType)
)
return
  bundle as Bundle, internalType as InternalType

Tycho

Provides a scanner for tycho modules.

Scanner for Tycho projects

Adds Tycho specific resources to be scanned to the file system scanner.

RDBMS

Provides a scanner for importing the metadata of a relational database schema.

Scanner for metadata of a relational database schema

Imports the metadata of a relational database schema, i.e. schemas, tables and columns.

The connection properties are taken from property files containing jqassistant.plugin.rdbms, e.g. "jqassistant.plugin.rdbms_test.properties", and which contains at least the properties "driver", "url", "user" and "password", e.g.

jqassistant.plugin.rdbms_test.properties
## Required configuration properties
driver=org.hsqldb.jdbc.JDBCDriver
url=jdbc:hsqldb:file:target/myDatabase
user=SA
password=

## Optional properties which are passed to Schema Crawler (http://schemacrawler.sourceforge.net/), they affect the level of queried information.

## The name of the database specific driver provided by schema crawler, supported values are "sybaseiq", "sqlserver", "sqlite", "postgresql", "oracle", "mysql", "hsqldb", "derby", "db2"
# bundled_driver=mysql

## It may be necessary to use another info level for performance or compatibility reasons, e.g. if a database does not support retrieving metadata for stored
## procedures you might try to set "retrieve_routines=false". Allowed values are "standard", "minimum", "maximum" or "detailed"
# info_level=standard

## Activation/deactivation of single options on the selected info level
# retrieve_additional_column_attributes=true
# retrieve_additional_database_info=true
# retrieve_additional_jdbc_driver_info=true
# retrieve_additional_table_attributes=true
# retrieve_foreign_keys=true
# retrieve_indices=true
# retrieve_index_information=true
# retrieve_routines=true
# retrieve_routine_columns=true
# retrieve_routine_information=true
# retrieve_schema_crawler_info=true
# retrieve_sequence_information=true
# retrieve_tables=true
# retrieve_table_columns=true
# retrieve_trigger_information=true
# retrieve_view_information=true

NOTE The JDBC driver must be available on the jQAssistant classpath, e.g. as dependency of the Maven plugin or copied to the plugins/ folder of the distribution.

:Rdbms:Connection:Properties

Represents a file containing the connection properties described above which have been used to read the schema metadata. It provides the same properties and relations as :File:Properties.

Table 83. Relations of :Rdbms:Connection:Properties
Name Target label(s) Cardinality Description

DESCRIBES_SCHEMA

:Rdbms:Schema

1

References the schema

:Rdbms:Schema

Describes a database schema.

Table 84. Properties of :Rdbms:Schema
Name Description

name

The name of the schema.

Table 85. Relations of :Rdbms:Schema
Name Target label(s) Cardinality Description

HAS_TABLE

:Rdbms:Table

0..n

References the tables in the schema

HAS_VIEW

:Rdbms:View

0..n

References the views in the schema

HAS_SEQUENCE

:Rdbms:Sequence

0..n

References the sequences in the schema

:Rdbms:Table

Describes a database table.

Table 86. Properties of :Rdbms:Table
Name Description

name

The name of the table.

Table 87. Relations of :Rdbms:Table
Name Target label(s) Cardinality Description

HAS_COLUMN

:Rdbms:Column

0..n

References the columns of the table

HAS_PRIMARY_KEY

:Rdbms:PrimaryKey

0..1

References the primary key of the table

HAS_INDEX

:Rdbms:Index

0..*

References indices defined for the table

:Rdbms:View

Describes a database view.

Table 88. Properties of :Rdbms:View
Name Description

name

The name of the view.

Table 89. Relations of :Rdbms:View
Name Target label(s) Cardinality Description

HAS_COLUMN

:Rdbms:Column

0..n

References the columns of the view

:Rdbms:Column

Describes a column of a table.

Table 90. Properties of :Rdbms:Column
Name Description

name

The name of the column

autoIncremented

Indicates an auto incremented value

generated

Indicates a generated value

defaultValue

The default value

size

The size of the column

decimalDigits

The number of digits for decimal types

partOfIndex

Indicates that the column is part of an index

partOfPrimaryKey

Indicates that the column is part of the primary key

partOfForeignKey

Indicates that the column is part of a foreign key

Table 91. Relations of :Rdbms:Column
Name Target label(s) Cardinality Description

OF_COLUMN_TYPE

:Rdbms:ColumnType

1

References the column type

:Rdbms:ColumnType

Describes a column data type, e.g. VARCHAR.

Table 92. Properties of :Rdbms:ColumnType
Name Description

databaseType

The database specific name of the type

autoIncrementable

Indicates that values of this type can auto incremented

precision

The precision

minimumScale

The minimum scale

maximumScale

The maximum scale

fixedPrecisionScale

The fixed precision scale

numericPrecisionRadix

The numeric precision radix

caseSensitive

Indicates that the type is case sensitive

unsigned

Indicates that the type is unsigned

userDefined

Indicates that the type is user defined

:Rdbms:PrimaryKey

Describes a primary key of a table.

Table 93. Properties of :Rdbms:PrimaryKey
Name Description

name

The name of the primary key.

Table 94. Relations of :Rdbms:PrimaryKey
Name Target label(s) Cardinality Description

ON_PRIMARY_KEY_COLUMN

:Rdbms:ColumnType

1

References a primary key column

ON_PRIMARY_KEY_COLUMN

Describes the properties of a column in a primary key.

Table 95. Properties of ON_PRIMARY_KEY_COLUMN
Name Description

indexOrdinalPosition

The ordinal position of the column in the primary key.

sortSequence

The sort sequence, i.e. "ascending" or "descending".

:Rdbms:Index

Describes an index defined for table.

Table 96. Properties of :Rdbms:Index
Name Description

name

The name of the index.

unique

"true" if the index is unique.

cardinality

The cardinality of the index.

indexType

The index type.

pages

The pages.

Table 97. Relations of :Rdbms:Index
Name Target label(s) Cardinality Description

ON_INDEX_COLUMN

:Rdbms:ColumnType

1

References an indexed column

ON_INDEX_COLUMN

Describes the properties of a column used by an index.

Table 98. Properties of ON_INDEX_COLUMN
Name Description

indexOrdinalPosition

The ordinal position of the column in the primary key.

sortSequence

The sort sequence, i.e. "ascending" or "descending".

:Rdbms:ForeignKey

Describes a foreign key.

Table 99. Properties of :Rdbms:ForeignKey
Name Description

name

The name of the foreign key

deferrability

The deferrability

deleteRule

The delete rule, e.g. "cascade"

updateRule

The update rule

Table 100. Relations of :Rdbms:ForeignKey
Name Target label(s) Cardinality Description

HAS_FOREIGN_KEY_REFERENCE

:Rdbms:ForeignKeyReference

1..n

The foreign key references

:Rdbms:ForeignKeyReference

Describes a foreign key reference, i.e. a pair consisting of a foreign key referencing a primary key.

Table 101. Relations of :Rdbms:ForeignKeyReference
Name Target label(s) Cardinality Description

FROM_FOREIGN_KEY_COLUMN

:Rdbms:Column

1

The foreign key column

TO_PRIMARY_KEY_COLUMN

:Rdbms:Column

1

The primary key column

:Rdbms:Sequence

Describes a database sequence.

Table 102. Properties of :Rdbms:Sequence
Name Description

name

The name of the sequence

minimumValue

The minimum value

maximumValue

The maximum value

increment

The increment

cycle

Indicates that the sequence restarts at the minimumValue if the the maximumValue has been reached.

Refer to the plugin Javadoc for details about the model.

XML

Generic scanner for XML and XSD files

Imports all XML or XSD files in a generic representation, e.g. namespaces, elements, attributes and text.

:File:Xml

Represents an XML file.

Table 103. Properties of :File:Xml
Name Description

xmlVersion

The XML version

standalone

The "standalone" attribute of the XML declaration.

characterEncodingScheme

The encoding of the XML file.

xmlWellFormed

Indicates if the document is well-formed, i.e. could be parsed.

Table 104. Relations of :File:Xml
Name Target label(s) Cardinality Description

HAS_ROOT_ELEMENT

:Xml:Element

1

References the root element of the document.

:Xml:Element

An XML element.

Table 105. Relations of :Xml:Element
Name Target label(s) Cardinality Description

DECLARES_NAMESPACE

:Xml:Namespace

0..n

References namespaces which are declared on the element.

OF_NAMESPACE

:Xml:Namespace

0..1

References the namespace of the element.

HAS_ELEMENT

:Xml:Element

0..n

References child elements of the element.

HAS_ATTRIBUTE

:Xml:Attribute

0..n

References attributes of the element.

HAS_TEXT

:Xml:Text

0..n

References the text values of the element.

:Xml:Namespace

A XML namespace declaration.

Table 106. Properties of :Xml:Namespace
Name Description

uri

The namespace URI.

prefix

The optional namespace prefix

:Xml:Attribute

An XML attribute.

Table 107. Properties of :Xml:Attribute
Name Description

name

The name of the atribute.

value

The value of the attribute.

Table 108. Relations of :Xml:Attribute
Name Target label(s) Cardinality Description

OF_NAMESPACE

:Xml:Namespace

0..1

References the namespace of the attribute.

:Xml:Text

A text value of an XML element.

Table 109. Properties of :Xml:Element
Name Description

value

The text value.

Refer to the plugin Javadoc for details about the model.