├── .editorconfig ├── .github ├── CODEOWNERS └── ISSUE_TEMPLATE │ ├── 01-template-for-feature.md │ ├── 02-template-for-bug.md │ ├── 03-template-for-task.md │ └── config.yml ├── .gitignore ├── LICENSE ├── analysis ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── buschmais │ │ │ └── jqassistant │ │ │ └── core │ │ │ └── analysis │ │ │ ├── api │ │ │ ├── Analyzer.java │ │ │ ├── AnalyzerContext.java │ │ │ ├── RuleInterpreterPlugin.java │ │ │ ├── configuration │ │ │ │ └── Analyze.java │ │ │ └── model │ │ │ │ ├── AnalyzeTaskDescriptor.java │ │ │ │ ├── ConceptDescriptor.java │ │ │ │ ├── ConstraintDescriptor.java │ │ │ │ ├── ExecutableRuleTemplate.java │ │ │ │ ├── GroupDescriptor.java │ │ │ │ ├── RuleDescriptor.java │ │ │ │ └── RuleGroupTemplate.java │ │ │ ├── impl │ │ │ ├── AbstractCypherRuleInterpreterPlugin.java │ │ │ ├── AbstractMinMaxVerificationStrategy.java │ │ │ ├── AggregationVerificationStrategy.java │ │ │ ├── AnalyzerContextImpl.java │ │ │ ├── AnalyzerImpl.java │ │ │ ├── AnalyzerRuleVisitor.java │ │ │ ├── CypherRuleInterpreterPlugin.java │ │ │ ├── RowCountVerificationStrategy.java │ │ │ ├── ScriptRuleInterpreterPlugin.java │ │ │ └── VerificationStrategy.java │ │ │ └── spi │ │ │ ├── AnalyzerPluginRepository.java │ │ │ └── RuleRepository.java │ └── resources │ │ └── META-INF │ │ └── jqassistant-plugin.xml │ └── test │ └── java │ └── com │ └── buschmais │ └── jqassistant │ └── core │ └── analysis │ └── impl │ ├── AggregationVerificationStrategyTest.java │ ├── AnalyzerContextImplTest.java │ ├── AnalyzerRuleVisitorTest.java │ ├── CypherRuleInterpreterPluginTest.java │ └── RowCountVerificationStrategyTest.java ├── jqassistant └── jqa-core-framework.xml ├── pom.xml ├── readme.adoc ├── report ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── buschmais │ │ │ └── jqassistant │ │ │ └── core │ │ │ └── report │ │ │ ├── api │ │ │ ├── LanguageHelper.java │ │ │ ├── ReportContext.java │ │ │ ├── ReportException.java │ │ │ ├── ReportHelper.java │ │ │ ├── ReportPlugin.java │ │ │ ├── ReportReader.java │ │ │ ├── ReportTransformer.java │ │ │ ├── ReportTransformerException.java │ │ │ ├── SourceProvider.java │ │ │ ├── configuration │ │ │ │ └── Report.java │ │ │ ├── graph │ │ │ │ ├── SubGraphFactory.java │ │ │ │ └── model │ │ │ │ │ ├── Identifiable.java │ │ │ │ │ ├── Node.java │ │ │ │ │ ├── PropertyContainer.java │ │ │ │ │ ├── Relationship.java │ │ │ │ │ └── SubGraph.java │ │ │ └── model │ │ │ │ ├── Column.java │ │ │ │ ├── Language.java │ │ │ │ ├── LanguageElement.java │ │ │ │ ├── Result.java │ │ │ │ ├── Row.java │ │ │ │ ├── Suppress.java │ │ │ │ └── source │ │ │ │ ├── AbstractLocation.java │ │ │ │ ├── ArtifactLocation.java │ │ │ │ └── FileLocation.java │ │ │ └── impl │ │ │ ├── CompositeReportPlugin.java │ │ │ ├── HtmlReportTransformer.java │ │ │ ├── InMemoryReportPlugin.java │ │ │ ├── ReportContextImpl.java │ │ │ └── XmlReportPlugin.java │ └── resources │ │ └── META-INF │ │ ├── jqassistant-plugin.xml │ │ └── xsl │ │ ├── jqassistant-report-embedded.xsl │ │ ├── jqassistant-report-standalone.xsl │ │ └── jqassistant-report.xsl │ └── test │ ├── java │ └── com │ │ └── buschmais │ │ └── jqassistant │ │ └── core │ │ └── report │ │ ├── CompositeReportPluginTest.java │ │ ├── HtmlReportTransformerTest.java │ │ ├── LanguageHelperTest.java │ │ ├── XmlReportTest.java │ │ ├── XmlReportTestHelper.java │ │ ├── api │ │ ├── ReportHelperTest.java │ │ ├── ReportReaderTest.java │ │ └── graph │ │ │ └── SubGraphFactoryTest.java │ │ ├── impl │ │ └── ReportContextImplTest.java │ │ └── model │ │ ├── DerivedTestDescriptor.java │ │ ├── DerivedTestDescriptorWithLanguageElement.java │ │ ├── TestDescriptorWithLanguageElement.java │ │ └── TestLanguage.java │ └── resources │ ├── jqassistant-report-with-reports.xml │ └── jqassistant-report-with-severities.xml ├── rule ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── buschmais │ │ └── jqassistant │ │ └── core │ │ └── rule │ │ ├── api │ │ ├── RuleHelper.java │ │ ├── configuration │ │ │ └── Rule.java │ │ ├── executor │ │ │ ├── AbstractRuleVisitor.java │ │ │ ├── CollectRulesVisitor.java │ │ │ ├── RuleSetExecutor.java │ │ │ └── RuleVisitor.java │ │ ├── filter │ │ │ └── RuleFilter.java │ │ ├── model │ │ │ ├── AbstractExecutableRule.java │ │ │ ├── AbstractRule.java │ │ │ ├── AbstractRuleBucket.java │ │ │ ├── AbstractRuleBucketSpec.java │ │ │ ├── AbstractSeverityRule.java │ │ │ ├── Concept.java │ │ │ ├── ConceptBucket.java │ │ │ ├── Constraint.java │ │ │ ├── ConstraintBucket.java │ │ │ ├── CypherExecutable.java │ │ │ ├── Executable.java │ │ │ ├── ExecutableRule.java │ │ │ ├── Group.java │ │ │ ├── GroupsBucket.java │ │ │ ├── Parameter.java │ │ │ ├── Report.java │ │ │ ├── Rule.java │ │ │ ├── RuleException.java │ │ │ ├── RuleSelection.java │ │ │ ├── RuleSet.java │ │ │ ├── RuleSetBuilder.java │ │ │ ├── ScriptExecutable.java │ │ │ ├── Severity.java │ │ │ ├── SeverityRule.java │ │ │ └── Verification.java │ │ ├── reader │ │ │ ├── AggregationVerification.java │ │ │ ├── RowCountVerification.java │ │ │ └── RuleParserPlugin.java │ │ ├── source │ │ │ ├── ClasspathRuleSource.java │ │ │ ├── FileRuleSource.java │ │ │ ├── RuleSource.java │ │ │ └── UrlRuleSource.java │ │ └── writer │ │ │ └── RuleSetWriter.java │ │ ├── asciidoctor.adoc │ │ ├── impl │ │ ├── SourceExecutable.java │ │ ├── reader │ │ │ ├── AbstractRuleParserPlugin.java │ │ │ ├── AbstractStreamWriterDelegate.java │ │ │ ├── CDataXMLStreamWriter.java │ │ │ ├── ErrorMessageGenerator.java │ │ │ ├── IndentHelper.java │ │ │ ├── JsonSchemaValidator.java │ │ │ ├── RuleParser.java │ │ │ ├── ValidationResult.java │ │ │ ├── XmlHelper.java │ │ │ ├── XmlRuleParserPlugin.java │ │ │ └── YamlRuleParserPlugin.java │ │ └── writer │ │ │ └── XmlRuleSetWriter.java │ │ ├── index.adoc │ │ ├── spi │ │ └── RulePluginRepository.java │ │ ├── xml.adoc │ │ ├── yaml-concepts-and-constraints.adoc │ │ ├── yaml-examples.adoc │ │ ├── yaml-groups.adoc │ │ ├── yaml-schema.adoc │ │ └── yaml.adoc │ └── test │ ├── java │ └── com │ │ └── buschmais │ │ └── jqassistant │ │ └── core │ │ └── rule │ │ ├── api │ │ ├── filter │ │ │ └── RuleFilterTest.java │ │ ├── matcher │ │ │ └── RuleSourceMatcher.java │ │ ├── model │ │ │ ├── AbstractRuleBucketTest.java │ │ │ ├── DescriptionTest.java │ │ │ ├── ExecutablesTest.java │ │ │ ├── ParameterTest.java │ │ │ ├── ReportTest.java │ │ │ ├── RuleDependenciesTest.java │ │ │ ├── RuleParserTest.java │ │ │ ├── RuleSetBuilderTest.java │ │ │ ├── RuleSetExecutorTest.java │ │ │ ├── RuleSetTestHelper.java │ │ │ ├── SeverityTest.java │ │ │ ├── VerificationTest.java │ │ │ └── XmlRuleParserPluginTest.java │ │ └── source │ │ │ ├── AbstractRuleSourceTest.java │ │ │ ├── ClasspathRuleSourceTest.java │ │ │ └── FileRuleSourceTest.java │ │ └── impl │ │ └── reader │ │ ├── IndentHelperTest.java │ │ ├── JsonSchemaValidatorTest.java │ │ └── YamlRuleParserPluginTest.java │ └── resources │ ├── META-INF │ └── jqassistant-rules │ │ ├── index.adoc │ │ ├── readme.md │ │ ├── rules.xml │ │ └── subdirectory │ │ └── rules.xml │ ├── descriptions.xml │ ├── executables.xml │ ├── javascript-rules.xml │ ├── parameters.xml │ ├── report.xml │ ├── resultVerification.xml │ ├── rule-dependencies.xml │ ├── rule-dependencies.yaml │ ├── rules-1.8.xml │ ├── severity.xml │ ├── test-concepts.xml │ └── yaml │ ├── concept-provides-concepts.yaml │ ├── concept-single-rule-language-explicitly-set-to-js.yaml │ ├── concept-single-rule-language-explicitly-set.yaml │ ├── concept-single-rule-language-not-explicitly-set.yaml │ ├── concept-single-simple.yaml │ ├── concept-single-with-dependency-one.yaml │ ├── concept-single-with-dependency-with-missing-required-key.yaml │ ├── concept-single-with-dependency-with-unsupported-key.yaml │ ├── concept-single-with-missing-keyword-id.yaml │ ├── concept-single-with-one-dependency-and-unsupported-key.yaml │ ├── concept-single-with-one-parameter.yaml │ ├── concept-single-with-severity.yaml │ ├── concept-single-with-two-parameters.yaml │ ├── concept-single-with-verification-aggrgation.yaml │ ├── concept-single-with-verification-and-rowcount.yaml │ ├── concept-single-with-verification-rowcount.yaml │ ├── concept-single-with-verification-unsupported-keyword.yaml │ ├── concept-with-parameter-and-unsupported-keyword.yml │ ├── concept-with-parameter-empty-list-of-parameters.yml │ ├── concept-with-parameter-invalid-missing-field-name.yaml │ ├── concept-with-parameter-invalid-missing-field-type.yaml │ ├── concept-with-parameter-missing-default-value.yml │ ├── concept-with-parameter-missing-name.yml │ ├── concept-with-parameter-missing-type.yml │ ├── concept-with-parameter-unsupported-type.yml │ ├── concept-with-parameter-with-illegal-datastructure.yml │ ├── constraint-with-report-all-possible-keys.yaml │ ├── constraint-with-report-and-with-unknown-keyword.yml │ ├── constraint-with-report-many-properties.yaml │ ├── constraint-with-report-no-properties.yaml │ ├── constraint-with-report-with-invalid-block-structure-01.yaml │ ├── constraint-with-report-with-invalid-block-structure-02.yaml │ ├── constraint-with-report-with-report-type-multiple.yaml │ ├── constraint-with-report-with-report-type.yaml │ ├── constraint-with-report-without-any-key.yaml │ ├── descriptions.yaml │ ├── document-empty-empty-file.yaml │ ├── document-empty.yaml │ ├── document-only-toplevel-keywords-but-all-empty.yaml │ ├── document-unknown-toplevel-keyword.yml │ ├── group-single-include-concept-additional-keyword.yaml │ ├── group-single-include-concept-empty-list.yaml │ ├── group-single-include-concept-missing-refid.yaml │ ├── group-single-include-concept-severity-unknown.yml │ ├── group-single-include-concept-two.yaml │ ├── group-single-include-constraint-different-severity.yaml │ ├── group-single-include-constraint-empty-list.yaml │ ├── group-single-include-constraint-two.yaml │ ├── group-single-include-group-empty-list.yaml │ ├── group-single-missing-keyword.yaml │ ├── group-single-one-included-constraint.yaml │ ├── group-single-severity-explicitly-set.yaml │ ├── group-single-severity-not-set.yaml │ ├── group-single-with-include-concept-no-value-for-severity.yaml │ ├── group-single-with-one-included-concept-with-own-severity.yaml │ ├── group-single-with-one-included-concept.yaml │ ├── group-single-with-one-included-group.yaml │ ├── group-single-with-two-included-groups.yaml │ ├── group-single-with-unknown-keyword.yaml │ ├── group-single.yaml │ ├── group-two.yaml │ ├── i18n-emoji-usage.yaml │ └── i18n-japanese-description.yaml ├── runtime ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── buschmais │ │ └── jqassistant │ │ └── core │ │ └── runtime │ │ ├── api │ │ ├── configuration │ │ │ ├── Configuration.java │ │ │ ├── ConfigurationBuilder.java │ │ │ ├── ConfigurationMappingLoader.java │ │ │ ├── ConfigurationSerializer.java │ │ │ └── Server.java │ │ └── plugin │ │ │ ├── PluginClassLoader.java │ │ │ ├── PluginConfigurationReader.java │ │ │ ├── PluginInfo.java │ │ │ ├── PluginRepository.java │ │ │ ├── PluginRepositoryException.java │ │ │ └── PluginResolver.java │ │ └── impl │ │ └── plugin │ │ ├── AbstractPluginRepository.java │ │ ├── AetherArtifactProvider.java │ │ ├── AnalyzerPluginRepositoryImpl.java │ │ ├── PluginConfigurationReaderImpl.java │ │ ├── PluginIdGenerator.java │ │ ├── PluginInfoImpl.java │ │ ├── PluginRepositoryImpl.java │ │ ├── PluginResolverImpl.java │ │ ├── RulePluginRepositoryImpl.java │ │ ├── ScannerPluginRepositoryImpl.java │ │ └── StorePluginRepositoryImpl.java │ └── test │ ├── java │ └── com │ │ └── buschmais │ │ └── jqassistant │ │ └── core │ │ └── runtime │ │ ├── api │ │ ├── configuration │ │ │ └── ConfigurationBuilderTest.java │ │ └── plugin │ │ │ └── PluginInfoTest.java │ │ └── impl │ │ ├── configuration │ │ ├── ConfigurationMappingLoaderTest.java │ │ ├── ConfigurationSerializerTest.java │ │ └── TestConfiguration.java │ │ └── plugin │ │ ├── PluginConfigurationReaderImplTest.java │ │ ├── PluginIdGeneratorTest.java │ │ ├── PluginRepositoryImplTest.java │ │ ├── RulePluginRepositoryImplTest.java │ │ ├── ScannerPluginRepositoryTest.java │ │ ├── TestReportPlugin.java │ │ ├── TestScannerPlugin.java │ │ └── TestScope.java │ └── resources │ ├── .jqassistant.yml │ ├── META-INF │ └── jqassistant-plugin.xml │ ├── testdata │ ├── plugin-info-data.left-and-right-are-equal.csv │ └── plugin-info-data.left-less-then-right.csv │ ├── userhome │ └── .jqassistant.yml │ └── working directory │ └── .jqassistant │ ├── plugins.yml │ ├── profile.yml │ ├── readme.txt │ └── scan │ └── scan.yaml ├── scanner ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── buschmais │ │ └── jqassistant │ │ └── core │ │ └── scanner │ │ ├── api │ │ ├── DefaultScope.java │ │ ├── Scanner.java │ │ ├── ScannerContext.java │ │ ├── ScannerPlugin.java │ │ ├── Scope.java │ │ ├── ScopeHelper.java │ │ └── configuration │ │ │ ├── Include.java │ │ │ └── Scan.java │ │ ├── impl │ │ ├── ScannerContextImpl.java │ │ ├── ScannerImpl.java │ │ └── UnrecoverableScannerException.java │ │ └── spi │ │ └── ScannerPluginRepository.java │ └── test │ └── java │ └── com │ └── buschmais │ └── jqassistant │ └── core │ └── scanner │ ├── api │ └── ScopeHelperTest.java │ └── impl │ ├── DependentTestItemDescriptor.java │ ├── DependentTestItemScannerPlugin.java │ ├── NestedTestItemDescriptor.java │ ├── NestedTestItemScannerPlugin.java │ ├── ScannerContextImplTest.java │ ├── ScannerImplTest.java │ ├── TestItem.java │ ├── TestItemDescriptor.java │ ├── TestItemScannerPlugin.java │ └── TestScope.java ├── schemata ├── pom.xml └── src │ └── main │ └── resources │ └── META-INF │ ├── plugin │ └── xsd │ │ ├── jqassistant-plugin-v1.10.xsd │ │ ├── jqassistant-plugin-v1.8.xsd │ │ └── jqassistant-plugin-v2.2.xsd │ ├── report │ └── xsd │ │ ├── jqassistant-report-v1.11.xsd │ │ ├── jqassistant-report-v1.12.xsd │ │ ├── jqassistant-report-v1.8.xsd │ │ ├── jqassistant-report-v2.0.xsd │ │ └── jqassistant-report-v2.3.xsd │ └── rule │ ├── jsonschema │ ├── jqassistant-rule-v1.10.schema.json │ ├── jqassistant-rule-v1.8.schema.json │ ├── jqassistant-rule-v1.8.schema.readme │ └── jqassistant-rule-v2.2.schema.json │ └── xsd │ ├── jqassistant-rule-v1.10.xsd │ ├── jqassistant-rule-v1.8.xsd │ ├── jqassistant-rule-v2.0.xsd │ └── jqassistant-rule-v2.2.xsd ├── shared ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── buschmais │ └── jqassistant │ └── core │ └── shared │ ├── annotation │ ├── Description.java │ ├── PublicApi.java │ └── ToBeRemovedInVersion.java │ ├── artifact │ └── ArtifactProvider.java │ ├── configuration │ ├── Exclusion.java │ └── Plugin.java │ ├── io │ ├── ClasspathResource.java │ ├── FileNameNormalizer.java │ └── FilePattern.java │ ├── lifecycle │ ├── ConfigurableLifecycleAware.java │ ├── ContextualConfigurableLifecycleAware.java │ └── LifecycleAware.java │ ├── map │ └── MapBuilder.java │ ├── option │ └── OptionHelper.java │ ├── reflection │ └── ClassHelper.java │ ├── transaction │ └── Transactional.java │ └── xml │ └── JAXBUnmarshaller.java ├── src └── main │ └── asciidoc │ └── release-notes.adoc ├── store ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── buschmais │ │ └── jqassistant │ │ └── core │ │ └── store │ │ ├── api │ │ ├── Store.java │ │ ├── StoreFactory.java │ │ ├── configuration │ │ │ ├── Embedded.java │ │ │ ├── Remote.java │ │ │ └── Store.java │ │ └── model │ │ │ ├── Descriptor.java │ │ │ ├── FullQualifiedNameDescriptor.java │ │ │ ├── TaskDescriptor.java │ │ │ └── jQAssistantDescriptor.java │ │ ├── impl │ │ ├── AbstractGraphStore.java │ │ ├── EmbeddedGraphStore.java │ │ └── RemoteGraphStore.java │ │ └── spi │ │ └── StorePluginRepository.java │ └── test │ └── java │ └── com │ └── buschmais │ └── jqassistant │ └── core │ └── store │ └── api │ └── StoreFactoryTest.java └── test ├── pom.xml └── src └── main └── java └── com └── buschmais └── jqassistant └── core └── test ├── matcher ├── AbstractDescriptorMatcher.java ├── AbstractRuleMatcher.java ├── ConceptMatcher.java ├── ConstraintMatcher.java ├── GroupMatcher.java └── ResultMatcher.java ├── mockito └── MethodNotMockedAnswer.java └── plugin ├── AbstractPluginIT.java └── AbstractServerPluginIT.java /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | insert_final_newline = true 8 | indent_style = space 9 | 10 | [*.{java,xml}] 11 | indent_size = 4 12 | trim_trailing_whitespace = true 13 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @obfischer @DirkMahler @StephanPirnbaum 2 | 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/01-template-for-feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request Template 3 | about: Request a feature for this particular subproject. 4 | title: New Feature 5 | labels: status:teamdiscussion 6 | assignees: '' 7 | 8 | --- 9 | _This hint can be removed_ 10 | **We are happy, what you are going to send us your feature request. Please try to fillout as many sections as good as you can. If you can't provide us any information for a particular section, that is not problem. It is more important to us, to know more about our users and their needs. Even if this template looks very formal, we aren't.** 11 | 12 | ### Feature Description 13 | _Remove this hint: Provide here a short description of the feature you would like to see. Try to use the form of a user story. See https://en.wikipedia.org/wiki/User_story._ 14 | 15 | I, as... 16 | would like... 17 | to that... 18 | 19 | ### Additional information on the requested Feature 20 | _Remove this hint: Feel free to let us know what ever you wan't :wink:_ 21 | 22 | ### How to Test 23 | _Remove this hint: How can we test if the feature works as you expect it to work?_ 24 | 25 | To test this feature... 26 | 27 | ### Available Test data 28 | _Remove this hint: To test new features, we need some examples or test data sets. Please let us know if you can provide them for us or there we can find them. 29 | 30 | ### Definition of Done for the Implementers 31 | _Remove this hint: these checkboxes can be checked like this: [x]_ 32 | - [ ] We got a final feedback from the reporting user (_if applicable_) 33 | - [ ] Unittests have been written (_if applicable_) 34 | - [ ] Integration tests have been written (_if applicable_) 35 | - [ ] Test coverage is the same or even better then before (_if applicable_) 36 | - [ ] Documentation has been written (_if applicable_) 37 | - [ ] Added a note on the new feature to the release notes (_if applicable_) 38 | 39 | 40 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/03-template-for-task.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Task Template 3 | about: Used mainly by the team behind jQAssistant for issues which aren't a feature nor a bug, but must be done and should'nt be forgotten. 4 | title: Please fullfil this task 5 | labels: type:task 6 | assignees: '' 7 | --- 8 | 9 | ### Task Description 10 | 11 | ### Definition of Done for the Implementers 12 | _Remove this hint: these checkboxes can be checked like this: [x]_ 13 | - [ ] We got a final feedback from the reporting user (_if applicable_) 14 | - [ ] Unittests have been written (_if applicable_) 15 | - [ ] Integration tests have been written (_if applicable_) 16 | - [ ] Test coverage is the same or even better then before (_if applicable_) 17 | - [ ] Documentation has been written (_if applicable_) 18 | - [ ] Added a note on the new feature to the release notes (_if applicable_) 19 | 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | 3 | contact_links: 4 | - name: Use Stackoverflow for your question on jQAssistant 5 | url: https://stackoverflow.com/questions/tagged/jqassistant 6 | about: Please use stackoverflow for supporting issues. Using stackoverflow will help us to have all questions in a plublic space and you have the chance to get help from the whole jQAssistant community. 7 | - name: Use our Idea Hub for new Ideas and Suggestions 8 | url: https://github.com/jQAssistant/jQA-Idea-Hub 9 | about: Some features might be not releated to any particular subproject or will affect all of them. To report such issues, please use this project. 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | *.iml 3 | *.ipr 4 | *~ 5 | *.log 6 | .DS_Store 7 | pom.xml.versionsBackup 8 | .java-version 9 | *.backup 10 | rule/.asciidoctor/ 11 | 12 | # Files generated by the release tooling of jQAssistant 13 | pom.xml.updatetorelease 14 | pom.xml.updatetonextdevversion 15 | 16 | # Maven related files and directories 17 | target 18 | /.mvn 19 | 20 | # Ignore temporary shell scripts used to script small tasks 21 | *.sh.ignore 22 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/api/Analyzer.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.api; 2 | 3 | import com.buschmais.jqassistant.core.analysis.api.configuration.Analyze; 4 | import com.buschmais.jqassistant.core.rule.api.model.RuleException; 5 | import com.buschmais.jqassistant.core.rule.api.model.RuleSelection; 6 | import com.buschmais.jqassistant.core.rule.api.model.RuleSet; 7 | 8 | /** 9 | * Defines the interface for the analyzer. 10 | */ 11 | public interface Analyzer { 12 | 13 | /** 14 | * Return the {@link Analyze} configuration. 15 | * 16 | * @return The {@link Analyze} configuration. 17 | */ 18 | Analyze getConfiguration(); 19 | 20 | /** 21 | * Executes the given rule set. 22 | * 23 | * @param ruleSet 24 | * The rules set. 25 | * @param ruleSelection 26 | * The rule selection. 27 | */ 28 | void execute(RuleSet ruleSet, RuleSelection ruleSelection) throws RuleException; 29 | } 30 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/api/model/AnalyzeTaskDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.api.model; 2 | 3 | import com.buschmais.jqassistant.core.store.api.model.TaskDescriptor; 4 | import com.buschmais.xo.neo4j.api.annotation.Label; 5 | 6 | @Label("Analyze") 7 | public interface AnalyzeTaskDescriptor extends TaskDescriptor, RuleGroupTemplate { 8 | } 9 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/api/model/ConceptDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.api.model; 2 | 3 | import java.util.List; 4 | 5 | import com.buschmais.xo.neo4j.api.annotation.Label; 6 | import com.buschmais.xo.neo4j.api.annotation.Relation; 7 | 8 | /** 9 | * Describes an executed constraint. 10 | */ 11 | @Label("Concept") 12 | public interface ConceptDescriptor extends RuleDescriptor, ExecutableRuleTemplate { 13 | 14 | @Relation("PROVIDES_CONCEPT") 15 | List getProvidesConcepts(); 16 | } 17 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/api/model/ConstraintDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.api.model; 2 | 3 | import com.buschmais.xo.neo4j.api.annotation.Label; 4 | 5 | /** 6 | * Describes an executed concept. 7 | */ 8 | @Label("Constraint") 9 | public interface ConstraintDescriptor extends RuleDescriptor, ExecutableRuleTemplate { 10 | } 11 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/api/model/ExecutableRuleTemplate.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.api.model; 2 | 3 | import java.util.List; 4 | 5 | import com.buschmais.jqassistant.core.report.api.model.Result; 6 | import com.buschmais.xo.neo4j.api.annotation.Relation; 7 | 8 | public interface ExecutableRuleTemplate { 9 | 10 | Result.Status getStatus(); 11 | 12 | void setStatus(Result.Status status); 13 | 14 | @Relation("REQUIRES_CONCEPT") 15 | List getRequiresConcepts(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/api/model/GroupDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.api.model; 2 | 3 | import com.buschmais.xo.neo4j.api.annotation.Label; 4 | 5 | /** 6 | * Describes an executed group. 7 | */ 8 | @Label("Group") 9 | public interface GroupDescriptor extends RuleDescriptor, RuleGroupTemplate { 10 | } 11 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/api/model/RuleDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.api.model; 2 | 3 | import com.buschmais.jqassistant.core.rule.api.model.Severity; 4 | import com.buschmais.jqassistant.core.store.api.model.jQAssistantDescriptor; 5 | import com.buschmais.xo.api.annotation.Abstract; 6 | import com.buschmais.xo.neo4j.api.annotation.Label; 7 | 8 | @Label("Rule") 9 | @Abstract 10 | public interface RuleDescriptor extends jQAssistantDescriptor { 11 | 12 | String getId(); 13 | 14 | void setId(String id); 15 | 16 | Severity getSeverity(); 17 | 18 | void setSeverity(Severity severity); 19 | 20 | Severity getEffectiveSeverity(); 21 | 22 | void setEffectiveSeverity(Severity severity); 23 | } 24 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/api/model/RuleGroupTemplate.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.api.model; 2 | 3 | import java.util.List; 4 | 5 | import com.buschmais.xo.neo4j.api.annotation.Relation; 6 | 7 | public interface RuleGroupTemplate { 8 | 9 | @Relation("INCLUDES_CONCEPT") 10 | List getIncludesConcepts(); 11 | 12 | @Relation("INCLUDES_CONSTRAINT") 13 | List getIncludesConstraints(); 14 | 15 | @Relation("INCLUDES_GROUP") 16 | List getIncludesGroups(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/impl/AbstractMinMaxVerificationStrategy.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.impl; 2 | 3 | import com.buschmais.jqassistant.core.report.api.configuration.Report; 4 | import com.buschmais.jqassistant.core.report.api.model.Result; 5 | import com.buschmais.jqassistant.core.rule.api.model.*; 6 | 7 | import static com.buschmais.jqassistant.core.report.api.model.Result.Status.*; 8 | 9 | public abstract class AbstractMinMaxVerificationStrategy implements VerificationStrategy { 10 | 11 | private final Severity.Threshold warnOnSeverity; 12 | 13 | private final Severity.Threshold failOnSeverity; 14 | 15 | protected AbstractMinMaxVerificationStrategy(Report configuration) throws RuleException { 16 | this.warnOnSeverity = Severity.Threshold.from(configuration.warnOnSeverity()); 17 | this.failOnSeverity = Severity.Threshold.from(configuration.failOnSeverity()); 18 | } 19 | 20 | protected Result.Status getStatus(T executable, Severity severity, int value, Integer min, Integer max) { 21 | if (min == null && max == null) { 22 | if (executable instanceof Concept) { 23 | min = 1; 24 | } 25 | if (executable instanceof Constraint) { 26 | max = 0; 27 | } 28 | } 29 | boolean success = (min == null || value >= min) && (max == null || value <= max); 30 | return getStatus(severity, success); 31 | } 32 | 33 | private Result.Status getStatus(Severity severity, boolean success) { 34 | if (!success) { 35 | if (severity.exceeds(failOnSeverity)) { 36 | return FAILURE; 37 | } else { 38 | if (severity.exceeds(warnOnSeverity)) { 39 | return WARNING; 40 | } 41 | } 42 | } 43 | return SUCCESS; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/impl/CypherRuleInterpreterPlugin.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.impl; 2 | 3 | import java.util.Collection; 4 | import java.util.Map; 5 | 6 | import com.buschmais.jqassistant.core.analysis.api.AnalyzerContext; 7 | import com.buschmais.jqassistant.core.analysis.api.RuleInterpreterPlugin; 8 | import com.buschmais.jqassistant.core.report.api.model.Result; 9 | import com.buschmais.jqassistant.core.rule.api.model.Executable; 10 | import com.buschmais.jqassistant.core.rule.api.model.ExecutableRule; 11 | import com.buschmais.jqassistant.core.rule.api.model.RuleException; 12 | import com.buschmais.jqassistant.core.rule.api.model.Severity; 13 | import com.buschmais.jqassistant.core.rule.impl.SourceExecutable; 14 | 15 | import static java.util.Collections.singletonList; 16 | 17 | /** 18 | * Implementation of a {@link RuleInterpreterPlugin} for executing Cypher rules. 19 | */ 20 | public class CypherRuleInterpreterPlugin extends AbstractCypherRuleInterpreterPlugin { 21 | 22 | private static final Collection LANGUAGES = singletonList("cypher"); 23 | 24 | @Override 25 | public Collection getLanguages() { 26 | return LANGUAGES; 27 | } 28 | 29 | @Override 30 | public > boolean accepts(T executableRule) { 31 | return executableRule.getExecutable() instanceof SourceExecutable; 32 | } 33 | 34 | @Override 35 | public > Result execute(T executableRule, Map parameters, Severity severity, AnalyzerContext context) 36 | throws RuleException { 37 | Executable executable = executableRule.getExecutable(); 38 | String cypher = executable.getSource(); 39 | return execute(cypher, executableRule, parameters, severity, context); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/impl/RowCountVerificationStrategy.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.impl; 2 | 3 | import java.util.List; 4 | 5 | import com.buschmais.jqassistant.core.report.api.configuration.Report; 6 | import com.buschmais.jqassistant.core.report.api.model.Result; 7 | import com.buschmais.jqassistant.core.report.api.model.Row; 8 | import com.buschmais.jqassistant.core.rule.api.model.ExecutableRule; 9 | import com.buschmais.jqassistant.core.rule.api.model.RuleException; 10 | import com.buschmais.jqassistant.core.rule.api.model.Severity; 11 | import com.buschmais.jqassistant.core.rule.api.reader.RowCountVerification; 12 | 13 | public class RowCountVerificationStrategy extends AbstractMinMaxVerificationStrategy { 14 | 15 | public RowCountVerificationStrategy(Report configuration) throws RuleException { 16 | super(configuration); 17 | } 18 | 19 | @Override 20 | public Class getVerificationType() { 21 | return RowCountVerification.class; 22 | } 23 | 24 | @Override 25 | public Result.Status verify(T executable, Severity severity, RowCountVerification verification, List columnNames, 26 | List rows) { 27 | return getStatus(executable, severity, rows.size(), verification.getMin(), verification.getMax()); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/impl/VerificationStrategy.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.impl; 2 | 3 | import java.util.List; 4 | 5 | import com.buschmais.jqassistant.core.report.api.model.Result; 6 | import com.buschmais.jqassistant.core.report.api.model.Row; 7 | import com.buschmais.jqassistant.core.rule.api.model.ExecutableRule; 8 | import com.buschmais.jqassistant.core.rule.api.model.RuleException; 9 | import com.buschmais.jqassistant.core.rule.api.model.Severity; 10 | import com.buschmais.jqassistant.core.rule.api.model.Verification; 11 | 12 | /** 13 | * Defines the interface for strategies to verify the result of an executable 14 | * rule. 15 | */ 16 | public interface VerificationStrategy { 17 | 18 | Class getVerificationType(); 19 | 20 | Result.Status verify(T executable, Severity severity, V verification, List columnNames, List rows) 21 | throws RuleException; 22 | } 23 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/spi/AnalyzerPluginRepository.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.spi; 2 | 3 | import java.util.Collection; 4 | import java.util.Map; 5 | 6 | import com.buschmais.jqassistant.core.analysis.api.RuleInterpreterPlugin; 7 | import com.buschmais.jqassistant.core.report.api.ReportContext; 8 | import com.buschmais.jqassistant.core.report.api.ReportPlugin; 9 | import com.buschmais.jqassistant.core.report.api.configuration.Report; 10 | import com.buschmais.jqassistant.core.shared.lifecycle.LifecycleAware; 11 | 12 | /** 13 | * Defines the interface for the analysis plugin repository. 14 | */ 15 | public interface AnalyzerPluginRepository extends LifecycleAware { 16 | 17 | /** 18 | * Return the {@link RuleInterpreterPlugin}s. 19 | * 20 | * @param properties 21 | * The configuration properties. 22 | * @return The {@link RuleInterpreterPlugin}s. 23 | */ 24 | Map> getRuleInterpreterPlugins(Map properties); 25 | 26 | /** 27 | * Return the instances of the configured report plugins. 28 | * 29 | * @param configuration 30 | * The {@link Report} configuration. 31 | * @param reportContext 32 | * The {@link ReportContext}. 33 | * @return The instances of the configured report plugins. 34 | */ 35 | Map getReportPlugins(Report configuration, ReportContext reportContext); 36 | 37 | @Override 38 | void initialize(); 39 | 40 | void destroy(); 41 | } 42 | -------------------------------------------------------------------------------- /analysis/src/main/java/com/buschmais/jqassistant/core/analysis/spi/RuleRepository.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.analysis.spi; 2 | 3 | import com.buschmais.jqassistant.core.analysis.api.model.ConceptDescriptor; 4 | import com.buschmais.jqassistant.core.analysis.api.model.ConstraintDescriptor; 5 | import com.buschmais.jqassistant.core.analysis.api.model.GroupDescriptor; 6 | import com.buschmais.xo.api.annotation.Repository; 7 | import com.buschmais.xo.api.annotation.ResultOf; 8 | import com.buschmais.xo.api.annotation.ResultOf.Parameter; 9 | import com.buschmais.xo.neo4j.api.annotation.Cypher; 10 | 11 | @Repository 12 | public interface RuleRepository { 13 | 14 | @ResultOf 15 | @Cypher("MATCH (concept:jQAssistant:Rule:Concept{id: $id}) RETURN concept") 16 | ConceptDescriptor findConcept(@Parameter("id") String id); 17 | 18 | @ResultOf 19 | @Cypher("MERGE (concept:jQAssistant:Rule:Concept{id: $id}) RETURN concept") 20 | ConceptDescriptor mergeConcept(@Parameter("id") String id); 21 | 22 | @ResultOf 23 | @Cypher("MERGE (constraint:jQAssistant:Rule:Constraint{id: $id}) RETURN constraint") 24 | ConstraintDescriptor mergeConstraint(@Parameter("id") String id); 25 | 26 | @ResultOf 27 | @Cypher("MERGE (group:jQAssistant:Rule:Group{id: $id}) RETURN group") 28 | GroupDescriptor mergeGroup(@Parameter("id") String id); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /analysis/src/main/resources/META-INF/jqassistant-plugin.xml: -------------------------------------------------------------------------------- 1 | 7 | Provides elements for storing analysis results. 8 | 9 | com.buschmais.jqassistant.core.analysis.api.model.AnalyzeTaskDescriptor 10 | com.buschmais.jqassistant.core.analysis.api.model.ConceptDescriptor 11 | com.buschmais.jqassistant.core.analysis.api.model.ConstraintDescriptor 12 | com.buschmais.jqassistant.core.analysis.api.model.GroupDescriptor 13 | com.buschmais.jqassistant.core.analysis.spi.RuleRepository 14 | 15 | 16 | com.buschmais.jqassistant.core.rule.impl.reader.XmlRuleParserPlugin 17 | com.buschmais.jqassistant.core.rule.impl.reader.YamlRuleParserPlugin 18 | 19 | 20 | com.buschmais.jqassistant.core.analysis.impl.CypherRuleInterpreterPlugin 21 | com.buschmais.jqassistant.core.analysis.impl.ScriptRuleInterpreterPlugin 22 | 23 | 24 | -------------------------------------------------------------------------------- /jqassistant/jqa-core-framework.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | MATCH 13 | (test:Maven:Project{artifactId:"test"}) 14 | SET 15 | test:jQASuppress 16 | SET 17 | test.suppressIds=["jqa-maven-constraints:AvoidDependenciesTojQAssistantTestArtifacts"] 18 | RETURN 19 | test 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /readme.adoc: -------------------------------------------------------------------------------- 1 | = jQAssistant Core Framework 2 | 3 | The jQAssistant Core Framework provides the functionality 4 | of jQAssistant which is used by all depending projects 5 | as the plugins of jQAssistant. 6 | 7 | 8 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/ReportException.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api; 2 | 3 | import com.buschmais.jqassistant.core.rule.api.model.RuleException; 4 | 5 | public class ReportException extends RuleException { 6 | 7 | public ReportException(String message) { 8 | super(message); 9 | } 10 | 11 | public ReportException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/ReportTransformer.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api; 2 | 3 | import javax.xml.transform.Result; 4 | import javax.xml.transform.Source; 5 | 6 | /** 7 | * Defines functionality to transform an XML report to HTML representation. 8 | */ 9 | public interface ReportTransformer { 10 | 11 | /** 12 | * Transforms the source to an HTML fragment which may be embedded into 13 | * other documents. 14 | * 15 | * @param source 16 | * The source. 17 | * @param target 18 | * The target. 19 | * @throws ReportTransformerException 20 | * If transformation fails. 21 | */ 22 | void toEmbedded(Source source, Result target) throws ReportTransformerException; 23 | 24 | /** 25 | * Transforms the source to a standalone HTML document. 26 | * 27 | * @param source 28 | * The source. 29 | * @param target 30 | * The target. 31 | * @throws ReportTransformerException 32 | * If transformation fails. 33 | */ 34 | void toStandalone(Source source, Result target) throws ReportTransformerException; 35 | } 36 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/ReportTransformerException.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api; 2 | 3 | /** 4 | * The exception will be thrown by report transformer operations to indicate 5 | * problems. 6 | */ 7 | public class ReportTransformerException extends Exception { 8 | 9 | private static final long serialVersionUID = 1L; 10 | 11 | public ReportTransformerException(String message) { 12 | super(message); 13 | } 14 | 15 | public ReportTransformerException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/SourceProvider.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api; 2 | 3 | import java.util.Optional; 4 | 5 | import com.buschmais.jqassistant.core.report.api.model.source.FileLocation; 6 | import com.buschmais.xo.api.CompositeObject; 7 | 8 | import static java.util.Optional.empty; 9 | 10 | /** 11 | * Defines a provider which allows looking up source code information from 12 | * {@link CompositeObject}s. 13 | */ 14 | public interface SourceProvider { 15 | 16 | /** 17 | * Return the name representing the language element. 18 | * 19 | * @return The name. 20 | */ 21 | String getName(D descriptor); 22 | 23 | /** 24 | * Return the {@link FileLocation} for a {@link CompositeObject}. 25 | * 26 | * @param descriptor 27 | * The {@link CompositeObject} 28 | * @return The {@link FileLocation} or null if it cannot be 29 | * determined. 30 | */ 31 | default Optional getSourceLocation(D descriptor) { 32 | return empty(); 33 | } 34 | 35 | ; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/configuration/Report.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.configuration; 2 | 3 | import java.util.Map; 4 | import java.util.Optional; 5 | 6 | import com.buschmais.jqassistant.core.shared.annotation.Description; 7 | 8 | import io.smallrye.config.ConfigMapping; 9 | import io.smallrye.config.WithDefault; 10 | 11 | @ConfigMapping(prefix = "jqassistant.analyze.report") 12 | public interface Report { 13 | 14 | String DIRECTORY = "directory"; 15 | 16 | @Description("The directory for generated reports.") 17 | Optional directory(); 18 | 19 | String PROPERTIES = "properties"; 20 | 21 | @Description("The properties to configure report plugins. The supported properties are plugin specific.") 22 | Map properties(); 23 | 24 | String WARN_ON_SEVERITY = "warn-on-severity"; 25 | 26 | @Description("Determines the severity level to report warnings for rules with equal or higher severities.") 27 | @WithDefault("MINOR") 28 | String warnOnSeverity(); 29 | 30 | String FAIL_ON_SEVERITY = "fail-on-severity"; 31 | 32 | @Description("Determines the severity level to report failures for rules with equal or higher severities.") 33 | @WithDefault("MAJOR") 34 | String failOnSeverity(); 35 | 36 | String CONTINUE_ON_FAILURE = "continue-on-failure"; 37 | 38 | @Description("Determines if jQAssistant shall continue the build if failures have been detected.") 39 | @WithDefault("false") 40 | boolean continueOnFailure(); 41 | 42 | String CREATE_ARCHIVE = "create-archive"; 43 | 44 | @Description("Create an archive containing all generated reports.") 45 | @WithDefault("false") 46 | boolean createArchive(); 47 | } 48 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/graph/model/Identifiable.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.graph.model; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | @Getter 9 | @Setter 10 | @EqualsAndHashCode(of = "id") 11 | @ToString 12 | public abstract class Identifiable { 13 | 14 | private long id; 15 | 16 | private String label; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/graph/model/Node.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.graph.model; 2 | 3 | import java.util.Set; 4 | import java.util.TreeSet; 5 | 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import lombok.ToString; 9 | 10 | @Getter 11 | @Setter 12 | @ToString(callSuper = true) 13 | public class Node extends PropertyContainer { 14 | 15 | private Set labels = new TreeSet<>(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/graph/model/PropertyContainer.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.graph.model; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import lombok.ToString; 9 | 10 | @Getter 11 | @Setter 12 | @ToString(callSuper = true) 13 | public abstract class PropertyContainer extends Identifiable { 14 | 15 | private Map properties = new HashMap<>(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/graph/model/Relationship.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.graph.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | @Getter 8 | @Setter 9 | @ToString(callSuper = true) 10 | public class Relationship extends PropertyContainer { 11 | 12 | private String type; 13 | 14 | private Node startNode; 15 | 16 | private Node endNode; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/graph/model/SubGraph.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.graph.model; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import lombok.ToString; 9 | 10 | @Getter 11 | @Setter 12 | @ToString(callSuper = true) 13 | public class SubGraph extends Identifiable { 14 | 15 | private Node parent = null; 16 | 17 | private Map nodes = new HashMap<>(); 18 | 19 | private Map relationships = new HashMap<>(); 20 | 21 | private Map subGraphs = new HashMap<>(); 22 | } 23 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/model/Column.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.model; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | @Getter 8 | @Builder 9 | @ToString 10 | public class Column { 11 | 12 | private V value; 13 | 14 | private String label; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/model/Language.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.model; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | import com.buschmais.xo.api.CompositeObject; 9 | 10 | /** 11 | * A meta-annotation to mark {@link CompositeObject}s as language elements. 12 | */ 13 | @Target(ElementType.ANNOTATION_TYPE) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface Language { 16 | } 17 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/model/LanguageElement.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.model; 2 | 3 | import com.buschmais.jqassistant.core.report.api.SourceProvider; 4 | import com.buschmais.xo.api.CompositeObject; 5 | 6 | /** 7 | * Defines the interface for language elements to be returned by 8 | * {@link Language} annotations. 9 | */ 10 | public interface LanguageElement { 11 | 12 | String getLanguage(); 13 | 14 | /** 15 | * The name of the language element. 16 | * 17 | * @return The name of the language element. 18 | */ 19 | String name(); 20 | 21 | SourceProvider getSourceProvider(); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/model/Result.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.model; 2 | 3 | import java.util.List; 4 | 5 | import com.buschmais.jqassistant.core.rule.api.model.ExecutableRule; 6 | import com.buschmais.jqassistant.core.rule.api.model.Rule; 7 | import com.buschmais.jqassistant.core.rule.api.model.Severity; 8 | 9 | import lombok.*; 10 | 11 | /** 12 | * The result of an executed {@link Rule}. 13 | * 14 | * @param 15 | * The rule type. 16 | * 17 | * @see Rule 18 | */ 19 | @Builder 20 | @RequiredArgsConstructor 21 | @Getter 22 | @ToString 23 | public class Result { 24 | 25 | /** 26 | * The defined status for the result of a rule. 27 | */ 28 | public enum Status { 29 | SUCCESS, FAILURE, WARNING, SKIPPED; 30 | } 31 | 32 | /** 33 | * The executed rule. 34 | */ 35 | private final T rule; 36 | 37 | private final Status status; 38 | 39 | /** 40 | * The effective severity. 41 | */ 42 | private final Severity severity; 43 | 44 | /** 45 | * The list of returned columns. 46 | */ 47 | private final List columnNames; 48 | 49 | /** 50 | * The returned rows. 51 | */ 52 | @Singular 53 | private final List rows; 54 | 55 | public boolean isEmpty() { 56 | return rows.isEmpty(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/model/Row.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.model; 2 | 3 | import java.util.Map; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | import lombok.NonNull; 8 | import lombok.RequiredArgsConstructor; 9 | 10 | @Builder 11 | @Getter 12 | @RequiredArgsConstructor 13 | public class Row { 14 | 15 | @NonNull 16 | private final String key; 17 | 18 | @NonNull 19 | private final Map> columns; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/model/Suppress.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.model; 2 | 3 | import com.buschmais.xo.api.annotation.Abstract; 4 | import com.buschmais.xo.neo4j.api.annotation.Label; 5 | 6 | @Abstract 7 | @Label("jQASuppress") 8 | public interface Suppress { 9 | 10 | String[] getSuppressIds(); 11 | 12 | void setSuppressIds(String[] suppressIds); 13 | 14 | String getSuppressColumn(); 15 | void setSuppressColumn(String suppressColumn); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/model/source/AbstractLocation.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.model.source; 2 | 3 | import java.util.Optional; 4 | 5 | import lombok.Builder.Default; 6 | import lombok.Getter; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.ToString; 9 | import lombok.experimental.SuperBuilder; 10 | 11 | import static lombok.AccessLevel.PROTECTED; 12 | 13 | /** 14 | * Abstract base class for source locations. 15 | * 16 | * @param

