diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index ce711731..f4d834da 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,502 +1,10 @@
eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
-org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
-org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
-org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
-org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
-org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
-org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
-org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
-org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
-
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
-org.eclipse.jdt.core.compiler.problem.APILeak=warning
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
-org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
-org.eclipse.jdt.core.compiler.problem.deadCode=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
-org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
-org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
-org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
-org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
-org.eclipse.jdt.core.compiler.problem.nullReference=warning
-org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
-org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
-org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
-org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore
-org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
-org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
-org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.processAnnotations=disabled
-org.eclipse.jdt.core.compiler.release=disabled
-org.eclipse.jdt.core.compiler.source=1.8
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
-org.eclipse.jdt.core.compiler.compliance=1.8
-org.eclipse.jdt.core.compiler.problem.APILeak=warning
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
-org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
-org.eclipse.jdt.core.compiler.problem.deadCode=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
-org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
-org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
-org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
-org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
-org.eclipse.jdt.core.compiler.problem.nullReference=warning
-org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
-org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
-org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
-org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore
-org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
-org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
-org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.processAnnotations=disabled
-org.eclipse.jdt.core.compiler.release=disabled
-org.eclipse.jdt.core.compiler.source=1.8
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
-org.eclipse.jdt.core.compiler.compliance=1.8
-org.eclipse.jdt.core.compiler.problem.APILeak=warning
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
-org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
-org.eclipse.jdt.core.compiler.problem.deadCode=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
-org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
-org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
-org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
-org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
-org.eclipse.jdt.core.compiler.problem.nullReference=warning
-org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
-org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
-org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
-org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore
-org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
-org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
-org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.processAnnotations=disabled
-org.eclipse.jdt.core.compiler.release=disabled
-org.eclipse.jdt.core.compiler.source=1.8
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
-org.eclipse.jdt.core.compiler.compliance=1.8
-org.eclipse.jdt.core.compiler.problem.APILeak=warning
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
-org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
-org.eclipse.jdt.core.compiler.problem.deadCode=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
-org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
-org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
-org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
-org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
-org.eclipse.jdt.core.compiler.problem.nullReference=warning
-org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
-org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
-org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
-org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore
-org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
-org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
-org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.processAnnotations=disabled
-org.eclipse.jdt.core.compiler.release=disabled
-org.eclipse.jdt.core.compiler.source=1.8
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
-org.eclipse.jdt.core.compiler.compliance=1.8
-org.eclipse.jdt.core.compiler.problem.APILeak=warning
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
-org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
-org.eclipse.jdt.core.compiler.problem.deadCode=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
-org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
-org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
-org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
-org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
-org.eclipse.jdt.core.compiler.problem.nullReference=warning
-org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
-org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
-org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
-org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore
-org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
-org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
-org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.processAnnotations=disabled
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
diff --git a/doc/design.md b/doc/design.md
index 340e3753..b1608f71 100644
--- a/doc/design.md
+++ b/doc/design.md
@@ -327,6 +327,40 @@ Covers:
Needs: impl, utest
+#### Plain Text Report Contains Specification Item Origin
+`dsn~reporting.plain-text.specification-item-origin~1`
+
+If enabled, the plain text report shows the origin of a specification item
+
+* for files: `:`
+
+Rationale:
+
+This format is recognized by most IDEs and automatically turned into a link in the IDE's console.
+
+Covers:
+
+* `req~reporting.requirement-origin~1`
+
+#### Plain Text Report Link Contains Specification Item Origin
+`dsn~reporting.plain-text.linked-specification-item-origin~1`
+
+If enabled, the links in the plain text report show the origin of a specification item
+
+* for files: `:`
+
+Rationale:
+
+This format is recognized by most IDEs and automatically turned into a link in the IDE's console.
+
+Covers:
+
+* `req~reporting.requirement-origin~1`
+
+Needs: impl, utest, itest
+
+### HTML Report
+
#### HTML Report Inlines CSS
`dsn~reporting.html.inline_css~1`
@@ -354,6 +388,26 @@ Covers:
Needs: impl, itest
+#### HTML Report Contains Specification Item Origin
+`dsn~reporting.html.specification-item-origin~1`
+
+If enabled, the HTML report shows the origin of a specification item as an HTML link pointing to the source.
+
+Covers:
+
+* `req~reporting.requirement-origin~1`
+
+#### HTML Report Link Contains Specification Item Origin
+`dsn~reporting.html.linked-specification-item-origin~1`
+
+If enabled, the links in the plain text report show the origin of a specification item as an HTML link pointing to the source.
+
+Covers:
+
+* `req~reporting.requirement-origin~1`
+
+Needs: impl, utest, itest
+
# Deployment View
# Concepts
diff --git a/doc/system_requirements.md b/doc/system_requirements.md
index 8dcb0c12..93626ead 100644
--- a/doc/system_requirements.md
+++ b/doc/system_requirements.md
@@ -452,6 +452,25 @@ Reports are the main way to find out if a projects requirements are covered prop
#### Common Report Functions
+##### Requirement Origin in Report
+`req~reporting.requirement-origin~1`
+
+Users can choose to display the requirement origin (e.g. file and line number) in reports:
+
+* In the body of a specification item
+* For each link to a specification item
+
+Rationale:
+
+This is especially useful for debugging since it makes finding broken sources faster.
+
+Covers:
+
+* [feat~plain-text-report~1](#plain-text-report)
+* [feat~html-report~1](#html-report)
+
+Needs: dsn
+
#### Plain Text Report
The plain text report is the most basic report variant. It serves two main purposes:
diff --git a/doc/usage.txt b/doc/usage.txt
index 9420757b..90b649a3 100644
--- a/doc/usage.txt
+++ b/doc/usage.txt
@@ -16,6 +16,8 @@ Tracing options:
Converting options:
-o, --output-format format Requirements format, one of "specobject"
Defaults to "specobject"
+ -s, --show-origin Show the origin of specification items
+ (e.g. file and line number)
Common options:
-f, --file path The output file. Defaults to STDOUT.
diff --git a/doc/user_guide.md b/doc/user_guide.md
index 7e2587db..419af2e4 100644
--- a/doc/user_guide.md
+++ b/doc/user_guide.md
@@ -420,59 +420,105 @@ Defaults to the platform standard if not given.
If you are a software developer planning to integrate OFT into one of your programs or scripts, you will probably want to use the OFT API.
-Below you find a few short examples of how to use the OFT API. For details check the JavaDoc documentation of the interfaces in the source code.
-
-* [org.itsallcode.openfasttrace.Converter](../src/main/java/org/itsallcoded/openfasttrace/Converter.java)
-* [org.itsallcode.openfasttrace.Reporter](../src/main/java/org/itsallcoded/openfasttrace/Reporter.java)
+Below you find a few short examples of how to use the OFT API. For details check the JavaDoc documentation of the interface [org.itsallcode.openfasttrace.Oft](../src/main/java/org/itsallcoded/openfasttrace/Oft.java) in the source code.
### Using OFT From Java
The Java interface uses the "fluent programming" paradigm to make the code more compact and easy to read.
-#### Using the Converter From Java
+The steps that you need to program using the OFT API depend on whether you want to covert between requirement formats
+
+ import -> export
+
+or run a report.
+
+ import -> link -> trace -> report
+
+#### Converting File from Java
-The following example code configures a `Converter` to read input form the relative paths `doc`, `src/main/java` and `src/main/test` and output the result to `/tmp/out.xml` in SpecObject format using Unix newlines.
+The following example code use a OFT as a converter that scans the current working directory recursively (default import setting) and exports the found artifacts with the standard settings to a ReqM2 file.
```JAVA
-import org.itsallcode.openfasttrace.Converter;
-import org.itsallcode.openfasttrace.core.Newline;
-import org.itsallcode.openfasttrace.mode.ConvertMode;
+import org.itsallcode.openfasttrace.Oft;
+import org.itsallcode.openfasttrace.core.SpecificationItem;
+```
-final List inputs = Arrays.asList("doc", "src/main/java", "src/main/test");
-final Converter converter = new ConvertMode();
+Select input paths and import specification items from there:
-converter.addInputs(inputs)
- .setNewline(Newline.UNIX)
- .convertToFileInFormat("/tmp/out.xml", "specobject");
+```JAVA
+final Oft oft = Oft.create();
+final List items = oft.importItems(settings);
```
-#### Using the Tracer From Java
+Export the items:
-The example below shows how to read documents for the `doc` directory ignoring the artifact types `feat` and `dsn`. The collected specification items are then traced and finally output in a plain text report to STDOUT with verbosity level `ALL`.
+```JAVA
+oft.exportToPath(items, Paths.get("/output/path/export.oreqm"));
+```
+
+#### Tracing and Reporting From Java
+
+The example below shows how to use OFT as a reporter.
```JAVA
-import org.itsallcode.openfasttrace.Reporter;
+import org.itsallcode.openfasttrace.Oft;
+import org.itsallcode.openfasttrace.core.LinkedSpecificationItem;
+import org.itsallcode.openfasttrace.core.SpecificationItem;
import org.itsallcode.openfasttrace.core.Trace;
-import org.itsallcode.openfasttrace.mode.ReportMode;
+```
+
+The import is similar to the converter case, except this time we add an input path explicitly for the sake of demonstration:
-final List inputs = Arrays.asList("doc");
-final List ignoreTypes = Arras.asList("feat", "dsn");
-final Reporter reporter = new ReportMode();
+```JAVA
+final ImportSettings settings = ImportSettings //
+ .builder() //
+ .addInputs("/input/path") //
+ .build;
+final Oft oft = Oft.create();
+final List items = oft.importItems(settings);
+```
-reporter.addInputs(inputs)
- .ignoreArtifactTypes(ignoreTypes);
+Now link the items together (i.e. make them navigable):
-final Trace trace = reporter.trace();
+```JAVA
+final List linkedItems = oft.link(items);
+```
-reporter.setReportVerbosity(ReportVerbosity.ALL)
- .reportToStdOutInFormat(trace, "plain");
+Run the tracer on the linked items:
-if(trace.isAllCovered())
+```JAVA
+final Trace trace = oft.trace(linkedItems);
+```
+
+Create a report from the trace:
+
+```JAVA
+oft.reportToStdOut(trace);
+```
+
+You can also use the trace results in you own code:
+
+```JAVA
+if (trace.hasNoDefects())
{
- // do something
+ // ... do something
}
```
+#### Configuring the Steps
+
+Import, export and report each have a overloaded variant that can be configured using the following classes
+
+* [org.itsallcode.openfasttrace.ImportSettings](../src/main/java/org/itsallcoded/openfasttrace/ImportSettings.java)
+* [org.itsallcode.openfasttrace.ExportSettings](../src/main/java/org/itsallcoded/openfasttrace/ExportSettings.java)
+* [org.itsallcode.openfasttrace.ReportSettings](../src/main/java/org/itsallcoded/openfasttrace/ReportSettings.java)
+
+Each of those classes comes with a builder which is called like this:
+
+```JAVA
+ReportSettings settings = ReportSettings.builder().newline(Newline.UNIX).build();
+```
+
## Tool Support
### Tools for Authoring OFT Documents
diff --git a/pom.xml b/pom.xml
index 9bd5c74b..924173cf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
org.itsallcode
openfasttrace
- 1.2.2
+ 2.0.0
OpenFastTrace
Free requirement tracking suite
https://github.com/itsallcode/openfasttrace
@@ -240,7 +240,7 @@
org.itsallcode.openfasttrace.cli.CliStarter
- trace doc src/main/java src/test/java
+ trace -s doc src/main/java src/test/java
diff --git a/src/main/java/org/itsallcode/openfasttrace/Converter.java b/src/main/java/org/itsallcode/openfasttrace/Converter.java
deleted file mode 100644
index 2a23bc29..00000000
--- a/src/main/java/org/itsallcode/openfasttrace/Converter.java
+++ /dev/null
@@ -1,93 +0,0 @@
-
-package org.itsallcode.openfasttrace;
-
-/*-
- * #%L
- \* OpenFastTrace
- * %%
- * Copyright (C) 2016 - 2017 itsallcode.org
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-import java.nio.file.Path;
-import java.util.List;
-
-import org.itsallcode.openfasttrace.core.Newline;
-import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig;
-
-/**
- * Convert between different requirements formats (e.g. from ReqM2 to Markdown)
- */
-public interface Converter
-{
- /**
- * Select one or more input files
- *
- * @param inputs
- * input files
- * @return a Converter
instance for fluent programming
- */
- public Converter addInputs(final Path... inputs);
-
- /**
- * Select one or more input files
- *
- * @param inputs
- * input files
- * @return a Converter
instance for fluent programming
- */
- public Converter addInputs(final List inputs);
-
- /**
- * Set the filters to be applied during conversion
- *
- * @param filterSettings
- * the filter settings
- */
- public Converter setFilters(FilterSettings filterSettings);
-
- /**
- * Set the representation for new line
- *
- * @param newline
- * type of newline
- * @return a Converter
instance for fluent programming
- */
- public Converter setNewline(Newline newline);
-
- /**
- * Set the {@link TagImporterConfig} for the
- * {@link LegacyTagImporterFactory}.
- *
- * @param config
- * the {@link TagImporterConfig} to set.
- * @return a Converter
instance for fluent programming
- */
- public Converter setLegacyTagImporterPathConfig(final TagImporterConfig config);
-
- /**
- * Convert the collected requirements into target requirement format
- *
- * @param output
- * output file
- *
- * @param format
- * target format (this is a name defined in the respective
- * exporter plug-in)
- */
- public void convertToFileInFormat(final Path output, final String format);
-}
diff --git a/src/main/java/org/itsallcode/openfasttrace/ExportSettings.java b/src/main/java/org/itsallcode/openfasttrace/ExportSettings.java
new file mode 100644
index 00000000..bf71287d
--- /dev/null
+++ b/src/main/java/org/itsallcode/openfasttrace/ExportSettings.java
@@ -0,0 +1,129 @@
+package org.itsallcode.openfasttrace;
+
+/*-
+ * #%L
+ * OpenFastTrace
+ * %%
+ * Copyright (C) 2016 - 2018 itsallcode.org
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import org.itsallcode.openfasttrace.core.Newline;
+import org.itsallcode.openfasttrace.exporter.ExporterConstants;
+
+/**
+ * This class implements a parameter object to control the settings of OFT's
+ * export mode.
+ */
+public class ExportSettings
+{
+ private final String outputFormat;
+ private final Newline newline;
+
+ private ExportSettings(final Builder builder)
+ {
+ this.outputFormat = builder.outputFormat;
+ this.newline = builder.newline;
+ }
+
+ /**
+ * Get the conversion output format
+ *
+ * @return output format
+ */
+ public String getOutputFormat()
+ {
+ return this.outputFormat;
+ }
+
+ /**
+ * Get the newline format used in the conversion results
+ *
+ * @return newline format
+ */
+ public Newline getNewline()
+ {
+ return this.newline;
+ }
+
+ /**
+ * Create default exporter settings
+ *
+ * @return default exporter settings
+ */
+ public static ExportSettings createDefault()
+ {
+ return builder().build();
+ }
+
+ /**
+ * Create an export settings builder
+ */
+ public static Builder builder()
+ {
+ return new Builder();
+ }
+
+ /**
+ * Builder for {@link ExportSettings}
+ */
+ public static class Builder
+ {
+ private String outputFormat = ExporterConstants.DEFAULT_OUTPUT_FORMAT;
+ private Newline newline = Newline.UNIX;
+
+ private Builder()
+ {
+ }
+
+ /**
+ * Set the converter output format
+ *
+ * @param outputFormat
+ * output format
+ * @return this
for fluent programming
+ */
+ public Builder outputFormat(final String outputFormat)
+ {
+ this.outputFormat = outputFormat;
+ return this;
+ }
+
+ /**
+ * Get the newline format to be used in the conversion result
+ *
+ * @param newline
+ * newline format
+ * @return this
for fluent programming
+ */
+ public Builder newline(final Newline newline)
+ {
+ this.newline = newline;
+ return this;
+ }
+
+ /**
+ * Create a new instance of {@link ExportSettings}
+ *
+ * @return new instance
+ */
+ public ExportSettings build()
+ {
+ return new ExportSettings(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java b/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java
new file mode 100644
index 00000000..ed35b966
--- /dev/null
+++ b/src/main/java/org/itsallcode/openfasttrace/ImportSettings.java
@@ -0,0 +1,171 @@
+package org.itsallcode.openfasttrace;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.itsallcode.openfasttrace.importer.tag.config.PathConfig;
+
+/*-
+ * #%L
+ * OpenFastTrace
+ * %%
+ * Copyright (C) 2016 - 2018 itsallcode.org
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+public class ImportSettings
+{
+ private final List inputs;
+ private final FilterSettings filter;
+ private final List pathConfigs;
+
+ protected ImportSettings(final Builder builder)
+ {
+ this.inputs = builder.inputs;
+ this.filter = builder.filter;
+ this.pathConfigs = builder.pathConfigs;
+ }
+
+ /**
+ * Get the list of paths to be scanned for importable artifacts
+ *
+ * @return list of input paths
+ */
+ public List getInputs()
+ {
+ return this.inputs;
+ }
+
+ /**
+ * Get the filter settings
+ *
+ * @return filter settings
+ */
+ public FilterSettings getFilters()
+ {
+ return this.filter;
+ }
+
+ /**
+ * Get path configurations. Those are per-path settings that define how the
+ * importer should interpret the specification item tags it found.
+ *
+ * @return path configurations
+ */
+ public List getPathConfigs()
+ {
+ return this.pathConfigs;
+ }
+
+ /**
+ * Create a the default import settings
+ *
+ * @return default import settings
+ */
+ public static ImportSettings createDefault()
+ {
+ return builder().build();
+ }
+
+ /**
+ * Create an export settings builder
+ */
+ public static Builder builder()
+ {
+ return new Builder();
+ }
+
+ /**
+ * Builder for {@link ImportSettings}
+ */
+ public static class Builder
+ {
+ private final List inputs = new ArrayList<>();
+ private FilterSettings filter = FilterSettings.createAllowingEverything();
+ private List pathConfigs = new ArrayList<>();
+
+ private Builder()
+ {
+ }
+
+ /**
+ * Add a list of input paths to be scanned for importable artifacts
+ *
+ * @param inputs
+ * input paths to be scanned
+ * @return this
for fluent programming
+ */
+ public Builder addInputs(final List inputs)
+ {
+ this.inputs.addAll(inputs);
+ return this;
+ }
+
+ /**
+ * Add one or more input paths to be scanned for importable artifacts
+ *
+ * @param inputs
+ * input paths to be scanned
+ * @return this
for fluent programming
+ */
+ public Builder addInputs(final Path... inputs)
+ {
+ for (final Path input : inputs)
+ {
+ this.inputs.add(input);
+ }
+ return this;
+ }
+
+ /**
+ * Set the filters to be used during import
+ *
+ * @param filter
+ * filter settings
+ * @return this
for fluent programming
+ */
+ public Builder filter(final FilterSettings filter)
+ {
+ this.filter = filter;
+ return this;
+ }
+
+ /**
+ * Set path configurations
+ *
+ * @param pathConfigs
+ * per-path importer configurations
+ * @return this
for fluent programming
+ */
+ public Builder pathConfigs(final List pathConfigs)
+ {
+ this.pathConfigs = pathConfigs;
+ return this;
+ }
+
+ /**
+ * Create a new instance of {@link ImportSettings}
+ *
+ * @return import settings instance
+ */
+ public ImportSettings build()
+ {
+ return new ImportSettings(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/itsallcode/openfasttrace/Oft.java b/src/main/java/org/itsallcode/openfasttrace/Oft.java
new file mode 100644
index 00000000..ee32a0b3
--- /dev/null
+++ b/src/main/java/org/itsallcode/openfasttrace/Oft.java
@@ -0,0 +1,146 @@
+package org.itsallcode.openfasttrace;
+
+/*-
+ * #%L
+ \* OpenFastTrace
+ * %%
+ * Copyright (C) 2016 - 2017 itsallcode.org
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import java.nio.file.Path;
+import java.util.List;
+
+import org.itsallcode.openfasttrace.core.*;
+
+/**
+ * Import requirements (e.g. from ReqM2 to Markdown)
+ */
+public interface Oft
+{
+ /**
+ * Run an import with default settings
+ *
+ * @return list of imported specification items
+ */
+ public List importItems();
+
+ /**
+ * Run an import
+ *
+ * @param settings
+ * import stage settings
+ *
+ * @return list of imported specification items.
+ */
+ public List importItems(ImportSettings settings);
+
+ /**
+ * Link specification items
+ *
+ * @param items
+ * specification items to be interlinked
+ * @return list of linked specification items
+ */
+ public List link(List items);
+
+ /**
+ * Trace a list of linked specification items
+ *
+ * @param linkedItems
+ * items to be traced
+ * @return trace result
+ */
+ public Trace trace(List linkedItems);
+
+ /**
+ * Export items with default settings
+ *
+ * @param items
+ * items to be exported
+ * @param path
+ * output path for export
+ */
+ public void exportToPath(List items, final Path path);
+
+ /**
+ * Export items
+ *
+ * @param items
+ * items to be exported
+ * @param path
+ * output path for export
+ * @param settings
+ * export settings
+ */
+ public void exportToPath(final List items, final Path path,
+ ExportSettings settings);
+
+ /**
+ * Generate a report with default settings
+ */
+ public void reportToStdOut(Trace trace);
+
+ /**
+ * Generate a report
+ *
+ * @param trace
+ * specification item trace to be turned into a report
+ *
+ * @param settings
+ * report settings
+ */
+ public void reportToStdOut(Trace trace, ReportSettings settings);
+
+ /**
+ * Generate a report
+ *
+ * @param trace
+ * specification item trace to be turned into a report
+ *
+ * @param outputPath
+ * path the report should be written to (or file in case this is
+ * a single-file report)
+ *
+ * @param settings
+ * report settings
+ */
+ public void reportToPath(Trace trace, Path outputPath);
+
+ /**
+ * Generate a report
+ *
+ * @param trace
+ * specification item trace to be turned into a report
+ *
+ * @param outputPath
+ * path the report should be written to (or file in case this is
+ * a single-file report)
+ *
+ * @param settings
+ * report settings
+ */
+ public void reportToPath(Trace trace, Path outputPath, ReportSettings settings);
+
+ /**
+ * Create a new instance of a object implementing the {@link Oft} interface
+ */
+ public static Oft create()
+ {
+ return new OftRunner();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java b/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java
new file mode 100644
index 00000000..d8ead882
--- /dev/null
+++ b/src/main/java/org/itsallcode/openfasttrace/ReportSettings.java
@@ -0,0 +1,186 @@
+package org.itsallcode.openfasttrace;
+
+/*-
+ * #%L
+ * OpenFastTrace
+ * %%
+ * Copyright (C) 2016 - 2018 itsallcode.org
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import org.itsallcode.openfasttrace.core.Newline;
+import org.itsallcode.openfasttrace.report.ReportConstants;
+import org.itsallcode.openfasttrace.report.ReportVerbosity;
+
+/**
+ * This class implements a parameter object to control the settings of OFT's
+ * report mode.
+ */
+public class ReportSettings
+{
+ private final ReportVerbosity verbosity;
+ private final boolean showOrigin;
+ private final String outputFormat;
+ private final Newline newline;
+
+ private ReportSettings(final Builder builder)
+ {
+ this.verbosity = builder.verbosity;
+ this.showOrigin = builder.showOrigin;
+ this.outputFormat = builder.outputFormat;
+ this.newline = builder.newline;
+ }
+
+ /**
+ * Get the report verbosity
+ *
+ * @return report verbosity
+ */
+ public ReportVerbosity getReportVerbosity()
+ {
+ return this.verbosity;
+ }
+
+ /**
+ * Should the origin of a specification item be shown in the report?
+ *
+ * @return true
if the origin should be shown
+ */
+ public boolean showOrigin()
+ {
+ return this.showOrigin;
+ }
+
+ /**
+ * Get the report output format (e.g. "plain" or "html")
+ *
+ * @return report output format
+ */
+ public String getOutputFormat()
+ {
+ return this.outputFormat;
+ }
+
+ /**
+ * Get the newline format
+ *
+ * @return newline format
+ */
+ public Newline getNewline()
+ {
+ return this.newline;
+ }
+
+ /**
+ * Create default report settings
+ *
+ * @return default settings
+ */
+ public static ReportSettings createDefault()
+ {
+ return builder().build();
+ }
+
+ /**
+ * Create a builder for {@link ReportSettings}
+ *
+ * @return builder
+ */
+ public static Builder builder()
+ {
+ return new Builder();
+ }
+
+ /**
+ * Builder for {@link ReportSettings}
+ */
+ public static class Builder
+ {
+ public Newline newline = Newline.UNIX;
+ public String outputFormat = ReportConstants.DEFAULT_REPORT_FORMAT;
+ public boolean showOrigin = false;
+ ReportVerbosity verbosity = ReportVerbosity.FAILURE_DETAILS;
+
+ private Builder()
+ {
+
+ }
+
+ /**
+ * Create a new instance of {@link ReportSettings}
+ *
+ * @return
+ */
+ public ReportSettings build()
+ {
+ return new ReportSettings(this);
+ }
+
+ /**
+ * Set the report verbosity
+ *
+ * @param verbosity
+ * report verbosity
+ * @return this
for fluent programming
+ */
+ public Builder verbosity(final ReportVerbosity verbosity)
+ {
+ this.verbosity = verbosity;
+ return this;
+ }
+
+ /**
+ * Set the whether the origin of specification items should be shown in
+ * the report
+ *
+ * @param showOrign
+ * set to true
if the origin should be shown
+ * @return this
for fluent programming
+ */
+ public Builder showOrigin(final boolean showOrigin)
+ {
+ this.showOrigin = showOrigin;
+ return this;
+ }
+
+ /**
+ * Set the output format
+ *
+ * @param outputFormat
+ * output format
+ * @return this
for fluent programming
+ */
+ public Builder outputFormat(final String outputFormat)
+ {
+ this.outputFormat = outputFormat;
+ return this;
+ }
+
+ /**
+ * Set the newline format
+ *
+ * @param newline
+ * newline format
+ * @return this
for fluent programming
+ */
+ public Builder newline(final Newline newline)
+ {
+ this.newline = newline;
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/itsallcode/openfasttrace/Reporter.java b/src/main/java/org/itsallcode/openfasttrace/Reporter.java
deleted file mode 100644
index f70c8beb..00000000
--- a/src/main/java/org/itsallcode/openfasttrace/Reporter.java
+++ /dev/null
@@ -1,124 +0,0 @@
-
-package org.itsallcode.openfasttrace;
-
-/*-
- * #%L
- \* OpenFastTrace
- * %%
- * Copyright (C) 2016 - 2017 itsallcode.org
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-import java.nio.file.Path;
-import java.util.List;
-
-import org.itsallcode.openfasttrace.core.Newline;
-import org.itsallcode.openfasttrace.core.Trace;
-import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig;
-import org.itsallcode.openfasttrace.report.ReportVerbosity;
-
-/**
- * OFT requirements tracer
- */
-public interface Reporter
-{
- /**
- * Select one or more input files
- *
- * @param inputs
- * input files
- * @return a Reporter
instance for fluent programming
- */
- public Reporter addInputs(final Path... inputs);
-
- /**
- * Select one or more input files
- *
- * @param inputs
- * input files
- * @return a Reporter
instance for fluent programming
- */
- public Reporter addInputs(final List inputs);
-
- /**
- * Set the filters to be applied during conversion
- *
- * @param filterSettings
- * the filter settings
- */
- public Reporter setFilters(FilterSettings filterSettings);
-
- /**
- * Set the representation for new line
- *
- * @param newline
- * type of newline
- * @return a Reporter
instance for fluent programming
- */
- public Reporter setNewline(Newline newline);
-
- /**
- * Select how verbose the tracing stream should be
- *
- * @param verbosity
- * stream verbosity
- * @return a Reporter
instance for fluent programming
- */
- public Reporter setReportVerbosity(final ReportVerbosity verbosity);
-
- /**
- * Set the {@link TagImporterConfig} for the
- * {@link LegacyTagImporterFactory}.
- *
- * @param config
- * the {@link TagImporterConfig} to set.
- * @return a Reporter
instance for fluent programming
- */
- public Reporter setLegacyTagImporterPathConfig(final TagImporterConfig config);
-
- /**
- * Run a trace on the input files
- */
- public Trace trace();
-
- /**
- * Write the tracing stream to a file
- *
- * @param trace
- * trace result to be written
- *
- * @param output
- * output file or directory
- *
- * @param format
- * stream format (this is a name defined in the respective
- * reporter plug-in)
- */
- public void reportToFileInFormat(final Trace trace, final Path output, final String format);
-
- /**
- * Write the tracing stream to standard out
- *
- * @param trace
- * trace result to be written
- *
- * @param format
- * stream format (this is a name defined in the respective
- * reporter plug-in)
- */
- public void reportToStdOutInFormat(final Trace trace, final String format);
-}
diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/CliArguments.java b/src/main/java/org/itsallcode/openfasttrace/cli/CliArguments.java
index 83295080..9715123a 100644
--- a/src/main/java/org/itsallcode/openfasttrace/cli/CliArguments.java
+++ b/src/main/java/org/itsallcode/openfasttrace/cli/CliArguments.java
@@ -51,6 +51,7 @@ public class CliArguments
private ReportVerbosity reportVerbosity;
private Set wantedArtifactTypes = Collections.emptySet();
private Set wantedTags = Collections.emptySet();
+ private boolean showOrigin;
/**
* Get the output file path
@@ -316,4 +317,39 @@ public void setT(final String tags)
{
setWantedTags(tags);
}
+
+ /**
+ * Check if origin information should be shown in reports.
+ *
+ * @return true
if origin information should be shown in
+ * reports.
+ */
+ public boolean getShowOrigin()
+ {
+ return this.showOrigin;
+ }
+
+ /**
+ * Choose whether to show origin information in reports.
+ *
+ * @param showOrigin
+ * true
if origin information should be shown in
+ * reports
+ */
+ public void setShowOrigin(final boolean showOrigin)
+ {
+ this.showOrigin = showOrigin;
+ }
+
+ /**
+ * Choose whether to show origin information in reports.
+ *
+ * @param showOrigin
+ * true
if origin information should be shown in
+ * reports
+ */
+ public void setS(final boolean showOrigin)
+ {
+ setShowOrigin(showOrigin);
+ }
}
diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java
index e5fbb7e5..3c3fac00 100644
--- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java
+++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/AbstractCommand.java
@@ -30,7 +30,10 @@
import java.util.Set;
import org.itsallcode.openfasttrace.FilterSettings;
+import org.itsallcode.openfasttrace.ImportSettings;
+import org.itsallcode.openfasttrace.Oft;
import org.itsallcode.openfasttrace.cli.CliArguments;
+import org.itsallcode.openfasttrace.core.SpecificationItem;
/**
* This class is the abstract base class for all commands that process a list of
@@ -39,10 +42,12 @@
public abstract class AbstractCommand implements Performable
{
protected CliArguments arguments;
+ protected final Oft oft;
protected AbstractCommand(final CliArguments arguments)
{
this.arguments = arguments;
+ this.oft = Oft.create();
}
public List toPaths(final List inputs)
@@ -89,4 +94,14 @@ private void setTagFilter(final FilterSettings.Builder builder)
builder.tags(wantedTags);
}
}
+
+ protected List importItems()
+ {
+ final ImportSettings importSettings = ImportSettings //
+ .builder() //
+ .addInputs(this.toPaths(this.arguments.getInputs())) //
+ .filter(createFilterSettingsFromArguments()) //
+ .build();
+ return this.oft.importItems(importSettings);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java
index 7d170038..31bb4fef 100644
--- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java
+++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/ConvertCommand.java
@@ -3,9 +3,9 @@
/*-
* #%L
- \* OpenFastTrace
+ * OpenFastTrace
* %%
- * Copyright (C) 2016 - 2017 itsallcode.org
+ * Copyright (C) 2016 - 2018 itsallcode.org
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
@@ -23,11 +23,11 @@
* #L%
*/
-import java.nio.file.Path;
+import java.util.List;
-import org.itsallcode.openfasttrace.Converter;
+import org.itsallcode.openfasttrace.ExportSettings;
import org.itsallcode.openfasttrace.cli.CliArguments;
-import org.itsallcode.openfasttrace.mode.ConvertMode;
+import org.itsallcode.openfasttrace.core.SpecificationItem;
/**
* Handler for specification item conversion CLI command.
@@ -50,23 +50,22 @@ public ConvertCommand(final CliArguments arguments)
@Override
public boolean run()
{
- final Converter converter = createConverter();
- convert(converter);
+ final List items = importItems();
+ convert(items);
return true;
}
- private Converter createConverter()
+ private void convert(final List items)
{
- final Converter converter = new ConvertMode();
- converter.addInputs(toPaths(this.arguments.getInputs())) //
- .setFilters(createFilterSettingsFromArguments()) //
- .setNewline(this.arguments.getNewline());
- return converter;
+ final ExportSettings exportSettings = createExportSettingsFromArguments();
+ this.oft.exportToPath(items, this.arguments.getOutputPath(), exportSettings);
}
- private void convert(final Converter converter)
+ private ExportSettings createExportSettingsFromArguments()
{
- final Path outputPath = this.arguments.getOutputPath();
- converter.convertToFileInFormat(outputPath, this.arguments.getOutputFormat());
+ return ExportSettings.builder() //
+ .newline(this.arguments.getNewline()) //
+ .outputFormat(this.arguments.getOutputFormat()) //
+ .build();
}
}
diff --git a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java
index dc94c429..12c6fd11 100644
--- a/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java
+++ b/src/main/java/org/itsallcode/openfasttrace/cli/commands/TraceCommand.java
@@ -24,11 +24,14 @@
*/
import java.nio.file.Path;
+import java.util.List;
-import org.itsallcode.openfasttrace.Reporter;
+import org.itsallcode.openfasttrace.Oft;
+import org.itsallcode.openfasttrace.ReportSettings;
import org.itsallcode.openfasttrace.cli.CliArguments;
+import org.itsallcode.openfasttrace.core.LinkedSpecificationItem;
+import org.itsallcode.openfasttrace.core.SpecificationItem;
import org.itsallcode.openfasttrace.core.Trace;
-import org.itsallcode.openfasttrace.mode.ReportMode;
/**
* Handler for requirement tracing CLI command.
@@ -51,34 +54,43 @@ public TraceCommand(final CliArguments arguments)
@Override
public boolean run()
{
- final Reporter reporter = createReporter();
- final Trace trace = report(reporter);
+ final List items = importItems();
+ final List linkedItems = linkItems(items);
+ final Trace trace = traceItems(linkedItems);
+ report(this.oft, trace);
return trace.hasNoDefects();
}
- private Reporter createReporter()
+ private List linkItems(final List items)
{
- final Reporter reporter = new ReportMode();
- reporter.addInputs(toPaths(this.arguments.getInputs())) //
- .setFilters(createFilterSettingsFromArguments()) //
- .setNewline(this.arguments.getNewline())
- .setReportVerbosity(this.arguments.getReportVerbosity());
- return reporter;
+ return this.oft.link(items);
}
- private Trace report(final Reporter reporter)
+ private Trace traceItems(final List linkedItems)
+ {
+ return this.oft.trace(linkedItems);
+ }
+
+ private void report(final Oft oft, final Trace trace)
{
- final Trace trace = reporter.trace();
final Path outputPath = this.arguments.getOutputPath();
+ final ReportSettings reportSettings = convertCommandLineArgumentsToReportSettings();
if (null == outputPath)
{
- reporter.reportToStdOutInFormat(trace, this.arguments.getOutputFormat());
+ oft.reportToStdOut(trace, reportSettings);
}
else
{
- reporter.reportToFileInFormat(trace, this.arguments.getOutputPath(),
- this.arguments.getOutputFormat());
+ oft.reportToPath(trace, this.arguments.getOutputPath(), reportSettings);
}
- return trace;
}
-}
+
+ private ReportSettings convertCommandLineArgumentsToReportSettings()
+ {
+ return ReportSettings.builder() //
+ .verbosity(this.arguments.getReportVerbosity()) //
+ .newline(this.arguments.getNewline()) //
+ .showOrigin(this.arguments.getShowOrigin()) //
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java b/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java
new file mode 100644
index 00000000..2c467fd5
--- /dev/null
+++ b/src/main/java/org/itsallcode/openfasttrace/core/OftRunner.java
@@ -0,0 +1,111 @@
+package org.itsallcode.openfasttrace.core;
+
+/*-
+ * #%L
+ * OpenFastTrace
+ * %%
+ * Copyright (C) 2016 - 2018 itsallcode.org
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import java.nio.file.Path;
+import java.util.List;
+
+import org.itsallcode.openfasttrace.*;
+import org.itsallcode.openfasttrace.core.serviceloader.InitializingServiceLoader;
+import org.itsallcode.openfasttrace.exporter.ExporterService;
+import org.itsallcode.openfasttrace.importer.*;
+import org.itsallcode.openfasttrace.report.ReportService;
+
+public class OftRunner implements Oft
+{
+ @Override
+ public List importItems(final ImportSettings settings)
+ {
+ return createImporterService(settings) //
+ .createImporter() //
+ .importAny(settings.getInputs()) //
+ .getImportedItems();
+ }
+
+ private ImporterService createImporterService(final ImportSettings settings)
+ {
+ final ImporterContext context = new ImporterContext(settings);
+ final InitializingServiceLoader serviceLoader = InitializingServiceLoader
+ .load(ImporterFactory.class, context);
+ final ImporterService service = new ImporterService(
+ new ImporterFactoryLoader(serviceLoader), settings);
+ context.setImporterService(service);
+ return service;
+ }
+
+ @Override
+ public List importItems()
+ {
+ return importItems(ImportSettings.createDefault());
+ }
+
+ @Override
+ public List link(final List items)
+ {
+ return new Linker(items).link();
+ }
+
+ @Override
+ public Trace trace(final List linkedItems)
+ {
+ return new Tracer().trace(linkedItems);
+ }
+
+ @Override
+ public void exportToPath(final List items, final Path path)
+ {
+ exportToPath(items, path, ExportSettings.createDefault());
+ }
+
+ @Override
+ public void exportToPath(final List items, final Path path,
+ final ExportSettings settings)
+ {
+ new ExporterService().exportToPath(items.stream(), path, settings);
+ }
+
+ @Override
+ public void reportToStdOut(final Trace trace)
+ {
+ new ReportService().reportTraceToStdOut(trace, ReportSettings.createDefault());
+ }
+
+ @Override
+ public void reportToStdOut(final Trace trace, final ReportSettings settings)
+ {
+ new ReportService().reportTraceToStdOut(trace, settings);
+ }
+
+ @Override
+ public void reportToPath(final Trace trace, final Path outputPath)
+ {
+ new ReportService().reportTraceToPath(trace, outputPath, ReportSettings.createDefault());
+ }
+
+ @Override
+ public void reportToPath(final Trace trace, final Path outputPath,
+ final ReportSettings settings)
+ {
+ new ReportService().reportTraceToPath(trace, outputPath, settings);
+ }
+}
diff --git a/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterFactory.java b/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterFactory.java
index dff87ae6..0d2a6bc7 100644
--- a/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterFactory.java
+++ b/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterFactory.java
@@ -147,4 +147,4 @@ private Writer createFileWriter(final Path file, final Charset charset)
*/
protected abstract Exporter createExporter(final Writer writer,
Stream linkedSpecItemStream, final Newline newline);
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterService.java b/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterService.java
index 90bf5abb..37df83be 100644
--- a/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterService.java
+++ b/src/main/java/org/itsallcode/openfasttrace/exporter/ExporterService.java
@@ -26,8 +26,8 @@
import java.nio.file.Path;
import java.util.stream.Stream;
+import org.itsallcode.openfasttrace.ExportSettings;
import org.itsallcode.openfasttrace.core.LinkedSpecificationItem;
-import org.itsallcode.openfasttrace.core.Newline;
import org.itsallcode.openfasttrace.core.SpecificationItem;
public class ExporterService
@@ -51,18 +51,15 @@ public ExporterService(final ExporterFactoryLoader factoryLoader)
*
* @param itemStream
* the {@link SpecificationItem} to export
- * @param format
- * the output format
- * @param outputFile
- * the output file
- * @param newline
- * the newline format
+ * @param settings
+ * the exporter settings
*/
- public void exportFile(final Stream itemStream, final String format,
- final Path outputFile, final Newline newline)
+ public void exportToPath(final Stream itemStream, final Path outputFile,
+ final ExportSettings settings)
{
- final ExporterFactory factory = this.factoryLoader.getExporterFactory(format);
- factory.createExporter(outputFile, format, StandardCharsets.UTF_8, newline, itemStream)
- .runExport();
+ final ExporterFactory factory = this.factoryLoader
+ .getExporterFactory(settings.getOutputFormat());
+ factory.createExporter(outputFile, settings.getOutputFormat(), StandardCharsets.UTF_8,
+ settings.getNewline(), itemStream).runExport();
}
}
diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/ImporterContext.java b/src/main/java/org/itsallcode/openfasttrace/importer/ImporterContext.java
index 11535afc..492e3d9f 100644
--- a/src/main/java/org/itsallcode/openfasttrace/importer/ImporterContext.java
+++ b/src/main/java/org/itsallcode/openfasttrace/importer/ImporterContext.java
@@ -23,7 +23,7 @@
*/
import java.util.Objects;
-import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig;
+import org.itsallcode.openfasttrace.ImportSettings;
/**
* Common context shared by all {@link ImporterFactory}s. This allows importers
@@ -31,18 +31,18 @@
*/
public class ImporterContext
{
- private final TagImporterConfig tagImporterConfig;
+ private final ImportSettings settings;
private ImporterService importerService;
/**
* Creates a new {@link ImporterContext}.
*
- * @param tagImporterConfig
+ * @param settings
* importer specific configuration.
*/
- public ImporterContext(final TagImporterConfig tagImporterConfig)
+ public ImporterContext(final ImportSettings settings)
{
- this.tagImporterConfig = tagImporterConfig;
+ this.settings = settings;
}
/**
@@ -72,8 +72,8 @@ public ImporterService getImporterService()
*
* @return importer specific configuration.
*/
- public TagImporterConfig getTagImporterConfig()
+ public ImportSettings getImportSettings()
{
- return this.tagImporterConfig;
+ return this.settings;
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/ImporterService.java b/src/main/java/org/itsallcode/openfasttrace/importer/ImporterService.java
index dc351797..10927535 100644
--- a/src/main/java/org/itsallcode/openfasttrace/importer/ImporterService.java
+++ b/src/main/java/org/itsallcode/openfasttrace/importer/ImporterService.java
@@ -23,7 +23,7 @@
*/
import java.util.List;
-import org.itsallcode.openfasttrace.FilterSettings;
+import org.itsallcode.openfasttrace.ImportSettings;
import org.itsallcode.openfasttrace.core.SpecificationItem;
import org.itsallcode.openfasttrace.importer.input.InputFile;
@@ -35,26 +35,29 @@
public class ImporterService
{
private final ImporterFactoryLoader factoryLoader;
- private FilterSettings filterSettings;
+ private final ImportSettings settings;
- public ImporterService(final ImporterFactoryLoader factoryLoader)
+ /**
+ * Create a new instance of an {@link ImporterService}
+ *
+ * @param factoryLoader
+ * loader for importer factories depending on the source
+ * @param settings
+ * import settings (e.g. filters)
+ */
+ public ImporterService(final ImporterFactoryLoader factoryLoader, final ImportSettings settings)
{
this.factoryLoader = factoryLoader;
+ this.settings = settings;
}
/**
- * Set the filters to be applied
+ * Import a file's contents
*
- * @param filterSettings
- * filter settings
- * @return this
for fluent programming style
+ * @param file
+ * file to be imported
+ * @return list of recognized specification items
*/
- public ImporterService setFilters(final FilterSettings filterSettings)
- {
- this.filterSettings = filterSettings;
- return this;
- }
-
public List importFile(final InputFile file)
{
return createImporter() //
@@ -69,6 +72,7 @@ public MultiFileImporter createImporter(final ImportEventListener builder)
public MultiFileImporter createImporter()
{
- return createImporter(SpecificationListBuilder.createWithFilter(this.filterSettings));
+ return createImporter(
+ SpecificationListBuilder.createWithFilter(this.settings.getFilters()));
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java
index c053aafb..e008f2ed 100644
--- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java
+++ b/src/main/java/org/itsallcode/openfasttrace/importer/tag/TagImporterFactory.java
@@ -7,6 +7,7 @@
import java.util.regex.Pattern;
import java.util.stream.Stream;
+import org.itsallcode.openfasttrace.ImportSettings;
/*-
* #%L
* OpenFastTrace
@@ -31,7 +32,6 @@
import org.itsallcode.openfasttrace.importer.*;
import org.itsallcode.openfasttrace.importer.input.InputFile;
import org.itsallcode.openfasttrace.importer.tag.config.PathConfig;
-import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig;
/**
* {@link ImporterFactory} for tags in source code files.
@@ -85,7 +85,7 @@ public Importer createImporter(final InputFile path, final ImportEventListener l
private Stream getPathConfigs()
{
- final TagImporterConfig config = getContext().getTagImporterConfig();
- return config == null ? Stream.empty() : config.getPathConfigs().stream();
+ final ImportSettings settings = getContext().getImportSettings();
+ return settings == null ? Stream.empty() : settings.getPathConfigs().stream();
}
}
diff --git a/src/main/java/org/itsallcode/openfasttrace/importer/tag/config/TagImporterConfig.java b/src/main/java/org/itsallcode/openfasttrace/importer/tag/config/TagImporterConfig.java
deleted file mode 100644
index 7d1a4ff8..00000000
--- a/src/main/java/org/itsallcode/openfasttrace/importer/tag/config/TagImporterConfig.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.itsallcode.openfasttrace.importer.tag.config;
-
-/*-
- * #%L
- * OpenFastTrace
- * %%
- * Copyright (C) 2016 - 2018 itsallcode.org
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-import static java.util.Collections.emptyList;
-
-import java.util.List;
-
-/**
- * Configuration for the {@link ShortTagImportingLineConsumer}.
- */
-public class TagImporterConfig
-{
- private final List pathConfigs;
-
- /**
- * Create a new configuration object.
- *
- * @param pathConfigs
- * a list of {@link PathConfig} objects.
- */
- public TagImporterConfig(final List pathConfigs)
- {
- this.pathConfigs = pathConfigs;
- }
-
- /**
- * Creates a new, empty configuration.
- */
- public static TagImporterConfig empty()
- {
- return new TagImporterConfig(emptyList());
- }
-
- public List getPathConfigs()
- {
- return this.pathConfigs;
- }
-}
diff --git a/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java b/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java
deleted file mode 100644
index ca73705a..00000000
--- a/src/main/java/org/itsallcode/openfasttrace/mode/AbstractMode.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.itsallcode.openfasttrace.mode;
-
-/*-
- * #%L
- \* OpenFastTrace
- * %%
- * Copyright (C) 2016 - 2017 itsallcode.org
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import org.itsallcode.openfasttrace.FilterSettings;
-import org.itsallcode.openfasttrace.core.*;
-import org.itsallcode.openfasttrace.core.serviceloader.InitializingServiceLoader;
-import org.itsallcode.openfasttrace.importer.*;
-import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig;
-
-abstract class AbstractMode>
-{
- protected final List inputs = new ArrayList<>();
- protected Newline newline = Newline.UNIX;
- private FilterSettings filterSettings = FilterSettings.createAllowingEverything();
- private TagImporterConfig tagImporterConfig = TagImporterConfig.empty();
-
- protected abstract T self();
-
- public T addInputs(final Path... inputs)
- {
- return this.addInputs(Arrays.asList(inputs));
- }
-
- public T addInputs(final List inputs)
- {
- this.inputs.addAll(inputs);
- return self();
- }
-
- public T setNewline(final Newline newline)
- {
-
- this.newline = newline;
- return self();
- }
-
- public T setFilters(final FilterSettings filterSettings)
- {
- this.filterSettings = filterSettings;
- return self();
- }
-
- public T setLegacyTagImporterPathConfig(final TagImporterConfig tagImporterConfig)
- {
- this.tagImporterConfig = tagImporterConfig;
- return self();
- }
-
- protected List importLinkedSpecificationItems()
- {
- final Stream items = importItems();
- final Linker linker = new Linker(items.collect(Collectors.toList()));
- return linker.link();
- }
-
- protected Stream importItems()
- {
- return createImporterService() //
- .setFilters(this.filterSettings) //
- .createImporter() //
- .importAny(this.inputs) //
- .getImportedItems() //
- .stream();
- }
-
- private ImporterService createImporterService()
- {
- final ImporterContext context = new ImporterContext(this.tagImporterConfig);
- final InitializingServiceLoader serviceLoader = InitializingServiceLoader
- .load(ImporterFactory.class, context);
- final ImporterService service = new ImporterService(
- new ImporterFactoryLoader(serviceLoader));
- context.setImporterService(service);
- return service;
- }
-}
diff --git a/src/main/java/org/itsallcode/openfasttrace/mode/ConvertMode.java b/src/main/java/org/itsallcode/openfasttrace/mode/ConvertMode.java
deleted file mode 100644
index 01088a7e..00000000
--- a/src/main/java/org/itsallcode/openfasttrace/mode/ConvertMode.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.itsallcode.openfasttrace.mode;
-
-/*-
- * #%L
- \* OpenFastTrace
- * %%
- * Copyright (C) 2016 - 2017 itsallcode.org
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-import java.nio.file.Path;
-
-import org.itsallcode.openfasttrace.Converter;
-import org.itsallcode.openfasttrace.exporter.ExporterService;
-
-public class ConvertMode extends AbstractMode implements Converter
-{
- private final ExporterService exporterService = new ExporterService();
-
- @Override
- public void convertToFileInFormat(final Path output, final String format)
- {
- this.exporterService.exportFile(importItems(), format, output, this.newline);
- }
-
- @Override
- protected ConvertMode self()
- {
- return this;
- }
-}
diff --git a/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java b/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java
deleted file mode 100644
index 6f159bd7..00000000
--- a/src/main/java/org/itsallcode/openfasttrace/mode/ReportMode.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.itsallcode.openfasttrace.mode;
-
-/*-
- * #%L
- \* OpenFastTrace
- * %%
- * Copyright (C) 2016 - 2017 itsallcode.org
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program. If not, see
- * .
- * #L%
- */
-
-import java.nio.file.Path;
-import java.util.List;
-
-import org.itsallcode.openfasttrace.Reporter;
-import org.itsallcode.openfasttrace.core.LinkedSpecificationItem;
-import org.itsallcode.openfasttrace.core.Trace;
-import org.itsallcode.openfasttrace.core.Tracer;
-import org.itsallcode.openfasttrace.report.ReportService;
-import org.itsallcode.openfasttrace.report.ReportVerbosity;
-
-public class ReportMode extends AbstractMode implements Reporter
-{
- private final Tracer tracer = new Tracer();
- private final ReportService reportService = new ReportService();
- private ReportVerbosity verbosity = ReportVerbosity.FAILURE_DETAILS;
-
- @Override
- public Trace trace()
- {
- final List linkedItems = importLinkedSpecificationItems();
- return this.tracer.trace(linkedItems);
- }
-
- @Override
- public void reportToFileInFormat(final Trace trace, final Path output, final String format)
- {
- this.reportService.reportTraceToPath(trace, output, format, this.verbosity, this.newline);
- }
-
- @Override
- public Reporter setReportVerbosity(final ReportVerbosity verbosity)
- {
- this.verbosity = verbosity;
- return this;
- }
-
- @Override
- public void reportToStdOutInFormat(final Trace trace, final String format)
- {
- this.reportService.reportTraceToStdOut(trace, format, this.verbosity, this.newline);
- }
-
- @Override
- protected ReportMode self()
- {
- return this;
- }
-}
diff --git a/src/main/java/org/itsallcode/openfasttrace/report/ReportService.java b/src/main/java/org/itsallcode/openfasttrace/report/ReportService.java
index 7ace1413..4006d9d2 100644
--- a/src/main/java/org/itsallcode/openfasttrace/report/ReportService.java
+++ b/src/main/java/org/itsallcode/openfasttrace/report/ReportService.java
@@ -25,19 +25,19 @@
import java.nio.file.Files;
import java.nio.file.Path;
-import org.itsallcode.openfasttrace.core.Newline;
+import org.itsallcode.openfasttrace.ReportSettings;
import org.itsallcode.openfasttrace.core.Trace;
import org.itsallcode.openfasttrace.report.html.HtmlReport;
import org.itsallcode.openfasttrace.report.plaintext.PlainTextReport;
public class ReportService
{
- public void reportTraceToPath(final Trace trace, final Path outputPath, final String format,
- final ReportVerbosity verbosity, final Newline newline)
+ public void reportTraceToPath(final Trace trace, final Path outputPath,
+ final ReportSettings settings)
{
try (OutputStream outputStream = Files.newOutputStream(outputPath))
{
- reportTraceToStream(trace, format, verbosity, newline, outputStream);
+ reportTraceToStream(trace, outputStream, settings);
}
catch (final IOException e)
{
@@ -45,10 +45,9 @@ public void reportTraceToPath(final Trace trace, final Path outputPath, final St
}
}
- public void reportTraceToStdOut(final Trace trace, final String format,
- final ReportVerbosity verbosity, final Newline newline)
+ public void reportTraceToStdOut(final Trace trace, final ReportSettings settings)
{
- reportTraceToStream(trace, format, verbosity, newline, getStdOutStream());
+ reportTraceToStream(trace, getStdOutStream(), settings);
}
// Using System.out by intention
@@ -58,12 +57,12 @@ private PrintStream getStdOutStream()
return System.out;
}
- private void reportTraceToStream(final Trace trace, final String format,
- final ReportVerbosity verbosity, final Newline newline, final OutputStream outputStream)
+ private void reportTraceToStream(final Trace trace, final OutputStream outputStream,
+ final ReportSettings settings)
{
final OutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
- final Reportable report = createReport(trace, format, newline);
- report.renderToStreamWithVerbosityLevel(bufferedOutputStream, verbosity);
+ final Reportable report = createReport(trace, settings);
+ report.renderToStream(bufferedOutputStream);
try
{
bufferedOutputStream.flush();
@@ -74,13 +73,14 @@ private void reportTraceToStream(final Trace trace, final String format,
}
}
- protected Reportable createReport(final Trace trace, final String format, final Newline newline)
+ protected Reportable createReport(final Trace trace, final ReportSettings settings)
{
Reportable report = null;
+ final String format = settings.getOutputFormat();
switch (ReportFormat.parse(format))
{
case PLAIN_TEXT:
- report = new PlainTextReport(trace, newline);
+ report = new PlainTextReport(trace, settings);
break;
case HTML:
report = new HtmlReport(trace);
diff --git a/src/main/java/org/itsallcode/openfasttrace/report/Reportable.java b/src/main/java/org/itsallcode/openfasttrace/report/Reportable.java
index 2dc8833d..7520f086 100644
--- a/src/main/java/org/itsallcode/openfasttrace/report/Reportable.java
+++ b/src/main/java/org/itsallcode/openfasttrace/report/Reportable.java
@@ -34,10 +34,7 @@ public interface Reportable
* Render the plain text coverage stream.
*
* @param outputStream
- * the output stream to which the stream is rendered.
- * @param verbosity
- * the level of detail that is reported.
+ * output stream to which the stream is rendered
*/
- public void renderToStreamWithVerbosityLevel(OutputStream outputStream,
- ReportVerbosity verbosity);
+ public void renderToStream(final OutputStream outputStream);
}
diff --git a/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java b/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java
index ed3aedba..2542cb12 100644
--- a/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java
+++ b/src/main/java/org/itsallcode/openfasttrace/report/html/HtmlReport.java
@@ -29,7 +29,6 @@
import org.itsallcode.openfasttrace.core.LinkedSpecificationItem;
import org.itsallcode.openfasttrace.core.Trace;
-import org.itsallcode.openfasttrace.report.ReportVerbosity;
import org.itsallcode.openfasttrace.report.Reportable;
import org.itsallcode.openfasttrace.report.view.ViewFactory;
import org.itsallcode.openfasttrace.report.view.Viewable;
@@ -41,6 +40,12 @@ public class HtmlReport implements Reportable
private final Trace trace;
private static final String REPORT_CSS_FILE = "/css/report.css";
+ /**
+ * Create a new instance of an {@link HtmlReport}
+ *
+ * @param trace
+ * trace to be reported on
+ */
public HtmlReport(final Trace trace)
{
this.trace = trace;
@@ -57,8 +62,7 @@ public static URL getCssUrl()
}
@Override
- public void renderToStreamWithVerbosityLevel(final OutputStream outputStream,
- final ReportVerbosity verbosity)
+ public void renderToStream(final OutputStream outputStream)
{
final ViewFactory factory = HtmlViewFactory.create(outputStream, getCssUrl());
final ViewableContainer view = factory.createView("", "Specification items by title");
diff --git a/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java b/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java
index 76a61c9e..77d76bdd 100644
--- a/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java
+++ b/src/main/java/org/itsallcode/openfasttrace/report/plaintext/PlainTextReport.java
@@ -33,9 +33,9 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.itsallcode.openfasttrace.ReportSettings;
import org.itsallcode.openfasttrace.core.*;
import org.itsallcode.openfasttrace.report.ReportException;
-import org.itsallcode.openfasttrace.report.ReportVerbosity;
import org.itsallcode.openfasttrace.report.Reportable;
/**
@@ -47,32 +47,31 @@ public class PlainTextReport implements Reportable
private final Trace trace;
private static final Comparator LINKED_ITEM_BY_ID = Comparator
.comparing(LinkedSpecificationItem::getId);
- private final Newline newline;
private int nonEmptySections = 0;
+ private final ReportSettings settings;
/**
* Create a new instance of {@link PlainTextReport}
*
* @param trace
* the trace that will be reported.
- * @param newline
- * the newline format
+ * @param settings
+ * report settings
*/
// [impl->dsn~newline-format~1]
- public PlainTextReport(final Trace trace, final Newline newline)
+ public PlainTextReport(final Trace trace, final ReportSettings settings)
{
this.trace = trace;
- this.newline = newline;
+ this.settings = settings;
}
@Override
- public void renderToStreamWithVerbosityLevel(final OutputStream outputStream,
- final ReportVerbosity verbosity)
+ public void renderToStream(final OutputStream outputStream)
{
final Charset charset = StandardCharsets.UTF_8;
try (final PrintStream report = new PrintStream(outputStream, false, charset.displayName()))
{
- renderToPrintStreamWithVerbosityLevel(report, verbosity);
+ renderToPrintStream(report);
}
catch (final UnsupportedEncodingException e)
{
@@ -80,10 +79,9 @@ public void renderToStreamWithVerbosityLevel(final OutputStream outputStream,
}
}
- private void renderToPrintStreamWithVerbosityLevel(final PrintStream report,
- final ReportVerbosity verbosity)
+ private void renderToPrintStream(final PrintStream report)
{
- switch (verbosity)
+ switch (this.settings.getReportVerbosity())
{
case QUIET:
break;
@@ -102,18 +100,18 @@ private void renderToPrintStreamWithVerbosityLevel(final PrintStream report,
renderSummary(report);
break;
case FAILURE_DETAILS:
- renderFailureDetails(report);
+ renderFailureDetails(report, this.settings.showOrigin());
separateItemsFromSummary(report);
renderSummary(report);
break;
case ALL:
- renderAll(report);
- report.print(this.newline);
+ renderAll(report, this.settings.showOrigin());
+ report.print(this.settings.getNewline());
renderSummary(report);
break;
default:
- throw new IllegalStateException(
- "Unable to create stream for unknown verbosity level " + verbosity);
+ throw new IllegalStateException("Unable to create stream for unknown verbosity level "
+ + this.settings.getReportVerbosity());
}
}
@@ -121,14 +119,14 @@ private void separateItemsFromSummary(final PrintStream report)
{
if (this.trace.countDefects() > 0)
{
- report.print(this.newline);
+ report.print(this.settings.getNewline());
}
}
private void renderResultStatus(final PrintStream report)
{
report.print(translateStatus(this.trace.hasNoDefects()));
- report.print(this.newline.toString());
+ report.print(this.settings.getNewline().toString());
}
private String translateStatus(final boolean ok)
@@ -149,7 +147,7 @@ private void renderSummary(final PrintStream report)
report.print(this.trace.countDefects());
report.print(" defect");
}
- report.print(this.newline);
+ report.print(this.settings.getNewline());
}
private void renderFailureIds(final PrintStream report)
@@ -158,7 +156,7 @@ private void renderFailureIds(final PrintStream report)
.sorted()//
.forEachOrdered(id -> {
report.print(id);
- report.print(this.newline.toString());
+ report.print(this.settings.getNewline().toString());
});
}
@@ -180,7 +178,7 @@ private void renderItemSummary(final PrintStream report, final LinkedSpecificati
report.print(" ");
renderMaturity(report, item);
report.print(translateArtifactTypeCoverage(item));
- report.print(this.newline);
+ report.print(this.settings.getNewline());
}
private String translateArtifactTypeCoverage(final LinkedSpecificationItem item)
@@ -225,33 +223,47 @@ private void renderMaturity(final PrintStream report, final LinkedSpecificationI
}
}
- private void renderFailureDetails(final PrintStream report)
+ private void renderFailureDetails(final PrintStream report, final boolean showOrigin)
{
this.trace.getDefectItems().stream() //
.sorted(LINKED_ITEM_BY_ID) //
- .forEachOrdered(item -> renderItemDetails(report, item));
+ .forEachOrdered(item -> renderItemDetails(report, item, showOrigin));
}
- private void renderAll(final PrintStream report)
+ private void renderAll(final PrintStream report, final boolean showOrigin)
{
this.trace.getItems().stream() //
.sorted(LINKED_ITEM_BY_ID) //
- .forEachOrdered(item -> renderItemDetails(report, item));
+ .forEachOrdered(item -> renderItemDetails(report, item, showOrigin));
}
- private void renderItemDetails(final PrintStream report, final LinkedSpecificationItem item)
+ private void renderItemDetails(final PrintStream report, final LinkedSpecificationItem item,
+ final boolean showOrigin)
{
renderItemSummary(report, item);
renderDescription(report, item);
- renderLinks(report, item);
+ if (showOrigin)
+ {
+ renderOrigin(report, item);
+ }
+ renderLinks(report, item, showOrigin);
renderTags(report, item);
renderItemDetailsEnd(report);
}
+ private void renderOrigin(final PrintStream report, final Location location)
+ {
+ report.print("(");
+ report.print(location.getPath());
+ report.print(":");
+ report.print(location.getLine());
+ report.print(")");
+ }
+
private void renderEmptyItemDetailsLine(final PrintStream report)
{
report.print("|");
- report.print(this.newline);
+ report.print(this.settings.getNewline());
}
private void renderDescription(final PrintStream report, final LinkedSpecificationItem item)
@@ -264,40 +276,53 @@ private void renderDescription(final PrintStream report, final LinkedSpecificati
{
report.print("| ");
report.print(line);
- report.print(this.newline);
+ report.print(this.settings.getNewline());
}
++this.nonEmptySections;
}
}
// [impl->dsn~reporting.plain-text.link-details~1]
- private void renderLinks(final PrintStream report, final LinkedSpecificationItem item)
+ private void renderLinks(final PrintStream report, final LinkedSpecificationItem item,
+ final boolean showOrigin)
{
if (item.hasLinks())
{
renderEmptyItemDetailsLine(report);
- renderOrderedLinks(report, item);
+ renderOrderedLinks(report, item, showOrigin);
++this.nonEmptySections;
}
}
- private void renderOrderedLinks(final PrintStream report, final LinkedSpecificationItem item)
+ private void renderOrderedLinks(final PrintStream report, final LinkedSpecificationItem item,
+ final boolean showOrigin)
{
item.getTracedLinks() //
.stream() //
.sorted((a, b) -> a.getOtherLinkEnd().getId()
.compareTo(b.getOtherLinkEnd().getId())) //
- .forEachOrdered(link -> renderLink(report, link));
+ .forEachOrdered(link -> renderLink(report, link, showOrigin));
}
- private void renderLink(final PrintStream report, final TracedLink link)
+ private void renderLink(final PrintStream report, final TracedLink link,
+ final boolean showOrigin)
{
final LinkStatus status = link.getStatus();
report.print(status.isIncoming() ? "|<-- (" : "|--> (");
report.print(status.getShortTag());
report.print(") ");
report.print(link.getOtherLinkEnd().getId());
- report.print(this.newline);
+ report.print(this.settings.getNewline());
+ if (showOrigin)
+ {
+ final Location location = link.getOtherLinkEnd().getLocation();
+ if (location != null)
+ {
+ report.print("| ");
+ renderOrigin(report, location);
+ report.print(this.settings.getNewline());
+ }
+ }
}
private void renderTags(final PrintStream report, final LinkedSpecificationItem item)
@@ -308,11 +333,26 @@ private void renderTags(final PrintStream report, final LinkedSpecificationItem
renderEmptyItemDetailsLine(report);
report.print("| #: ");
report.print(tags.stream().collect(Collectors.joining(", ")));
- report.print(this.newline);
+ report.print(this.settings.getNewline());
++this.nonEmptySections;
}
}
+ private void renderOrigin(final PrintStream report, final LinkedSpecificationItem item)
+ {
+ final Location location = item.getLocation();
+ if (location != null)
+ {
+ renderEmptyItemDetailsLine(report);
+ report.print("| (");
+ report.print(location.getPath());
+ report.print(":");
+ report.print(location.getLine());
+ report.print(")");
+ report.print(this.settings.getNewline());
+ }
+ }
+
private void renderItemDetailsEnd(final PrintStream report)
{
if (this.nonEmptySections > 0)
diff --git a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlSpecificationItem.java b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlSpecificationItem.java
index d6041d98..676dd72f 100644
--- a/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlSpecificationItem.java
+++ b/src/main/java/org/itsallcode/openfasttrace/report/view/html/HtmlSpecificationItem.java
@@ -35,6 +35,7 @@
public class HtmlSpecificationItem implements Viewable
{
+
private final LinkedSpecificationItem item;
private final PrintStream stream;
private final MarkdownConverter converter = new MarkdownConverter();
@@ -57,6 +58,7 @@ public void render(final int level)
renderRationale(indentation);
renderComment(indentation);
renderNeeds(indentation);
+ renderOrigin(indentation);
renderLinks(indentation);
renderEnd(indentation);
}
@@ -167,6 +169,17 @@ private String translateArtifactTypeCoverage(final LinkedSpecificationItem item)
.collect(Collectors.joining(", "));
}
+ private void renderOrigin(final String indentation)
+ {
+ final String origin = OriginLinkFormatter.formatAsBlock(this.item.getLocation());
+ if (!origin.isEmpty())
+ {
+ this.stream.print(indentation);
+ this.stream.print(" ");
+ this.stream.println(origin);
+ }
+ }
+
private void renderLinks(final String indentation)
{
renderLinkForDirection(indentation, true);
@@ -225,10 +238,22 @@ protected void renderLinkEntry(final List outLinks, final String ind
{
this.stream.print(" (" + link.getStatus() + ")");
}
+ renderLinkOrigin(link);
this.stream.println("");
}
}
+ private void renderLinkOrigin(final TracedLink link)
+ {
+ final String origin = OriginLinkFormatter
+ .formatAsSpan(link.getOtherLinkEnd().getLocation());
+ if (!origin.isEmpty())
+ {
+ this.stream.print(" ");
+ this.stream.print(origin);
+ }
+ }
+
protected void renderEnd(final String indentation)
{
this.stream.print(indentation);
diff --git a/src/main/java/org/itsallcode/openfasttrace/report/view/html/OriginLinkFormatter.java b/src/main/java/org/itsallcode/openfasttrace/report/view/html/OriginLinkFormatter.java
new file mode 100644
index 00000000..397f7362
--- /dev/null
+++ b/src/main/java/org/itsallcode/openfasttrace/report/view/html/OriginLinkFormatter.java
@@ -0,0 +1,148 @@
+package org.itsallcode.openfasttrace.report.view.html;
+
+/*-
+ * #%L
+ * OpenFastTrace
+ * %%
+ * Copyright (C) 2016 - 2018 itsallcode.org
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import java.net.URI;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.regex.Pattern;
+
+import org.itsallcode.openfasttrace.core.Location;
+
+/**
+ * This class renders {@link Location} object as HTML spans or blocks.
+ */
+public final class OriginLinkFormatter
+{
+ private static final Pattern PROTOCOL_PREFIX_PATTERN = Pattern
+ .compile("^file://|ftp://|mailto:|https?://.*");
+
+ private OriginLinkFormatter()
+ {
+ // prevent instantiation.
+ }
+
+ /**
+ * Render an origin to an HTML span
+ *
+ * @param location
+ * origin location
+ * @return a string representing an HTML span containing a link to the
+ * origin
+ */
+ public static String formatAsSpan(final Location location)
+ {
+ return format(location, true);
+ }
+
+ /**
+ * Render an origin to an HTML block
+ *
+ * @param location
+ * origin location
+ * @return a string representing an HTML block containing a link to the
+ * origin
+ */
+ public static String formatAsBlock(final Location location)
+ {
+ return format(location, false);
+ }
+
+ private static String format(final Location location, final boolean asSpan)
+ {
+ if ((location != null) && !location.getPath().isEmpty())
+ {
+ return formatNonEmptyLocation(location, asSpan);
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ private static String formatNonEmptyLocation(final Location location, final boolean asSpan)
+ {
+ final String path = location.getPath();
+ final URI uri = checkPathHasProtocol(path) ? convertPathWithProtocolToUri(path)
+ : convertPathWithoutProtocolToUri(path);
+ final StringBuilder builder = new StringBuilder();
+ builder.append(asSpan ? "");
+ if (uri != null)
+ {
+ builder.append("");
+ builder.append(path);
+ builder.append("");
+ }
+ else
+ {
+ builder.append(path);
+ }
+ builder.append(":");
+ final int line = location.getLine();
+ builder.append(line);
+ builder.append(asSpan ? "" : "
");
+ return builder.toString();
+ }
+
+ private static boolean checkPathHasProtocol(final String path)
+ {
+ return PROTOCOL_PREFIX_PATTERN.matcher(path).matches();
+ }
+
+ private static URI convertPathWithProtocolToUri(final String path)
+ {
+ URI uri;
+ try
+ {
+ uri = URI.create(path);
+ }
+ catch (final IllegalArgumentException e)
+ {
+ uri = null;
+ }
+ return uri;
+ }
+
+ private static URI convertPathWithoutProtocolToUri(final String path)
+ {
+ URI uri;
+ final Path realPath = Paths.get(unWindowsify(path));
+ if (realPath.isAbsolute())
+ {
+ uri = realPath.toUri();
+ }
+ else
+ {
+ uri = null;
+ }
+ return uri;
+ }
+
+ private static String unWindowsify(final String path)
+ {
+ return path.replaceAll("([A-Z]:)", "/$1").replaceAll("\\\\", "/");
+ }
+}
diff --git a/src/main/resources/css/report.css b/src/main/resources/css/report.css
index a10dd10b..6754fd8e 100644
--- a/src/main/resources/css/report.css
+++ b/src/main/resources/css/report.css
@@ -119,3 +119,16 @@ summary .title {
border-top: 1px solid lightgrey;
font-family: courier;
}
+
+.origin:before {
+ content: "\1F78B";
+ margin: 0 0.5em;
+}
+
+.origin {
+ font-family: courier;
+}
+
+.sitem p.origin {
+ padding-left: 0.5em;
+}
\ No newline at end of file
diff --git a/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java b/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java
new file mode 100644
index 00000000..731b26c9
--- /dev/null
+++ b/src/test/java/org/itsallcode/openfasttrace/TestExportSettings.java
@@ -0,0 +1,68 @@
+package org.itsallcode.openfasttrace;
+
+/*-
+ * #%L
+ * OpenFastTrace
+ * %%
+ * Copyright (C) 2016 - 2018 itsallcode.org
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.itsallcode.openfasttrace.core.Newline;
+import org.itsallcode.openfasttrace.exporter.ExporterConstants;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestExportSettings
+{
+ private ExportSettings.Builder builder;
+
+ @Before
+ public void before()
+ {
+ this.builder = ExportSettings.builder();
+ }
+
+ @Test
+ public void testDefaultOutputFormat()
+ {
+ assertThat(this.builder.build().getOutputFormat(),
+ equalTo(ExporterConstants.DEFAULT_OUTPUT_FORMAT));
+ }
+
+ @Test
+ public void testDefaultNewline()
+ {
+ assertThat(this.builder.build().getNewline(), equalTo(Newline.UNIX));
+ }
+
+ @Test
+ public void testBuildWithOutputFormat()
+ {
+ assertThat(this.builder.outputFormat("foo").build().getOutputFormat(), equalTo("foo"));
+ }
+
+ @Test
+ public void testBuildWithNewline()
+ {
+ assertThat(this.builder.newline(Newline.OLDMAC).build().getNewline(),
+ equalTo(Newline.OLDMAC));
+ }
+}
diff --git a/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java b/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java
new file mode 100644
index 00000000..b209b4d0
--- /dev/null
+++ b/src/test/java/org/itsallcode/openfasttrace/TestImportSettings.java
@@ -0,0 +1,101 @@
+package org.itsallcode.openfasttrace;
+
+/*-
+ * #%L
+ * OpenFastTrace
+ * %%
+ * Copyright (C) 2016 - 2018 itsallcode.org
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.collection.IsEmptyIterable.emptyIterableOf;
+import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
+import static org.junit.Assert.assertThat;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+
+import org.itsallcode.openfasttrace.importer.tag.config.PathConfig;
+import org.junit.Test;
+
+/**
+ * This class implements a parameter object to control the settings of OFT's
+ * export mode.
+ */
+public class TestImportSettings
+{
+ @Test
+ public void testInputListEmptyByDefault()
+ {
+ assertThat(ImportSettings.createDefault().getInputs(), emptyIterableOf(Path.class));
+ }
+
+ @Test
+ public void testDefaultFilter()
+ {
+ assertThat(ImportSettings.createDefault().getFilters(),
+ equalTo(FilterSettings.createAllowingEverything()));
+ }
+
+ @Test
+ public void testDefaultPathConfigs()
+ {
+ assertThat(ImportSettings.createDefault().getPathConfigs(),
+ emptyIterableOf(PathConfig.class));
+ }
+
+ @Test
+ public void testAddInputList()
+ {
+ final Path[] expectedInputs = { Paths.get("/a/path"), Paths.get("/another/path") };
+ assertThat(ImportSettings.builder().addInputs(Arrays.asList(expectedInputs)).build()
+ .getInputs(), containsInAnyOrder(expectedInputs));
+ }
+
+ @Test
+ public void testAddInputArray()
+ {
+ final Path[] expectedInputs = { Paths.get("/a/path"), Paths.get("/another/path") };
+ assertThat(ImportSettings.builder().addInputs(expectedInputs).build().getInputs(),
+ containsInAnyOrder(expectedInputs));
+ }
+
+ @Test
+ public void testBuildWithFilter()
+ {
+ final String[] expectedTags = { "a", "b" };
+ final FilterSettings filter = new FilterSettings.Builder()
+ .tags(new HashSet<>(Arrays.asList(expectedTags))).build();
+ assertThat(ImportSettings.builder().filter(filter).build().getFilters().getTags(),
+ containsInAnyOrder(expectedTags));
+ }
+
+ @Test
+ public void testBuildWithPathConfigs()
+ {
+ final List expectedPathConfigs = new ArrayList<>();
+ final PathConfig.Builder builder = PathConfig.builder();
+ final PathConfig expectedFirstPathConfig = builder.patternPathMatcher("src")
+ .coveredItemArtifactType("a1").coveredItemNamePrefix("b1").tagArtifactType("c1")
+ .build();
+ expectedPathConfigs.add(expectedFirstPathConfig);
+ assertThat(ImportSettings.builder().pathConfigs(expectedPathConfigs).build()
+ .getPathConfigs().get(0), equalTo(expectedFirstPathConfig));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java b/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java
new file mode 100644
index 00000000..270d50bc
--- /dev/null
+++ b/src/test/java/org/itsallcode/openfasttrace/TestReportSettings.java
@@ -0,0 +1,94 @@
+package org.itsallcode.openfasttrace;
+
+/*-
+ * #%L
+ * OpenFastTrace
+ * %%
+ * Copyright (C) 2016 - 2018 itsallcode.org
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.itsallcode.openfasttrace.ReportSettings.Builder;
+import org.itsallcode.openfasttrace.core.Newline;
+import org.itsallcode.openfasttrace.report.ReportVerbosity;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestReportSettings
+{
+ private Builder builder;
+
+ @Before
+ public void before()
+ {
+ this.builder = ReportSettings.builder();
+ }
+
+ @Test
+ public void testDefaultVerbosity()
+ {
+ assertThat(this.builder.build().getReportVerbosity(),
+ equalTo(ReportVerbosity.FAILURE_DETAILS));
+ }
+
+ @Test
+ public void testOriginNotShownByDefault()
+ {
+ assertThat(this.builder.build().showOrigin(), equalTo(false));
+ }
+
+ @Test
+ public void testDefaultOutputFormat()
+ {
+ assertThat(this.builder.build().getOutputFormat(), equalTo("plain"));
+ }
+
+ @Test
+ public void testDefaultNewline()
+ {
+ assertThat(this.builder.build().getNewline(), equalTo(Newline.UNIX));
+ }
+
+ @Test
+ public void testBuildWithVerbosity()
+ {
+ assertThat(this.builder.verbosity(ReportVerbosity.ALL).build().getReportVerbosity(),
+ equalTo(ReportVerbosity.ALL));
+ }
+
+ @Test
+ public void testBuildWithOriginShown()
+ {
+ assertThat(this.builder.showOrigin(true).build().showOrigin(), equalTo(true));
+ }
+
+ @Test
+ public void testBuildWithOutputFormat()
+ {
+ assertThat(this.builder.outputFormat("html").build().getOutputFormat(), equalTo("html"));
+ }
+
+ @Test
+ public void testBuildWithNewline()
+ {
+ assertThat(this.builder.newline(Newline.OLDMAC).build().getNewline(),
+ equalTo(Newline.OLDMAC));
+ }
+}
diff --git a/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java b/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java
index 46c9661d..17d0f25f 100644
--- a/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java
+++ b/src/test/java/org/itsallcode/openfasttrace/cli/TestCliArguments.java
@@ -222,4 +222,36 @@ public void testSetWantedTagsIncludingNone()
assertThat(AFTER_SETTER, this.arguments.getWantedTags(),
containsInAnyOrder("_", "client", "server"));
}
+
+ // [utest->dsn~reporting.plain-text.specification-item-origin~1]]
+ // [utest->dsn~reporting.plain-text.linked-specification-item-origin~1]
+ // [utest->dsn~reporting.html.specification-item-origin~1]
+ // [utest->dsn~reporting.html.linked-specification-item-origin~1]
+ @Test
+ public void testShowOriginDisabledByDefault()
+ {
+ assertThat(this.arguments.getShowOrigin(), is(false));
+ }
+
+ // [utest->dsn~reporting.plain-text.specification-item-origin~1]]
+ // [utest->dsn~reporting.plain-text.linked-specification-item-origin~1]
+ // [utest->dsn~reporting.html.specification-item-origin~1]
+ // [utest->dsn~reporting.html.linked-specification-item-origin~1]
+ @Test
+ public void testSetShowOrigin()
+ {
+ this.arguments.setShowOrigin(true);
+ assertThat(this.arguments.getShowOrigin(), is(true));
+ }
+
+ // [utest->dsn~reporting.plain-text.specification-item-origin~1]]
+ // [utest->dsn~reporting.plain-text.linked-specification-item-origin~1]
+ // [utest->dsn~reporting.html.specification-item-origin~1]
+ // [utest->dsn~reporting.html.linked-specification-item-origin~1]
+ @Test
+ public void testSetS()
+ {
+ this.arguments.setS(true);
+ assertThat(this.arguments.getShowOrigin(), is(true));
+ }
}
\ No newline at end of file
diff --git a/src/test/java/org/itsallcode/openfasttrace/core/TestLocation.java b/src/test/java/org/itsallcode/openfasttrace/core/TestLocation.java
index 21dbdef3..ede74e83 100644
--- a/src/test/java/org/itsallcode/openfasttrace/core/TestLocation.java
+++ b/src/test/java/org/itsallcode/openfasttrace/core/TestLocation.java
@@ -88,4 +88,4 @@ public void testIsNotCompleteEnoughWithoutPath()
assertThat("builder with path set to null is complete", builderB.isCompleteEnough(),
equalTo(false));
}
-}
+}
\ No newline at end of file
diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java b/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java
index 901a3906..fcac4f28 100644
--- a/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java
+++ b/src/test/java/org/itsallcode/openfasttrace/importer/ImporterFactoryTestBase.java
@@ -1,7 +1,5 @@
package org.itsallcode.openfasttrace.importer;
-import static java.util.Collections.emptyList;
-
/*-
* #%L
\* OpenFastTrace
@@ -33,8 +31,8 @@
import java.nio.file.Paths;
import java.util.List;
+import org.itsallcode.openfasttrace.ImportSettings;
import org.itsallcode.openfasttrace.importer.input.InputFile;
-import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -59,8 +57,7 @@ public abstract class ImporterFactoryTestBase
public void initMocks()
{
MockitoAnnotations.initMocks(this);
- when(this.contextMock.getTagImporterConfig())
- .thenReturn(new TagImporterConfig(emptyList()));
+ when(this.contextMock.getImportSettings()).thenReturn(ImportSettings.createDefault());
}
@Test
diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java b/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java
index 5652513d..239984a5 100644
--- a/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java
+++ b/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterContext.java
@@ -25,7 +25,7 @@
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat;
-import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig;
+import org.itsallcode.openfasttrace.ImportSettings;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
@@ -34,7 +34,7 @@
public class TestImporterContext
{
@Mock
- private TagImporterConfig configMock;
+ private ImportSettings settingsMock;
@Mock
private ImporterService importerServiceMock;
@@ -44,13 +44,13 @@ public class TestImporterContext
public void setup()
{
MockitoAnnotations.initMocks(this);
- this.context = new ImporterContext(this.configMock);
+ this.context = new ImporterContext(this.settingsMock);
}
@Test
public void testGetImporterConfig()
{
- assertThat(this.context.getTagImporterConfig(), sameInstance(this.configMock));
+ assertThat(this.context.getImportSettings(), sameInstance(this.settingsMock));
}
@Test(expected = NullPointerException.class)
@@ -65,4 +65,4 @@ public void testGetImporterService()
this.context.setImporterService(this.importerServiceMock);
assertThat(this.context.getImporterService(), sameInstance(this.importerServiceMock));
}
-}
+}
\ No newline at end of file
diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterService.java b/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterService.java
index f3723136..99de953b 100644
--- a/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterService.java
+++ b/src/test/java/org/itsallcode/openfasttrace/importer/TestImporterService.java
@@ -33,6 +33,7 @@
import java.nio.file.Paths;
import java.util.List;
+import org.itsallcode.openfasttrace.ImportSettings;
import org.itsallcode.openfasttrace.core.SpecificationItem;
import org.itsallcode.openfasttrace.importer.input.InputFile;
import org.itsallcode.openfasttrace.testutil.OsDetector;
@@ -67,7 +68,8 @@ public class TestImporterService
public void setUp()
{
MockitoAnnotations.initMocks(this);
- this.importerService = new ImporterService(this.factoryLoaderMock);
+ this.importerService = new ImporterService(this.factoryLoaderMock,
+ ImportSettings.createDefault());
this.file = InputFile.forPath(Paths.get("dir", "file"));
when(this.factoryLoaderMock.getImporterFactory(any(InputFile.class)))
diff --git a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactoryWithConfig.java b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactoryWithConfig.java
index 89eb1a72..6ad36dac 100644
--- a/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactoryWithConfig.java
+++ b/src/test/java/org/itsallcode/openfasttrace/importer/tag/TestTagImporterFactoryWithConfig.java
@@ -35,10 +35,10 @@
import java.nio.file.Path;
import java.nio.file.Paths;
+import org.itsallcode.openfasttrace.ImportSettings;
import org.itsallcode.openfasttrace.importer.*;
import org.itsallcode.openfasttrace.importer.input.InputFile;
import org.itsallcode.openfasttrace.importer.tag.config.PathConfig;
-import org.itsallcode.openfasttrace.importer.tag.config.TagImporterConfig;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -119,29 +119,29 @@ public void testFactoryThrowsExceptionForMissingFile() throws IOException
importer.runImport();
}
- private void assertSupportsFile(final TagImporterConfig config, final String path,
+ private void assertSupportsFile(final ImportSettings settings, final String path,
final boolean expected)
{
final InputFile file = InputFile.forPath(Paths.get(path));
- assertThat(create(config).supportsFile(file), equalTo(expected));
+ assertThat(create(settings).supportsFile(file), equalTo(expected));
}
- private Importer createImporter(final TagImporterConfig config, final Path path)
+ private Importer createImporter(final ImportSettings settings, final Path path)
{
final InputFile file = InputFile.forPath(path, StandardCharsets.UTF_8);
- return create(config).createImporter(file, this.listenerMock);
+ return create(settings).createImporter(file, this.listenerMock);
}
- private TagImporterConfig configure(final PathConfig... pathConfigs)
+ private ImportSettings configure(final PathConfig... pathConfigs)
{
- return new TagImporterConfig(asList(pathConfigs));
+ return ImportSettings.builder().pathConfigs(asList(pathConfigs)).build();
}
- private TagImporterFactory create(final TagImporterConfig config)
+ private TagImporterFactory create(final ImportSettings settings)
{
final TagImporterFactory factory = new TagImporterFactory();
factory.init(this.contextMock);
- when(this.contextMock.getTagImporterConfig()).thenReturn(config);
+ when(this.contextMock.getImportSettings()).thenReturn(settings);
return factory;
}
diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftModeTest.java b/src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftTest.java
similarity index 93%
rename from src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftModeTest.java
rename to src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftTest.java
index f76bc014..61efcb77 100644
--- a/src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftModeTest.java
+++ b/src/test/java/org/itsallcode/openfasttrace/mode/AbstractOftTest.java
@@ -22,15 +22,11 @@
* #L%
*/
-
import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
+import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -39,7 +35,7 @@
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
-public abstract class AbstractOftModeTest
+public abstract class AbstractOftTest
{
protected static final String NEWLINE = "\n";
@@ -85,4 +81,4 @@ protected void assertStdOutEmpty()
{
assertThat("STDOUT stream is empty", this.outputStream.size(), equalTo(0));
}
-}
+}
\ No newline at end of file
diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsConverter.java
similarity index 74%
rename from src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java
rename to src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsConverter.java
index 3a7b2b1a..0ec1521f 100644
--- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestConverter.java
+++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsConverter.java
@@ -24,31 +24,32 @@
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.util.List;
-import org.itsallcode.openfasttrace.Converter;
-import org.itsallcode.openfasttrace.exporter.ExporterConstants;
+import org.itsallcode.openfasttrace.ImportSettings;
+import org.itsallcode.openfasttrace.Oft;
+import org.itsallcode.openfasttrace.core.SpecificationItem;
import org.junit.Before;
import org.junit.Test;
-public class ITestConverter extends AbstractOftModeTest
+public class ITestOftAsConverter extends AbstractOftTest
{
private static final String REQM2_PREAMBLE = "";
-
- private Converter converter;
+ private Oft oft;
@Before
public void setUp() throws UnsupportedEncodingException
{
perpareOutput();
- this.converter = new ConvertMode();
+ this.oft = Oft.create();
}
@Test
public void testConvertToSpecobjectFile() throws IOException
{
- this.converter.addInputs(this.docDir);
- this.converter.convertToFileInFormat(this.outputFile,
- ExporterConstants.DEFAULT_OUTPUT_FORMAT);
+ final ImportSettings settings = ImportSettings.builder().addInputs(this.docDir).build();
+ final List items = this.oft.importItems(settings);
+ this.oft.exportToPath(items, this.outputFile);
assertStandardFileExportResult();
}
@@ -57,4 +58,4 @@ private void assertStandardFileExportResult() throws IOException
assertOutputFileExists(true);
assertOutputFileContentStartsWith(REQM2_PREAMBLE + "");
}
-}
+}
\ No newline at end of file
diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java
similarity index 59%
rename from src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java
rename to src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java
index e2a22bf6..3f988d4e 100644
--- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporter.java
+++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestOftAsReporter.java
@@ -29,45 +29,42 @@
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.*;
-import org.itsallcode.openfasttrace.FilterSettings;
-import org.itsallcode.openfasttrace.Reporter;
-import org.itsallcode.openfasttrace.core.Newline;
-import org.itsallcode.openfasttrace.core.Trace;
-import org.itsallcode.openfasttrace.report.ReportConstants;
+import org.itsallcode.openfasttrace.*;
+import org.itsallcode.openfasttrace.core.*;
import org.itsallcode.openfasttrace.report.ReportVerbosity;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.contrib.java.lang.system.SystemErrRule;
-public class ITestReporter extends AbstractOftModeTest
+public class ITestOftAsReporter extends AbstractOftTest
{
- private Reporter reporter;
+ private Oft oft;
+ @Rule
+ public final SystemErrRule systemErrRule = new SystemErrRule().enableLog();
+ private Trace trace;
+ private List linkedItems;
@Before
public void setUp() throws UnsupportedEncodingException
{
perpareOutput();
- this.reporter = new ReportMode();
+ final ImportSettings settings = ImportSettings.builder().addInputs(this.docDir).build();
+ this.oft = Oft.create();
+ final List items = this.oft.importItems(settings);
+ this.linkedItems = this.oft.link(items);
+ this.trace = this.oft.trace(this.linkedItems);
}
@Test
public void testTraceToFile() throws IOException
{
- final Trace trace = this.reporter.addInputs(this.docDir) //
- .trace();
- writePlainTextReportFromTrace(trace);
+ this.oft.reportToPath(this.trace, this.outputFile);
assertStandardReportFileResult();
}
- private void writePlainTextReportFromTrace(final Trace trace)
- {
- this.reporter.reportToFileInFormat(trace, this.outputFile,
- ReportConstants.DEFAULT_REPORT_FORMAT);
- }
-
private void assertStandardReportFileResult() throws IOException
{
assertOutputFileExists(true);
@@ -77,10 +74,9 @@ private void assertStandardReportFileResult() throws IOException
@Test
public void testTraceWithReportVerbosityMinimal() throws IOException
{
- final Trace trace = this.reporter.addInputs(this.docDir) //
- .setReportVerbosity(ReportVerbosity.MINIMAL) //
- .trace();
- writePlainTextReportFromTrace(trace);
+ final ReportSettings settings = ReportSettings.builder().verbosity(ReportVerbosity.MINIMAL)
+ .build();
+ this.oft.reportToPath(this.trace, this.outputFile, settings);
assertOutputFileExists(true);
assertOutputFileContentStartsWith("ok");
}
@@ -88,10 +84,10 @@ public void testTraceWithReportVerbosityMinimal() throws IOException
@Test
public void testTraceMacNewlines() throws IOException
{
- final Trace trace = this.reporter.addInputs(this.docDir) //
- .setNewline(Newline.OLDMAC) //
- .trace();
- writePlainTextReportFromTrace(trace);
+ final ReportSettings settings = ReportSettings.builder() //
+ .newline(Newline.OLDMAC) //
+ .build();
+ this.oft.reportToPath(this.trace, this.outputFile, settings);
assertThat(Files.exists(this.outputFile), equalTo(true));
assertThat("Has old Mac newlines", getOutputFileContent().contains(CARRIAGE_RETURN),
equalTo(true));
@@ -102,9 +98,7 @@ public void testTraceMacNewlines() throws IOException
@Test
public void testTraceToStdOut() throws IOException
{
- final Trace trace = this.reporter.addInputs(this.docDir) //
- .trace();
- this.reporter.reportToStdOutInFormat(trace, ReportConstants.DEFAULT_REPORT_FORMAT);
+ this.oft.reportToStdOut(this.trace);
assertStandardReportStdOutResult();
}
@@ -118,15 +112,24 @@ private void assertStandardReportStdOutResult() throws IOException
public void testFilterAllowsAllAtrifactsButDsn()
{
final Set artifactTypes = new HashSet<>(Arrays.asList("feat", "req"));
- this.reporter.addInputs(this.docDir);
- final Trace fullTrace = this.reporter.trace();
assertThat("Number of items with type \"dsn\" in regular trace",
- countItemsOfArtifactTypeInTrace("dsn", fullTrace), greaterThan(0L));
- final Trace trace = this.reporter //
- .setFilters(new FilterSettings.Builder().artifactTypes(artifactTypes).build())//
- .trace();
+ countItemsOfArtifactTypeInTrace("dsn", this.trace), greaterThan(0L));
+ final FilterSettings filterSettings = new FilterSettings.Builder()
+ .artifactTypes(artifactTypes).build();
+ final Trace filteredTrace = traceWithFilters(filterSettings);
assertThat("Number of items with ignored type \"dsn\" in filtered trace",
- countItemsOfArtifactTypeInTrace("dsn", trace), equalTo(0L));
+ countItemsOfArtifactTypeInTrace("dsn", filteredTrace), equalTo(0L));
+ }
+
+ private Trace traceWithFilters(final FilterSettings filterSettings)
+ {
+ final ImportSettings importSettings = ImportSettings.builder().filter(filterSettings)
+ .build();
+ final List filteredItems = this.oft.importItems(importSettings);
+ final List filteredSpecificationItems = this.oft
+ .link(filteredItems);
+ final Trace filteredTrace = this.oft.trace(filteredSpecificationItems);
+ return filteredTrace;
}
private long countItemsOfArtifactTypeInTrace(final String artifactType, final Trace trace)
diff --git a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java
index 0c5ac6f5..b8f9dfab 100644
--- a/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java
+++ b/src/test/java/org/itsallcode/openfasttrace/mode/ITestReporterWithFilter.java
@@ -32,7 +32,10 @@
import java.util.stream.Collectors;
import org.itsallcode.openfasttrace.FilterSettings;
-import org.itsallcode.openfasttrace.Reporter;
+import org.itsallcode.openfasttrace.ImportSettings;
+import org.itsallcode.openfasttrace.Oft;
+import org.itsallcode.openfasttrace.core.LinkedSpecificationItem;
+import org.itsallcode.openfasttrace.core.SpecificationItem;
import org.itsallcode.openfasttrace.core.Trace;
import org.itsallcode.openfasttrace.testutil.AbstractFileBasedTest;
import org.junit.Before;
@@ -61,14 +64,13 @@ public class ITestReporterWithFilter extends AbstractFileBasedTest
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
- private Reporter reporter;
+ private Oft oft;
@Before
public void before() throws IOException
{
writeTextFile(this.tempFolder.newFile("spec.md"), SPECIFICATION);
- this.reporter = new ReportMode();
- this.reporter.addInputs(this.tempFolder.getRoot().toPath());
+ this.oft = Oft.create();
}
// [itest->dsn~filtering-by-tags-during-import~1]
@@ -85,9 +87,13 @@ public void testFilterWithAtLeastOneMatchingTag()
private List getIdsFromTraceWithFilterSettings(final FilterSettings filterSettings)
{
- final Trace trace = this.reporter //
- .setFilters(filterSettings) //
- .trace();
+ final ImportSettings importSettings = ImportSettings.builder() //
+ .addInputs(this.tempFolder.getRoot().toPath()) //
+ .filter(filterSettings) //
+ .build();
+ final List items = this.oft.importItems(importSettings);
+ final List linkedItems = this.oft.link(items);
+ final Trace trace = this.oft.trace(linkedItems);
final List filteredIds = trace.getItems() //
.stream() //
.map(item -> item.getId().toString()) //
@@ -104,6 +110,5 @@ public void testFilterWithAtLeastOneMatchingTagOrNoTags()
.build();
final List filteredIds = getIdsFromTraceWithFilterSettings(filterSettings);
assertThat(filteredIds, containsInAnyOrder("feat~a~1", "req~b~2", "dsn~c~3", "impl~d~4"));
-
}
}
\ No newline at end of file
diff --git a/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java b/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java
index 21839aeb..ae280090 100644
--- a/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java
+++ b/src/test/java/org/itsallcode/openfasttrace/report/TestReportService.java
@@ -29,7 +29,7 @@
import java.io.File;
import java.io.IOException;
-import org.itsallcode.openfasttrace.core.Newline;
+import org.itsallcode.openfasttrace.ReportSettings;
import org.itsallcode.openfasttrace.core.Trace;
import org.junit.Before;
import org.junit.Rule;
@@ -61,24 +61,27 @@ public void prepareTest()
@Test
public void testReportPlainText()
{
- this.service.reportTraceToStdOut(this.traceMock, "plain", ReportVerbosity.MINIMAL,
- Newline.UNIX);
+ final ReportSettings settings = ReportSettings.builder().verbosity(ReportVerbosity.MINIMAL)
+ .build();
+ this.service.reportTraceToStdOut(this.traceMock, settings);
assertThat(this.systemOutRule.getLog(), equalTo("not ok\n"));
}
@Test
public void testReportHtml()
{
- this.service.reportTraceToStdOut(this.traceMock, "html", ReportVerbosity.MINIMAL,
- Newline.UNIX);
+ final ReportSettings settings = ReportSettings.builder().outputFormat("html")
+ .verbosity(ReportVerbosity.MINIMAL).build();
+ this.service.reportTraceToStdOut(this.traceMock, settings);
assertThat(this.systemOutRule.getLog(), startsWith(""));
}
@Test(expected = IllegalArgumentException.class)
public void testInvalidReportFormatThrowsIllegalArgumentException()
{
- this.service.reportTraceToStdOut(this.traceMock, "invalid", ReportVerbosity.QUIET,
- Newline.UNIX);
+ final ReportSettings settings = ReportSettings.builder().outputFormat("invalid")
+ .verbosity(ReportVerbosity.QUIET).build();
+ this.service.reportTraceToStdOut(this.traceMock, settings);
}
@Test(expected = ReportException.class)
@@ -86,7 +89,8 @@ public void testReportToIllegalPathThrowsReportExpection() throws IOException
{
final File readOnlyFile = this.temporaryFolder.newFile();
readOnlyFile.setReadOnly();
- this.service.reportTraceToPath(this.traceMock, readOnlyFile.toPath(), "plain",
- ReportVerbosity.QUIET, Newline.UNIX);
+ final ReportSettings settings = ReportSettings.builder().verbosity(ReportVerbosity.QUIET)
+ .build();
+ this.service.reportTraceToPath(this.traceMock, readOnlyFile.toPath(), settings);
}
}
diff --git a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReport.java b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReport.java
index 6829edd5..95ee2dd0 100644
--- a/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReport.java
+++ b/src/test/java/org/itsallcode/openfasttrace/report/html/TestHtmlReport.java
@@ -31,7 +31,6 @@
import java.util.Arrays;
import org.itsallcode.openfasttrace.core.*;
-import org.itsallcode.openfasttrace.report.ReportVerbosity;
import org.itsallcode.openfasttrace.report.Reportable;
import org.junit.Before;
import org.junit.Test;
@@ -62,7 +61,7 @@ protected String renderToString()
{
final OutputStream outputStream = new ByteArrayOutputStream();
final Reportable report = new HtmlReport(this.traceMock);
- report.renderToStreamWithVerbosityLevel(outputStream, ReportVerbosity.ALL);
+ report.renderToStream(outputStream);
final String outputAsString = outputStream.toString();
return outputAsString;
}
diff --git a/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java b/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java
index b382e6af..dcb44340 100644
--- a/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java
+++ b/src/test/java/org/itsallcode/openfasttrace/report/plaintext/TestPlainTextReport.java
@@ -37,6 +37,7 @@
import java.io.OutputStream;
import java.util.*;
+import org.itsallcode.openfasttrace.ReportSettings;
import org.itsallcode.openfasttrace.core.*;
import org.itsallcode.openfasttrace.report.ReportVerbosity;
import org.itsallcode.openfasttrace.report.Reportable;
@@ -62,8 +63,9 @@ public void prepareTest()
public void testOutputStreamClosed() throws IOException
{
final OutputStream outputStreamMock = mock(OutputStream.class);
- new PlainTextReport(this.traceMock, NEWLINE_SEPARATOR)
- .renderToStreamWithVerbosityLevel(outputStreamMock, ReportVerbosity.SUMMARY);
+ final ReportSettings settings = ReportSettings.builder().verbosity(ReportVerbosity.SUMMARY)
+ .build();
+ new PlainTextReport(this.traceMock, settings).renderToStream(outputStreamMock);
verify(outputStreamMock).close();
}
@@ -83,9 +85,15 @@ public void testReportLevel_Minimal_OK()
private void assertReportOutput(final ReportVerbosity verbosity,
final String... expectedReportLines)
+ {
+ assertReportOutput(verbosity, false, expectedReportLines);
+ }
+
+ private void assertReportOutput(final ReportVerbosity verbosity, final boolean showOrigin,
+ final String... expectedReportLines)
{
final String expectedReportText = getExpectedReportText(expectedReportLines);
- assertThat(getReportOutput(verbosity), matchesAllLines(expectedReportText));
+ assertThat(getReportOutput(verbosity, showOrigin), matchesAllLines(expectedReportText));
}
private String getExpectedReportText(final String... expectedReportLines)
@@ -99,18 +107,20 @@ private String getExpectedReportText(final String... expectedReportLines)
+ NEWLINE_SEPARATOR;
}
- private String getReportOutput(final ReportVerbosity verbosity)
+ private String getReportOutput(final ReportVerbosity verbosity, final boolean showOrigin)
{
final Newline newline = NEWLINE_SEPARATOR;
- return getReportOutputWithNewline(verbosity, newline);
+ return getReportOutputWithNewline(verbosity, newline, showOrigin);
}
private String getReportOutputWithNewline(final ReportVerbosity verbosity,
- final Newline newline)
+ final Newline newline, final boolean showOrigin)
{
final OutputStream outputStream = new ByteArrayOutputStream();
- final Reportable report = new PlainTextReport(this.traceMock, newline);
- report.renderToStreamWithVerbosityLevel(outputStream, verbosity);
+ final ReportSettings settings = ReportSettings.builder().verbosity(verbosity)
+ .newline(newline).showOrigin(showOrigin).build();
+ final Reportable report = new PlainTextReport(this.traceMock, settings);
+ report.renderToStream(outputStream);
return outputStream.toString();
}
@@ -353,7 +363,7 @@ public void testReportWithDifferentLineSeparator()
when(this.traceMock.hasNoDefects()).thenReturn(true);
when(this.traceMock.getItems()).thenReturn(asList(itemAMock, itemBMock));
- assertThat(getReportOutputWithNewline(ReportVerbosity.ALL, separator), //
+ assertThat(getReportOutputWithNewline(ReportVerbosity.ALL, separator, false), //
equalTo("ok - 0/0>0>0/0 - a~a~1 (dsn)" + separator//
+ "|" + separator //
+ "| This is" + separator //
@@ -368,4 +378,44 @@ public void testReportWithDifferentLineSeparator()
+ "ok - 2 total" + separator));
}
+
+ // [utest->dsn~reporting.plain-text.specification-item-origin~1]
+ // [utest->dsn~reporting.plain-text.linked-specification-item-origin~1]
+ @Test
+ public void testReportWithOriginDisplayEnabled()
+ {
+ final LinkedSpecificationItem itemMock = createLinkedItemMock("req~item.with-source~77",
+ "Description", 0, 1, 0, 0, 0);
+ when(itemMock.getNeedsArtifactTypes()).thenReturn(asList(DSN));
+ when(itemMock.getCoveredArtifactTypes()).thenReturn(new HashSet<>(asList(DSN)));
+ final LinkedSpecificationItem other = createOtherItemMock("dsn~the-other~1");
+ when(other.getLocation()).thenReturn(Location.create("baz/zoo", 10));
+ final List links = new ArrayList<>();
+ links.add(new TracedLink(other, LinkStatus.COVERED_SHALLOW));
+ when(itemMock.getTracedLinks()).thenReturn(links);
+ when(itemMock.hasLinks()).thenReturn(true);
+ when(itemMock.getLocation()).thenReturn(Location.create("/foo/bar", 42));
+ when(this.traceMock.count()).thenReturn(1);
+ when(this.traceMock.countDefects()).thenReturn(0);
+ when(this.traceMock.hasNoDefects()).thenReturn(true);
+ when(this.traceMock.getItems()).thenReturn(asList(itemMock));
+ assertReportOutputWithOrigin(ReportVerbosity.ALL, //
+ "ok - 0/1>0>0/0 - req~item.with-source~77 (dsn)", //
+ "|", //
+ "| Description", //
+ "|", //
+ "| (/foo/bar:42)", //
+ "|", //
+ "|<-- ( ) dsn~the-other~1", //
+ "| (baz/zoo:10)", //
+ "|", //
+ "", //
+ "ok - 1 total");
+ }
+
+ private void assertReportOutputWithOrigin(final ReportVerbosity verbosity,
+ final String... expectedReportLines)
+ {
+ assertReportOutput(verbosity, true, expectedReportLines);
+ }
}
diff --git a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlSpecificationItem.java b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlSpecificationItem.java
index f53026e1..0c56ebc8 100644
--- a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlSpecificationItem.java
+++ b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestHtmlSpecificationItem.java
@@ -169,4 +169,66 @@ public void testRenderIncomingLinks()
"", //
"");
}
+
+ @Test
+ public void testRenderOutgoingLinks()
+ {
+ final SpecificationItem item = new SpecificationItem.Builder() //
+ .id(ITEM_A_ID) //
+ .build();
+ final LinkedSpecificationItem linkedItem = new LinkedSpecificationItem(item);
+ linkedItem.addLinkToItemWithStatus(this.itemMockB, LinkStatus.COVERS);
+ linkedItem.addLinkToItemWithStatus(this.itemMockC, LinkStatus.UNWANTED);
+ final Viewable view = this.factory.createSpecificationItem(linkedItem);
+ view.render(0);
+ assertOutputLines( //
+ "", //
+ " ", //
+ " " + CHECKMARK
+ + " name-a, rev. 1, dsn
", //
+ " " + ITEM_A_ID + "
", //
+ " ", //
+ "
Out: 2
", //
+ "
", //
+ "
", //
+ " ", //
+ "", //
+ "");
+ }
+
+ @Test
+ public void testRenderOrigin()
+ {
+ final Location location = Location.create("foo/bar", 13);
+ final SpecificationItem item = new SpecificationItem.Builder() //
+ .id(ITEM_A_ID) //
+ .location(location) //
+ .build();
+ final LinkedSpecificationItem linkedItem = new LinkedSpecificationItem(item);
+ linkedItem.addLinkToItemWithStatus(this.itemMockB, LinkStatus.COVERED_SHALLOW);
+ when(this.itemMockB.getLocation())
+ .thenReturn(Location.create("http://example.org/foo.txt", 3));
+ final Viewable view = this.factory.createSpecificationItem(linkedItem);
+ view.render(0);
+ assertOutputLines("", //
+ " ", //
+ " " + CHECKMARK
+ + " name-a, rev. 1, dsn
", //
+ " " + ITEM_A_ID + "
", //
+ " foo/bar:13
", //
+ " ", //
+ "
In: 1
", //
+ "
", //
+ "
", //
+ " ", //
+ "", //
+ "");
+ }
}
\ No newline at end of file
diff --git a/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestOriginLinkFormatter.java b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestOriginLinkFormatter.java
new file mode 100644
index 00000000..e8676252
--- /dev/null
+++ b/src/test/java/org/itsallcode/openfasttrace/report/view/html/TestOriginLinkFormatter.java
@@ -0,0 +1,107 @@
+package org.itsallcode.openfasttrace.report.view.html;
+
+/*-
+ * #%L
+ * OpenFastTrace
+ * %%
+ * Copyright (C) 2016 - 2018 itsallcode.org
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.itsallcode.openfasttrace.report.view.html.OriginLinkFormatter.formatAsBlock;
+import static org.itsallcode.openfasttrace.report.view.html.OriginLinkFormatter.formatAsSpan;
+import static org.junit.Assert.assertThat;
+
+import org.itsallcode.openfasttrace.core.Location;
+import org.junit.Test;
+
+public class TestOriginLinkFormatter
+{
+ @Test
+ public void testNullOrigin()
+ {
+ assertThat(formatAsSpan(null), equalTo(""));
+ }
+
+ @Test
+ public void testEmptyOrigin()
+ {
+ assertThat(formatAsSpan(Location.create("", 1)), equalTo(""));
+ }
+
+ @Test
+ public void testFormatMinimalHttpLink()
+ {
+ assertPathAndLineRenderedToSpan("http://example.org", 1,
+ "http://example.org:1");
+ }
+
+ private void assertPathAndLineRenderedToSpan(final String path, final int line,
+ final String expected)
+ {
+ assertThat(formatAsSpan(Location.create(path, line)),
+ equalTo("" + expected + ""));
+ }
+
+ @Test
+ public void testFormatMinimalHttpLinkAsBlock()
+ {
+ assertPathAndLineRenderedToBlock("http://example.org", 1,
+ "http://example.org:1");
+ }
+
+ private void assertPathAndLineRenderedToBlock(final String path, final int line,
+ final String expected)
+ {
+ assertThat(formatAsBlock(Location.create(path, line)),
+ equalTo("" + expected + "
"));
+ }
+
+ @Test
+ public void testLongerHttpLink()
+ {
+ assertPathAndLineRenderedToSpan("http://example.org/foo/bar%20baz?zoo", 1,
+ "http://example.org/foo/bar%20baz?zoo:1");
+ }
+
+ @Test
+ public void testFormatRegularAbsoluteUnixPath()
+ {
+ assertPathAndLineRenderedToSpan("/foo/bar/baz", 1111,
+ "/foo/bar/baz:1111");
+ }
+
+ @Test
+ public void testFormatAbsoluteUnixPathWithSpecialCharacters()
+ {
+ assertPathAndLineRenderedToSpan("/fo o/bär/baz", 12345678,
+ "/fo o/bär/baz:12345678");
+ }
+
+ @Test
+ public void testFormatRelativeUnixPath()
+ {
+ assertPathAndLineRenderedToSpan("foo/bar/baz", 2, "foo/bar/baz:2");
+ }
+
+ @Test
+ public void testIllegalUri()
+ {
+ assertPathAndLineRenderedToSpan("http://example.org/a b", 5, "http://example.org/a b:5");
+ }
+}
diff --git a/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractFileBasedTest.java b/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractFileBasedTest.java
index fba40cfc..7ff7a055 100644
--- a/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractFileBasedTest.java
+++ b/src/test/java/org/itsallcode/openfasttrace/testutil/AbstractFileBasedTest.java
@@ -45,4 +45,4 @@ protected void runWithArguments(final String... args)
{
CliStarter.main(args);
}
-}
+}
\ No newline at end of file