17 | * The parent type. 18 | */ 19 | @Getter 20 | @SuperBuilder 21 | @RequiredArgsConstructor(access = PROTECTED) 22 | @ToString 23 | public abstract class AbstractLocation

{ 24 | 25 | /** 26 | * The optional parent containing the file. 27 | */ 28 | @Default 29 | private final Optional

parent = Optional.empty(); 30 | 31 | /** 32 | * The file name. If a {@link #parent} is available, then this file name is 33 | * relative to it. 34 | */ 35 | private final String fileName; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/model/source/ArtifactLocation.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.model.source; 2 | 3 | import java.util.Optional; 4 | 5 | import lombok.Getter; 6 | import lombok.ToString; 7 | import lombok.experimental.SuperBuilder; 8 | 9 | /** 10 | * Represents an artifact location with optional coordinates. 11 | */ 12 | @Getter 13 | @SuperBuilder 14 | @ToString 15 | public class ArtifactLocation extends AbstractLocation { 16 | 17 | private Optional group; 18 | 19 | private Optional name; 20 | 21 | private Optional version; 22 | 23 | private Optional classifier; 24 | 25 | private Optional type; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /report/src/main/java/com/buschmais/jqassistant/core/report/api/model/source/FileLocation.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api.model.source; 2 | 3 | import java.util.Optional; 4 | 5 | import lombok.Builder.Default; 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | import lombok.experimental.SuperBuilder; 9 | 10 | import static java.util.Optional.empty; 11 | 12 | /** 13 | * Represents a source file location including an optional line number. 14 | */ 15 | @Getter 16 | @SuperBuilder 17 | @ToString 18 | public class FileLocation extends AbstractLocation { 19 | 20 | @Default 21 | private final Optional startLine = empty(); 22 | 23 | @Default 24 | private final Optional endLine = empty(); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /report/src/main/resources/META-INF/jqassistant-plugin.xml: -------------------------------------------------------------------------------- 1 | 7 | Core Report 8 | 9 | com.buschmais.jqassistant.core.analysis.api.model.ConceptDescriptor 10 | com.buschmais.jqassistant.core.analysis.api.model.ConstraintDescriptor 11 | com.buschmais.jqassistant.core.analysis.api.model.GroupDescriptor 12 | com.buschmais.jqassistant.core.analysis.api.model.AnalyzeTaskDescriptor 13 | 14 | 15 | com.buschmais.jqassistant.core.report.impl.XmlReportPlugin 16 | 17 | 18 | -------------------------------------------------------------------------------- /report/src/main/resources/META-INF/xsl/jqassistant-report-embedded.xsl: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /report/src/main/resources/META-INF/xsl/jqassistant-report-standalone.xsl: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 9 | 10 | jQAssistant Report 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /report/src/test/java/com/buschmais/jqassistant/core/report/api/ReportReaderTest.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.api; 2 | 3 | import java.io.File; 4 | import java.net.URL; 5 | import java.util.List; 6 | 7 | import org.jqassistant.schema.report.v2.ConceptType; 8 | import org.jqassistant.schema.report.v2.GroupType; 9 | import org.jqassistant.schema.report.v2.JqassistantReport; 10 | import org.jqassistant.schema.report.v2.ReferencableRuleType; 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | 15 | class ReportReaderTest { 16 | 17 | private final ReportReader reportReader = new ReportReader(); 18 | 19 | @Test 20 | void read() { 21 | URL reportUrl = ReportReaderTest.class.getResource("/jqassistant-report-with-reports.xml"); 22 | File reportFile = new File(reportUrl.getFile()); 23 | 24 | JqassistantReport jqassistantReport = reportReader.read(reportFile); 25 | 26 | assertThat(jqassistantReport).isNotNull(); 27 | List groupOrConceptOrConstraint = jqassistantReport.getGroupOrConceptOrConstraint(); 28 | assertThat(groupOrConceptOrConstraint).hasSize(1); 29 | ReferencableRuleType referencableRuleType = groupOrConceptOrConstraint.get(0); 30 | assertThat(referencableRuleType).isInstanceOf(GroupType.class); 31 | GroupType groupType = (GroupType) referencableRuleType; 32 | assertThat(groupType.getId()).isEqualTo("default"); 33 | List groupOrConceptOrConstraint1 = groupType.getGroupOrConceptOrConstraint(); 34 | assertThat(groupOrConceptOrConstraint1).hasSize(1); 35 | ReferencableRuleType referencableRuleType1 = groupOrConceptOrConstraint1.get(0); 36 | assertThat(referencableRuleType1).isInstanceOf(ConceptType.class); 37 | ConceptType conceptType = (ConceptType) referencableRuleType1; 38 | assertThat(conceptType.getId()).isEqualTo("concept-with-reports"); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /report/src/test/java/com/buschmais/jqassistant/core/report/model/DerivedTestDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.model; 2 | 3 | public interface DerivedTestDescriptor extends TestDescriptorWithLanguageElement { 4 | } 5 | -------------------------------------------------------------------------------- /report/src/test/java/com/buschmais/jqassistant/core/report/model/DerivedTestDescriptorWithLanguageElement.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.model; 2 | 3 | import static com.buschmais.jqassistant.core.report.model.TestLanguage.TestLanguageElement.DerivedTestElement; 4 | 5 | @TestLanguage(DerivedTestElement) 6 | public interface DerivedTestDescriptorWithLanguageElement extends TestDescriptorWithLanguageElement { 7 | } 8 | -------------------------------------------------------------------------------- /report/src/test/java/com/buschmais/jqassistant/core/report/model/TestDescriptorWithLanguageElement.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.report.model; 2 | 3 | import com.buschmais.xo.api.CompositeObject; 4 | 5 | import static com.buschmais.jqassistant.core.report.model.TestLanguage.TestLanguageElement.TestElement; 6 | 7 | /** 8 | * A test descriptor. 9 | */ 10 | @TestLanguage(TestElement) 11 | public interface TestDescriptorWithLanguageElement extends CompositeObject { 12 | 13 | String getValue(); 14 | } 15 | -------------------------------------------------------------------------------- /report/src/test/resources/jqassistant-report-with-reports.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Column 1 9 | 10 | 11 | 12 | 13 | Value 1 14 | 15 | 16 | 17 | 18 | 19 | file:image1.png 20 | file:table.csv 21 | file:image2.png 22 | 23 | success 24 | info 25 | 140 26 | 27 | 140 28 | 29 | 30 | -------------------------------------------------------------------------------- /report/src/test/resources/jqassistant-report-with-severities.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Minor Success 5 | success 6 | major 7 | 10 8 | 9 | 10 | Major Warning 11 | warning 12 | major 13 | 10 14 | 15 | 16 | Critical Failure 17 | failure 18 | critical 19 | 10 20 | 21 | 22 | Minor Success 23 | success 24 | major 25 | 10 26 | 27 | 28 | Major Warning 29 | warning 30 | major 31 | 10 32 | 33 | 34 | Critical Failure 35 | failure 36 | critical 37 | 10 38 | 39 | 40 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/configuration/Rule.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.configuration; 2 | 3 | import java.util.Optional; 4 | 5 | import com.buschmais.jqassistant.core.rule.api.model.Severity; 6 | import com.buschmais.jqassistant.core.shared.annotation.Description; 7 | 8 | import io.smallrye.config.ConfigMapping; 9 | import io.smallrye.config.WithDefault; 10 | 11 | @ConfigMapping(prefix = "jqassistant.analyze.rule") 12 | public interface Rule { 13 | 14 | String DIRECTORY = "directory"; 15 | 16 | @Description("The name of the directory containing project rules.") 17 | Optional directory(); 18 | 19 | String DEFAULT_CONCEPT_SEVERITY = "default-concept-severity"; 20 | 21 | @Description("The default severity of concepts without an explicit severity.") 22 | Optional defaultConceptSeverity(); 23 | 24 | String DEFAULT_CONSTRAINT_SEVERITY = "default-constraint-severity"; 25 | 26 | @Description("The default severity of constraints without an explicit severity.") 27 | Optional defaultConstraintSeverity(); 28 | 29 | String DEFAULT_GROUP_SEVERITY = "default-group-severity"; 30 | 31 | @Description("The default severity of groups without an explicit severity.") 32 | Optional defaultGroupSeverity(); 33 | 34 | String REQUIRED_CONCEPTS_ARE_OPTIONAL_BY_DEFAULT = "required-concepts-are-optional-by-default"; 35 | 36 | @Description("Specifies if a rule is executed even if one of the required concepts cannot be applied.") 37 | @WithDefault("true") 38 | boolean requiredConceptsAreOptionalByDefault(); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/executor/AbstractRuleVisitor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.executor; 2 | 3 | import java.util.Map; 4 | 5 | import com.buschmais.jqassistant.core.rule.api.model.*; 6 | 7 | /** 8 | * Abstract base implementation of a {@link RuleVisitor}. 9 | */ 10 | public abstract class AbstractRuleVisitor implements RuleVisitor { 11 | 12 | @Override 13 | public boolean isSuccess(R result) { 14 | return true; 15 | } 16 | 17 | @Override 18 | public void beforeRules() throws RuleException { 19 | } 20 | 21 | @Override 22 | public void afterRules() throws RuleException { 23 | } 24 | 25 | @Override 26 | public R visitConcept(Concept concept, Severity effectiveSeverity, Map, R> requiredConceptResults, 27 | Map providingConceptResults) throws RuleException { 28 | throw new RuleException("Cannot visit concept" + concept); 29 | } 30 | 31 | @Override 32 | public void skipConcept(Concept concept, Severity effectiveSeverity, Map, R> requiredConceptResults) throws RuleException { 33 | } 34 | 35 | @Override 36 | public R visitConstraint(Constraint constraint, Severity effectiveSeverity, Map, R> requiredConceptResults) 37 | throws RuleException { 38 | throw new RuleException("Cannot visit constraint" + constraint); 39 | } 40 | 41 | @Override 42 | public void skipConstraint(Constraint constraint, Severity effectiveSeverity, Map, R> requiredConceptResults) 43 | throws RuleException { 44 | } 45 | 46 | @Override 47 | public void beforeGroup(Group group, Severity effectiveSeverity) throws RuleException { 48 | } 49 | 50 | @Override 51 | public void afterGroup(Group group) throws RuleException { 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/executor/CollectRulesVisitor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.executor; 2 | 3 | import java.util.*; 4 | 5 | import com.buschmais.jqassistant.core.rule.api.model.*; 6 | 7 | public class CollectRulesVisitor extends AbstractRuleVisitor { 8 | 9 | private static final Comparator RULE_COMPARATOR = Comparator.comparing(Rule::getId); 10 | 11 | private Map concepts = new TreeMap<>(RULE_COMPARATOR); 12 | private Map constraints = new TreeMap<>(RULE_COMPARATOR); 13 | private Set groups = new TreeSet<>(RULE_COMPARATOR); 14 | 15 | private Set missingConcepts = new TreeSet<>(); 16 | private Set missingConstraints = new TreeSet<>(); 17 | private Set missingGroups = new TreeSet<>(); 18 | 19 | @Override 20 | public Boolean visitConcept(Concept concept, Severity effectiveSeverity, Map, Boolean> requiredConceptResults, 21 | Map providingConceptResults) { 22 | concepts.put(concept, effectiveSeverity); 23 | return true; 24 | } 25 | 26 | @Override 27 | public Boolean visitConstraint(Constraint constraint, Severity effectiveSeverity, Map, Boolean> requiredConceptResults) { 28 | constraints.put(constraint, effectiveSeverity); 29 | return true; 30 | } 31 | 32 | @Override 33 | public void beforeGroup(Group group, Severity effectiveSeverity) { 34 | groups.add(group); 35 | } 36 | 37 | public Map getConcepts() { 38 | return concepts; 39 | } 40 | 41 | public Map getConstraints() { 42 | return constraints; 43 | } 44 | 45 | public Set getGroups() { 46 | return groups; 47 | } 48 | 49 | public Set getMissingConcepts() { 50 | return missingConcepts; 51 | } 52 | 53 | public Set getMissingConstraints() { 54 | return missingConstraints; 55 | } 56 | 57 | public Set getMissingGroups() { 58 | return missingGroups; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/AbstractRuleBucketSpec.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | public interface AbstractRuleBucketSpec { 4 | 5 | void callingNewNoRuleExceptionThrowsCorrectException() throws Exception; 6 | 7 | void callingNewDuplicateRuleExceptionThrowsCorrectException() throws Exception; 8 | } 9 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/AbstractSeverityRule.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | /** 4 | * Abstract base class for rules with a severity. 5 | */ 6 | public abstract class AbstractSeverityRule extends AbstractRule implements SeverityRule { 7 | /** 8 | * The severity of the rule. 9 | */ 10 | private Severity severity; 11 | 12 | @Override 13 | public Severity getSeverity() { 14 | return severity; 15 | } 16 | 17 | protected abstract static class Builder, R extends AbstractSeverityRule> extends AbstractRule.Builder { 18 | 19 | protected Builder(R rule) { 20 | super(rule); 21 | } 22 | 23 | public B severity(Severity severity) { 24 | AbstractSeverityRule r = build(); 25 | r.severity = severity; 26 | return getThis(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/Concept.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | import java.util.LinkedHashSet; 4 | import java.util.Set; 5 | 6 | import lombok.Getter; 7 | 8 | import static com.buschmais.jqassistant.core.rule.api.model.Severity.MINOR; 9 | 10 | /** 11 | * Defines a concept which can be applied. 12 | * 13 | * Used to add information to the database. 14 | */ 15 | @Getter 16 | public class Concept extends AbstractExecutableRule { 17 | 18 | public static Severity DEFAULT_SEVERITY = MINOR; 19 | 20 | private final Set providedConcepts = new LinkedHashSet<>(); 21 | 22 | public static class ConceptBuilder extends AbstractExecutableRule.Builder { 23 | private ConceptBuilder(Concept rule) { 24 | super(rule); 25 | } 26 | 27 | @Override 28 | protected ConceptBuilder getThis() { 29 | return this; 30 | } 31 | 32 | public ConceptBuilder providedConcepts(Set providedConcepts) { 33 | Concept r = build(); 34 | r.providedConcepts.addAll(providedConcepts); 35 | return this; 36 | } 37 | } 38 | 39 | public static ConceptBuilder builder() { 40 | return new ConceptBuilder(new Concept()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/ConceptBucket.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | /** 4 | * Container for a set of unique concepts. 5 | *

6 | * A collection of unique rules identified by their id. That means that this 7 | * bucket cannot contain a concept with the same id twice. 8 | */ 9 | public class ConceptBucket extends AbstractRuleBucket { 10 | 11 | @Override 12 | protected String getRuleTypeName() { 13 | return "concept"; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/Constraint.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | import static com.buschmais.jqassistant.core.rule.api.model.Severity.MAJOR; 4 | 5 | /** 6 | * Defines a constraint to be validated. 7 | */ 8 | public class Constraint extends AbstractExecutableRule { 9 | 10 | public static Severity DEFAULT_SEVERITY = MAJOR; 11 | 12 | public static class ConstraintBuilder extends AbstractExecutableRule.Builder { 13 | public ConstraintBuilder(Constraint rule) { 14 | super(rule); 15 | } 16 | 17 | @Override 18 | protected ConstraintBuilder getThis() { 19 | return this; 20 | } 21 | } 22 | 23 | public static ConstraintBuilder builder() { 24 | return new ConstraintBuilder(new Constraint()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/ConstraintBucket.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | /** 4 | * Container for a set of unique constraints. 5 | * 6 | * A collection of unique constraint rules identified by their id. That means that this bucket 7 | * cannot contain a constraint with the same id twice. 8 | */ 9 | public class ConstraintBucket extends AbstractRuleBucket { 10 | 11 | @Override 12 | protected String getRuleTypeName() { 13 | return "constraint"; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/CypherExecutable.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | import com.buschmais.jqassistant.core.rule.impl.SourceExecutable; 4 | 5 | /** 6 | * Defines a cypher statement which may be executed. 7 | */ 8 | public class CypherExecutable extends SourceExecutable { 9 | 10 | private static final String LANGUAGE = "cypher"; 11 | 12 | public CypherExecutable(String statement) { 13 | super(LANGUAGE, statement, String.class); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/Executable.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | /** 4 | * Defines an executable, e.g. a cypher query, script or template. 5 | * 6 | * @param 7 | * The rule source type, e.g. an Asciidoc block or XML type 8 | */ 9 | public interface Executable { 10 | 11 | /** 12 | * Return the language. 13 | * 14 | * @return The language. 15 | */ 16 | String getLanguage(); 17 | 18 | /** 19 | * Return the executable source. 20 | * 21 | * @return The source. 22 | */ 23 | S getSource(); 24 | 25 | /** 26 | * Return the source type. 27 | * 28 | * @return The source type. 29 | */ 30 | Class getType(); 31 | } 32 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/ExecutableRule.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * Defines the interface for rules which can be executed on the database. 7 | */ 8 | public interface ExecutableRule extends Rule { 9 | 10 | /* 11 | * Return the severity. 12 | * 13 | * @return The severity. 14 | */ 15 | Severity getSeverity(); 16 | 17 | /** 18 | * Return the ids of required rules. 19 | * 20 | * @return The ids of required rules. 21 | */ 22 | Map getRequiresConcepts(); 23 | 24 | /** 25 | * Return the executable. 26 | * 27 | * @return The executable. 28 | */ 29 | E getExecutable(); 30 | 31 | /** 32 | * Return the map of required parameters. 33 | * 34 | * @return The parameters. 35 | */ 36 | Map getParameters(); 37 | 38 | /** 39 | * Return the result verification for this rule. 40 | * 41 | * @return The result verification. 42 | */ 43 | Verification getVerification(); 44 | 45 | /** 46 | * Return the report settings for this rule. 47 | * 48 | * @return The report settings. 49 | */ 50 | Report getReport(); 51 | } 52 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/GroupsBucket.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | public class GroupsBucket extends AbstractRuleBucket { 4 | 5 | @Override 6 | protected String getRuleTypeName() { 7 | return "group"; 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/Report.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | import java.util.*; 4 | 5 | import lombok.*; 6 | 7 | /** 8 | * Report definition for a rule. 9 | */ 10 | @Getter 11 | @Builder 12 | @AllArgsConstructor(access = AccessLevel.PRIVATE) 13 | public class Report { 14 | 15 | private Set selectedTypes; 16 | 17 | private String primaryColumn; 18 | 19 | @Builder.Default 20 | private Properties properties = new Properties(); 21 | 22 | public static Set selectTypes(String reportTypes) { 23 | Set selectedTypes = new TreeSet<>(); 24 | Scanner scanner = new Scanner(reportTypes).useDelimiter(","); 25 | while (scanner.hasNext()) { 26 | String reportType = scanner.next(); 27 | selectedTypes.add(reportType.trim()); 28 | } 29 | return selectedTypes; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/Rule.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | import com.buschmais.jqassistant.core.rule.api.source.RuleSource; 4 | 5 | /** 6 | * Interface for all rules. 7 | */ 8 | public interface Rule { 9 | 10 | /** 11 | * Return the id of the rule. 12 | * 13 | * @return The id of the rule. 14 | */ 15 | String getId(); 16 | 17 | /** 18 | * Return the description of the rule. 19 | * 20 | * @return The description of the rule. 21 | */ 22 | String getDescription(); 23 | 24 | /** 25 | * Return the source of the rule. 26 | * 27 | * @return The source of the rule. 28 | */ 29 | RuleSource getSource(); 30 | 31 | /** 32 | * Return the (optional) deprecation message. 33 | * 34 | * @return The deprecation message. 35 | */ 36 | String getDeprecation(); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/RuleException.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | public class RuleException extends Exception { 4 | 5 | public RuleException(String message) { 6 | super(message); 7 | } 8 | 9 | public RuleException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/RuleSelection.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | import java.util.LinkedHashSet; 4 | import java.util.List; 5 | import java.util.Optional; 6 | import java.util.Set; 7 | 8 | import lombok.*; 9 | 10 | import static lombok.AccessLevel.PRIVATE; 11 | 12 | /** 13 | * Represents a selection of rules. 14 | */ 15 | @Getter 16 | @Builder 17 | @ToString 18 | @AllArgsConstructor(access = PRIVATE) 19 | public class RuleSelection { 20 | 21 | private static final String GROUP_DEFAULT = "default"; 22 | 23 | @Singular 24 | private Set conceptIds; 25 | 26 | @Singular 27 | private Set constraintIds; 28 | 29 | @Singular 30 | private Set excludeConstraintIds; 31 | 32 | @Singular 33 | private Set groupIds; 34 | 35 | public static RuleSelection select(RuleSet ruleSet, Optional> groupIds, Optional> constraintIds, 36 | Optional> excludeConstraintIds, Optional> conceptIds) { 37 | RuleSelectionBuilder builder = builder(); 38 | if (groupIds.isEmpty() && conceptIds.isEmpty() && constraintIds.isEmpty() && ruleSet.getGroupsBucket() 39 | .getIds() 40 | .contains(GROUP_DEFAULT)) { 41 | builder.groupIds(Set.of(GROUP_DEFAULT)); 42 | } else { 43 | // use LinkedHashSet to keep order of selection 44 | groupIds.ifPresent(groups -> builder.groupIds(new LinkedHashSet<>(groups))); 45 | constraintIds.ifPresent(constraints -> builder.constraintIds(new LinkedHashSet<>(constraints))); 46 | conceptIds.ifPresent(concepts -> builder.conceptIds(new LinkedHashSet<>(concepts))); 47 | } 48 | excludeConstraintIds.ifPresent(builder::excludeConstraintIds); 49 | return builder.build(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/RuleSet.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | import java.util.Map; 4 | import java.util.Set; 5 | 6 | public interface RuleSet { 7 | 8 | ConceptBucket getConceptBucket(); 9 | 10 | Map> getProvidedConcepts(); 11 | 12 | Map> getProvidingConcepts(); 13 | 14 | ConstraintBucket getConstraintBucket(); 15 | 16 | GroupsBucket getGroupsBucket(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/ScriptExecutable.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | import com.buschmais.jqassistant.core.rule.impl.SourceExecutable; 4 | 5 | /** 6 | * Represents an executable script. 7 | */ 8 | public class ScriptExecutable extends SourceExecutable { 9 | 10 | public ScriptExecutable(String language, String source) { 11 | super(language, source, String.class); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/SeverityRule.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | /** 4 | * Represents a rule with a severity. 5 | */ 6 | public interface SeverityRule extends Rule { 7 | 8 | /** 9 | * Return the severity. 10 | * 11 | * @return The severity. 12 | */ 13 | Severity getSeverity(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/model/Verification.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | /** 4 | * Describes the verification of the result of an executable rule. 5 | */ 6 | public interface Verification { 7 | } 8 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/reader/AggregationVerification.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.reader; 2 | 3 | import com.buschmais.jqassistant.core.rule.api.model.Verification; 4 | 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Getter; 8 | import lombok.NoArgsConstructor; 9 | import lombok.Setter; 10 | import lombok.ToString; 11 | 12 | import static lombok.AccessLevel.PRIVATE; 13 | 14 | /** 15 | * Indicates that a result shall be verified by evaluating aggregated values 16 | * from a result column. 17 | */ 18 | @Getter 19 | @Setter 20 | @ToString 21 | @Builder 22 | @NoArgsConstructor(access = PRIVATE) 23 | @AllArgsConstructor(access = PRIVATE) 24 | public class AggregationVerification implements Verification { 25 | 26 | /** 27 | * Specifies the column containing the aggregation value to verify. 28 | */ 29 | private String column; 30 | 31 | private Integer min; 32 | 33 | private Integer max; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/reader/RowCountVerification.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.reader; 2 | 3 | import com.buschmais.jqassistant.core.rule.api.model.Verification; 4 | 5 | import lombok.*; 6 | 7 | import static lombok.AccessLevel.PRIVATE; 8 | 9 | /** 10 | * Indicates that a result shall be verified by the count of returned rows. 11 | */ 12 | @Getter 13 | @Setter 14 | @ToString 15 | @Builder 16 | @NoArgsConstructor(access = PRIVATE) 17 | @AllArgsConstructor(access = PRIVATE) 18 | public class RowCountVerification implements Verification { 19 | 20 | private Integer max; 21 | 22 | private Integer min; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/reader/RuleParserPlugin.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.reader; 2 | 3 | import javax.xml.transform.Source; 4 | 5 | import com.buschmais.jqassistant.core.rule.api.configuration.Rule; 6 | import com.buschmais.jqassistant.core.rule.api.model.RuleException; 7 | import com.buschmais.jqassistant.core.rule.api.model.RuleSetBuilder; 8 | import com.buschmais.jqassistant.core.rule.api.source.RuleSource; 9 | import com.buschmais.jqassistant.core.shared.lifecycle.ConfigurableLifecycleAware; 10 | 11 | /** 12 | * Defines the interface of the rule parser. 13 | */ 14 | public interface RuleParserPlugin extends ConfigurableLifecycleAware { 15 | 16 | /** 17 | * Initialize the parser. 18 | */ 19 | @Override 20 | default void initialize() throws RuleException { 21 | } 22 | 23 | /** 24 | * Configure the parser. 25 | * 26 | * @param rule 27 | * The {@link Rule} configuration to use. 28 | */ 29 | @Override 30 | default void configure(Rule rule) throws RuleException { 31 | } 32 | 33 | @Override 34 | default void destroy() throws RuleException { 35 | } 36 | 37 | /** 38 | * Determine if the reader accepts the {@link RuleSource}. 39 | * 40 | * @param ruleSource 41 | * The {@link RuleSource}. 42 | * @return true if the reader accepts the source. 43 | */ 44 | boolean accepts(RuleSource ruleSource) throws RuleException; 45 | 46 | /** 47 | * Parse the given {@link Source} and adds contained rules using the 48 | * {@link RuleSetBuilder}. 49 | * 50 | * @param ruleSource 51 | * The source to be read. 52 | * @param ruleSetBuilder 53 | * {@link RuleSetBuilder}. 54 | */ 55 | void parse(RuleSource ruleSource, RuleSetBuilder ruleSetBuilder) throws RuleException; 56 | 57 | } 58 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/source/ClasspathRuleSource.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.source; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.net.URL; 7 | import java.util.Optional; 8 | 9 | /** 10 | * A rule source which is provided from a classpath resource. 11 | */ 12 | public class ClasspathRuleSource extends RuleSource { 13 | 14 | /** 15 | * The resource path where to load rule files from. 16 | */ 17 | public static final String RULE_RESOURCE_PATH = "META-INF/jqassistant-rules"; 18 | 19 | private final ClassLoader classLoader; 20 | private final String resource; 21 | private final String relativePath; 22 | 23 | public ClasspathRuleSource(ClassLoader classLoader, String relativePath) { 24 | this.classLoader = classLoader; 25 | this.relativePath = relativePath; 26 | this.resource = RULE_RESOURCE_PATH + "/" + relativePath; 27 | 28 | } 29 | 30 | @Override 31 | public String getId() { 32 | return resource; 33 | } 34 | 35 | @Override 36 | public URL getURL() { 37 | return getClassLoader().getResource(resource); 38 | } 39 | 40 | @Override 41 | public Optional getDirectory() { 42 | return Optional.empty(); 43 | } 44 | 45 | @Override 46 | public String getRelativePath() { 47 | return relativePath; 48 | } 49 | 50 | @Override 51 | public InputStream getInputStream() throws IOException { 52 | ClassLoader currentClassloader = getClassLoader(); 53 | InputStream stream = currentClassloader.getResourceAsStream(resource); 54 | if (stream == null) { 55 | throw new IOException("Cannot load resource from " + resource); 56 | } 57 | return stream; 58 | } 59 | 60 | private ClassLoader getClassLoader() { 61 | return classLoader != null ? classLoader : Thread.currentThread().getContextClassLoader(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/source/RuleSource.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.source; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.net.URL; 7 | import java.util.Optional; 8 | 9 | /** 10 | * Defines a source containing rules. 11 | * 12 | * @author mh 13 | * @since 12.10.14 14 | */ 15 | public abstract class RuleSource { 16 | 17 | /** 18 | * Return a unique identifier of this {@link RuleSource}. 19 | * 20 | * @return The identifier. 21 | */ 22 | public abstract String getId(); 23 | 24 | /** 25 | * Return the {@link URL} of the {@link RuleSource}. 26 | * 27 | * @return The {@link URL}. 28 | * @throws IOException 29 | * If the {@link URL} cannot be determined. 30 | */ 31 | public abstract URL getURL() throws IOException; 32 | 33 | /** 34 | * Return the relative path of the rule source (e.g. relative to the jqassistant 35 | * rule directory or within the classpath). 36 | * 37 | * @return The relative path. 38 | */ 39 | public abstract String getRelativePath(); 40 | 41 | public abstract Optional getDirectory(); 42 | 43 | /** 44 | * Open an {@link InputStream} providing the content of the {@link RuleSource}. 45 | * 46 | * @return The {@link InputStream}. 47 | * @throws IOException 48 | * If the {@link InputStream} cannot be opened. 49 | */ 50 | public abstract InputStream getInputStream() throws IOException; 51 | 52 | @Override 53 | public final boolean equals(Object o) { 54 | if (this == o) { 55 | return true; 56 | } 57 | 58 | if (o == null || getClass() != o.getClass()) { 59 | return false; 60 | } 61 | RuleSource that = (RuleSource) o; 62 | return getId().equals(that.getId()); 63 | } 64 | 65 | @Override 66 | public final int hashCode() { 67 | return getId().hashCode(); 68 | } 69 | 70 | @Override 71 | public final String toString() { 72 | return getId(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/source/UrlRuleSource.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.source; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.net.URL; 7 | import java.util.Optional; 8 | 9 | /** 10 | * A rule source which is provided from an URL. 11 | */ 12 | public class UrlRuleSource extends RuleSource { 13 | 14 | private URL url; 15 | 16 | public UrlRuleSource(URL url) { 17 | this.url = url; 18 | } 19 | 20 | @Override 21 | public String getId() { 22 | return url.toExternalForm(); 23 | } 24 | 25 | @Override 26 | public URL getURL() { 27 | return this.url; 28 | } 29 | 30 | @Override 31 | public Optional getDirectory() { 32 | return Optional.empty(); 33 | } 34 | 35 | @Override 36 | public String getRelativePath() { 37 | return url.getPath(); 38 | } 39 | 40 | @Override 41 | public InputStream getInputStream() throws IOException { 42 | return url.openStream(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/api/writer/RuleSetWriter.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.writer; 2 | 3 | import java.io.Writer; 4 | 5 | import com.buschmais.jqassistant.core.rule.api.model.RuleException; 6 | import com.buschmais.jqassistant.core.rule.api.model.RuleSet; 7 | 8 | /** 9 | * Provides methods to write rule sets to XML files. 10 | */ 11 | public interface RuleSetWriter { 12 | 13 | /** 14 | * Writes the given {@link RuleSet} to an XML file. 15 | * 16 | * @param ruleSet 17 | * The {@link RuleSet} . 18 | * @param writer 19 | * The {@link Writer}. 20 | */ 21 | void write(RuleSet ruleSet, Writer writer) throws RuleException; 22 | } 23 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/asciidoctor.adoc: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | 5 | == Asciidoctor 6 | 7 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/impl/SourceExecutable.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.impl; 2 | 3 | import com.buschmais.jqassistant.core.rule.api.model.Executable; 4 | 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | 9 | /** 10 | * The implementation of 11 | * {@link Executable}. 12 | */ 13 | @Getter 14 | @ToString 15 | @AllArgsConstructor 16 | public class SourceExecutable implements Executable { 17 | 18 | private String language; 19 | 20 | private S source; 21 | 22 | private Class type; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/impl/reader/CDataXMLStreamWriter.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.impl.reader; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | import javax.xml.stream.XMLStreamException; 6 | import javax.xml.stream.XMLStreamWriter; 7 | 8 | /** 9 | * A {@link XMLStreamWriter} which transparently writes CDATA blocks if 10 | * special characters are detected. 11 | * 12 | * @see http://blog.mi-ernst.de/2012/05/04/jaxb-and-cdata-sections[JAXB and CDATA Sections^] 13 | */ 14 | public class CDataXMLStreamWriter extends AbstractStreamWriterDelegate { 15 | 16 | private static final Pattern XML_CHARS = Pattern.compile("[&<>]"); 17 | 18 | public CDataXMLStreamWriter(XMLStreamWriter delegate) { 19 | super(delegate); 20 | } 21 | 22 | @Override 23 | public void writeCharacters(String text) throws XMLStreamException { 24 | boolean useCData = XML_CHARS.matcher(text).find(); 25 | if (useCData) { 26 | super.writeCData(text); 27 | } else { 28 | super.writeCharacters(text); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/impl/reader/RuleParser.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.impl.reader; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | 6 | import com.buschmais.jqassistant.core.rule.api.model.RuleException; 7 | import com.buschmais.jqassistant.core.rule.api.model.RuleSet; 8 | import com.buschmais.jqassistant.core.rule.api.model.RuleSetBuilder; 9 | import com.buschmais.jqassistant.core.rule.api.reader.RuleParserPlugin; 10 | import com.buschmais.jqassistant.core.rule.api.source.RuleSource; 11 | 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | /** 16 | * @author Michael Hunger 17 | */ 18 | public class RuleParser { 19 | private final Logger logger = LoggerFactory.getLogger(RuleParser.class); 20 | 21 | private Collection ruleParserPlugins; 22 | 23 | public RuleParser(Collection ruleParserPlugins) { 24 | this.ruleParserPlugins = ruleParserPlugins; 25 | } 26 | 27 | public RuleSet parse(List sources) throws RuleException { 28 | RuleSetBuilder ruleSetBuilder = RuleSetBuilder.newInstance(); 29 | for (RuleSource source : sources) { 30 | parse(source, ruleSetBuilder); 31 | } 32 | return ruleSetBuilder.getRuleSet(); 33 | } 34 | 35 | private void parse(RuleSource source, RuleSetBuilder ruleSetBuilder) throws RuleException { 36 | for (RuleParserPlugin ruleParserPlugin : ruleParserPlugins) { 37 | if (ruleParserPlugin.accepts(source)) { 38 | logger.debug("Parsing rule source with id '{}' using '{}'.", source.getId(), ruleParserPlugin); 39 | ruleParserPlugin.parse(source, ruleSetBuilder); 40 | return; 41 | } 42 | } 43 | logger.debug("Rule source with id '{}' has not been accepted by any rule parser.", source.getId()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/impl/reader/ValidationResult.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.impl.reader; 2 | 3 | import java.util.Set; 4 | 5 | import com.networknt.schema.ValidationMessage; 6 | 7 | class ValidationResult { 8 | private boolean sourceWasEmpty; 9 | private Set validationMessages; 10 | 11 | public boolean isSourceWasEmpty() { 12 | return sourceWasEmpty; 13 | } 14 | 15 | public void setSourceWasEmpty(boolean sourceWasEmpty) { 16 | this.sourceWasEmpty = sourceWasEmpty; 17 | } 18 | 19 | public Set getValidationMessages() { 20 | return validationMessages; 21 | } 22 | 23 | public void setValidationMessages(Set validationMessages) { 24 | this.validationMessages = validationMessages; 25 | } 26 | 27 | public boolean hasErrors() { 28 | return !validationMessages.isEmpty(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/impl/reader/XmlHelper.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.impl.reader; 2 | 3 | import javax.xml.XMLConstants; 4 | import javax.xml.validation.Schema; 5 | import javax.xml.validation.SchemaFactory; 6 | 7 | import org.xml.sax.SAXException; 8 | 9 | /** 10 | * Provides utility functions for working with XML files. 11 | */ 12 | public class XmlHelper { 13 | 14 | /** 15 | * Return a {@link Schema} instance for the given resource. 16 | * 17 | * @param resource 18 | * The resource. 19 | * @return The {@link Schema} instance. 20 | */ 21 | public static Schema getSchema(String resource) { 22 | Schema schema; 23 | try { 24 | SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 25 | schema = schemaFactory.newSchema(XmlHelper.class.getResource(resource)); 26 | } catch (SAXException e) { 27 | throw new IllegalStateException("Cannot read rules schema.", e); 28 | } 29 | return schema; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/index.adoc: -------------------------------------------------------------------------------- 1 | = Supported Formats for Rule Documents 2 | 3 | jQAssistant allows you to write your own rules, contraints and 4 | concepts, in three different format: XML, YAML, and Asciidoctor. 5 | This allows you to choose the document format which fits at best 6 | to your project and your environment. XML was the first and orginal 7 | document format supported by jQAssistant. Later jQAssistant allowed 8 | you embed rules in Asciidoctor documents, because Asciidoctor 9 | allows you to document your constraints and concepts and the ideas 10 | behind them much better than XML. YAML as document format is the latest 11 | addition to the set of supported formats. People how read and write 12 | a lot of YAML documents during their daily work might prefer it 13 | because of its clear structure. 14 | 15 | // todo Add a xref to the user guide. 2020-04-07, Oliver B. Fischer 16 | The following sections provide a guidance how to embedded jQAssistant rules 17 | in these formats. How to write rules is described in the manual. 18 | 19 | include::./yaml.adoc[] 20 | include::./xml.adoc[] 21 | include::./asciidoctor.adoc[] 22 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/spi/RulePluginRepository.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.spi; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | 6 | import com.buschmais.jqassistant.core.rule.api.configuration.Rule; 7 | import com.buschmais.jqassistant.core.rule.api.model.RuleException; 8 | import com.buschmais.jqassistant.core.rule.api.reader.RuleParserPlugin; 9 | import com.buschmais.jqassistant.core.rule.api.source.RuleSource; 10 | import com.buschmais.jqassistant.core.shared.lifecycle.LifecycleAware; 11 | 12 | /** 13 | * Defines the interface for the scanner plugin repository. 14 | */ 15 | public interface RulePluginRepository extends LifecycleAware { 16 | 17 | @Override 18 | void initialize(); 19 | 20 | @Override 21 | void destroy(); 22 | 23 | /** 24 | * Get a list of sources providing rules. 25 | * 26 | * @return The list of sources providing rules. 27 | */ 28 | List getRuleSources(); 29 | 30 | /** 31 | * Return the {@link RuleParserPlugin}s. 32 | * 33 | * @param rule 34 | * The {@link Rule} configuration. 35 | * @return The {@link RuleParserPlugin}s. 36 | */ 37 | Collection getRuleParserPlugins(Rule rule) throws RuleException; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/xml.adoc: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | 5 | == XML 6 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/yaml-examples.adoc: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | 5 | === Examples 6 | 7 | 8 | // See https://github.com/jQAssistant/jqa-core-framework/issues/54 9 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/yaml-groups.adoc: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | 5 | === Groups 6 | 7 | A group in a YAML rule document is represented as a map of keys. 8 | 9 | .Keys of a map to specify a group in a YAML rule document 10 | [cols="2,1,5",options="header"] 11 | |=== 12 | 13 | | Key 14 | | Cardinality 15 | | Description 16 | 17 | | `id` 18 | | 1 19 | | The unique id for this group. 20 | 21 | | `severity` 22 | | 0..1 23 | | Severity for all included groups, constraints, and concept, overwriting 24 | the specified severity for those. 25 | Must be one of `blocker`, `critical`, `major`, `minor`, or `info`. 26 | 27 | | `includedConcepts` 28 | | 0..1 29 | | Sequence of rule references to concepts to be included in this group. 30 | See xref:yaml-rule-references[] for details 31 | 32 | | `includedConstraints` 33 | | 0..1 34 | | Sequence of rule references to constraints to be included in this group. 35 | See xref:yaml-rule-references[] for details 36 | 37 | | `includedGroups` 38 | | 0..1 39 | | Sequence of references to other groups to be included in this group. 40 | See xref:yaml-rule-references[] for details 41 | |=== 42 | 43 | 44 | [[yaml-rule-references]] 45 | .Keys of a map to specify a rule reference 46 | [cols="2,1,5",options="header"] 47 | |=== 48 | 49 | | Key 50 | | Cardinality 51 | | Description 52 | 53 | | `refId` 54 | | 1 55 | | The id of a rule or group which should be included in the containing group. 56 | 57 | | `severity` 58 | | 0..1 59 | | The severity to be applied to the referenced rule or group, overwriting 60 | the actual specified severity. 61 | 62 | | `optional` 63 | | 0..1 64 | | Specifies if the rule or group is optional or not. Possible values are `true` 65 | and `false`. The default value is `false`. 66 | 67 | |=== 68 | -------------------------------------------------------------------------------- /rule/src/main/java/com/buschmais/jqassistant/core/rule/yaml-schema.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[apdx-json-schema]] 3 | [appendix] 4 | = JSON Schema for rule documents 5 | 6 | .JSON Schema 1.8 for jQAssitant rule documents 7 | [source,json,linenums] 8 | ---- 9 | include::../../../../../META-INF/jsonschema/jqassistant-rule-v1.8.schema.json[] 10 | ---- 11 | 12 | 13 | -------------------------------------------------------------------------------- /rule/src/test/java/com/buschmais/jqassistant/core/rule/api/filter/RuleFilterTest.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.filter; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | import static java.util.Arrays.asList; 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | class RuleFilterTest { 11 | 12 | @Test 13 | void filter() { 14 | List rules = asList("wildcard", "foo", "bar"); 15 | 16 | SortedSet result = RuleFilter.match(rules, "foo, w?ldc*d"); 17 | 18 | assertThat(result).containsExactly("foo", "wildcard"); 19 | } 20 | 21 | @Test 22 | void negation() { 23 | List rules = asList("foo", "bar"); 24 | 25 | SortedSet result = RuleFilter.match(rules, "*, !b*r"); 26 | 27 | assertThat(result).containsExactly("foo"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /rule/src/test/java/com/buschmais/jqassistant/core/rule/api/matcher/RuleSourceMatcher.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.matcher; 2 | 3 | import com.buschmais.jqassistant.core.rule.api.source.RuleSource; 4 | 5 | import org.hamcrest.Description; 6 | import org.hamcrest.Matcher; 7 | import org.hamcrest.TypeSafeMatcher; 8 | 9 | public class RuleSourceMatcher extends TypeSafeMatcher { 10 | 11 | private final String ruleSourceId; 12 | 13 | private RuleSourceMatcher(String id) { 14 | ruleSourceId = id; 15 | } 16 | 17 | @Override 18 | protected boolean matchesSafely(RuleSource ruleSource) { 19 | return ruleSourceId.equals(ruleSource.getId()); 20 | } 21 | 22 | @Override 23 | public void describeTo(Description description) { 24 | description.appendText(ruleSourceId); 25 | } 26 | 27 | @Override 28 | protected void describeMismatchSafely(RuleSource item, Description mismatchDescription) { 29 | mismatchDescription.appendText(item.getId()); 30 | } 31 | 32 | public static Matcher matchesById(String id) { 33 | return new RuleSourceMatcher(id); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /rule/src/test/java/com/buschmais/jqassistant/core/rule/api/model/RuleDependenciesTest.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.model; 2 | 3 | import java.util.Map; 4 | import java.util.Set; 5 | 6 | import com.buschmais.jqassistant.core.rule.api.configuration.Rule; 7 | 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.jupiter.api.extension.ExtendWith; 10 | import org.mockito.Mock; 11 | import org.mockito.junit.jupiter.MockitoExtension; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | 15 | @ExtendWith(MockitoExtension.class) 16 | class RuleDependenciesTest { 17 | 18 | @Mock 19 | private Rule rule; 20 | 21 | @Test 22 | void xml() throws Exception { 23 | verifyRuleset(RuleSetTestHelper.readRuleSet("/rule-dependencies.xml", rule)); 24 | } 25 | 26 | @Test 27 | void yaml() throws Exception { 28 | verifyRuleset(RuleSetTestHelper.readRuleSet("/rule-dependencies.yaml", rule)); 29 | } 30 | 31 | private void verifyRuleset(RuleSet ruleSet) { 32 | assertThat(ruleSet.getProvidedConcepts()).containsExactlyEntriesOf( 33 | Map.of("test:AbstractConcept", Set.of("test:ProvidingConcept1", "test:ProvidingConcept2"))); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /rule/src/test/java/com/buschmais/jqassistant/core/rule/api/source/AbstractRuleSourceTest.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.source; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static java.util.stream.Collectors.toMap; 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | abstract class AbstractRuleSourceTest { 14 | 15 | @Test 16 | void classpathRuleSource() throws IOException { 17 | List ruleSources = getRuleSources(); 18 | 19 | Map sources = ruleSources.stream().collect(toMap(k -> k.getRelativePath(), v -> v)); 20 | assertThat(sources).hasSize(4); 21 | 22 | assertThat(sources.keySet()).containsExactlyInAnyOrder("rules.xml", "index.adoc", "readme.md", "subdirectory/rules.xml"); 23 | 24 | for (RuleSource ruleSource : ruleSources) { 25 | try (InputStream inputStream = ruleSource.getInputStream()) { 26 | assertThat(inputStream).isNotNull(); 27 | } 28 | } 29 | } 30 | 31 | protected abstract List getRuleSources() throws IOException; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /rule/src/test/java/com/buschmais/jqassistant/core/rule/api/source/ClasspathRuleSourceTest.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.source; 2 | 3 | import java.util.List; 4 | import java.util.stream.Stream; 5 | 6 | import static java.util.stream.Collectors.toList; 7 | 8 | class ClasspathRuleSourceTest extends AbstractRuleSourceTest { 9 | 10 | @Override 11 | protected List getRuleSources() { 12 | return Stream.of("rules.xml", "index.adoc", "readme.md", "subdirectory/rules.xml") 13 | .map(relativePath -> new ClasspathRuleSource(ClasspathRuleSourceTest.class.getClassLoader(), relativePath)).collect(toList()); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /rule/src/test/java/com/buschmais/jqassistant/core/rule/api/source/FileRuleSourceTest.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.api.source; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.net.URL; 6 | import java.util.List; 7 | 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | class FileRuleSourceTest extends AbstractRuleSourceTest { 13 | 14 | @Test 15 | protected List getRuleSources() throws IOException { 16 | URL resource = FileRuleSource.class.getClassLoader().getResource("META-INF/jqassistant-rules"); 17 | return FileRuleSource.getRuleSources(new File(resource.getPath())); 18 | } 19 | 20 | @Test 21 | void nonExistingRulesDirectory() throws IOException { 22 | assertThat(FileRuleSource.getRuleSources(new File("non-existing-directory"))).isEmpty(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /rule/src/test/java/com/buschmais/jqassistant/core/rule/impl/reader/JsonSchemaValidatorTest.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.rule.impl.reader; 2 | 3 | import com.buschmais.jqassistant.core.rule.api.model.RuleException; 4 | 5 | import org.junit.jupiter.api.BeforeEach; 6 | import org.junit.jupiter.api.Disabled; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class JsonSchemaValidatorTest { 10 | private JsonSchemaValidator validator; 11 | 12 | @BeforeEach 13 | void setUp() throws RuleException { 14 | validator = new JsonSchemaValidator(); 15 | } 16 | 17 | @Disabled 18 | @Test 19 | void thereIsNoFuckingTest() { 20 | throw new RuntimeException("Add some fucking tests!"); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /rule/src/test/resources/META-INF/jqassistant-rules/index.adoc: -------------------------------------------------------------------------------- 1 | = Test Sources 2 | -------------------------------------------------------------------------------- /rule/src/test/resources/META-INF/jqassistant-rules/readme.md: -------------------------------------------------------------------------------- 1 | # Test Source 2 | -------------------------------------------------------------------------------- /rule/src/test/resources/META-INF/jqassistant-rules/rules.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /rule/src/test/resources/META-INF/jqassistant-rules/subdirectory/rules.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /rule/src/test/resources/javascript-rules.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | A test concept based on JavaScript. 7 | 10 | 11 | 12 | 13 | A test constraint based on JavaScript. 14 | 17 | 18 | 19 | 20 | A test concept based on JavaScript. 21 | 22 | 23 | 24 | 25 | 26 | 27 | A test constraint based on JavaScript. 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /rule/src/test/resources/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test Concept. 5 | 15 | 16 | value1 17 | value2 18 | 19 | 20 | 21 | 22 | Test Constraint. 23 | 33 | 34 | value1 35 | value2 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /rule/src/test/resources/resultVerification.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A test concept. 5 | (testMethod:Test:Method) 8 | return 9 | testType as TestType, count(testMethod) as TestMethods 10 | ]]> 11 | 12 | 13 | 14 | A test concept. 15 | (testMethod:Test:Method) 18 | return 19 | testType as TestType, count(testMethod) as TestMethods 20 | ]]> 21 | 22 | 23 | 24 | 25 | 26 | 27 | A test concept. 28 | (testMethod:Test:Method) 31 | return 32 | testType as TestType, count(testMethod) as TestMethods 33 | ]]> 34 | 35 | 36 | 37 | 38 | 39 | 40 | A test concept. 41 | (testMethod:Test:Method) 44 | return 45 | testType as TestType, count(testMethod) as TestMethods 46 | ]]> 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /rule/src/test/resources/rule-dependencies.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Test constraint 21 | 27 | 28 | 29 | 30 | 31 | Test concept 32 | 38 | 39 | 40 | 41 | Abstract test concept 42 | 48 | 49 | 50 | 51 | 52 | Providing test concept 1 53 | 59 | 60 | 61 | 62 | Providing test concept 2 63 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /rule/src/test/resources/rule-dependencies.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: test 4 | includedGroups: 5 | - refId: test1 6 | - refId: test2 7 | - id: test1 8 | includedConstraints: 9 | - refId: test:Constraint 10 | - id: test2 11 | includedConcepts: 12 | - refId: test:ProvidingConcept2 13 | providesConcepts: 14 | - refId: test:AbstractConcept 15 | 16 | constraints: 17 | - id: test:Constraint 18 | description: Test Constraint 19 | requiresConcepts: 20 | - refId: test:Concept 21 | source: | 22 | match 23 | (n) 24 | return 25 | n 26 | 27 | concepts: 28 | - id: test:Concept 29 | description: Test Concept 30 | requiresConcepts: 31 | - refId: test:AbstractConcept 32 | source: | 33 | match 34 | (n) 35 | return 36 | n 37 | 38 | - id: test:AbstractConcept 39 | description: Abstract Test Concept 40 | source: | 41 | match 42 | (n) 43 | return 44 | n 45 | 46 | - id: test:ProvidingConcept1 47 | description: Providing Test Concept 1 48 | providesConcepts: 49 | - refId: test:AbstractConcept 50 | source: | 51 | match 52 | (n) 53 | return 54 | n 55 | 56 | - id: test:ProvidingConcept2 57 | description: Providing Test Concept 2 58 | source: | 59 | match 60 | (n) 61 | return 62 | n 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /rule/src/test/resources/rules-1.8.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | "Test 7 | MATCH (n) RETURN n 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /rule/src/test/resources/severity.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test Concept. 5 | 15 | 16 | 17 | 18 | Test Constraint. 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /rule/src/test/resources/test-concepts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Labels types deriving from java.lang.Throwable as "Throwable". 5 | (t:Type) 8 | where 9 | t.fqn = 'java.lang.Throwable' 10 | SET 11 | throwable:Throwable 12 | return 13 | count(throwable) AS Throwables 14 | ]]> 15 | 16 | 17 | 18 | 19 | 20 | 21 | Constructors of java.util.Date must not be used. 22 | (forbiddenMethod:Method), 25 | (type:Type)-[:DECLARES]->(method:Method)-[:INVOKES]->(forbiddenMethod) 26 | where 27 | dateType.fqn = 'java.util.Date' 28 | and forbiddenMethod:Constructor 29 | return 30 | method as Method 31 | ]]> 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-provides-concepts.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: test:ProvidingConcept 4 | description: Test Concept1. 5 | providesConcepts: 6 | - refId: test:Concept1 7 | - refId: test:Concept2 8 | source: | 9 | match 10 | (n) 11 | return 12 | n 13 | 14 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-rule-language-explicitly-set-to-js.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: > 5 | Returns a result containing the number of declared methods for each class. 6 | language: JavaScript 7 | source: | 8 | // Define the columns returned by the constraint 9 | var columnNames = java.util.Arrays.asList("Type", "MethodsOfType"); 10 | // Define the list of rows returned by the constraint 11 | var rows = new java.util.ArrayList(); 12 | // Execute a query using the store 13 | var typeIterator = store.executeQuery("match (t:Type:Class) return t").iterator(); 14 | while(typeIterator.hasNext()) { 15 | // Get the next row from the query result 16 | var typeRow = typeIterator.next(); 17 | // Get the column "t" from the row, it represents a type 18 | // descriptor as defined by the Java plugin 19 | var type = typeRow.get("t", com.buschmais.jqassistant.plugin.java.api.model.TypeDescriptor.class); 20 | // Get the declared methods of the type and count them 21 | var methodIterator = type.getDeclaredMethods().iterator(); 22 | var methodsOfType = 0; 23 | while( methodIterator.hasNext()) { 24 | methodIterator.next(); 25 | methodsOfType++; 26 | } 27 | // Define the row for the result and put the value for each defined column 28 | var resultRow = new java.util.HashMap(); 29 | resultRow.put("Class", type); 30 | resultRow.put("MethodsOfType", methodsOfType); 31 | rows.add(resultRow); 32 | } 33 | // Return the result 34 | var status = com.buschmais.jqassistant.core.analysis.api.Result.Status.SUCCESS; 35 | new com.buschmais.jqassistant.core.analysis.api.Result(rule, status, severity, columnNames, rows); 36 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-rule-language-explicitly-set.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | language: cypher 6 | source: | 7 | match 8 | (throwable)-[:EXTENDS*]->(t:Type) 9 | where 10 | t.fqn = 'java.lang.Throwable' 11 | SET 12 | throwable:Throwable 13 | return 14 | count(throwable) AS Throwables 15 | 16 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-rule-language-not-explicitly-set.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | # language must not be given for the unit test using this document 6 | source: | 7 | match 8 | (throwable)-[:EXTENDS*]->(t:Type) 9 | where 10 | t.fqn = 'java.lang.Throwable' 11 | SET 12 | throwable:Throwable 13 | return 14 | count(throwable) AS Throwables 15 | 16 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-simple.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | source: | 6 | match 7 | (throwable)-[:EXTENDS*]->(t:Type) 8 | where 9 | t.fqn = 'java.lang.Throwable' 10 | SET 11 | throwable:Throwable 12 | return 13 | count(throwable) AS Throwables 14 | 15 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-with-dependency-one.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresConcepts: 6 | - refId: concept:other 7 | optional: false 8 | source: | 9 | match 10 | (throwable)-[:EXTENDS*]->(t:Type) 11 | where 12 | t.fqn = 'java.lang.Throwable' 13 | SET 14 | throwable:Throwable 15 | return 16 | count(throwable) AS Throwables 17 | 18 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-with-dependency-with-missing-required-key.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresConcepts: 6 | - # this is the missing required key => refId: concept:other 7 | optional: false 8 | source: | 9 | match 10 | (throwable)-[:EXTENDS*]->(t:Type) 11 | where 12 | t.fqn = 'java.lang.Throwable' 13 | SET 14 | throwable:Throwable 15 | return 16 | count(throwable) AS Throwables 17 | 18 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-with-dependency-with-unsupported-key.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiredConcepts: 6 | - refId: concept:other 7 | optional: false 8 | unsupportedKey: value 9 | source: | 10 | match 11 | (throwable)-[:EXTENDS*]->(t:Type) 12 | where 13 | t.fqn = 'java.lang.Throwable' 14 | SET 15 | throwable:Throwable 16 | return 17 | count(throwable) AS Throwables 18 | 19 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-with-missing-keyword-id.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - description: Description 4 | source: | 5 | match 6 | (throwable)-[:EXTENDS*]->(t:Type) 7 | where 8 | t.fqn = 'java.lang.Throwable' 9 | SET 10 | throwable:Throwable 11 | return 12 | count(throwable) AS Throwables 13 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-with-one-dependency-and-unsupported-key.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresConcepts: 6 | - refId: concept:other 7 | optional: false 8 | thisKeyIsNotSupported: yes 9 | source: | 10 | match 11 | (throwable)-[:EXTENDS*]->(t:Type) 12 | where 13 | t.fqn = 'java.lang.Throwable' 14 | SET 15 | throwable:Throwable 16 | return 17 | count(throwable) AS Throwables 18 | 19 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-with-one-parameter.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresParameters: 6 | - name: fqcn 7 | type: String 8 | defaultValue: foobar 9 | 10 | source: | 11 | match 12 | (throwable)-[:EXTENDS*]->(t:Type) 13 | where 14 | t.fqn = 'java.lang.Throwable' 15 | SET 16 | throwable:Throwable 17 | return 18 | count(throwable) AS Throwables 19 | 20 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-with-severity.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | severity: blocker 6 | source: | 7 | match 8 | (throwable)-[:EXTENDS*]->(t:Type) 9 | where 10 | t.fqn = 'java.lang.Throwable' 11 | SET 12 | throwable:Throwable 13 | return 14 | count(throwable) AS Throwables 15 | 16 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-with-two-parameters.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | 6 | requiresParameters: 7 | - name: fqcn 8 | type: String 9 | defaultValue: foobar 10 | - name: foobar 11 | type: String 12 | 13 | source: | 14 | match 15 | (throwable)-[:EXTENDS*]->(t:Type) 16 | where 17 | t.fqn = 'java.lang.Throwable' 18 | SET 19 | throwable:Throwable 20 | return 21 | count(throwable) AS Throwables 22 | 23 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-with-verification-aggrgation.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresConcepts: 6 | - refId: concept:other 7 | optional: false 8 | source: | 9 | match 10 | (throwable)-[:EXTENDS*]->(t:Type) 11 | where 12 | t.fqn = 'java.lang.Throwable' 13 | SET 14 | throwable:Throwable 15 | return 16 | count(throwable) AS Throwables 17 | verify: 18 | aggregation: 19 | column: Throwables 20 | min: 10 21 | max: 20 22 | 23 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-with-verification-and-rowcount.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresConcepts: 6 | - refId: concept:other 7 | optional: false 8 | source: | 9 | match 10 | (throwable)-[:EXTENDS*]->(t:Type) 11 | where 12 | t.fqn = 'java.lang.Throwable' 13 | SET 14 | throwable:Throwable 15 | return 16 | count(throwable) AS Throwables 17 | verify: 18 | aggregation: 19 | column: Throwables 20 | min: 10 21 | max: 20 22 | rowCount: 23 | min: 10 24 | max: 20 25 | 26 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-with-verification-rowcount.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresConcepts: 6 | - refId: concept:other 7 | optional: false 8 | source: | 9 | match 10 | (throwable)-[:EXTENDS*]->(t:Type) 11 | where 12 | t.fqn = 'java.lang.Throwable' 13 | SET 14 | throwable:Throwable 15 | return 16 | count(throwable) AS Throwables 17 | verify: 18 | rowCount: 19 | min: 10 20 | max: 20 21 | 22 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-single-with-verification-unsupported-keyword.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiredConcepts: 6 | - refId: concept:other 7 | optional: false 8 | source: | 9 | match 10 | (throwable)-[:EXTENDS*]->(t:Type) 11 | where 12 | t.fqn = 'java.lang.Throwable' 13 | SET 14 | throwable:Throwable 15 | return 16 | count(throwable) AS Throwables 17 | verify: 18 | unsupportedKeyWord: value 19 | aggregation: 20 | aggregationColumn: Throwables 21 | aggregationMin: 10 22 | aggregationMax: 20 23 | 24 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-with-parameter-and-unsupported-keyword.yml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiredParameters: 6 | - name: fqcn 7 | unsupported: not allowed here 8 | defaultValue: foobar 9 | type: String 10 | 11 | source: | 12 | match 13 | (throwable)-[:EXTENDS*]->(t:Type) 14 | where 15 | t.fqn = 'java.lang.Throwable' 16 | SET 17 | throwable:Throwable 18 | return 19 | count(throwable) AS Throwables 20 | 21 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-with-parameter-empty-list-of-parameters.yml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresParameters: 6 | # empty list of parameters 7 | source: | 8 | match 9 | (throwable)-[:EXTENDS*]->(t:Type) 10 | where 11 | t.fqn = 'java.lang.Throwable' 12 | SET 13 | throwable:Throwable 14 | return 15 | count(throwable) AS Throwables 16 | 17 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-with-parameter-invalid-missing-field-name.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiredParameters: 6 | - type: String 7 | defaultValue: foobar 8 | 9 | source: | 10 | match 11 | (throwable)-[:EXTENDS*]->(t:Type) 12 | where 13 | t.fqn = 'java.lang.Throwable' 14 | SET 15 | throwable:Throwable 16 | return 17 | count(throwable) AS Throwables 18 | 19 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-with-parameter-invalid-missing-field-type.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiredParameters: 6 | - name: fqcn 7 | defaultValue: foobar 8 | 9 | source: | 10 | match 11 | (throwable)-[:EXTENDS*]->(t:Type) 12 | where 13 | t.fqn = 'java.lang.Throwable' 14 | SET 15 | throwable:Throwable 16 | return 17 | count(throwable) AS Throwables 18 | 19 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-with-parameter-missing-default-value.yml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresParameters: 6 | - name: fqcn 7 | defaultValue: 8 | type: String 9 | 10 | source: | 11 | match 12 | (throwable)-[:EXTENDS*]->(t:Type) 13 | where 14 | t.fqn = 'java.lang.Throwable' 15 | SET 16 | throwable:Throwable 17 | return 18 | count(throwable) AS Throwables 19 | 20 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-with-parameter-missing-name.yml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresParameters: 6 | - name: 7 | defaultValue: foorbar 8 | type: String 9 | 10 | source: | 11 | match 12 | (throwable)-[:EXTENDS*]->(t:Type) 13 | where 14 | t.fqn = 'java.lang.Throwable' 15 | SET 16 | throwable:Throwable 17 | return 18 | count(throwable) AS Throwables 19 | 20 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-with-parameter-missing-type.yml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresParameters: 6 | - type: 7 | name: fqcn 8 | 9 | source: | 10 | match 11 | (throwable)-[:EXTENDS*]->(t:Type) 12 | where 13 | t.fqn = 'java.lang.Throwable' 14 | SET 15 | throwable:Throwable 16 | return 17 | count(throwable) AS Throwables 18 | 19 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-with-parameter-unsupported-type.yml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresParameters: 6 | - type: snafu 7 | name: fqcn 8 | defaultValue: foobar 9 | 10 | source: | 11 | match 12 | (throwable)-[:EXTENDS*]->(t:Type) 13 | where 14 | t.fqn = 'java.lang.Throwable' 15 | SET 16 | throwable:Throwable 17 | return 18 | count(throwable) AS Throwables 19 | 20 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/concept-with-parameter-with-illegal-datastructure.yml: -------------------------------------------------------------------------------- 1 | --- 2 | concepts: 3 | - id: java:Throwable 4 | description: Labels types deriving from java.lang.Throwable as "Throwable". 5 | requiresParameters: 6 | - name: fqcn 7 | defaultValue: foobar 8 | type: 9 | - S 10 | - t 11 | - r 12 | - i 13 | - n 14 | - g 15 | 16 | source: | 17 | match 18 | (throwable)-[:EXTENDS*]->(t:Type) 19 | where 20 | t.fqn = 'java.lang.Throwable' 21 | SET 22 | throwable:Throwable 23 | return 24 | count(throwable) AS Throwables 25 | 26 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/constraint-with-report-all-possible-keys.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | constraints: 3 | - id: id 4 | source: | 5 | match 6 | (throwable)-[:EXTENDS*]->(t:Type) 7 | where 8 | t.fqn = 'java.lang.Throwable' 9 | SET 10 | throwable:Throwable 11 | return 12 | count(throwable) AS c 13 | report: 14 | primaryColumn: lamp 15 | type: snafu 16 | properties: 17 | asciidoc.foobar: A 18 | b: B 19 | c: C 20 | 21 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/constraint-with-report-and-with-unknown-keyword.yml: -------------------------------------------------------------------------------- 1 | --- 2 | constraints: 3 | - id: id 4 | source: | 5 | match 6 | (throwable)-[:EXTENDS*]->(t:Type) 7 | where 8 | t.fqn = 'java.lang.Throwable' 9 | SET 10 | throwable:Throwable 11 | return 12 | count(throwable) AS c 13 | report: 14 | wtf: 15 | snafu: 16 | foobar: 17 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/constraint-with-report-many-properties.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | constraints: 3 | - id: id 4 | source: | 5 | match 6 | (throwable)-[:EXTENDS*]->(t:Type) 7 | where 8 | t.fqn = 'java.lang.Throwable' 9 | SET 10 | throwable:Throwable 11 | return 12 | count(throwable) AS c 13 | report: 14 | primaryColumn: c 15 | type: a 16 | properties: 17 | asciidoc.foobar: A 18 | A: 3 19 | b: B 20 | c: C 21 | 22 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/constraint-with-report-no-properties.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | constraints: 3 | - id: id 4 | source: | 5 | match 6 | (throwable)-[:EXTENDS*]->(t:Type) 7 | where 8 | t.fqn = 'java.lang.Throwable' 9 | SET 10 | throwable:Throwable 11 | return 12 | count(throwable) AS c 13 | report: 14 | type: ddd 15 | primaryColumn: c 16 | 17 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/constraint-with-report-with-invalid-block-structure-01.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | constraints: 3 | - id: id 4 | source: | 5 | match 6 | (throwable)-[:EXTENDS*]->(t:Type) 7 | where 8 | t.fqn = 'java.lang.Throwable' 9 | SET 10 | throwable:Throwable 11 | return 12 | count(throwable) AS c 13 | report: 14 | - a 15 | - b 16 | - c 17 | 18 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/constraint-with-report-with-invalid-block-structure-02.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | constraints: 3 | - id: id 4 | source: | 5 | match 6 | (throwable)-[:EXTENDS*]->(t:Type) 7 | where 8 | t.fqn = 'java.lang.Throwable' 9 | SET 10 | throwable:Throwable 11 | return 12 | count(throwable) AS c 13 | report: 14 | primaryColumn: 15 | a: A 16 | b: B 17 | 18 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/constraint-with-report-with-report-type-multiple.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | constraints: 3 | - id: id 4 | source: | 5 | match 6 | (throwable)-[:EXTENDS*]->(t:Type) 7 | where 8 | t.fqn = 'java.lang.Throwable' 9 | SET 10 | throwable:Throwable 11 | return 12 | count(throwable) AS c 13 | report: 14 | primaryColumn: c 15 | type: csv, xml, json # whitespace are intended 16 | 17 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/constraint-with-report-with-report-type.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | constraints: 3 | - id: id 4 | source: | 5 | match 6 | (throwable)-[:EXTENDS*]->(t:Type) 7 | where 8 | t.fqn = 'java.lang.Throwable' 9 | SET 10 | throwable:Throwable 11 | return 12 | count(throwable) AS c 13 | report: 14 | primaryColumn: c 15 | type: csv 16 | 17 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/constraint-with-report-without-any-key.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | constraints: 3 | - id: id 4 | source: | 5 | match 6 | (throwable)-[:EXTENDS*]->(t:Type) 7 | where 8 | t.fqn = 'java.lang.Throwable' 9 | SET 10 | throwable:Throwable 11 | return 12 | count(throwable) AS c 13 | report: 14 | 15 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/descriptions.yaml: -------------------------------------------------------------------------------- 1 | concepts: 2 | - id: "test:WithoutDescription" 3 | source: | 4 | Cypher Concept 5 | - id: "test:EmptyDescription" 6 | description: "" 7 | source: | 8 | Cypher Concept 9 | - id: "test:SingleLineDescription" 10 | description: " Cal took a long, deep breath, struggling to control his own emotions. " 11 | source: | 12 | Cypher Concept 13 | - id: "test:MultiMixEmptyLineDescription" 14 | description: | 15 | Cal took a long, deep breath, 16 | 17 | struggling to control his own emotions. 18 | source: | 19 | Cypher Concept 20 | 21 | constraints: 22 | - id: "test:WithoutDescription" 23 | source: | 24 | Cypher Constraint 25 | - id: "test:EmptyDescription" 26 | description: "" 27 | source: | 28 | Cypher Constraint 29 | - id: "test:SingleLineDescription" 30 | description: " When he arrived at the station, the bus had already left. " 31 | source: | 32 | Cypher Constraint 33 | - id: "test:MultiMixEmptyLineDescription" 34 | description: | 35 | 36 | When he arrived at the station, 37 | 38 | the bus had already left. 39 | 40 | source: | 41 | Cypher Constraint 42 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/document-empty-empty-file.yaml: -------------------------------------------------------------------------------- 1 | # intentionally empty 2 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/document-empty.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ... 3 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/document-only-toplevel-keywords-but-all-empty.yaml: -------------------------------------------------------------------------------- 1 | groups: 2 | concepts: 3 | constraints: 4 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/document-unknown-toplevel-keyword.yml: -------------------------------------------------------------------------------- 1 | groups: 2 | concepts: 3 | constraints: 4 | foobar: 5 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-include-concept-additional-keyword.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: snafu 4 | includedConcepts: 5 | - refId: other 6 | severity: info 7 | foo: bar # Unsupported keyword foo 8 | ... 9 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-include-concept-empty-list.yaml: -------------------------------------------------------------------------------- 1 | groups: 2 | - id: g 3 | includedConcepts: 4 | includedConstraints: 5 | - refId: ic 6 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-include-concept-missing-refid.yaml: -------------------------------------------------------------------------------- 1 | groups: 2 | - id: my_group 3 | includedConcepts: 4 | - severity: info 5 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-include-concept-severity-unknown.yml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: snafu 4 | includedConcepts: 5 | - refId: other 6 | severity: PENG 7 | ... 8 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-include-concept-two.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: zzz 4 | includedConcepts: 5 | - refId: xxx 6 | - refId: yyy 7 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-include-constraint-different-severity.yaml: -------------------------------------------------------------------------------- 1 | groups: 2 | - id: first_group 3 | includedConstraints: 4 | - refId: referenced_constraint 5 | severity: info 6 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-include-constraint-empty-list.yaml: -------------------------------------------------------------------------------- 1 | groups: 2 | - id: group 3 | includedConstraints: 4 | includedConcepts: 5 | - refId: other_concept 6 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-include-constraint-two.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: abc 4 | includedConstraints: 5 | - refId: x 6 | - refId: y 7 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-include-group-empty-list.yaml: -------------------------------------------------------------------------------- 1 | groups: 2 | - id: group 3 | includedGroups: 4 | includedConstraints: 5 | - refId: constraint 6 | includedConcepts: 7 | - refId: concept 8 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-missing-keyword.yaml: -------------------------------------------------------------------------------- 1 | groups: 2 | - includedConcepts: 3 | - refId: a 4 | - refId: b 5 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-one-included-constraint.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: ttt 4 | includedConstraints: 5 | - refId: uuu 6 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-severity-explicitly-set.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: a 4 | severity: blocker 5 | ... 6 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-severity-not-set.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: abc 4 | ... 5 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-with-include-concept-no-value-for-severity.yaml: -------------------------------------------------------------------------------- 1 | groups: 2 | - id: myGroup 3 | includedConcepts: 4 | - refId: concept_a 5 | severity: 6 | ... 7 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-with-one-included-concept-with-own-severity.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: zzz 4 | includedConcepts: 5 | - refId: xxx 6 | severity: minor 7 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-with-one-included-concept.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: cccc 4 | includedConcepts: 5 | - refId: efg 6 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-with-one-included-group.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: nnn 4 | includedGroups: 5 | - refId: mmm 6 | severity: blocker 7 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-with-two-included-groups.yaml: -------------------------------------------------------------------------------- 1 | groups: 2 | - id: p_g 3 | includedGroups: 4 | - refId: a_g 5 | - refId: b_g 6 | 7 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single-with-unknown-keyword.yaml: -------------------------------------------------------------------------------- 1 | groups: 2 | - id: a_group 3 | foo: bar 4 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-single.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: a 4 | ... 5 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/group-two.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | groups: 3 | - id: a 4 | - id: b 5 | ... 6 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/i18n-emoji-usage.yaml: -------------------------------------------------------------------------------- 1 | concepts: 2 | - id: 🐶 3 | description: 🐱 4 | source: MATCH (a) RETURN a 5 | -------------------------------------------------------------------------------- /rule/src/test/resources/yaml/i18n-japanese-description.yaml: -------------------------------------------------------------------------------- 1 | concepts: 2 | - id: concept 3 | description: おはようございます。 4 | source: MATCH (a) RETURN a 5 | -------------------------------------------------------------------------------- /runtime/src/main/java/com/buschmais/jqassistant/core/runtime/api/configuration/Configuration.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.api.configuration; 2 | 3 | import java.util.List; 4 | 5 | import com.buschmais.jqassistant.core.analysis.api.configuration.Analyze; 6 | import com.buschmais.jqassistant.core.scanner.api.configuration.Scan; 7 | import com.buschmais.jqassistant.core.shared.annotation.Description; 8 | import com.buschmais.jqassistant.core.shared.configuration.Plugin; 9 | import com.buschmais.jqassistant.core.store.api.configuration.Store; 10 | 11 | import io.smallrye.config.ConfigMapping; 12 | import io.smallrye.config.WithDefault; 13 | 14 | /** 15 | * Represents the runtime configuration for jQAssistant. 16 | */ 17 | @ConfigMapping(prefix = Configuration.PREFIX) 18 | public interface Configuration { 19 | 20 | String PREFIX = "jqassistant"; 21 | 22 | String SKIP = "skip"; 23 | 24 | @WithDefault("false") 25 | @Description("Skip execution of jQAssistant tasks/goals.") 26 | boolean skip(); 27 | 28 | /** 29 | * The default plugins to provision, to be used by distributions. 30 | * 31 | * @return The {@link List} of plugins. 32 | */ 33 | List defaultPlugins(); 34 | 35 | /** 36 | * The plugins to provision. 37 | * 38 | * @return The {@link List} of plugins. 39 | */ 40 | List plugins(); 41 | 42 | /** 43 | * The {@link Store} configuration. 44 | * 45 | * @return The {@link Store} configuration. 46 | */ 47 | Store store(); 48 | 49 | /** 50 | * The {@link Scan} configuration. 51 | * 52 | * @return The {@link Scan} configuration. 53 | */ 54 | Scan scan(); 55 | 56 | /** 57 | * The {@link Analyze} configuration. 58 | * 59 | * @return The {@link Analyze} configuration. 60 | */ 61 | Analyze analyze(); 62 | 63 | /** 64 | * The {@link Server} configuration. 65 | * 66 | * @return The {@link Server} configuration. 67 | */ 68 | Server server(); 69 | } 70 | -------------------------------------------------------------------------------- /runtime/src/main/java/com/buschmais/jqassistant/core/runtime/api/configuration/Server.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.api.configuration; 2 | 3 | import com.buschmais.jqassistant.core.shared.annotation.Description; 4 | 5 | import io.smallrye.config.ConfigMapping; 6 | import io.smallrye.config.WithDefault; 7 | 8 | @ConfigMapping(prefix = "jqassistant.server") 9 | public interface Server { 10 | 11 | String DAEMON = "daemon"; 12 | 13 | @Description("Run the server as daemon.") 14 | @WithDefault("false") 15 | boolean daemon(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /runtime/src/main/java/com/buschmais/jqassistant/core/runtime/api/plugin/PluginClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.api.plugin; 2 | 3 | import java.net.URL; 4 | import java.net.URLClassLoader; 5 | import java.util.Collection; 6 | 7 | import static java.util.Collections.emptyList; 8 | 9 | /** 10 | * The classloader used for loading the plugins. 11 | */ 12 | public class PluginClassLoader extends URLClassLoader { 13 | 14 | public PluginClassLoader(ClassLoader parent) { 15 | this(parent, emptyList()); 16 | } 17 | 18 | public PluginClassLoader(ClassLoader parent, Collection classpath) { 19 | super(classpath.toArray(new URL[classpath.size()]), parent); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /runtime/src/main/java/com/buschmais/jqassistant/core/runtime/api/plugin/PluginConfigurationReader.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.api.plugin; 2 | 3 | import java.util.List; 4 | 5 | import org.jqassistant.schema.plugin.v2.JqassistantPlugin; 6 | 7 | /** 8 | * Defines the interface for plugin readers. 9 | */ 10 | public interface PluginConfigurationReader { 11 | 12 | String NAMESPACE = "http://schema.jqassistant.org/plugin/v2.2"; 13 | String PLUGIN_RESOURCE = "META-INF/jqassistant-plugin.xml"; 14 | String PLUGIN_SCHEMA_RESOURCE = "/META-INF/plugin/xsd/jqassistant-plugin-v2.2.xsd"; 15 | 16 | /** 17 | * Return the class loader used to resolve plugins. 18 | * 19 | * @return The class loader. 20 | */ 21 | ClassLoader getClassLoader(); 22 | 23 | /** 24 | * Return the list of detected plugins. 25 | * 26 | * @return The plugins. 27 | */ 28 | List getPlugins(); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /runtime/src/main/java/com/buschmais/jqassistant/core/runtime/api/plugin/PluginInfo.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.api.plugin; 2 | 3 | import java.util.Comparator; 4 | import java.util.Optional; 5 | 6 | /** 7 | * The {@code PluginInfo} class provides common information on 8 | * a plugin known by jQA. 9 | * 10 | * @author Oliver B. Fischer, Freiheitsgrade Consulting 11 | */ 12 | public interface PluginInfo { 13 | String getName(); 14 | 15 | String getId(); 16 | 17 | Optional getVersion(); 18 | 19 | /** 20 | * Comparator to compare two given plugin information based on their name, 21 | * ignoring case differences. 22 | */ 23 | PluginInfoComparator NAME_COMPARATOR = (left, right) -> left.getName() 24 | .compareToIgnoreCase(right.getName()); 25 | 26 | /** 27 | * Comparator to compare two given plugin information based on their id, 28 | * ignoring case differences. 29 | */ 30 | PluginInfoComparator ID_COMPARATOR = (left, right) -> left.getId() 31 | .compareToIgnoreCase(right.getId()); 32 | 33 | interface PluginInfoComparator extends Comparator { 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /runtime/src/main/java/com/buschmais/jqassistant/core/runtime/api/plugin/PluginRepository.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.api.plugin; 2 | 3 | import java.util.List; 4 | 5 | import com.buschmais.jqassistant.core.analysis.spi.AnalyzerPluginRepository; 6 | import com.buschmais.jqassistant.core.rule.spi.RulePluginRepository; 7 | import com.buschmais.jqassistant.core.scanner.spi.ScannerPluginRepository; 8 | import com.buschmais.jqassistant.core.shared.lifecycle.LifecycleAware; 9 | import com.buschmais.jqassistant.core.store.spi.StorePluginRepository; 10 | 11 | /** 12 | * Defines the interface for the plugin repository. 13 | */ 14 | public interface PluginRepository extends LifecycleAware { 15 | 16 | @Override 17 | void initialize(); 18 | 19 | @Override 20 | void destroy(); 21 | 22 | StorePluginRepository getStorePluginRepository(); 23 | 24 | ScannerPluginRepository getScannerPluginRepository(); 25 | 26 | RulePluginRepository getRulePluginRepository(); 27 | 28 | AnalyzerPluginRepository getAnalyzerPluginRepository(); 29 | 30 | ClassLoader getClassLoader(); 31 | 32 | List getPluginInfos(); 33 | 34 | void printPluginInfos(); 35 | } 36 | -------------------------------------------------------------------------------- /runtime/src/main/java/com/buschmais/jqassistant/core/runtime/api/plugin/PluginRepositoryException.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.api.plugin; 2 | 3 | /** 4 | * Exception thrown by the {@link PluginConfigurationReader}. 5 | */ 6 | public class PluginRepositoryException extends RuntimeException { 7 | 8 | /** 9 | * The serial version UID. 10 | */ 11 | private static final long serialVersionUID = -2317389179258285099L; 12 | 13 | /** 14 | * Constructor. 15 | * 16 | * @param message 17 | * The message. 18 | * @param cause 19 | * The cause. 20 | */ 21 | public PluginRepositoryException(String message, Throwable cause) { 22 | super(message, cause); 23 | } 24 | 25 | /** 26 | * Constructor. 27 | * 28 | * @param message 29 | * The message. 30 | */ 31 | public PluginRepositoryException(String message) { 32 | super(message); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /runtime/src/main/java/com/buschmais/jqassistant/core/runtime/api/plugin/PluginResolver.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.api.plugin; 2 | 3 | import com.buschmais.jqassistant.core.runtime.api.configuration.Configuration; 4 | 5 | /** 6 | * Defines the interface for a plugin resolver that takes a list of required plugins from the configuration, resolves the artifacts and provides the {@link PluginClassLoader}. 7 | */ 8 | public interface PluginResolver { 9 | 10 | /** 11 | * Resolve the required plugins. 12 | * 13 | * @param parent 14 | * The paren {@link ClassLoader}. 15 | * @param configuration 16 | * The {@link Configuration}. 17 | * @return The {@link PluginClassLoader}. 18 | */ 19 | PluginClassLoader createClassLoader(ClassLoader parent, Configuration configuration); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /runtime/src/main/java/com/buschmais/jqassistant/core/runtime/impl/plugin/PluginIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.impl.plugin; 2 | 3 | import java.util.function.Function; 4 | import java.util.function.IntUnaryOperator; 5 | 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.jqassistant.schema.plugin.v2.JqassistantPlugin; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class PluginIdGenerator implements Function { 12 | 13 | private static final Logger LOGGER = LoggerFactory.getLogger(PluginIdGenerator.class); 14 | 15 | private static final Character UNDERSCORE = '_'; 16 | 17 | @Override 18 | public JqassistantPlugin apply(JqassistantPlugin plugin) { 19 | if (StringUtils.isBlank(plugin.getId())) { 20 | String name = plugin.getName() 21 | .toLowerCase(); 22 | IntUnaryOperator replacer = i -> (Character.isWhitespace(i)) ? UNDERSCORE : i; 23 | StringBuilder generate = new StringBuilder(); 24 | 25 | for (int index = 0; index < name.length(); index++) { 26 | int updated = replacer.applyAsInt(name.charAt(index)); 27 | int lastChar = getLastChar(generate); 28 | 29 | if (!(updated == UNDERSCORE && lastChar == UNDERSCORE)) { 30 | generate.appendCodePoint(updated); 31 | } 32 | } 33 | 34 | plugin.setId(generate.toString()); 35 | 36 | LOGGER.debug("Assigned generated plugin id '{}' to plugin named '{}'", plugin.getName(), plugin.getId()); 37 | } 38 | 39 | return plugin; 40 | } 41 | 42 | private int getLastChar(CharSequence input) { 43 | if (input != null && input.length() > 0) { 44 | return input.charAt(input.length() - 1); 45 | } 46 | 47 | return -1; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /runtime/src/main/java/com/buschmais/jqassistant/core/runtime/impl/plugin/PluginInfoImpl.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.impl.plugin; 2 | 3 | import java.util.Optional; 4 | 5 | import com.buschmais.jqassistant.core.runtime.api.plugin.PluginInfo; 6 | 7 | import lombok.Builder; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | import lombok.ToString; 11 | 12 | @Getter 13 | @Setter 14 | @ToString 15 | @Builder 16 | public class PluginInfoImpl implements PluginInfo { 17 | private final String id; 18 | private final String name; 19 | private final Optional version; 20 | } 21 | -------------------------------------------------------------------------------- /runtime/src/test/java/com/buschmais/jqassistant/core/runtime/api/configuration/ConfigurationBuilderTest.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.api.configuration; 2 | 3 | import java.util.Map; 4 | 5 | import com.buschmais.jqassistant.core.shared.map.MapBuilder; 6 | 7 | import io.smallrye.config.ConfigMapping; 8 | import org.eclipse.microprofile.config.spi.ConfigSource; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import static java.util.Arrays.asList; 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | /** 15 | * Tests for {@link ConfigurationBuilder}. 16 | */ 17 | class ConfigurationBuilderTest { 18 | 19 | @ConfigMapping(prefix = "jqassistant.test") 20 | static class TestMapping { 21 | } 22 | 23 | private ConfigurationBuilder configurationBuilder = new ConfigurationBuilder("Test", 110); 24 | 25 | @Test 26 | void properties() { 27 | configurationBuilder.with(TestMapping.class, "boolean-value", true); 28 | // null values must not override existing configuration properties 29 | configurationBuilder.with(TestMapping.class, "boolean-value", (Boolean) null); 30 | Map map = MapBuilder.builder() 31 | .entry("key.1", "value1") 32 | .entry("key.2", "value2") 33 | .build(); 34 | configurationBuilder.with(TestMapping.class, "map-value", map); 35 | configurationBuilder.with(TestMapping.class, "list-value", asList("element0", "element1")); 36 | 37 | ConfigSource propertiesConfigSource = configurationBuilder.build(); 38 | 39 | assertThat(propertiesConfigSource.getValue("jqassistant.test.boolean-value")).isEqualTo("true"); 40 | assertThat(propertiesConfigSource.getValue("jqassistant.test.map-value.\"key.1\"")).isEqualTo("value1"); 41 | assertThat(propertiesConfigSource.getValue("jqassistant.test.map-value.\"key.2\"")).isEqualTo("value2"); 42 | assertThat(propertiesConfigSource.getValue("jqassistant.test.list-value[0]")).isEqualTo("element0"); 43 | assertThat(propertiesConfigSource.getValue("jqassistant.test.list-value[1]")).isEqualTo("element1"); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /runtime/src/test/java/com/buschmais/jqassistant/core/runtime/impl/configuration/TestConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.impl.configuration; 2 | 3 | import com.buschmais.jqassistant.core.runtime.api.configuration.Configuration; 4 | 5 | import io.smallrye.config.ConfigMapping; 6 | 7 | @ConfigMapping(prefix = Configuration.PREFIX) 8 | public interface TestConfiguration extends Configuration { 9 | } 10 | -------------------------------------------------------------------------------- /runtime/src/test/java/com/buschmais/jqassistant/core/runtime/impl/plugin/ScannerPluginRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.impl.plugin; 2 | 3 | import com.buschmais.jqassistant.core.runtime.api.plugin.PluginClassLoader; 4 | import com.buschmais.jqassistant.core.runtime.api.plugin.PluginConfigurationReader; 5 | import com.buschmais.jqassistant.core.scanner.spi.ScannerPluginRepository; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class ScannerPluginRepositoryTest { 12 | 13 | @Test 14 | void scopes() { 15 | PluginConfigurationReader pluginConfigurationReader = new PluginConfigurationReaderImpl( 16 | new PluginClassLoader(ScannerPluginRepositoryTest.class.getClassLoader())); 17 | ScannerPluginRepository repository = new ScannerPluginRepositoryImpl(pluginConfigurationReader); 18 | assertThat(repository.getScope("test:foo")).isEqualTo(TestScope.FOO); 19 | assertThat(repository.getScope("Test:foo")).isEqualTo(TestScope.FOO); 20 | assertThat(repository.getScope("test:Foo")).isEqualTo(TestScope.FOO); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /runtime/src/test/java/com/buschmais/jqassistant/core/runtime/impl/plugin/TestReportPlugin.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.impl.plugin; 2 | 3 | import java.util.Map; 4 | 5 | import com.buschmais.jqassistant.core.report.api.ReportContext; 6 | import com.buschmais.jqassistant.core.report.api.ReportPlugin; 7 | 8 | public class TestReportPlugin implements ReportPlugin { 9 | 10 | private Map properties; 11 | 12 | @Override 13 | public void configure(ReportContext reportContext, Map properties) { 14 | this.properties = properties; 15 | } 16 | 17 | public Map getProperties() { 18 | return properties; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /runtime/src/test/java/com/buschmais/jqassistant/core/runtime/impl/plugin/TestScannerPlugin.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.impl.plugin; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.Map; 6 | 7 | import com.buschmais.jqassistant.core.scanner.api.Scanner; 8 | import com.buschmais.jqassistant.core.scanner.api.ScannerContext; 9 | import com.buschmais.jqassistant.core.scanner.api.ScannerPlugin; 10 | import com.buschmais.jqassistant.core.scanner.api.Scope; 11 | import com.buschmais.jqassistant.core.store.api.model.Descriptor; 12 | 13 | public class TestScannerPlugin implements ScannerPlugin { 14 | 15 | private Map properties; 16 | 17 | @Override 18 | public void initialize() { 19 | } 20 | 21 | @Override 22 | public void configure(ScannerContext scannerContext, Map properties) { 23 | this.properties = properties; 24 | } 25 | 26 | @Override 27 | public Class getType() { 28 | return File.class; 29 | } 30 | 31 | @Override 32 | public Class getDescriptorType() { 33 | return Descriptor.class; 34 | } 35 | 36 | @Override 37 | public boolean accepts(File item, String path, Scope scope) throws IOException { 38 | return false; 39 | } 40 | 41 | @Override 42 | public Descriptor scan(File item, String path, Scope scope, Scanner scanner) throws IOException { 43 | return null; 44 | } 45 | 46 | public Map getProperties() { 47 | return properties; 48 | } 49 | 50 | @Override 51 | public String getName() { 52 | return TestScannerPlugin.class.getSimpleName(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /runtime/src/test/java/com/buschmais/jqassistant/core/runtime/impl/plugin/TestScope.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.runtime.impl.plugin; 2 | 3 | import com.buschmais.jqassistant.core.scanner.api.Scope; 4 | 5 | public enum TestScope implements Scope { 6 | 7 | FOO; 8 | 9 | @Override 10 | public String getPrefix() { 11 | return "test"; 12 | } 13 | 14 | @Override 15 | public String getName() { 16 | return name(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /runtime/src/test/resources/.jqassistant.yml: -------------------------------------------------------------------------------- 1 | # Test file for ConfigurationLoader 2 | jqassistant: 3 | default-plugins: 4 | - group-id: org.jqassistant.plugin 5 | artifact-id: test-plugin 6 | version: 1.0.0 7 | -------------------------------------------------------------------------------- /runtime/src/test/resources/META-INF/jqassistant-plugin.xml: -------------------------------------------------------------------------------- 1 | 4 | Test plugin. 5 | 6 | com.buschmais.jqassistant.core.runtime.impl.plugin.TestScope 7 | 8 | 9 | com.buschmais.jqassistant.core.runtime.impl.plugin.TestScannerPlugin 10 | 11 | 12 | com.buschmais.jqassistant.core.runtime.impl.plugin.TestReportPlugin 13 | com.buschmais.jqassistant.core.runtime.impl.plugin.TestReportPlugin 14 | 15 | 16 | -------------------------------------------------------------------------------- /runtime/src/test/resources/testdata/plugin-info-data.left-and-right-are-equal.csv: -------------------------------------------------------------------------------- 1 | leftName, leftId, rightName, rightId 2 | plugin a, plugin.a, plugin a, plugin.a 3 | Plugin a, plugin.a, Plugin A, plugin.a 4 | Plugin a, plugin.a, Plugin A, plugin.A 5 | Plugin a, plugin.a, Plugin A, plugin.A 6 | Plugin a, plugin.a, Plugin A, PLUGIN.A 7 | Plugin a, plugin.a, PLUGIN A, PLUGIN.A 8 | PLUGIN A, PLUGIN.A, PLUGIN A, PLUGIN.A 9 | -------------------------------------------------------------------------------- /runtime/src/test/resources/testdata/plugin-info-data.left-less-then-right.csv: -------------------------------------------------------------------------------- 1 | leftName, leftId, rightName, rightId 2 | Plugin a, plugin.a, Plugin B, plugin.b 3 | Plugin A, plugin.A, Plugin B, plugin.B 4 | -------------------------------------------------------------------------------- /runtime/src/test/resources/userhome/.jqassistant.yml: -------------------------------------------------------------------------------- 1 | jqassistant: 2 | scan: 3 | properties: 4 | overwritten-user-value: "default" 5 | user-value: "default" 6 | -------------------------------------------------------------------------------- /runtime/src/test/resources/working directory/.jqassistant/plugins.yml: -------------------------------------------------------------------------------- 1 | jqassistant: 2 | plugins: 3 | - group-id: com.buschmais.jqassistant.core 4 | artifact-id: minimal-test-plugin 5 | version: 1.0.0 6 | - group-id: com.buschmais.jqassistant.core 7 | artifact-id: full-test-plugin 8 | type: jqp 9 | version: 1.0.0 10 | active: false 11 | -------------------------------------------------------------------------------- /runtime/src/test/resources/working directory/.jqassistant/profile.yml: -------------------------------------------------------------------------------- 1 | "%test-profile": 2 | jqassistant: 3 | scan: 4 | properties: 5 | profile-user-value: "test-value" 6 | -------------------------------------------------------------------------------- /runtime/src/test/resources/working directory/.jqassistant/readme.txt: -------------------------------------------------------------------------------- 1 | This directory contains test configurations verifying configuration loading: 2 | 3 | - supported and not supported file extensions 4 | - sub-directories 5 | -------------------------------------------------------------------------------- /runtime/src/test/resources/working directory/.jqassistant/scan/scan.yaml: -------------------------------------------------------------------------------- 1 | jqassistant: 2 | scan: 3 | continue-on-error: ${continueOnError:true} 4 | reset: true 5 | include: 6 | files: 7 | - java:classpath::~/my-project/build/classes 8 | properties: 9 | overwritten-user-value: "overwritten" 10 | -------------------------------------------------------------------------------- /scanner/src/main/java/com/buschmais/jqassistant/core/scanner/api/DefaultScope.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.api; 2 | 3 | /** 4 | * The default scope(s). 5 | */ 6 | public enum DefaultScope implements Scope { 7 | 8 | NONE; 9 | @Override 10 | public String getPrefix() { 11 | return "default"; 12 | } 13 | 14 | @Override 15 | public String getName() { 16 | return name(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scanner/src/main/java/com/buschmais/jqassistant/core/scanner/api/Scanner.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.api; 2 | 3 | import java.io.IOException; 4 | 5 | import com.buschmais.jqassistant.core.scanner.api.configuration.Scan; 6 | import com.buschmais.jqassistant.core.store.api.model.Descriptor; 7 | 8 | /** 9 | * Defines the scanner interface. 10 | */ 11 | public interface Scanner { 12 | 13 | /** 14 | * Return the scanner configuration. 15 | */ 16 | Scan getConfiguration(); 17 | 18 | /** 19 | * Scan the given item, e.g. a file, inputstream, directory, etc. 20 | * 21 | * @param item 22 | * The item. 23 | * @param path 24 | * The path to be passed to the plugins. 25 | * @param scope 26 | * The scope to passed to the plugins. 27 | * @param 28 | * The item type. 29 | * @param 30 | * The corresponding descriptor type. 31 | * @return The {@link Descriptor} as returned by the plugins. 32 | * @throws IOException 33 | * If scanning fails. 34 | */ 35 | D scan(I item, String path, Scope scope); 36 | 37 | D scan(I item, D descriptor, String path, Scope scope); 38 | 39 | /** 40 | * Return an instance of the scanner context. 41 | * 42 | * @return The scanner context. 43 | */ 44 | ScannerContext getContext(); 45 | 46 | /** 47 | * Resolve the scope identified by the given fully qualified name. 48 | * 49 | * @param name 50 | * The fully qualified name. 51 | * @return The scope. 52 | */ 53 | Scope resolveScope(String name); 54 | } 55 | -------------------------------------------------------------------------------- /scanner/src/main/java/com/buschmais/jqassistant/core/scanner/api/Scope.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.api; 2 | 3 | /** 4 | * Interface defining a scope, e.g. a Java classpath. 5 | */ 6 | public interface Scope { 7 | 8 | /** 9 | * Return the prefix of the scope, e.g. "java". 10 | * 11 | * @return The prefix. 12 | */ 13 | String getPrefix(); 14 | 15 | /** 16 | * Return the name of the scope. 17 | * 18 | * @return The name. 19 | */ 20 | String getName(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /scanner/src/main/java/com/buschmais/jqassistant/core/scanner/api/configuration/Include.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.api.configuration; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | import com.buschmais.jqassistant.core.shared.annotation.Description; 7 | 8 | import io.smallrye.config.ConfigMapping; 9 | 10 | @ConfigMapping(prefix = "jqassistant.scan.include") 11 | @Description("The items and (e.g. files, URLs) to include for scanning. Every item may be prefixed by a scope using '::' as separator., e.g. 'java:classpath::build/classes'.") 12 | public interface Include { 13 | 14 | String FILES = "files"; 15 | 16 | @Description("The files to include.") 17 | Optional> files(); 18 | 19 | String URLS = "urls"; 20 | 21 | @Description("The URLs to include.") 22 | Optional> urls(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /scanner/src/main/java/com/buschmais/jqassistant/core/scanner/api/configuration/Scan.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.api.configuration; 2 | 3 | import java.util.Map; 4 | import java.util.Optional; 5 | 6 | import com.buschmais.jqassistant.core.shared.annotation.Description; 7 | 8 | import io.smallrye.config.ConfigMapping; 9 | import io.smallrye.config.WithDefault; 10 | 11 | @ConfigMapping(prefix = "jqassistant.scan") 12 | public interface Scan { 13 | 14 | String RESET = "reset"; 15 | 16 | @Description("Indicates whether to initially reset the store (i.e. clear all nodes and relationships) before scanning.") 17 | Optional reset(); 18 | 19 | String CONTINUE_ON_ERROR = "continue-on-error"; 20 | 21 | @Description("Specifies if a scan shall be continued if an error is encountered.") 22 | @WithDefault("false") 23 | boolean continueOnError(); 24 | 25 | String INCLUDE = "include"; 26 | 27 | @Description("The items to include for scanning.") 28 | Optional include(); 29 | 30 | String PROPERTIES = "properties"; 31 | 32 | @Description("The properties to configure scanner plugins. The supported properties are plugin specific.") 33 | Map properties(); 34 | } 35 | -------------------------------------------------------------------------------- /scanner/src/main/java/com/buschmais/jqassistant/core/scanner/impl/UnrecoverableScannerException.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.impl; 2 | 3 | /** 4 | * A specific {@link RuntimeException} that is thrown by the scanner if an 5 | * unrecoverable problem occurred. 6 | */ 7 | public class UnrecoverableScannerException extends RuntimeException { 8 | 9 | public UnrecoverableScannerException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /scanner/src/main/java/com/buschmais/jqassistant/core/scanner/spi/ScannerPluginRepository.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.spi; 2 | 3 | import java.util.Map; 4 | import java.util.Set; 5 | 6 | import com.buschmais.jqassistant.core.scanner.api.ScannerContext; 7 | import com.buschmais.jqassistant.core.scanner.api.ScannerPlugin; 8 | import com.buschmais.jqassistant.core.scanner.api.Scope; 9 | import com.buschmais.jqassistant.core.scanner.api.configuration.Scan; 10 | import com.buschmais.jqassistant.core.shared.lifecycle.LifecycleAware; 11 | 12 | /** 13 | * Defines the interface for the scanner plugin repository. 14 | */ 15 | public interface ScannerPluginRepository extends LifecycleAware { 16 | 17 | /** 18 | * Return the instances of the configured scanner plugins. 19 | * 20 | * @param scan 21 | * The scan configuration. 22 | * @param scannerContext 23 | * The scannerContext. 24 | * @return The instances of the configured scanner plugins. 25 | */ 26 | Set> getScannerPlugins(Scan scan, ScannerContext scannerContext); 27 | 28 | /** 29 | * Return the scope for the given name. 30 | * 31 | * @param name 32 | * The name. 33 | * @return The scope. 34 | */ 35 | Scope getScope(String name); 36 | 37 | /** 38 | * Return a map of all scopes identified by their fully qualified name. 39 | * 40 | * @return The map of all scopes. 41 | */ 42 | Map getScopes(); 43 | 44 | @Override 45 | void initialize(); 46 | 47 | @Override 48 | void destroy(); 49 | } 50 | -------------------------------------------------------------------------------- /scanner/src/test/java/com/buschmais/jqassistant/core/scanner/api/ScopeHelperTest.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.api; 2 | 3 | import java.util.List; 4 | 5 | import com.buschmais.jqassistant.core.scanner.api.ScopeHelper.ScopedResource; 6 | 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static java.util.Arrays.asList; 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | @Slf4j 14 | class ScopeHelperTest { 15 | 16 | private ScopeHelper scopeHelper = new ScopeHelper(log); 17 | 18 | /** 19 | * Verifies parsing scoped resources from a command line, including trimming of 20 | * leading/trailing slashes 21 | */ 22 | @Test 23 | void getScopedResourcesFromString() { 24 | List scopedResources = scopeHelper.getScopedResources(" build/images , java:classpath::build/classes "); 25 | verifyScopedResources(scopedResources); 26 | } 27 | 28 | /** 29 | * Verifies parsing scoped resources from a list. 30 | */ 31 | @Test 32 | void getScopedResourcesFromList() { 33 | List scopedResources = scopeHelper.getScopedResources(asList(" build/images ", " java:classpath::build/classes ")); 34 | verifyScopedResources(scopedResources); 35 | } 36 | 37 | private void verifyScopedResources(List scopedResources) { 38 | assertThat(scopedResources).hasSize(2); 39 | assertThat(scopedResources).containsExactly(ScopedResource.builder().resource("build/images").build(), 40 | ScopedResource.builder().resource("build/classes").scopeName("java:classpath").build()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /scanner/src/test/java/com/buschmais/jqassistant/core/scanner/impl/DependentTestItemDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.impl; 2 | 3 | import com.buschmais.xo.neo4j.api.annotation.Label; 4 | 5 | @Label("Dependent") 6 | public interface DependentTestItemDescriptor extends TestItemDescriptor { 7 | } 8 | -------------------------------------------------------------------------------- /scanner/src/test/java/com/buschmais/jqassistant/core/scanner/impl/DependentTestItemScannerPlugin.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.impl; 2 | 3 | import java.io.IOException; 4 | import java.util.Map; 5 | 6 | import com.buschmais.jqassistant.core.scanner.api.Scanner; 7 | import com.buschmais.jqassistant.core.scanner.api.ScannerContext; 8 | import com.buschmais.jqassistant.core.scanner.api.ScannerPlugin; 9 | import com.buschmais.jqassistant.core.scanner.api.ScannerPlugin.Requires; 10 | import com.buschmais.jqassistant.core.scanner.api.Scope; 11 | 12 | /** 13 | * Test plugin: delegates scanning of the item using a custom scope before 14 | * migrating the returned descriptor to TestDescriptor2. 15 | */ 16 | @Requires(TestItemDescriptor.class) 17 | public class DependentTestItemScannerPlugin implements ScannerPlugin { 18 | 19 | @Override 20 | public void initialize() { 21 | } 22 | 23 | @Override 24 | public void configure(ScannerContext scannerContext, Map properties) { 25 | } 26 | 27 | @Override 28 | public Class getType() { 29 | return TestItem.class; 30 | } 31 | 32 | @Override 33 | public Class getDescriptorType() { 34 | return DependentTestItemDescriptor.class; 35 | } 36 | 37 | @Override 38 | public boolean accepts(TestItem item, String path, Scope scope) throws IOException { 39 | return true; 40 | } 41 | 42 | @Override 43 | public DependentTestItemDescriptor scan(TestItem item, String path, Scope scope, Scanner scanner) { 44 | NestedTestItemDescriptor nestedTestItemDescriptor = scanner.scan(item, path, TestScope.TEST); 45 | return scanner.getContext().getStore().addDescriptorType(nestedTestItemDescriptor, DependentTestItemDescriptor.class); 46 | } 47 | 48 | @Override 49 | public String getName() { 50 | return DependentTestItemScannerPlugin.class.getSimpleName(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /scanner/src/test/java/com/buschmais/jqassistant/core/scanner/impl/NestedTestItemDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.impl; 2 | 3 | import com.buschmais.jqassistant.core.store.api.model.Descriptor; 4 | import com.buschmais.xo.neo4j.api.annotation.Label; 5 | 6 | @Label("Nested") 7 | public interface NestedTestItemDescriptor extends Descriptor { 8 | } 9 | -------------------------------------------------------------------------------- /scanner/src/test/java/com/buschmais/jqassistant/core/scanner/impl/NestedTestItemScannerPlugin.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.impl; 2 | 3 | import java.util.Map; 4 | 5 | import com.buschmais.jqassistant.core.scanner.api.Scanner; 6 | import com.buschmais.jqassistant.core.scanner.api.ScannerContext; 7 | import com.buschmais.jqassistant.core.scanner.api.ScannerPlugin; 8 | import com.buschmais.jqassistant.core.scanner.api.Scope; 9 | 10 | /** 11 | * Test plugin: migrates a required {@link TestItemDescriptor} to a {@link NestedTestItemDescriptor}. 12 | */ 13 | public class NestedTestItemScannerPlugin implements ScannerPlugin { 14 | 15 | @Override 16 | public void initialize() { 17 | } 18 | 19 | @Override 20 | public void configure(ScannerContext scannerContext, Map properties) { 21 | } 22 | 23 | @Override 24 | public String getName() { 25 | return NestedTestItemScannerPlugin.class.getSimpleName(); 26 | } 27 | 28 | @Override 29 | public Class getType() { 30 | return TestItem.class; 31 | } 32 | 33 | @Override 34 | public Class getDescriptorType() { 35 | return NestedTestItemDescriptor.class; 36 | } 37 | 38 | @Override 39 | public boolean accepts(TestItem item, String path, Scope scope) { 40 | return TestScope.TEST.equals(scope); 41 | } 42 | 43 | @Override 44 | public NestedTestItemDescriptor scan(TestItem item, String path, Scope scope, Scanner scanner) { 45 | TestItemDescriptor testItemDescriptor = scanner.getContext().getCurrentDescriptor(); 46 | return scanner.getContext().getStore().addDescriptorType(testItemDescriptor, NestedTestItemDescriptor.class); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /scanner/src/test/java/com/buschmais/jqassistant/core/scanner/impl/TestItem.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.impl; 2 | 3 | public class TestItem { 4 | } 5 | -------------------------------------------------------------------------------- /scanner/src/test/java/com/buschmais/jqassistant/core/scanner/impl/TestItemDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.impl; 2 | 3 | import com.buschmais.jqassistant.core.store.api.model.Descriptor; 4 | import com.buschmais.xo.neo4j.api.annotation.Label; 5 | 6 | @Label("Item") 7 | public interface TestItemDescriptor extends Descriptor { 8 | } 9 | -------------------------------------------------------------------------------- /scanner/src/test/java/com/buschmais/jqassistant/core/scanner/impl/TestItemScannerPlugin.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.impl; 2 | 3 | import java.io.IOException; 4 | import java.util.Map; 5 | 6 | import com.buschmais.jqassistant.core.scanner.api.Scanner; 7 | import com.buschmais.jqassistant.core.scanner.api.ScannerContext; 8 | import com.buschmais.jqassistant.core.scanner.api.ScannerPlugin; 9 | import com.buschmais.jqassistant.core.scanner.api.Scope; 10 | 11 | /** 12 | * Test plugin: creates a TestDescriptor1. 13 | */ 14 | public class TestItemScannerPlugin implements ScannerPlugin { 15 | 16 | @Override 17 | public void initialize() { 18 | } 19 | 20 | @Override 21 | public void configure(ScannerContext scannerContext, Map properties) { 22 | } 23 | 24 | @Override 25 | public Class getType() { 26 | return TestItem.class; 27 | } 28 | 29 | @Override 30 | public Class getDescriptorType() { 31 | return TestItemDescriptor.class; 32 | } 33 | 34 | @Override 35 | public boolean accepts(TestItem item, String path, Scope scope) throws IOException { 36 | return true; 37 | } 38 | 39 | @Override 40 | public TestItemDescriptor scan(TestItem item, String path, Scope scope, Scanner scanner) throws IOException { 41 | return scanner.getContext().getStore().create(TestItemDescriptor.class); 42 | } 43 | 44 | @Override 45 | public String getName() { 46 | return TestItemScannerPlugin.class.getSimpleName(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /scanner/src/test/java/com/buschmais/jqassistant/core/scanner/impl/TestScope.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.scanner.impl; 2 | 3 | import com.buschmais.jqassistant.core.scanner.api.Scope; 4 | 5 | public enum TestScope implements Scope { 6 | 7 | TEST; 8 | 9 | @Override 10 | public String getPrefix() { 11 | return "test"; 12 | } 13 | 14 | @Override 15 | public String getName() { 16 | return name(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /schemata/src/main/resources/META-INF/rule/jsonschema/jqassistant-rule-v1.8.schema.readme: -------------------------------------------------------------------------------- 1 | Comment on the Implementation of the Schema 2 | 3 | Unfortunately this scheme cannot make full use of definitions, as would 4 | be desirable. 5 | 6 | The reason is, that the current version (2019-09) does not offer 7 | full support for extending subschemas. allOf allows to combine 8 | two subschemas, but not to restrict the set of allowed properties 9 | by setting additionalProperties to false. Therefore some parts 10 | of the schema definition might seems to be redudant to the reader of 11 | the schema specification. 12 | 13 | For more details on that, please read the section "allOf" in the 14 | document "Combining schemas" at 15 | https://json-schema.org/understanding-json-schema/reference/combining.html 16 | 17 | 18 | Oliver B. Fischer 19 | 2020-04-01 20 | -------------------------------------------------------------------------------- /shared/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | com.buschmais.jqassistant.core 5 | parent 6 | 2.4.0-SNAPSHOT 7 | 8 | shared 9 | jQAssistant Core Shared 10 | 11 | 12 | 13 | io.smallrye.config 14 | smallrye-config-core 15 | 16 | 17 | javax.xml.bind 18 | jaxb-api 19 | 20 | 21 | javax.annotation 22 | javax.annotation-api 23 | 24 | 25 | org.slf4j 26 | slf4j-api 27 | compile 28 | 29 | 30 | org.slf4j 31 | jcl-over-slf4j 32 | runtime 33 | 34 | 35 | commons-lang 36 | commons-lang 37 | 38 | 39 | commons-codec 40 | commons-codec 41 | 42 | 43 | com.google.guava 44 | guava 45 | 46 | 47 | org.mapstruct 48 | mapstruct 49 | 50 | 51 | org.projectlombok 52 | lombok 53 | 54 | 55 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/annotation/Description.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | 5 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 6 | 7 | /** 8 | * Annotation providing a description text. 9 | */ 10 | @Retention(RUNTIME) 11 | public @interface Description { 12 | 13 | String value(); 14 | 15 | boolean deprecated() default false; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/annotation/PublicApi.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Marks a type as part of the public API of jQAssistant. 11 | */ 12 | @Retention(RetentionPolicy.CLASS) 13 | @Target({ElementType.TYPE}) 14 | @Documented 15 | public @interface PublicApi { 16 | } 17 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/annotation/ToBeRemovedInVersion.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | /** 7 | * Indicates in which version a deprecated element (e.g. class, method, etc.) will be removed. 8 | *

9 | * Every element annotated with {@link Deprecated} should also provide this annotation. 10 | * TODO: Verify with a jQA rule. 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface ToBeRemovedInVersion { 14 | 15 | /** 16 | * Return the major version. 17 | * 18 | * @return The major version. 19 | */ 20 | int major(); 21 | 22 | /** 23 | * Return the minor version. 24 | * 25 | * @return The minor version. 26 | */ 27 | int minor(); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/artifact/ArtifactProvider.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.artifact; 2 | 3 | import java.io.File; 4 | import java.util.List; 5 | 6 | import com.buschmais.jqassistant.core.shared.configuration.Plugin; 7 | 8 | public interface ArtifactProvider { 9 | 10 | List resolve(List plugins); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/configuration/Exclusion.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.configuration; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | import com.buschmais.jqassistant.core.shared.annotation.Description; 7 | 8 | import io.smallrye.config.ConfigMapping; 9 | import io.smallrye.config.WithDefault; 10 | 11 | @ConfigMapping 12 | @Description("Defines a dependency exclusion.") 13 | public interface Exclusion { 14 | 15 | @Description("The groupId of the exclusion.") 16 | String groupId(); 17 | 18 | @Description("The artifactId of the exclusion.") 19 | List artifactId(); 20 | 21 | @Description("The classifier of the exclusion (optional).") 22 | Optional classifier(); 23 | 24 | @Description("The type (extension) of the exclusion.") 25 | @WithDefault("jar") 26 | String type(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/configuration/Plugin.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.configuration; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | import com.buschmais.jqassistant.core.shared.annotation.Description; 7 | 8 | import io.smallrye.config.ConfigMapping; 9 | import io.smallrye.config.WithDefault; 10 | 11 | @ConfigMapping 12 | @Description("The configuration for a plugin which can be resolved by Maven coordinates, i.e. groupId, artifactId, type, classifier and version.") 13 | public interface Plugin { 14 | 15 | @Description("The groupId of the plugin.") 16 | String groupId(); 17 | 18 | @Description("The classifier of the plugin (optional).") 19 | Optional classifier(); 20 | 21 | @Description("The artifactId of the plugin.") 22 | List artifactId(); 23 | 24 | @Description("The type (extension) of the plugin.") 25 | @WithDefault("jar") 26 | String type(); 27 | 28 | @Description("The version of the plugin.") 29 | String version(); 30 | 31 | @Description("The exclusions of the plugin.") 32 | List exclusions(); 33 | } 34 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/io/ClasspathResource.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.io; 2 | 3 | import java.io.File; 4 | import java.io.UnsupportedEncodingException; 5 | import java.net.URL; 6 | import java.net.URLDecoder; 7 | 8 | /** 9 | * Provides functionality to load test resources. 10 | */ 11 | public class ClasspathResource { 12 | 13 | public static File getFile(String resource) { 14 | return getFile(ClasspathResource.class, resource); 15 | } 16 | 17 | public static File getFile(Class type, String resource) { 18 | URL url = type.getResource(resource); 19 | try { 20 | return new File(URLDecoder.decode(url.getFile(), "UTF-8")); 21 | } catch (UnsupportedEncodingException e) { 22 | throw new IllegalArgumentException("Cannot decode URL " + url, e); 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/io/FileNameNormalizer.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.io; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * Provides functionality for normalizing file names, e.g. replacing backslashes 7 | * by dashes (Unix style). 8 | */ 9 | public final class FileNameNormalizer { 10 | 11 | private FileNameNormalizer() { 12 | } 13 | 14 | /** 15 | * @param path 16 | * The path. 17 | * @return The slashified path. 18 | */ 19 | public static String normalize(String path) { 20 | return path.replace('\\', '/'); 21 | } 22 | 23 | /** 24 | * @param file 25 | * The {@link File}. 26 | * @return The slashified path. 27 | */ 28 | public static String normalize(File file) { 29 | return normalize(file.getAbsolutePath()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/io/FilePattern.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.io; 2 | 3 | import java.io.File; 4 | import java.util.Set; 5 | 6 | import lombok.Builder; 7 | import lombok.Getter; 8 | import lombok.ToString; 9 | 10 | /** 11 | * Represents file pattern consisting of includes and excludes, each of them supporting the wildcards "?" and "*". 12 | *

13 | * A matcher evaluates all include patterns before applying the exclude patterns. 14 | */ 15 | @Getter 16 | @Builder 17 | @ToString 18 | public class FilePattern { 19 | 20 | private File directory; 21 | 22 | private Set includes; 23 | 24 | private Set excludes; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/lifecycle/ConfigurableLifecycleAware.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.lifecycle; 2 | 3 | /** 4 | * Defines the interface for {@link LifecycleAware} instances that are 5 | * configurable. 6 | * 7 | * @param 8 | * The configuration type. 9 | */ 10 | public interface ConfigurableLifecycleAware extends LifecycleAware { 11 | 12 | /** 13 | * Configure the instance. 14 | * 15 | * This method is always called at least once after {@link #initialize()} and 16 | * allows re-configuring a an instance at runtime (e.g. in a Maven multi-module 17 | * build process). 18 | * 19 | * @param configuration 20 | * The configuration. 21 | * @throws Exception 22 | * If configuration fails. 23 | */ 24 | default void configure(CONFIGURATION configuration) throws Exception { 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/lifecycle/ContextualConfigurableLifecycleAware.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.lifecycle; 2 | 3 | /** 4 | * Defines the interface for {@link LifecycleAware} instances that are 5 | * configurable and using a context. 6 | * 7 | * @param 8 | * The context type. 9 | * @param 10 | * The configuration type. 11 | */ 12 | public interface ContextualConfigurableLifecycleAware extends LifecycleAware { 13 | 14 | /** 15 | * Configure the instance. 16 | * 17 | * This method is always called at least once after {@link #initialize()} and 18 | * allows re-configuring a an instance at runtime (e.g. in a Maven multi-module 19 | * build process). 20 | * 21 | * @param context 22 | * The context. 23 | * @param configuration 24 | * The configuration. 25 | * @throws Exception 26 | * If configuration fails. 27 | */ 28 | default void configure(CONTEXT context, CONFIGURATION configuration) throws Exception { 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/lifecycle/LifecycleAware.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.lifecycle; 2 | 3 | /** 4 | * Defines the interface for instances that have a lifecycle managed by the 5 | * framework. 6 | */ 7 | public interface LifecycleAware { 8 | 9 | /** 10 | * Initialize the instance. 11 | * 12 | * Life cycle callback to perform initialization (e.g. expensive instantiaion of 13 | * {@link javax.xml.bind.JAXBContext}s), will be called exactly once. 14 | * 15 | * @throws Exception 16 | * If initialization fails. 17 | */ 18 | default void initialize() throws Exception { 19 | } 20 | 21 | /** 22 | * Destroy the instance, will be called exactly once. 23 | * 24 | * @throws Exception 25 | * If destruction fails. 26 | */ 27 | default void destroy() throws Exception { 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/map/MapBuilder.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.map; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import static java.util.Collections.unmodifiableMap; 7 | 8 | /** 9 | * Utility class for building maps using a fluent API. 10 | * 11 | * @param 12 | * The key type. 13 | * @param 14 | * The value Type. 15 | */ 16 | public class MapBuilder { 17 | 18 | private Map map = new HashMap<>(); 19 | 20 | /** 21 | * Private constructor. 22 | */ 23 | protected MapBuilder() { 24 | } 25 | 26 | /** 27 | * Create a map builder instance. 28 | * 29 | * @return The map builder instance. 30 | */ 31 | public static MapBuilder builder() { 32 | return new MapBuilder<>(); 33 | } 34 | 35 | /** 36 | * Add an entry. 37 | * 38 | * @param key 39 | * The key. 40 | * @param value 41 | * The value. 42 | * @return The map builder. 43 | */ 44 | public MapBuilder entry(K key, V value) { 45 | map.put(key, value); 46 | return this; 47 | } 48 | 49 | /** 50 | * Return the map. 51 | * 52 | * @return The map. 53 | */ 54 | public Map build() { 55 | return unmodifiableMap(map); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/option/OptionHelper.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.option; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | /** 7 | * Provides shared functionality for working with options, e.g. from the command 8 | * line. 9 | */ 10 | public final class OptionHelper { 11 | 12 | private static final Logger LOGGER = LoggerFactory.getLogger(OptionHelper.class); 13 | 14 | /** 15 | * Determine the first non-null value from the given options. 16 | * 17 | * @param values 18 | * The option that override the default value, the first non-null 19 | * value will be accepted. 20 | * @param 21 | * The value type. 22 | * @return The value. 23 | */ 24 | public static T coalesce(T... values) { 25 | for (T override : values) { 26 | if (override != null) { 27 | return override; 28 | } 29 | } 30 | return null; 31 | } 32 | 33 | /** 34 | * Verify if a deprecated option has been used and emit a warning. 35 | * 36 | * @param deprecatedOption 37 | * The name of the deprecated option. 38 | * @param value 39 | * The provided value. 40 | * @param option 41 | * The option to use. 42 | * @param 43 | * The value type. 44 | */ 45 | public static void verifyDeprecatedOption(String deprecatedOption, T value, String option) { 46 | if (value != null) { 47 | LOGGER.warn("The option '" + deprecatedOption + "' is deprecated, use '" + option + "' instead."); 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/reflection/ClassHelper.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.reflection; 2 | 3 | /** 4 | * Provides functionality related to class loading and instance creation. 5 | */ 6 | public class ClassHelper { 7 | 8 | private ClassLoader classLoader; 9 | 10 | /** 11 | * Constructor. 12 | * 13 | * @param classLoader The classloader to use. 14 | */ 15 | public ClassHelper(ClassLoader classLoader) { 16 | this.classLoader = classLoader; 17 | } 18 | 19 | /** 20 | * Create and return an instance of the given type name. 21 | * 22 | * @param typeName The type name. 23 | * @param The type. 24 | * @return The instance. 25 | */ 26 | public Class getType(String typeName) { 27 | try { 28 | return (Class) classLoader.loadClass(typeName); 29 | } catch (ClassNotFoundException e) { 30 | throw new IllegalArgumentException("Cannot find class " + typeName, e); 31 | } 32 | } 33 | 34 | /** 35 | * Create an instance of the given class. 36 | * 37 | * @param type The type. 38 | * @param typeName The type name. 39 | * @param The type. 40 | * @return The scanner plugin instance. 41 | */ 42 | public T createInstance(Class type, String typeName) { 43 | try { 44 | return type.cast(getType(typeName).newInstance()); 45 | } catch (InstantiationException | IllegalAccessException e) { 46 | throw new IllegalArgumentException("Cannot create instance of class " + type.getName(), e); 47 | } 48 | } 49 | 50 | /** 51 | * Create an instance of the given class. 52 | * 53 | * @param type The type. 54 | * @param The type. 55 | * @return The scanner plugin instance. 56 | */ 57 | public T createInstance(Class type) { 58 | try { 59 | return type.newInstance(); 60 | } catch (InstantiationException | IllegalAccessException e) { 61 | throw new IllegalArgumentException("Cannot create instance of class " + type.getName(), e); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /shared/src/main/java/com/buschmais/jqassistant/core/shared/transaction/Transactional.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.shared.transaction; 2 | 3 | /** 4 | * Defines the interface for transactional actions. 5 | */ 6 | public interface Transactional { 7 | 8 | /** 9 | * Execute a transactional action. 10 | * @param transactionalAction The {@link TransactionalAction}. 11 | * @param The execption type. 12 | * @throws E The execption type. 13 | */ 14 | void requireTransaction(TransactionalAction transactionalAction) throws E; 15 | 16 | /** 17 | * Execute a transactional supplier. 18 | * @param transactionalSupplier The {@link TransactionalAction}. 19 | * @param The execption type. 20 | * @throws E The execption type. 21 | */ 22 | T requireTransaction(TransactionalSupplier transactionalSupplier) throws E; 23 | 24 | /** 25 | * Defines a transactional action. 26 | */ 27 | interface TransactionalAction { 28 | void execute() throws E; 29 | } 30 | 31 | /** 32 | * Defines a transactional supplier. 33 | */ 34 | interface TransactionalSupplier { 35 | T execute() throws E; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /store/src/main/java/com/buschmais/jqassistant/core/store/api/configuration/Embedded.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.store.api.configuration; 2 | 3 | import java.io.File; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | import com.buschmais.jqassistant.core.shared.configuration.Plugin; 8 | 9 | import io.smallrye.config.ConfigMapping; 10 | import io.smallrye.config.WithDefault; 11 | 12 | @ConfigMapping(prefix = "jqassistant.store.embedded") 13 | public interface Embedded { 14 | 15 | String DEFAULT_LISTEN_ADDRESS = "localhost"; 16 | String DEFAULT_BOLT_PORT = "7687"; 17 | String DEFAULT_HTTP_PORT = "7474"; 18 | 19 | String CONNECTOR_ENABLED = "connector-enabled"; 20 | 21 | @WithDefault("false") 22 | boolean connectorEnabled(); 23 | 24 | String LISTEN_ADDRESS = "listen-address"; 25 | 26 | @WithDefault(DEFAULT_LISTEN_ADDRESS) 27 | String listenAddress(); 28 | 29 | String BOLT_PORT = "bolt-port"; 30 | 31 | @WithDefault(DEFAULT_BOLT_PORT) 32 | Integer boltPort(); 33 | 34 | String HTTP_PORT = "http-port"; 35 | 36 | @WithDefault(DEFAULT_HTTP_PORT) 37 | Integer httpPort(); 38 | 39 | String NEO4J_PLUGINS = "neo4j-plugins"; 40 | 41 | List neo4jPlugins(); 42 | 43 | String NEO4J_PLUGIN_DIRECTORY = "neo4j-plugin-directory"; 44 | Optional neo4jPluginDirectory(); 45 | } 46 | -------------------------------------------------------------------------------- /store/src/main/java/com/buschmais/jqassistant/core/store/api/configuration/Remote.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.store.api.configuration; 2 | 3 | import java.util.Map; 4 | import java.util.Optional; 5 | 6 | import com.buschmais.jqassistant.core.shared.annotation.Description; 7 | 8 | import io.smallrye.config.ConfigMapping; 9 | import io.smallrye.config.WithDefault; 10 | 11 | @ConfigMapping(prefix = "jqassistant.store.remote") 12 | public interface Remote { 13 | 14 | String USERNAME = "username"; 15 | 16 | @Description("The username 'bolt' connections.") 17 | Optional username(); 18 | 19 | String PASSWORD = "password"; 20 | 21 | @Description("The password 'bolt' connections.") 22 | Optional password(); 23 | 24 | String ENCRYPTION = "encryption"; 25 | 26 | @Description("Activate encryption level for 'bolt' connections.") 27 | @WithDefault("false") 28 | boolean encryption(); 29 | 30 | String TRUST_STRATEGY = "trust-strategy"; 31 | 32 | @Description("The trust strategy for 'bolt' connections: trustAllCertificates (default), trustCustomCaSignedCertificates or trustSystemCaSignedCertificates.") 33 | Optional trustStrategy(); 34 | 35 | String TRUST_CERTIFICATE = "trust-certificate"; 36 | 37 | @Description("The file containing the custom CA certificate for trust strategy.") 38 | Optional trustCertificate(); 39 | 40 | String PROPERTIES = "properties"; 41 | 42 | @Description("Additional properties to be passed to the store.") 43 | Map properties(); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /store/src/main/java/com/buschmais/jqassistant/core/store/api/configuration/Store.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.store.api.configuration; 2 | 3 | import java.net.URI; 4 | import java.util.Optional; 5 | 6 | import com.buschmais.jqassistant.core.shared.annotation.Description; 7 | 8 | import io.smallrye.config.ConfigMapping; 9 | 10 | @ConfigMapping(prefix = "jqassistant.store") 11 | public interface Store { 12 | 13 | String URI = "uri"; 14 | 15 | @Description("URI of the database to connect to. Supported URI schemes are 'file' for embedded databases and 'bolt' for connecting to a running Neo4j instance (3.x+).") 16 | Optional uri(); 17 | 18 | @Description("Configuration of the embedded store.") 19 | Embedded embedded(); 20 | 21 | @Description("Configuration of the remote store.") 22 | Remote remote(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /store/src/main/java/com/buschmais/jqassistant/core/store/api/model/Descriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.store.api.model; 2 | 3 | import com.buschmais.xo.api.CompositeObject; 4 | 5 | /** 6 | * Base interface for all descriptors (e.g. classes, fields, methods, etc.) 7 | */ 8 | public interface Descriptor extends CompositeObject { 9 | } 10 | -------------------------------------------------------------------------------- /store/src/main/java/com/buschmais/jqassistant/core/store/api/model/FullQualifiedNameDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.store.api.model; 2 | 3 | import com.buschmais.xo.neo4j.api.annotation.Indexed; 4 | import com.buschmais.xo.neo4j.api.annotation.Property; 5 | 6 | /** 7 | * Base interface for all indexed descriptors having a property full qualified 8 | * name. 9 | */ 10 | public interface FullQualifiedNameDescriptor extends Descriptor { 11 | 12 | /** 13 | * Return the full qualified name. 14 | * 15 | * @return The full qualified name. 16 | */ 17 | @Property("fqn") 18 | @Indexed 19 | public String getFullQualifiedName(); 20 | 21 | /** 22 | * Set the full qualified name. 23 | * 24 | * @param fullQualifiedName 25 | * The full qualified name. 26 | */ 27 | public void setFullQualifiedName(String fullQualifiedName); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /store/src/main/java/com/buschmais/jqassistant/core/store/api/model/TaskDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.store.api.model; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | import com.buschmais.xo.api.annotation.Abstract; 6 | import com.buschmais.xo.neo4j.api.annotation.Label; 7 | 8 | /** 9 | * Represents a task executed by JQAssistant. 10 | */ 11 | @Abstract 12 | @Label("Task") 13 | public interface TaskDescriptor extends jQAssistantDescriptor { 14 | 15 | LocalDateTime getTimestamp(); 16 | 17 | void setTimestamp(LocalDateTime timestamp); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /store/src/main/java/com/buschmais/jqassistant/core/store/api/model/jQAssistantDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.store.api.model; 2 | 3 | import com.buschmais.xo.api.annotation.Abstract; 4 | import com.buschmais.xo.neo4j.api.annotation.Label; 5 | 6 | @Label("jQAssistant") 7 | @Abstract 8 | public interface jQAssistantDescriptor extends Descriptor { 9 | } 10 | -------------------------------------------------------------------------------- /store/src/main/java/com/buschmais/jqassistant/core/store/spi/StorePluginRepository.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.store.spi; 2 | 3 | import java.util.List; 4 | 5 | import com.buschmais.jqassistant.core.shared.lifecycle.LifecycleAware; 6 | 7 | /** 8 | * Defines the interface for the scanner plugin repository. 9 | */ 10 | public interface StorePluginRepository extends LifecycleAware { 11 | 12 | ClassLoader getClassLoader(); 13 | 14 | /** 15 | * Return the instances of the configured descriptor mappers. 16 | * 17 | * @return The instances of the configured descriptor mappers. 18 | */ 19 | List> getDescriptorTypes(); 20 | 21 | List> getProcedureTypes(); 22 | 23 | List> getFunctionTypes(); 24 | 25 | @Override 26 | default void initialize() { 27 | } 28 | 29 | @Override 30 | default void destroy() { 31 | } 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /test/src/main/java/com/buschmais/jqassistant/core/test/matcher/AbstractDescriptorMatcher.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.test.matcher; 2 | 3 | import com.buschmais.jqassistant.core.store.api.model.FullQualifiedNameDescriptor; 4 | 5 | import lombok.RequiredArgsConstructor; 6 | import org.hamcrest.Description; 7 | import org.hamcrest.TypeSafeMatcher; 8 | 9 | import static lombok.AccessLevel.PROTECTED; 10 | 11 | @RequiredArgsConstructor(access = PROTECTED) 12 | public class AbstractDescriptorMatcher extends TypeSafeMatcher { 13 | 14 | private final Class type; 15 | 16 | private final String fullQualifiedName; 17 | 18 | @Override 19 | public boolean matchesSafely(T item) { 20 | return this.fullQualifiedName.equals(item.getFullQualifiedName()); 21 | } 22 | 23 | @Override 24 | public void describeTo(Description description) { 25 | description.appendText(type.getSimpleName()) 26 | .appendText("(") 27 | .appendText(fullQualifiedName) 28 | .appendText(")"); 29 | } 30 | 31 | @Override 32 | protected void describeMismatchSafely(T item, Description mismatchDescription) { 33 | mismatchDescription.appendText(item.getClass() 34 | .getSimpleName()) 35 | .appendText("(") 36 | .appendText(item.getFullQualifiedName()) 37 | .appendText(")"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/src/main/java/com/buschmais/jqassistant/core/test/matcher/AbstractRuleMatcher.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.test.matcher; 2 | 3 | import com.buschmais.jqassistant.core.rule.api.model.Rule; 4 | 5 | import lombok.RequiredArgsConstructor; 6 | import org.hamcrest.Description; 7 | import org.hamcrest.TypeSafeMatcher; 8 | 9 | import static lombok.AccessLevel.PROTECTED; 10 | 11 | /** 12 | * Abstract base class for rules matchers. 13 | */ 14 | @RequiredArgsConstructor(access = PROTECTED) 15 | public class AbstractRuleMatcher extends TypeSafeMatcher { 16 | 17 | private final Class type; 18 | 19 | private final String id; 20 | 21 | @Override 22 | public boolean matchesSafely(T item) { 23 | return this.id.equals(item.getId()); 24 | } 25 | 26 | @Override 27 | public void describeTo(Description description) { 28 | description.appendText(type.getSimpleName()) 29 | .appendText("(") 30 | .appendText(id) 31 | .appendText(")"); 32 | } 33 | 34 | @Override 35 | protected void describeMismatchSafely(T item, Description mismatchDescription) { 36 | mismatchDescription.appendText(item.getClass() 37 | .getSimpleName()) 38 | .appendText("(") 39 | .appendText(item.getId()) 40 | .appendText(")"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/src/main/java/com/buschmais/jqassistant/core/test/matcher/ConceptMatcher.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.test.matcher; 2 | 3 | import com.buschmais.jqassistant.core.rule.api.model.Concept; 4 | 5 | import org.hamcrest.Matcher; 6 | 7 | /** 8 | * A matcher for {@link Concept}s. 9 | */ 10 | public class ConceptMatcher extends AbstractRuleMatcher { 11 | 12 | /** 13 | * Constructor. 14 | * 15 | * @param id 16 | * The expected concept id. 17 | */ 18 | protected ConceptMatcher(String id) { 19 | super(Concept.class, id); 20 | } 21 | 22 | /** 23 | * Return a {@link ConceptMatcher}. 24 | * 25 | * @param id 26 | * The concept id. 27 | * @return The {@link ConceptMatcher}. 28 | */ 29 | public static Matcher concept(String id) { 30 | return new ConceptMatcher(id); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/src/main/java/com/buschmais/jqassistant/core/test/matcher/ConstraintMatcher.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.test.matcher; 2 | 3 | import com.buschmais.jqassistant.core.rule.api.model.Constraint; 4 | 5 | import org.hamcrest.Matcher; 6 | 7 | /** 8 | * A matcher for {@link Constraint}s. 9 | */ 10 | public class ConstraintMatcher extends AbstractRuleMatcher { 11 | 12 | /** 13 | * Constructor. 14 | * 15 | * @param id 16 | * The expected constraint id. 17 | */ 18 | protected ConstraintMatcher(String id) { 19 | super(Constraint.class, id); 20 | } 21 | 22 | /** 23 | * Return a {@link ConstraintMatcher}. 24 | * 25 | * @param id 26 | * The concept id. 27 | * @return The {@link ConstraintMatcher}. 28 | */ 29 | public static Matcher constraint(String id) { 30 | return new ConstraintMatcher(id); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/src/main/java/com/buschmais/jqassistant/core/test/matcher/GroupMatcher.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.test.matcher; 2 | 3 | import com.buschmais.jqassistant.core.rule.api.model.Group; 4 | 5 | import org.hamcrest.Matcher; 6 | 7 | /** 8 | * A matcher for {@link Group}s. 9 | */ 10 | public class GroupMatcher extends AbstractRuleMatcher { 11 | 12 | /** 13 | * Constructor. 14 | * 15 | * @param id 16 | * The expected group id. 17 | */ 18 | protected GroupMatcher(String id) { 19 | super(Group.class, id); 20 | } 21 | 22 | /** 23 | * Return a {@link GroupMatcher}. 24 | * 25 | * @param id 26 | * The group id. 27 | * @return The {@link GroupMatcher}. 28 | */ 29 | public static Matcher group(String id) { 30 | return new GroupMatcher(id); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/src/main/java/com/buschmais/jqassistant/core/test/mockito/MethodNotMockedAnswer.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.test.mockito; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | import org.mockito.invocation.InvocationOnMock; 6 | import org.mockito.stubbing.Answer; 7 | 8 | public class MethodNotMockedAnswer implements Answer { 9 | @Override 10 | public Object answer(InvocationOnMock invocation) throws Throwable { 11 | Method calledMethod = invocation.getMethod(); 12 | String signature = calledMethod.toGenericString(); 13 | 14 | throw new RuntimeException(signature + " is not mocked!"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/src/main/java/com/buschmais/jqassistant/core/test/plugin/AbstractServerPluginIT.java: -------------------------------------------------------------------------------- 1 | package com.buschmais.jqassistant.core.test.plugin; 2 | 3 | import com.buschmais.jqassistant.core.runtime.api.configuration.ConfigurationBuilder; 4 | import com.buschmais.jqassistant.core.store.api.configuration.Embedded; 5 | import com.buschmais.jqassistant.core.store.impl.EmbeddedGraphStore; 6 | import com.buschmais.jqassistant.neo4j.embedded.EmbeddedNeo4jServer; 7 | 8 | import org.junit.jupiter.api.AfterEach; 9 | import org.junit.jupiter.api.BeforeEach; 10 | 11 | /** 12 | * Abstract base class for server tests. 13 | */ 14 | public abstract class AbstractServerPluginIT extends AbstractPluginIT { 15 | 16 | private EmbeddedNeo4jServer server; 17 | 18 | @Override 19 | protected void configure(ConfigurationBuilder configurationBuilder) { 20 | configurationBuilder.with(Embedded.class, Embedded.CONNECTOR_ENABLED, true); 21 | } 22 | 23 | @BeforeEach 24 | void startServer() { 25 | EmbeddedGraphStore embeddedGraphStore = (EmbeddedGraphStore) store; 26 | server = embeddedGraphStore.getServer(); 27 | server.start(); 28 | } 29 | 30 | @AfterEach 31 | void stopServer() { 32 | if (server != null) { 33 | server.stop(); 34 | } 35 | } 36 | } 37 | --------------------------------------------------------------------------------